From 53f6dcfc882daf9edcf72aaeaa560411c1b2d50a Mon Sep 17 00:00:00 2001 From: smiley Date: Thu, 26 May 2022 23:04:54 +0200 Subject: [PATCH] :shower: --- src/Decoder/Binarizer.php | 40 +++++++++-------- src/Decoder/LuminanceSourceAbstract.php | 2 +- src/Decoder/LuminanceSourceInterface.php | 4 +- src/Detector/Detector.php | 56 +++++++++--------------- 4 files changed, 44 insertions(+), 58 deletions(-) diff --git a/src/Decoder/Binarizer.php b/src/Decoder/Binarizer.php index 9a5e8af63..b0088544c 100644 --- a/src/Decoder/Binarizer.php +++ b/src/Decoder/Binarizer.php @@ -46,12 +46,14 @@ final class Binarizer{ private const LUMINANCE_BUCKETS = 32; private LuminanceSourceInterface $source; + private array $luminances; /** * */ public function __construct(LuminanceSourceInterface $source){ - $this->source = $source; + $this->source = $source; + $this->luminances = $this->source->getLuminances(); } /** @@ -182,14 +184,13 @@ final class Binarizer{ // We delay reading the entire image luminance until the black point estimation succeeds. // Although we end up reading four rows twice, it is consistent with our motto of // "fail quickly" which is necessary for continuous scanning. - $localLuminances = $this->source->getMatrix(); - $matrix = new BitMatrix(max($width, $height)); + $matrix = new BitMatrix(max($width, $height)); for($y = 0; $y < $height; $y++){ $offset = $y * $width; for($x = 0; $x < $width; $x++){ - $matrix->set($x, $y, (($localLuminances[$offset + $x] & 0xff) < $blackPoint), QRMatrix::M_DATA); + $matrix->set($x, $y, (($this->luminances[$offset + $x] & 0xff) < $blackPoint), QRMatrix::M_DATA); } } @@ -202,7 +203,7 @@ final class Binarizer{ * * @see http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0 */ - private function calculateBlackPoints(array $luminances, int $subWidth, int $subHeight, int $width, int $height):array{ + private function calculateBlackPoints(int $subWidth, int $subHeight, int $width, int $height):array{ $blackPoints = array_fill(0, $subHeight, 0); foreach($blackPoints as $key => $point){ @@ -232,7 +233,7 @@ final class Binarizer{ for($yy = 0, $offset = $yoffset * $width + $xoffset; $yy < self::BLOCK_SIZE; $yy++, $offset += $width){ for($xx = 0; $xx < self::BLOCK_SIZE; $xx++){ - $pixel = (int)($luminances[(int)($offset + $xx)]) & 0xff; + $pixel = (int)($this->luminances[(int)($offset + $xx)]) & 0xff; $sum += $pixel; // still looking for good contrast if($pixel < $min){ @@ -249,7 +250,7 @@ final class Binarizer{ // finish the rest of the rows quickly for($yy++, $offset += $width; $yy < self::BLOCK_SIZE; $yy++, $offset += $width){ for($xx = 0; $xx < self::BLOCK_SIZE; $xx++){ - $sum += (int)($luminances[(int)($offset + $xx)]) & 0xff; + $sum += (int)($this->luminances[(int)($offset + $xx)]) & 0xff; } } } @@ -275,7 +276,9 @@ final class Binarizer{ // the boundaries is used for the interior. // The (min < bp) is arbitrary but works better than other heuristics that were tried. - $averageNeighborBlackPoint = (int)(($blackPoints[$y - 1][$x] + (2 * $blackPoints[$y][$x - 1]) + $blackPoints[$y - 1][$x - 1]) / 4); + $averageNeighborBlackPoint = (int)( + ($blackPoints[$y - 1][$x] + (2 * $blackPoints[$y][$x - 1]) + $blackPoints[$y - 1][$x - 1]) / 4 + ); if($min < $averageNeighborBlackPoint){ $average = $averageNeighborBlackPoint; @@ -295,15 +298,9 @@ final class Binarizer{ * of the blocks around it. Also handles the corner cases (fractional blocks are computed based * on the last pixels in the row/column which are also used in the previous block). */ - private function calculateThresholdForBlock( - int $subWidth, - int $subHeight, - int $width, - int $height - ):BitMatrix{ + private function calculateThresholdForBlock(int $subWidth, int $subHeight, int $width, int $height):BitMatrix{ $matrix = new BitMatrix(max($width, $height)); - $luminances = $this->source->getMatrix(); - $blackPoints = $this->calculateBlackPoints($luminances, $subWidth, $subHeight, $width, $height); + $blackPoints = $this->calculateBlackPoints($subWidth, $subHeight, $width, $height); for($y = 0; $y < $subHeight; $y++){ $yoffset = ($y << self::BLOCK_SIZE_POWER); @@ -326,8 +323,8 @@ final class Binarizer{ $sum = 0; for($z = -2; $z <= 2; $z++){ - $blackRow = $blackPoints[$top + $z]; - $sum += $blackRow[$left - 2] + $blackRow[$left - 1] + $blackRow[$left] + $blackRow[$left + 1] + $blackRow[$left + 2]; + $br = $blackPoints[$top + $z]; + $sum += $br[$left - 2] + $br[$left - 1] + $br[$left] + $br[$left + 1] + $br[$left + 2]; } $average = (int)($sum / 25); @@ -336,7 +333,9 @@ final class Binarizer{ for($j = 0, $o = $yoffset * $width + $xoffset; $j < self::BLOCK_SIZE; $j++, $o += $width){ for($i = 0; $i < self::BLOCK_SIZE; $i++){ // Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0. - $matrix->set($xoffset + $i, $yoffset + $j, (((int)($luminances[$o + $i]) & 0xff) <= $average), QRMatrix::M_DATA); + $v = (((int)($this->luminances[$o + $i]) & 0xff) <= $average); + + $matrix->set($xoffset + $i, $yoffset + $j, $v, QRMatrix::M_DATA); } } } @@ -345,6 +344,9 @@ final class Binarizer{ return $matrix; } + /** + * @noinspection PhpSameParameterValueInspection + */ private function cap(int $value, int $min, int $max):int{ if($value < $min){ diff --git a/src/Decoder/LuminanceSourceAbstract.php b/src/Decoder/LuminanceSourceAbstract.php index 8b6221bea..ed604c5d7 100644 --- a/src/Decoder/LuminanceSourceAbstract.php +++ b/src/Decoder/LuminanceSourceAbstract.php @@ -44,7 +44,7 @@ abstract class LuminanceSourceAbstract implements LuminanceSourceInterface{ } /** @inheritDoc */ - public function getMatrix():array{ + public function getLuminances():array{ return $this->luminances; } diff --git a/src/Decoder/LuminanceSourceInterface.php b/src/Decoder/LuminanceSourceInterface.php index 56ecbb86b..a512d9751 100644 --- a/src/Decoder/LuminanceSourceInterface.php +++ b/src/Decoder/LuminanceSourceInterface.php @@ -22,7 +22,7 @@ interface LuminanceSourceInterface{ * larger than width * height bytes on some platforms. Do not modify the contents * of the result. */ - public function getMatrix():array; + public function getLuminances():array; /** * @return int The width of the bitmap. @@ -39,7 +39,7 @@ interface LuminanceSourceInterface{ * 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. + * getLuminances() may never be called. * * @param int $y The row to fetch, which must be in [0,getHeight()) * diff --git a/src/Detector/Detector.php b/src/Detector/Detector.php index 4f04995e1..434399824 100644 --- a/src/Detector/Detector.php +++ b/src/Detector/Detector.php @@ -98,21 +98,10 @@ final class Detector{ * #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int) to figure the * width of each, measuring along the axis between their centers. */ - private function calculateModuleSizeOneWay(FinderPattern $pattern, FinderPattern $otherPattern):float{ + private function calculateModuleSizeOneWay(FinderPattern $a, FinderPattern $b):float{ - $moduleSizeEst1 = $this->sizeOfBlackWhiteBlackRunBothWays( - $pattern->getX(), - $pattern->getY(), - $otherPattern->getX(), - $otherPattern->getY() - ); - - $moduleSizeEst2 = $this->sizeOfBlackWhiteBlackRunBothWays( - $otherPattern->getX(), - $otherPattern->getY(), - $pattern->getX(), - $pattern->getY() - ); + $moduleSizeEst1 = $this->sizeOfBlackWhiteBlackRunBothWays($a->getX(), $a->getY(), $b->getX(), $b->getY()); + $moduleSizeEst2 = $this->sizeOfBlackWhiteBlackRunBothWays($b->getX(), $b->getY(), $a->getX(), $a->getY()); if(is_nan($moduleSizeEst1)){ return $moduleSizeEst2 / 7.0; @@ -247,14 +236,9 @@ final class Detector{ * * @throws \chillerlan\QRCode\Detector\QRCodeDetectorException */ - private function computeDimension( - FinderPattern $topLeft, - FinderPattern $topRight, - FinderPattern $bottomLeft, - float $moduleSize - ):int{ - $tltrCentersDimension = (int)round($topLeft->getDistance($topRight) / $moduleSize); - $tlblCentersDimension = (int)round($topLeft->getDistance($bottomLeft) / $moduleSize); + private function computeDimension(FinderPattern $nw, FinderPattern $ne, FinderPattern $sw, float $size):int{ + $tltrCentersDimension = (int)round($nw->getDistance($ne) / $size); + $tlblCentersDimension = (int)round($nw->getDistance($sw) / $size); $dimension = (int)((($tltrCentersDimension + $tlblCentersDimension) / 2) + 7); switch($dimension % 4){ @@ -322,24 +306,24 @@ final class Detector{ * */ private function createTransform( - FinderPattern $topLeft, - FinderPattern $topRight, - FinderPattern $bottomLeft, - int $dimension, - AlignmentPattern $alignmentPattern = null + FinderPattern $nw, + FinderPattern $ne, + FinderPattern $sw, + int $size, + AlignmentPattern $ap = null ):PerspectiveTransform{ - $dimMinusThree = (float)$dimension - 3.5; + $dimMinusThree = (float)$size - 3.5; - if($alignmentPattern instanceof AlignmentPattern){ - $bottomRightX = $alignmentPattern->getX(); - $bottomRightY = $alignmentPattern->getY(); + if($ap instanceof AlignmentPattern){ + $bottomRightX = $ap->getX(); + $bottomRightY = $ap->getY(); $sourceBottomRightX = $dimMinusThree - 3.0; $sourceBottomRightY = $sourceBottomRightX; } else{ // Don't have an alignment pattern, just make up the bottom-right point - $bottomRightX = ($topRight->getX() - $topLeft->getX()) + $bottomLeft->getX(); - $bottomRightY = ($topRight->getY() - $topLeft->getY()) + $bottomLeft->getY(); + $bottomRightX = ($ne->getX() - $nw->getX()) + $sw->getX(); + $bottomRightY = ($ne->getY() - $nw->getY()) + $sw->getY(); $sourceBottomRightX = $dimMinusThree; $sourceBottomRightY = $dimMinusThree; } @@ -349,10 +333,10 @@ final class Detector{ $dimMinusThree, 3.5, $sourceBottomRightX, $sourceBottomRightY, 3.5, $dimMinusThree, - $topLeft->getX(), $topLeft->getY(), - $topRight->getX(), $topRight->getY(), + $nw->getX(), $nw->getY(), + $ne->getX(), $ne->getY(), $bottomRightX, $bottomRightY, - $bottomLeft->getX(), $bottomLeft->getY() + $sw->getX(), $sw->getY() ); }