mirror of
https://github.com/chillerlan/php-qrcode.git
synced 2026-08-28 02:57:57 +00:00
:octocat: integrate reader into QRCode, extract LuminanceSourceInterface
This commit is contained in:
@@ -45,12 +45,12 @@ final class Binarizer{
|
||||
private const LUMINANCE_SHIFT = 3;
|
||||
private const LUMINANCE_BUCKETS = 32;
|
||||
|
||||
private LuminanceSource $source;
|
||||
private LuminanceSourceInterface $source;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct(LuminanceSource $source){
|
||||
public function __construct(LuminanceSourceInterface $source){
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,12 +31,12 @@ final class Decoder{
|
||||
* <p>Decodes a QR Code represented as a {@link \chillerlan\QRCode\Decoder\BitMatrix}.
|
||||
* A 1 or "true" is taken to mean a black module.</p>
|
||||
*
|
||||
* @param \chillerlan\QRCode\Decoder\LuminanceSource $source
|
||||
* @param \chillerlan\QRCode\Decoder\LuminanceSourceInterface $source
|
||||
*
|
||||
* @return \chillerlan\QRCode\Decoder\DecoderResult text and bytes encoded within the QR Code
|
||||
* @throws \Exception if the QR Code cannot be decoded
|
||||
*/
|
||||
public function decode(LuminanceSource $source):DecoderResult{
|
||||
public function decode(LuminanceSourceInterface $source):DecoderResult{
|
||||
$matrix = (new Binarizer($source))->getBlackMatrix();
|
||||
$bitMatrix = (new Detector($matrix))->detect();
|
||||
|
||||
|
||||
@@ -14,14 +14,15 @@
|
||||
namespace chillerlan\QRCode\Decoder;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use function get_resource_type, imagecolorat, imagecolorsforindex, imagesx, imagesy, is_resource;
|
||||
use function file_get_contents, get_resource_type, imagecolorat, imagecolorsforindex,
|
||||
imagecreatefromstring, imagesx, imagesy, is_resource;
|
||||
use const PHP_MAJOR_VERSION;
|
||||
|
||||
/**
|
||||
* This class is used to help decode images from files which arrive as GD Resource
|
||||
* It does not support rotation.
|
||||
*/
|
||||
final class GDLuminanceSource extends LuminanceSource{
|
||||
final class GDLuminanceSource extends LuminanceSourceAbstract{
|
||||
|
||||
/**
|
||||
* @var resource|\GdImage
|
||||
@@ -40,7 +41,7 @@ final class GDLuminanceSource extends LuminanceSource{
|
||||
/** @noinspection PhpFullyQualifiedNameUsageInspection */
|
||||
if(
|
||||
(PHP_MAJOR_VERSION >= 8 && !$gdImage instanceof \GdImage)
|
||||
|| (PHP_MAJOR_VERSION < 8 && (!is_resource($gdImage) || get_resource_type($gdImage) !== 'gd'))
|
||||
|| (!is_resource($gdImage) || get_resource_type($gdImage) !== 'gd')
|
||||
){
|
||||
throw new InvalidArgumentException('Invalid GD image source.');
|
||||
}
|
||||
@@ -66,4 +67,16 @@ final class GDLuminanceSource extends LuminanceSource{
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public static function fromFile(string $path):self{
|
||||
$path = self::checkFile($path);
|
||||
|
||||
return new self(imagecreatefromstring(file_get_contents($path)));
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public static function fromBlob(string $blob):self{
|
||||
return new self(imagecreatefromstring($blob));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ use function count;
|
||||
* This class is used to help decode images from files which arrive as Imagick Resource
|
||||
* It does not support rotation.
|
||||
*/
|
||||
final class IMagickLuminanceSource extends LuminanceSource{
|
||||
final class IMagickLuminanceSource extends LuminanceSourceAbstract{
|
||||
|
||||
private Imagick $imagick;
|
||||
|
||||
@@ -53,4 +53,19 @@ final class IMagickLuminanceSource extends LuminanceSource{
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public static function fromFile(string $path):self{
|
||||
$path = self::checkFile($path);
|
||||
|
||||
return new self(new Imagick($path));
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public static function fromBlob(string $blob):self{
|
||||
$im = new Imagick;
|
||||
$im->readImageBlob($blob);
|
||||
|
||||
return new self($im);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Class LuminanceSource
|
||||
* Class LuminanceSourceAbstract
|
||||
*
|
||||
* @created 24.01.2021
|
||||
* @author ZXing Authors
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace chillerlan\QRCode\Decoder;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use function array_slice, array_splice;
|
||||
use function array_slice, array_splice, file_exists, is_file, is_readable, realpath;
|
||||
|
||||
/**
|
||||
* The purpose of this class hierarchy is to abstract different bitmap implementations across
|
||||
@@ -23,7 +23,7 @@ use function array_slice, array_splice;
|
||||
*
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
*/
|
||||
abstract class LuminanceSource{
|
||||
abstract class LuminanceSourceAbstract implements LuminanceSourceInterface{
|
||||
|
||||
protected array $luminances;
|
||||
protected int $width;
|
||||
@@ -38,47 +38,24 @@ abstract class LuminanceSource{
|
||||
// In order to measure pure decoding speed, we convert the entire image to a greyscale array
|
||||
// up front, which is the same as the Y channel of the YUVLuminanceSource in the real app.
|
||||
$this->luminances = [];
|
||||
// @todo: grayscale?
|
||||
//$this->luminances = $this->grayScaleToBitmap($this->grayscale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches luminance data for the underlying bitmap. Values should be fetched using:
|
||||
* {@code int luminance = array[y * width + x] & 0xff}
|
||||
*
|
||||
* @return array A row-major 2D array of luminance values. Do not use result.length as it may be
|
||||
* larger than width * height bytes on some platforms. Do not modify the contents
|
||||
* of the result.
|
||||
*/
|
||||
/** @inheritDoc */
|
||||
public function getMatrix():array{
|
||||
return $this->luminances;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int The width of the bitmap.
|
||||
*/
|
||||
/** @inheritDoc */
|
||||
public function getWidth():int{
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int The height of the bitmap.
|
||||
*/
|
||||
/** @inheritDoc */
|
||||
public function getHeight():int{
|
||||
return $this->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches one row of luminance data from the underlying platform's bitmap. Values range from
|
||||
* 0 (black) to 255 (white). Because Java does not have an unsigned byte type, callers will have
|
||||
* to bitwise and with 0xff for each value. It is preferable for implementations of this method
|
||||
* to only fetch this row rather than the whole image, since no 2D Readers may be installed and
|
||||
* getMatrix() may never be called.
|
||||
*
|
||||
* @param int $y The row to fetch, which must be in [0,getHeight())
|
||||
*
|
||||
* @return array An array containing the luminance data.
|
||||
*/
|
||||
/** @inheritDoc */
|
||||
public function getRow(int $y):array{
|
||||
|
||||
if($y < 0 || $y >= $this->getHeight()){
|
||||
@@ -93,11 +70,7 @@ abstract class LuminanceSource{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $r
|
||||
* @param int $g
|
||||
* @param int $b
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setLuminancePixel(int $r, int $g, int $b):void{
|
||||
$this->luminances[] = $r === $g && $g === $b
|
||||
@@ -107,4 +80,23 @@ abstract class LuminanceSource{
|
||||
: ($r + 2 * $g + $b) / 4; // (((($r + 2 * $g + $b) / 4) + 128) % 256) - 128;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected static function checkFile(string $path):string{
|
||||
$path = trim($path);
|
||||
|
||||
if(!file_exists($path) || !is_file($path) || !is_readable($path)){
|
||||
throw new InvalidArgumentException('invalid file: '.$path);
|
||||
}
|
||||
|
||||
$realpath = realpath($path);
|
||||
|
||||
if($realpath === false){
|
||||
throw new InvalidArgumentException('unable to resolve path: '.$path);
|
||||
}
|
||||
|
||||
return $realpath;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* Interface LuminanceSourceInterface
|
||||
*
|
||||
* @created 18.11.2021
|
||||
* @author smiley <smiley@chillerlan.net>
|
||||
* @copyright 2021 smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace chillerlan\QRCode\Decoder;
|
||||
|
||||
/**
|
||||
*/
|
||||
interface LuminanceSourceInterface{
|
||||
|
||||
/**
|
||||
* Fetches luminance data for the underlying bitmap. Values should be fetched using:
|
||||
* {@code int luminance = array[y * width + x] & 0xff}
|
||||
*
|
||||
* @return array A row-major 2D array of luminance values. Do not use result.length as it may be
|
||||
* larger than width * height bytes on some platforms. Do not modify the contents
|
||||
* of the result.
|
||||
*/
|
||||
public function getMatrix():array;
|
||||
|
||||
/**
|
||||
* @return int The width of the bitmap.
|
||||
*/
|
||||
public function getWidth():int;
|
||||
|
||||
/**
|
||||
* @return int The height of the bitmap.
|
||||
*/
|
||||
public function getHeight():int;
|
||||
|
||||
/**
|
||||
* Fetches one row of luminance data from the underlying platform's bitmap. Values range from
|
||||
* 0 (black) to 255 (white). Because Java does not have an unsigned byte type, callers will have
|
||||
* to bitwise and with 0xff for each value. It is preferable for implementations of this method
|
||||
* to only fetch this row rather than the whole image, since no 2D Readers may be installed and
|
||||
* getMatrix() may never be called.
|
||||
*
|
||||
* @param int $y The row to fetch, which must be in [0,getHeight())
|
||||
*
|
||||
* @return array An array containing the luminance data.
|
||||
*/
|
||||
public function getRow(int $y):array;
|
||||
|
||||
|
||||
public static function fromFile(string $path):self;
|
||||
public static function fromBlob(string $blob):self;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user