Skip to content

Commit c55c64d

Browse files
committed
📖
1 parent 5536c26 commit c55c64d

File tree

11 files changed

+209
-120
lines changed

11 files changed

+209
-120
lines changed

README.md

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -125,40 +125,6 @@ Also, have a look [in the examples folder](https://github.com/chillerlan/php-qrc
125125
</p>
126126

127127

128-
## Reading QR Codes
129-
130-
Using the built-in QR Code reader is pretty straight-forward:
131-
132-
```php
133-
// it's generally a good idea to wrap the reader in a try/catch block because it WILL throw eventually
134-
try{
135-
$result = (new QRCode)->readFromFile('path/to/file.png'); // -> DecoderResult
136-
137-
// you can now use the result instance...
138-
$content = $result->data;
139-
$matrix = $result->getMatrix(); // -> QRMatrix
140-
141-
// ...or simply cast it to string to get the content:
142-
$content = (string)$result;
143-
}
144-
catch(Throwable $e){
145-
// oopsies!
146-
}
147-
```
148-
149-
150-
# Shameless advertising
151-
152-
Hi, please check out some of my other projects that are way cooler than qrcodes!
153-
154-
- [js-qrcode](https://github.com/chillerlan/js-qrcode) - a javascript port of this library
155-
- [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))
156-
- [php-httpinterface](https://github.com/chillerlan/php-httpinterface) - a PSR-7/15/17/18 implemetation
157-
- [php-oauth](https://github.com/chillerlan/php-oauth) - an OAuth 1/2 client library, fully PSR-7/PSR-17/PSR-18 compatible
158-
- [php-database](https://github.com/chillerlan/php-database) - a database client & querybuilder for MySQL, Postgres, SQLite, MSSQL, Firebird
159-
- [php-tootbot](https://github.com/php-tootbot/tootbot-template) - a Mastodon bot library (see [@dwil](https://github.com/php-tootbot/dwil))
160-
161-
162128
# Disclaimer!
163129

164130
I don't take responsibility for molten CPUs, misled applications, failed log-ins etc.. Use at your own risk!

docs/Appendix/Performance-considerations.md

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -44,35 +44,37 @@ is a complex and costly operation that is necessary to ensure the symbol is read
4444
to override the evaluation and manually set a mask pattern, this is not recommended unless you know exactly what you're doing
4545
as it can render a QR symbol unreadable.
4646

47-
The table below shows the performance impact (in miliseconds) of the mask pattern evaluation for each version, the times may vary between systems.
47+
The table below shows the performance impact (in miliseconds) of the mask pattern evaluation for select versions, the times may vary between systems.
4848

49-
| version | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
50-
|-----------|--------:|--------:|--------:|--------:|--------:|--------:|--------:|--------:|--------:|--------:|
51-
| **1-10** | 4.414 | 5.697 | 7.986 | 9.221 | 10.877 | 11.293 | 13.901 | 15.563 | 18.142 | 20.501 |
52-
| **11-20** | 22.662 | 27.779 | 29.622 | 33.017 | 36.358 | 39.712 | 43.685 | 47.121 | 51.389 | 57.865 |
53-
| **21-30** | 59.753 | 68.502 | 68.523 | 72.866 | 78.245 | 83.593 | 88.327 | 94.921 | 103.394 | 106.358 |
54-
| **31-40** | 113.311 | 120.484 | 126.215 | 132.931 | 139.783 | 145.617 | 170.576 | 165.996 | 167.365 | 175.821 |
49+
| version | time (ms) |
50+
|---------|----------:|
51+
| **1** | 2.285 |
52+
| **5** | 5.867 |
53+
| **10** | 12.737 |
54+
| **20** | 34.045 |
55+
| **30** | 64.914 |
56+
| **40** | 107.027 |
5557

5658

5759
## Output
5860

5961
Output rendering depends heavily on the size of the QR matrix, the desired type and the underlying libraries and/or PHP extensions.
60-
Especially the rendering of raster images through GD or ImagMagick can be very slow, depending on [the scale setting](../Usage/Configuration-settings.md#scale),
62+
Especially the rendering of raster images through GD or ImageMagick can be very slow, depending on [the scale setting](../Usage/Configuration-settings.md#scale),
6163
filters and image type.
6264

6365
Below a comparison of the performance for the several built-in output classes (times in miliseconds, scale = 5):
6466

65-
| | v5 | v10 | v15 | v20 | v25 | v30 | v35 | v40 |
66-
|-------------------|-------:|-------:|--------:|--------:|--------:|--------:|--------:|--------:|
67-
| **QRMarkupSVG** | 3.732 | 8.645 | 13.846 | 21.127 | 32.842 | 43.753 | 56.584 | 73.885 |
68-
| **QRMarkupHTML** | 0.522 | 1.308 | 2.062 | 2.761 | 3.907 | 5.201 | 7.931 | 9.572 |
69-
| **QRGdImageBMP** | 5.998 | 12.541 | 20.728 | 32.336 | 46.345 | 62.842 | 81.555 | 106.482 |
70-
| **QRGdImageGIF** | 3.427 | 6.817 | 12.226 | 17.925 | 25.453 | 35.136 | 44.706 | 57.477 |
71-
| **QRGdImageJPEG** | 2.284 | 4.882 | 8.161 | 12.097 | 17.333 | 23.862 | 30.327 | 40.226 |
72-
| **QRGdImagePNG** | 4.523 | 9.377 | 16.581 | 26.207 | 36.516 | 49.066 | 63.765 | 82.074 |
73-
| **QRGdImageWEBP** | 8.211 | 17.367 | 30.079 | 47.095 | 69.668 | 91.378 | 119.869 | 150.288 |
74-
| **QRStringJSON** | 0.043 | 0.066 | 0.107 | 0.158 | 0.215 | 0.301 | 0.369 | 0.492 |
75-
| **QRStringText** | 0.229 | 0.387 | 0.628 | 0.952 | 1.312 | 1.759 | 2.329 | 3.045 |
76-
| **QRImagick** | 37.694 | 68.808 | 114.415 | 172.962 | 242.338 | 325.085 | 419.999 | 529.897 |
77-
| **QRFpdf** | 6.578 | 12.466 | 21.169 | 33.021 | 45.469 | 61.198 | 80.092 | 100.059 |
78-
| **QREps** | 1.269 | 2.694 | 4.515 | 6.933 | 11.049 | 14.181 | 20.799 | 25.886 |
67+
| | v5 | v10 | v20 | v30 | v40 |
68+
|-------------------|-------:|-------:|--------:|--------:|--------:|
69+
| **QRMarkupSVG** | 3.732 | 8.645 | 21.127 | 43.753 | 73.885 |
70+
| **QRMarkupHTML** | 0.522 | 1.308 | 2.761 | 5.201 | 9.572 |
71+
| **QRGdImageBMP** | 5.998 | 12.541 | 32.336 | 62.842 | 106.482 |
72+
| **QRGdImageGIF** | 3.427 | 6.817 | 17.925 | 35.136 | 57.477 |
73+
| **QRGdImageJPEG** | 2.284 | 4.882 | 12.097 | 23.862 | 40.226 |
74+
| **QRGdImagePNG** | 4.523 | 9.377 | 26.207 | 49.066 | 82.074 |
75+
| **QRGdImageWEBP** | 8.211 | 17.367 | 47.095 | 91.378 | 150.288 |
76+
| **QRStringJSON** | 0.043 | 0.066 | 0.158 | 0.301 | 0.492 |
77+
| **QRStringText** | 0.229 | 0.387 | 0.952 | 1.759 | 3.045 |
78+
| **QRImagick** | 37.694 | 68.808 | 172.962 | 325.085 | 529.897 |
79+
| **QRFpdf** | 6.578 | 12.466 | 33.021 | 61.198 | 100.059 |
80+
| **QREps** | 1.269 | 2.694 | 6.933 | 14.181 | 25.886 |

docs/Appendix/Terminology.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## QR Code
44

5-
A [*QR code*](https://en.wikipedia.org/wiki/QR_code) (quick-response code) is a type of two-dimensional matrix barcode, invented
5+
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
66
in 1994 by Japanese company [Denso Wave](https://www.qrcode.com/en/faq.html#patentH2Title) for labelling automobile parts.
77
The QR labelling system was applied beyond the automobile industry due to its fast readability and greater storage capacity
88
compared to standard UPC barcodes.

docs/Readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ The markdown sources for the [Read the Docs online manual](https://php-qrcode.re
6262
- [Quickstart](./Usage/Quickstart.md)
6363
- [Advanced usage](./Usage/Advanced-usage.md)
6464
- [Configuration settings](./Usage/Configuration-settings.md)
65+
- [Reading QR Codes](./Usage/Reading-QRCodes.md)
66+
- [Logos and logo space](./Usage/Logos.md)
6567

6668

6769
### Customizing output

docs/Usage/Advanced-usage.md

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ $output = $qrcode->render();
173173
$qrcode->render(null, '/path/to/qrcode.svg');
174174
```
175175

176-
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`).
176+
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`).
177177
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.
178178

179179
```php
@@ -185,33 +185,6 @@ $qrcode->addHanziSegment($data);
185185
```
186186

187187

188-
### QR Code reader
189-
190-
In some cases it might be necessary to increase the contrast of a QR Code image:
191-
192-
```php
193-
$options->readerUseImagickIfAvailable = true;
194-
$options->readerIncreaseContrast = true;
195-
$options->readerGrayscale = true;
196-
197-
$qrcode = new QRCode($options);
198-
199-
$result = $qrcode->readFromFile('path/to/qrcode.png');
200-
$result = $qrcode->readFromBlob($imagedata);
201-
```
202-
203-
The `QRMatrix` object from the [`DecoderResult`](https://github.com/chillerlan/php-qrcode/blob/main/src/Decoder/DecoderResult.php) can be reused:
204-
205-
```php
206-
$matrix = $result->getQRMatrix();
207-
208-
// ...matrix modification...
209-
210-
$output = (new QRCode($options))->renderMatrix($matrix);
211-
212-
// ...output
213-
```
214-
215188
## Common output options
216189

217190
### Save to file
@@ -266,16 +239,3 @@ $imagick = $qrcode->render($data);
266239

267240
echo $imagick->getImageBlob();
268241
```
269-
270-
271-
### Add a logo space
272-
273-
274-
```php
275-
$options->addLogoSpace = true;
276-
$options->logoSpaceWidth = 9;
277-
$options->logoSpaceHeight = 9;
278-
$options->logoSpaceStartX = 10;
279-
$options->logoSpaceStartY = 10;
280-
281-
```

docs/Usage/Configuration-settings.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ Specifies which module types to exclude when `QROptions::$drawCircularModules` i
191191
(default: `[]`)
192192

193193

194+
194195
## connectPaths
195196

196197
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`.
215216
Specify which paths/patterns to exclude from connecting if `QROptions::$connectPaths` is set to `true`
216217

217218

219+
218220
**See also:**
219221

220222
- `\chillerlan\QRCode\QROptionsTrait::$connectPaths`
@@ -229,6 +231,7 @@ Module values map
229231
- `QREps`: `[C, M, Y, K]` // 0-255
230232

231233

234+
232235
**See also:**
233236

234237
- `\chillerlan\QRCode\Output\QROutputAbstract::setModuleValues()`
@@ -296,7 +299,6 @@ Defaults to `QROptions::$bgColor`.
296299
- `QRImagick`: `"color_str"`, this color is set in `Imagick::transparentPaintImage()`
297300

298301

299-
300302
**See also:**
301303

302304
- [php.net: `\imagecolortransparent()`](https://www.php.net/manual/function.imagecolortransparent)

docs/Usage/Logos.md

Lines changed: 74 additions & 0 deletions
Large diffs are not rendered by default.

docs/Usage/Quickstart.md

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,26 +41,6 @@ and [configuration settings](../Usage/Configuration-settings.md) for a list of a
4141
Also, have a look [in the examples folder](https://github.com/chillerlan/php-qrcode/tree/main/examples) for some more usage examples.
4242

4343

44-
## Reading QR Codes
45-
46-
Using the built-in QR Code reader is pretty straight-forward:
47-
```php
48-
try{
49-
$result = (new QRCode)->readFromFile('path/to/file.png'); // -> DecoderResult
50-
51-
// you can now use the result instance...
52-
$content = $result->data;
53-
54-
// ...or simply cast the result instance to string to get the content
55-
$content = (string)$result;
56-
}
57-
catch(Throwable $exception){
58-
// handle exception...
59-
}
60-
```
61-
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.
62-
63-
6444
## Notes
6545
The QR encoder, especially the subroutines for mask pattern testing, can cause high CPU load on increased matrix size.
6646
You can avoid a part of this load by choosing a fast output module, like SVG.

docs/Usage/Reading-QRCodes.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Reading QR Codes
2+
3+
## Basic usage
4+
5+
The QR Code reader can be called either from a `QRCode` instance or invoked directly via the `Decoder` class with a `QROptions` (`QRCodeReaderOptionsTrait`) instance.
6+
7+
```php
8+
$options = new QROptions
9+
10+
$options->readerUseImagickIfAvailable = true;
11+
$options->readerIncreaseContrast = true;
12+
$options->readerGrayscale = true;
13+
$options->readerInvertColors = false;
14+
```
15+
16+
The option `QROptions::$readerUseImagickIfAvailable` is exclusive to the `QRCode` instance in order to decide which `LuminanceSourceInterface` to use.
17+
The `QRCode` instance has 3 convenience methods related to the reader:
18+
```php
19+
$qrcode = new QRCode($options)
20+
21+
$result = $qrcode->readFromFile('path/to/qrcode.png');
22+
$result = $qrcode->readFromBlob($imagedata);
23+
24+
// from a luminance source instance
25+
$source = IMagickLuminanceSource::fromBlob($imagedata, $options);
26+
$result = $qrcode->readFromSource($source);
27+
```
28+
29+
## The `LuminanceSourceInterface`
30+
31+
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.
32+
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:
33+
34+
from an `Imagick` instance:
35+
```php
36+
$imagick = new Imagick;
37+
$imagick->readImageBlob($imagedata);
38+
39+
$source = new IMagickLuminanceSource($imagick, $options);
40+
```
41+
42+
from a `GdImage` instance:
43+
44+
```php
45+
$gdimage = imagecreatefromstring($imagedata);
46+
47+
$source = new GDLuminanceSource($gdimage, $options);
48+
```
49+
50+
## The `Decoder`
51+
52+
The `Decoder` takes a `QROptions` instance as parameter, which currently has no use - it is only handed over for possible future uses.
53+
54+
```php
55+
$result = (new Decoder($options))->decode($source);
56+
```
57+
58+
That is all! The decoder will either return a `DecoderResult` instance or throw an exception.
59+
It is generally a good practice to wrap the reading in a try/catch block:
60+
61+
```php
62+
try{
63+
$result = $qrcode->readFromFile('path/to/file.png'); // -> DecoderResult
64+
65+
// ... do stuff with the result
66+
}
67+
catch(QRCodeDecoderException){
68+
// ... adjust input image (position, contrast, invert, sharpen) and repeat the process
69+
}
70+
```
71+
72+
You can now use the result instance:
73+
74+
```php
75+
$content = $result->data;
76+
// ...or simply cast it to string:
77+
$content = (string)$result;
78+
```
79+
80+
The result instance also holds `Version`, `EccLevel`, `MaskPattern` and `BitBuffer` instances, as well as an array of `FinderPattern` instances,
81+
it also offers a method that returns a `QRMatrix` instance populated with the detected settings:
82+
83+
```php
84+
$matrix = $result->getQRMatrix();
85+
86+
// ...matrix modification...
87+
88+
$output = (new QRCode($options))->renderMatrix($matrix);
89+
90+
// ...dump output
91+
```
92+
93+
94+
## General considerations
95+
96+
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.
97+
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.
98+
99+
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.
100+
The test data set seemed to randomly produce errors depending on the given module scale, independent of the luminance source.
101+
However, scaling down to get a smaller module size isn't the best solution as it may produce additional challenges due to filter artifacts.

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def get_version():
4444
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
4545

4646
project = u'PHP-QRCode'
47-
copyright = u'2023, smiley'
47+
copyright = u'2025, smiley'
4848
author = u'smiley'
4949
epub_author = u'smiley'
5050

0 commit comments

Comments
 (0)