smiley 1 month ago
parent
commit
c55c64dfa0

+ 0 - 34
README.md

@@ -125,40 +125,6 @@ Also, have a look [in the examples folder](https://github.com/chillerlan/php-qrc
 </p>
 </p>
 
 
 
 
-## Reading QR Codes
-
-Using the built-in QR Code reader is pretty straight-forward:
-
-```php
-// it's generally a good idea to wrap the reader in a try/catch block because it WILL throw eventually
-try{
-	$result = (new QRCode)->readFromFile('path/to/file.png'); // -> DecoderResult
-
-	// you can now use the result instance...
-	$content = $result->data;
-	$matrix  = $result->getMatrix(); // -> QRMatrix
-
-	// ...or simply cast it to string to get the content:
-	$content = (string)$result;
-}
-catch(Throwable $e){
-	// oopsies!
-}
-```
-
-
-# Shameless advertising
-
-Hi, please check out some of my other projects that are way cooler than qrcodes!
-
-- [js-qrcode](https://github.com/chillerlan/js-qrcode) - a javascript port of this library
-- [php-authenticator](https://github.com/chillerlan/php-authenticator) - a Google Authenticator implementation (see [authenticator example](https://github.com/chillerlan/php-qrcode/blob/main/examples/authenticator.php))
-- [php-httpinterface](https://github.com/chillerlan/php-httpinterface) - a PSR-7/15/17/18 implemetation
-- [php-oauth](https://github.com/chillerlan/php-oauth) - an OAuth 1/2 client library, fully PSR-7/PSR-17/PSR-18 compatible
-- [php-database](https://github.com/chillerlan/php-database) - a database client & querybuilder for MySQL, Postgres, SQLite, MSSQL, Firebird
-- [php-tootbot](https://github.com/php-tootbot/tootbot-template) - a Mastodon bot library (see [@dwil](https://github.com/php-tootbot/dwil))
-
-
 # Disclaimer!
 # Disclaimer!
 
 
 I don't take responsibility for molten CPUs, misled applications, failed log-ins etc.. Use at your own risk!
 I don't take responsibility for molten CPUs, misled applications, failed log-ins etc.. Use at your own risk!

+ 24 - 22
docs/Appendix/Performance-considerations.md

@@ -44,35 +44,37 @@ is a complex and costly operation that is necessary to ensure the symbol is read
 to override the evaluation and manually set a mask pattern, this is not recommended unless you know exactly what you're doing
 to override the evaluation and manually set a mask pattern, this is not recommended unless you know exactly what you're doing
 as it can render a QR symbol unreadable.
 as it can render a QR symbol unreadable.
 
 
-The table below shows the performance impact (in miliseconds) of the mask pattern evaluation for each version, the times may vary between systems.
+The table below shows the performance impact (in miliseconds) of the mask pattern evaluation for select versions, the times may vary between systems.
 
 
-| version   |       1 |       2 |       3 |       4 |       5 |       6 |       7 |       8 |       9 |      10 |
-|-----------|--------:|--------:|--------:|--------:|--------:|--------:|--------:|--------:|--------:|--------:|
-| **1-10**  |   4.414 |   5.697 |   7.986 |   9.221 |  10.877 |  11.293 |  13.901 |  15.563 |  18.142 |  20.501 |
-| **11-20** |  22.662 |  27.779 |  29.622 |  33.017 |  36.358 |  39.712 |  43.685 |  47.121 |  51.389 |  57.865 |
-| **21-30** |  59.753 |  68.502 |  68.523 |  72.866 |  78.245 |  83.593 |  88.327 |  94.921 | 103.394 | 106.358 |
-| **31-40** | 113.311 | 120.484 | 126.215 | 132.931 | 139.783 | 145.617 | 170.576 | 165.996 | 167.365 | 175.821 |
+| version | time (ms) |
+|---------|----------:|
+| **1**   |     2.285 |
+| **5**   |     5.867 |
+| **10**  |    12.737 |
+| **20**  |    34.045 |
+| **30**  |    64.914 |
+| **40**  |   107.027 |
 
 
 
 
 ## Output
 ## Output
 
 
 Output rendering depends heavily on the size of the QR matrix, the desired type and the underlying libraries and/or PHP extensions.
 Output rendering depends heavily on the size of the QR matrix, the desired type and the underlying libraries and/or PHP extensions.
-Especially the rendering of raster images through GD or ImagMagick can be very slow, depending on [the scale setting](../Usage/Configuration-settings.md#scale),
+Especially the rendering of raster images through GD or ImageMagick can be very slow, depending on [the scale setting](../Usage/Configuration-settings.md#scale),
 filters and image type.
 filters and image type.
 
 
 Below a comparison of the performance for the several built-in output classes (times in miliseconds, scale = 5):
 Below a comparison of the performance for the several built-in output classes (times in miliseconds, scale = 5):
 
 
-|                   |     v5 |    v10 |     v15 |     v20 |     v25 |     v30 |     v35 |     v40 |
-|-------------------|-------:|-------:|--------:|--------:|--------:|--------:|--------:|--------:|
-| **QRMarkupSVG**   |  3.732 |  8.645 |  13.846 |  21.127 |  32.842 |  43.753 |  56.584 |  73.885 |
-| **QRMarkupHTML**  |  0.522 |  1.308 |   2.062 |   2.761 |   3.907 |   5.201 |   7.931 |   9.572 |
-| **QRGdImageBMP**  |  5.998 | 12.541 |  20.728 |  32.336 |  46.345 |  62.842 |  81.555 | 106.482 |
-| **QRGdImageGIF**  |  3.427 |  6.817 |  12.226 |  17.925 |  25.453 |  35.136 |  44.706 |  57.477 |
-| **QRGdImageJPEG** |  2.284 |  4.882 |   8.161 |  12.097 |  17.333 |  23.862 |  30.327 |  40.226 |
-| **QRGdImagePNG**  |  4.523 |  9.377 |  16.581 |  26.207 |  36.516 |  49.066 |  63.765 |  82.074 |
-| **QRGdImageWEBP** |  8.211 | 17.367 |  30.079 |  47.095 |  69.668 |  91.378 | 119.869 | 150.288 |
-| **QRStringJSON**  |  0.043 |  0.066 |   0.107 |   0.158 |   0.215 |   0.301 |   0.369 |   0.492 |
-| **QRStringText**  |  0.229 |  0.387 |   0.628 |   0.952 |   1.312 |   1.759 |   2.329 |   3.045 |
-| **QRImagick**     | 37.694 | 68.808 | 114.415 | 172.962 | 242.338 | 325.085 | 419.999 | 529.897 |
-| **QRFpdf**        |  6.578 | 12.466 |  21.169 |  33.021 |  45.469 |  61.198 |  80.092 | 100.059 |
-| **QREps**         |  1.269 |  2.694 |   4.515 |   6.933 |  11.049 |  14.181 |  20.799 |  25.886 |
+|                   |     v5 |    v10 |     v20 |     v30 |     v40 |
+|-------------------|-------:|-------:|--------:|--------:|--------:|
+| **QRMarkupSVG**   |  3.732 |  8.645 |  21.127 |  43.753 |  73.885 |
+| **QRMarkupHTML**  |  0.522 |  1.308 |   2.761 |   5.201 |   9.572 |
+| **QRGdImageBMP**  |  5.998 | 12.541 |  32.336 |  62.842 | 106.482 |
+| **QRGdImageGIF**  |  3.427 |  6.817 |  17.925 |  35.136 |  57.477 |
+| **QRGdImageJPEG** |  2.284 |  4.882 |  12.097 |  23.862 |  40.226 |
+| **QRGdImagePNG**  |  4.523 |  9.377 |  26.207 |  49.066 |  82.074 |
+| **QRGdImageWEBP** |  8.211 | 17.367 |  47.095 |  91.378 | 150.288 |
+| **QRStringJSON**  |  0.043 |  0.066 |   0.158 |   0.301 |   0.492 |
+| **QRStringText**  |  0.229 |  0.387 |   0.952 |   1.759 |   3.045 |
+| **QRImagick**     | 37.694 | 68.808 | 172.962 | 325.085 | 529.897 |
+| **QRFpdf**        |  6.578 | 12.466 |  33.021 |  61.198 | 100.059 |
+| **QREps**         |  1.269 |  2.694 |   6.933 |  14.181 |  25.886 |

+ 1 - 1
docs/Appendix/Terminology.md

@@ -2,7 +2,7 @@
 
 
 ## QR Code
 ## QR Code
 
 
-A [*QR code*](https://en.wikipedia.org/wiki/QR_code) (quick-response code) is a type of two-dimensional matrix barcode, invented
+A [*QR code*](https://en.wikipedia.org/wiki/QR_code) (quick-response code), sometimes referred to as  *QR symbol* or simply just *symbol*, is a type of two-dimensional matrix barcode, invented
 in 1994 by Japanese company [Denso Wave](https://www.qrcode.com/en/faq.html#patentH2Title) for labelling automobile parts.
 in 1994 by Japanese company [Denso Wave](https://www.qrcode.com/en/faq.html#patentH2Title) for labelling automobile parts.
 The QR labelling system was applied beyond the automobile industry due to its fast readability and greater storage capacity
 The QR labelling system was applied beyond the automobile industry due to its fast readability and greater storage capacity
 compared to standard UPC barcodes.
 compared to standard UPC barcodes.

+ 2 - 0
docs/Readme.md

@@ -62,6 +62,8 @@ The markdown sources for the [Read the Docs online manual](https://php-qrcode.re
 - [Quickstart](./Usage/Quickstart.md)
 - [Quickstart](./Usage/Quickstart.md)
 - [Advanced usage](./Usage/Advanced-usage.md)
 - [Advanced usage](./Usage/Advanced-usage.md)
 - [Configuration settings](./Usage/Configuration-settings.md)
 - [Configuration settings](./Usage/Configuration-settings.md)
+- [Reading QR Codes](./Usage/Reading-QRCodes.md)
+- [Logos and logo space](./Usage/Logos.md)
 
 
 
 
 ### Customizing output
 ### Customizing output

+ 1 - 41
docs/Usage/Advanced-usage.md

@@ -173,7 +173,7 @@ $output = $qrcode->render();
 $qrcode->render(null, '/path/to/qrcode.svg');
 $qrcode->render(null, '/path/to/qrcode.svg');
 ```
 ```
 
 
-The [`QRDataModeInterface`](https://github.com/chillerlan/php-qrcode/blob/main/src/Data/QRDataModeInterface.php) offers the `validateString()` method (implemended for `AlphaNum`, `Byte`, `Hanzi`, `Kanji` and `Number`).
+The [`QRDataModeInterface`](https://github.com/chillerlan/php-qrcode/blob/main/src/Data/QRDataModeInterface.php) offers the `validateString()` method (implemented for `AlphaNum`, `Byte`, `Hanzi`, `Kanji` and `Number`).
 This method is used internally when a data mode is invoked, but it can come in handy if you need to check input data beforehand.
 This method is used internally when a data mode is invoked, but it can come in handy if you need to check input data beforehand.
 
 
 ```php
 ```php
@@ -185,33 +185,6 @@ $qrcode->addHanziSegment($data);
 ```
 ```
 
 
 
 
-### QR Code reader
-
-In some cases it might be necessary to increase the contrast of a QR Code image:
-
-```php
-$options->readerUseImagickIfAvailable = true;
-$options->readerIncreaseContrast      = true;
-$options->readerGrayscale             = true;
-
-$qrcode = new QRCode($options);
-
-$result = $qrcode->readFromFile('path/to/qrcode.png');
-$result = $qrcode->readFromBlob($imagedata);
-```
-
-The `QRMatrix` object from the [`DecoderResult`](https://github.com/chillerlan/php-qrcode/blob/main/src/Decoder/DecoderResult.php) can be reused:
-
-```php
-$matrix = $result->getQRMatrix();
-
-// ...matrix modification...
-
-$output = (new QRCode($options))->renderMatrix($matrix);
-
-// ...output
-```
-
 ## Common output options
 ## Common output options
 
 
 ### Save to file
 ### Save to file
@@ -266,16 +239,3 @@ $imagick = $qrcode->render($data);
 
 
 echo $imagick->getImageBlob();
 echo $imagick->getImageBlob();
 ```
 ```
-
-
-### Add a logo space
-
-
-```php
-$options->addLogoSpace    = true;
-$options->logoSpaceWidth  = 9;
-$options->logoSpaceHeight = 9;
-$options->logoSpaceStartX = 10;
-$options->logoSpaceStartY = 10;
-
-```

+ 3 - 1
docs/Usage/Configuration-settings.md

@@ -191,6 +191,7 @@ Specifies which module types to exclude when `QROptions::$drawCircularModules` i
 (default: `[]`)
 (default: `[]`)
 
 
 
 
+
 ## connectPaths
 ## connectPaths
 
 
 Whether to connect the paths for the several module types to avoid weird glitches when using gradients etc.
 Whether to connect the paths for the several module types to avoid weird glitches when using gradients etc.
@@ -215,6 +216,7 @@ Currentty used in `QREps` and `QRMarkupSVG`.
 Specify which paths/patterns to exclude from connecting if `QROptions::$connectPaths` is set to `true`
 Specify which paths/patterns to exclude from connecting if `QROptions::$connectPaths` is set to `true`
 
 
 
 
+
 **See also:**
 **See also:**
 
 
 - `\chillerlan\QRCode\QROptionsTrait::$connectPaths`
 - `\chillerlan\QRCode\QROptionsTrait::$connectPaths`
@@ -229,6 +231,7 @@ Module values map
 - `QREps`: `[C, M, Y, K]` // 0-255
 - `QREps`: `[C, M, Y, K]` // 0-255
 
 
 
 
+
 **See also:**
 **See also:**
 
 
 - `\chillerlan\QRCode\Output\QROutputAbstract::setModuleValues()`
 - `\chillerlan\QRCode\Output\QROutputAbstract::setModuleValues()`
@@ -296,7 +299,6 @@ Defaults to `QROptions::$bgColor`.
 - `QRImagick`: `"color_str"`, this color is set in `Imagick::transparentPaintImage()`
 - `QRImagick`: `"color_str"`, this color is set in `Imagick::transparentPaintImage()`
 
 
 
 
-
 **See also:**
 **See also:**
 
 
 - [php.net: `\imagecolortransparent()`](https://www.php.net/manual/function.imagecolortransparent)
 - [php.net: `\imagecolortransparent()`](https://www.php.net/manual/function.imagecolortransparent)

File diff suppressed because it is too large
+ 72 - 0
docs/Usage/Logos.md


+ 0 - 20
docs/Usage/Quickstart.md

@@ -41,26 +41,6 @@ and [configuration settings](../Usage/Configuration-settings.md) for a list of a
 Also, have a look [in the examples folder](https://github.com/chillerlan/php-qrcode/tree/main/examples) for some more usage examples.
 Also, have a look [in the examples folder](https://github.com/chillerlan/php-qrcode/tree/main/examples) for some more usage examples.
 
 
 
 
-## Reading QR Codes
-
-Using the built-in QR Code reader is pretty straight-forward:
-```php
-try{
-	$result = (new QRCode)->readFromFile('path/to/file.png'); // -> DecoderResult
-
-	// you can now use the result instance...
-	$content = $result->data;
-
-	// ...or simply cast the result instance to string to get the content
-	$content = (string)$result;
-}
-catch(Throwable $exception){
-	// handle exception...
-}
-```
-It's generally a good idea to wrap the reading in a try/catch block to handle any errors that may occur in the process.
-
-
 ## Notes
 ## Notes
 The QR encoder, especially the subroutines for mask pattern testing, can cause high CPU load on increased matrix size.
 The QR encoder, especially the subroutines for mask pattern testing, can cause high CPU load on increased matrix size.
 You can avoid a part of this load by choosing a fast output module, like SVG.
 You can avoid a part of this load by choosing a fast output module, like SVG.

+ 101 - 0
docs/Usage/Reading-QRCodes.md

@@ -0,0 +1,101 @@
+# Reading QR Codes
+
+## Basic usage
+
+The QR Code reader can be called either from a `QRCode` instance or invoked directly via the `Decoder` class with a `QROptions` (`QRCodeReaderOptionsTrait`) instance.
+
+```php
+$options = new QROptions
+
+$options->readerUseImagickIfAvailable = true;
+$options->readerIncreaseContrast      = true;
+$options->readerGrayscale             = true;
+$options->readerInvertColors          = false;
+```
+
+The option `QROptions::$readerUseImagickIfAvailable` is exclusive to the `QRCode` instance in order to decide which `LuminanceSourceInterface` to use.
+The `QRCode` instance has 3 convenience methods related to the reader:
+```php
+$qrcode = new QRCode($options)
+
+$result = $qrcode->readFromFile('path/to/qrcode.png');
+$result = $qrcode->readFromBlob($imagedata);
+
+// from a luminance source instance
+$source = IMagickLuminanceSource::fromBlob($imagedata, $options);
+$result = $qrcode->readFromSource($source);
+```
+
+## The `LuminanceSourceInterface`
+
+The method `QRCode::readFromSource()` takes a `LuminanceSourceInterface` instance as parameter and is mainly for internal use, as you can invoke and call the decoder directly with it.
+Each `LuminanceSourceInterface` has the static convenience methods `fromFile()` and `fromBlob()` that will invoke the instance with the respective parameters, alternatively the instance(s) can be invoked manually:
+
+from an `Imagick` instance:
+```php
+$imagick = new Imagick;
+$imagick->readImageBlob($imagedata);
+
+$source = new IMagickLuminanceSource($imagick, $options);
+```
+
+from a `GdImage` instance:
+
+```php
+$gdimage = imagecreatefromstring($imagedata);
+
+$source = new GDLuminanceSource($gdimage, $options);
+```
+
+## The `Decoder`
+
+The `Decoder` takes a `QROptions` instance as parameter, which currently has no use - it is only handed over for possible future uses.
+
+```php
+$result = (new Decoder($options))->decode($source);
+```
+
+That is all! The decoder will either return a `DecoderResult` instance or throw an exception.
+It is generally a good practice to wrap the reading in a try/catch block:
+
+```php
+try{
+	$result = $qrcode->readFromFile('path/to/file.png'); // -> DecoderResult
+
+	// ... do stuff with the result
+}
+catch(QRCodeDecoderException){
+	// ... adjust input image (position, contrast, invert, sharpen) and repeat the process
+}
+```
+
+You can now use the result instance:
+
+```php
+$content = $result->data;
+// ...or simply cast it to string:
+$content = (string)$result;
+```
+
+The result instance also holds `Version`, `EccLevel`, `MaskPattern` and `BitBuffer` instances, as well as an array of `FinderPattern` instances,
+it also offers a method that returns a `QRMatrix` instance populated with the detected settings:
+
+```php
+$matrix = $result->getQRMatrix();
+
+// ...matrix modification...
+
+$output = (new QRCode($options))->renderMatrix($matrix);
+
+// ...dump output
+```
+
+
+## General considerations
+
+The QR Code reader reads the given QR symbol in a single pass, unlike e.g. a reader app on a mobile device with a camera, which repeats the reading process for a sequence of frames from the video input and takes the "best" result.
+It means that this reader may fail to properly decode a symbol that reads perfectly fine on a mobile - you'd need to emulate the same process of sequential reading while adjusting the input image to get a similar result.
+
+Further it seems ([per observation](https://github.com/chillerlan/php-qrcode/blob/92346420a5a88aeeb8dc16f731ef1f93331635d3/tests/QRCodeReaderTestAbstract.php#L168-L172)) that the reader favors smaller module sizes (1-2 pixel side length) from version 20 onwards.
+The test data set seemed to randomly produce errors depending on the given module scale, independent of the luminance source.
+However, scaling down to get a smaller module size isn't the best solution as it may produce additional challenges due to filter artifacts.

+ 1 - 1
docs/conf.py

@@ -44,7 +44,7 @@ lexers['php-annotations'] = PhpLexer(startinline=True)
 # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
 # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
 
 
 project = u'PHP-QRCode'
 project = u'PHP-QRCode'
-copyright = u'2023, smiley'
+copyright = u'2025, smiley'
 author = u'smiley'
 author = u'smiley'
 epub_author = u'smiley'
 epub_author = u'smiley'
 
 

+ 2 - 0
docs/index.rst

@@ -21,6 +21,8 @@ This work is licensed under the Creative Commons Attribution 4.0 International (
    Usage/Quickstart.md
    Usage/Quickstart.md
    Usage/Advanced-usage.md
    Usage/Advanced-usage.md
    Usage/Configuration-settings.md
    Usage/Configuration-settings.md
+   Usage/Reading-QRCodes.md
+   Usage/Logos.md
 
 
 .. toctree::
 .. toctree::
    :maxdepth: 3
    :maxdepth: 3

Some files were not shown because too many files changed in this diff