# 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.