From f4401a4b2b3482bf37209e0a85ee319deed0adc2 Mon Sep 17 00:00:00 2001 From: codemasher Date: Sat, 5 Jun 2021 01:16:21 +0200 Subject: [PATCH] :bath: cleanup --- src/Decoder/Binarizer.php | 4 +-- src/Decoder/BitMatrix.php | 3 +-- src/Decoder/BitMatrixParser.php | 33 +++++++++++++++++++++---- src/Decoder/LuminanceSource.php | 8 ++++-- src/Detector/AlignmentPatternFinder.php | 5 +--- src/Detector/Detector.php | 9 +++---- src/Detector/FinderPattern.php | 25 +++++++++++++------ src/Detector/FinderPatternFinder.php | 19 ++++++-------- src/Detector/GridSampler.php | 4 +-- src/Detector/ResultPoint.php | 4 +-- 10 files changed, 72 insertions(+), 42 deletions(-) diff --git a/src/Decoder/Binarizer.php b/src/Decoder/Binarizer.php index d3c7fdaf3..7173b5add 100644 --- a/src/Decoder/Binarizer.php +++ b/src/Decoder/Binarizer.php @@ -36,8 +36,8 @@ final class Binarizer{ // This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels. // So this is the smallest dimension in each axis we can accept. private const BLOCK_SIZE_POWER = 3; - private const BLOCK_SIZE = 8; // ...0100...00 - private const BLOCK_SIZE_MASK = 7; // ...0011...11 + private const BLOCK_SIZE = 8; // ...0100...00 + private const BLOCK_SIZE_MASK = 7; // ...0011...11 private const MINIMUM_DIMENSION = 40; private const MIN_DYNAMIC_RANGE = 24; diff --git a/src/Decoder/BitMatrix.php b/src/Decoder/BitMatrix.php index a8d41eefa..0f3b902fa 100644 --- a/src/Decoder/BitMatrix.php +++ b/src/Decoder/BitMatrix.php @@ -13,7 +13,6 @@ namespace chillerlan\QRCode\Decoder; use chillerlan\QRCode\Common\{MaskPattern, Version}; use InvalidArgumentException; -use function chillerlan\QRCode\Common\uRShift; use function array_fill, count; final class BitMatrix{ @@ -110,7 +109,7 @@ final class BitMatrix{ $this->bits[$offset] ??= 0; - return (uRShift($this->bits[$offset], ($x & 0x1f)) & 1) !== 0; + return (BitMatrixParser::uRShift($this->bits[$offset], ($x & 0x1f)) & 1) !== 0; } /** diff --git a/src/Decoder/BitMatrixParser.php b/src/Decoder/BitMatrixParser.php index f56165cca..da9f26666 100644 --- a/src/Decoder/BitMatrixParser.php +++ b/src/Decoder/BitMatrixParser.php @@ -13,8 +13,7 @@ namespace chillerlan\QRCode\Decoder; use RuntimeException; use chillerlan\QRCode\Common\{Version, FormatInformation}; -use function chillerlan\QRCode\Common\numBitsDiffering; -use const PHP_INT_MAX; +use const PHP_INT_MAX, PHP_INT_SIZE; /** * @author Sean Owen @@ -219,7 +218,7 @@ final class BitMatrixParser{ return new FormatInformation($maskedBits); } - $bitsDifference = numBitsDiffering($maskedFormatInfo1, $dataBits); + $bitsDifference = self::numBitsDiffering($maskedFormatInfo1, $dataBits); if($bitsDifference < $bestDifference){ $bestFormatInfo = $maskedBits; @@ -228,7 +227,7 @@ final class BitMatrixParser{ if($maskedFormatInfo1 !== $maskedFormatInfo2){ // also try the other option - $bitsDifference = numBitsDiffering($maskedFormatInfo2, $dataBits); + $bitsDifference = self::numBitsDiffering($maskedFormatInfo2, $dataBits); if($bitsDifference < $bestDifference){ $bestFormatInfo = $maskedBits; @@ -319,7 +318,7 @@ final class BitMatrixParser{ // Otherwise see if this is the closest to a real version info bit string // we have seen so far /** @phan-suppress-next-line PhanTypeMismatchArgumentNullable ($targetVersionPattern is never null here) */ - $bitsDifference = numBitsDiffering($versionBits, $targetVersionPattern); + $bitsDifference = self::numBitsDiffering($versionBits, $targetVersionPattern); if($bitsDifference < $bestDifference){ $bestVersion = $i; @@ -336,4 +335,28 @@ final class BitMatrixParser{ return null; } + public static function uRShift(int $a, int $b):int{ + + if($b === 0){ + return $a; + } + + return ($a >> $b) & ~((1 << (8 * PHP_INT_SIZE - 1)) >> ($b - 1)); + } + + private static function numBitsDiffering(int $a, int $b):int{ + // a now has a 1 bit exactly where its bit differs with b's + $a ^= $b; + // Offset i holds the number of 1 bits in the binary representation of i + $BITS_SET_IN_HALF_BYTE = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4]; + // Count bits set quickly with a series of lookups: + $count = 0; + + for($i = 0; $i < 32; $i += 4){ + $count += $BITS_SET_IN_HALF_BYTE[self::uRShift($a, $i) & 0x0F]; + } + + return $count; + } + } diff --git a/src/Decoder/LuminanceSource.php b/src/Decoder/LuminanceSource.php index fba88ab9e..5ed658b97 100644 --- a/src/Decoder/LuminanceSource.php +++ b/src/Decoder/LuminanceSource.php @@ -12,7 +12,7 @@ namespace chillerlan\QRCode\Decoder; use InvalidArgumentException; -use function chillerlan\QRCode\Common\arraycopy; +use function array_slice, array_splice; /** * The purpose of this class hierarchy is to abstract different bitmap implementations across @@ -82,7 +82,11 @@ abstract class LuminanceSource{ throw new InvalidArgumentException('Requested row is outside the image: '.$y); } - return arraycopy($this->luminances, $y * $this->width, [], 0, $this->width); + $arr = []; + + array_splice($arr, 0, $this->width, array_slice($this->luminances, $y * $this->width, $this->width)); + + return $arr; } /** diff --git a/src/Detector/AlignmentPatternFinder.php b/src/Detector/AlignmentPatternFinder.php index fcbb26296..a68e11589 100644 --- a/src/Detector/AlignmentPatternFinder.php +++ b/src/Detector/AlignmentPatternFinder.php @@ -14,7 +14,6 @@ namespace chillerlan\QRCode\Detector; use chillerlan\QRCode\Decoder\BitMatrix; use function abs, count; - /** *

This class attempts to find alignment patterns in a QR Code. Alignment patterns look like finder * patterns but are smaller and appear at regular intervals throughout the image.

@@ -35,7 +34,6 @@ final class AlignmentPatternFinder{ private float $moduleSize; /** @var \chillerlan\QRCode\Detector\AlignmentPattern[] */ private array $possibleCenters; - private array $crossCheckStateCount; /** *

Creates a finder that will look in a portion of the whole image.

@@ -47,7 +45,6 @@ final class AlignmentPatternFinder{ $this->bitMatrix = $image; $this->moduleSize = $moduleSize; $this->possibleCenters = []; - $this->crossCheckStateCount = []; } /** @@ -228,7 +225,7 @@ final class AlignmentPatternFinder{ */ private function crossCheckVertical(int $startI, int $centerJ, int $maxCount, int $originalStateCountTotal):?float{ $maxI = $this->bitMatrix->getDimension(); - $stateCount = $this->crossCheckStateCount; + $stateCount = []; $stateCount[0] = 0; $stateCount[1] = 0; $stateCount[2] = 0; diff --git a/src/Detector/Detector.php b/src/Detector/Detector.php index 810a98170..46dba837a 100644 --- a/src/Detector/Detector.php +++ b/src/Detector/Detector.php @@ -15,7 +15,6 @@ use RuntimeException; use chillerlan\QRCode\Common\Version; use chillerlan\QRCode\Decoder\BitMatrix; use function abs, is_nan, max, min, round; -use function chillerlan\QRCode\Common\distance; use const NAN; /** @@ -210,7 +209,7 @@ final class Detector{ if(($state === 1) === $this->bitMatrix->get($realX, $realY)){ if($state === 2){ - return distance($x, $y, $fromX, $fromY); + return FinderPattern::distance($x, $y, $fromX, $fromY); } $state++; @@ -233,7 +232,7 @@ final class Detector{ // is "white" so this last po$at (toX+xStep,toY) is the right ending. This is really a // small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this. if($state === 2){ - return distance($toX + $xstep, $toY, $fromX, $fromY); + return FinderPattern::distance($toX + $xstep, $toY, $fromX, $fromY); } // else we didn't find even black-white-black; no estimate is really possible @@ -252,8 +251,8 @@ final class Detector{ FinderPattern $bottomLeft, float $moduleSize ):int{ - $tltrCentersDimension = (int)round($topLeft->distance($topRight) / $moduleSize); - $tlblCentersDimension = (int)round($topLeft->distance($bottomLeft) / $moduleSize); + $tltrCentersDimension = (int)round($topLeft->getDistance($topRight) / $moduleSize); + $tlblCentersDimension = (int)round($topLeft->getDistance($bottomLeft) / $moduleSize); $dimension = (int)((($tltrCentersDimension + $tlblCentersDimension) / 2) + 7); switch($dimension % 4){ diff --git a/src/Detector/FinderPattern.php b/src/Detector/FinderPattern.php index e522d6cfd..6691b6dae 100644 --- a/src/Detector/FinderPattern.php +++ b/src/Detector/FinderPattern.php @@ -11,7 +11,7 @@ namespace chillerlan\QRCode\Detector; -use function chillerlan\QRCode\Common\{distance, squaredDistance}; +use function sqrt; /** *

Encapsulates a finder pattern, which are the three square patterns found in @@ -24,10 +24,10 @@ final class FinderPattern extends ResultPoint{ private int $count; - public function __construct(float $posX, float $posY, float $estimatedModuleSize, int $count = 1){ + public function __construct(float $posX, float $posY, float $estimatedModuleSize, int $count = null){ parent::__construct($posX, $posY, $estimatedModuleSize); - $this->count = $count; + $this->count = $count ?? 1; } public function getCount():int{ @@ -39,15 +39,15 @@ final class FinderPattern extends ResultPoint{ * * @return float distance between two points */ - public function distance(FinderPattern $b):float{ - return distance($this->getX(), $this->getY(), $b->getX(), $b->getY()); + public function getDistance(FinderPattern $b):float{ + return self::distance($this->x, $this->y, $b->x, $b->y); } /** * Get square of distance between a and b. */ - public function squaredDistance(FinderPattern $b):float{ - return squaredDistance($this->getX(), $this->getY(), $b->getX(), $b->getY()); + public function getSquaredDistance(FinderPattern $b):float{ + return self::squaredDistance($this->x, $this->y, $b->x, $b->y); } /** @@ -66,4 +66,15 @@ final class FinderPattern extends ResultPoint{ ); } + private static function squaredDistance(float $aX, float $aY, float $bX, float $bY):float{ + $xDiff = $aX - $bX; + $yDiff = $aY - $bY; + + return $xDiff * $xDiff + $yDiff * $yDiff; + } + + public static function distance(float $aX, float $aY, float $bX, float $bY):float{ + return sqrt(self::squaredDistance($aX, $aY, $bX, $bY)); + } + } diff --git a/src/Detector/FinderPatternFinder.php b/src/Detector/FinderPatternFinder.php index 374688931..6cd188c96 100644 --- a/src/Detector/FinderPatternFinder.php +++ b/src/Detector/FinderPatternFinder.php @@ -35,8 +35,6 @@ final class FinderPatternFinder{ /** @var \chillerlan\QRCode\Detector\FinderPattern[] */ private array $possibleCenters; private bool $hasSkipped = false; - /** @var int[] */ - private array $crossCheckStateCount; /** *

Creates a finder that will search the image for three finder patterns.

@@ -44,9 +42,8 @@ final class FinderPatternFinder{ * @param BitMatrix $bitMatrix image to search */ public function __construct(BitMatrix $bitMatrix){ - $this->bitMatrix = $bitMatrix; - $this->possibleCenters = []; - $this->crossCheckStateCount = $this->getCrossCheckStateCount(); + $this->bitMatrix = $bitMatrix; + $this->possibleCenters = []; } /** @@ -649,7 +646,7 @@ final class FinderPatternFinder{ for($j = $i + 1; $j < $startSize - 1; $j++){ $fpj = $this->possibleCenters[$j]; - $squares0 = $fpi->squaredDistance($fpj); + $squares0 = $fpi->getSquaredDistance($fpj); for($k = $j + 1; $k < $startSize; $k++){ $fpk = $this->possibleCenters[$k]; @@ -661,8 +658,8 @@ final class FinderPatternFinder{ } $a = $squares0; - $b = $fpj->squaredDistance($fpk); - $c = $fpi->squaredDistance($fpk); + $b = $fpj->getSquaredDistance($fpk); + $c = $fpi->getSquaredDistance($fpk); // sorts ascending - inlined if($a < $b){ @@ -734,9 +731,9 @@ final class FinderPatternFinder{ private function orderBestPatterns(array $patterns):array{ // Find distances between pattern centers - $zeroOneDistance = $patterns[0]->distance($patterns[1]); - $oneTwoDistance = $patterns[1]->distance($patterns[2]); - $zeroTwoDistance = $patterns[0]->distance($patterns[2]); + $zeroOneDistance = $patterns[0]->getDistance($patterns[1]); + $oneTwoDistance = $patterns[1]->getDistance($patterns[2]); + $zeroTwoDistance = $patterns[0]->getDistance($patterns[2]); // Assume one closest to other two is B; A and C will just be guesses at first if($oneTwoDistance >= $zeroOneDistance && $oneTwoDistance >= $zeroTwoDistance){ diff --git a/src/Detector/GridSampler.php b/src/Detector/GridSampler.php index 7f03c9436..2f252c9f9 100644 --- a/src/Detector/GridSampler.php +++ b/src/Detector/GridSampler.php @@ -132,10 +132,10 @@ final class GridSampler{ for($y = 0; $y < $dimension; $y++){ $max = count($points); - $iValue = (float)$y + 0.5; + $iValue = $y + 0.5; for($x = 0; $x < $max; $x += 2){ - $points[$x] = (float)($x / 2) + 0.5; + $points[$x] = ($x / 2) + 0.5; $points[$x + 1] = $iValue; } diff --git a/src/Detector/ResultPoint.php b/src/Detector/ResultPoint.php index f57dbaf25..4d69116b1 100644 --- a/src/Detector/ResultPoint.php +++ b/src/Detector/ResultPoint.php @@ -32,11 +32,11 @@ abstract class ResultPoint{ } public function getX():float{ - return (float)$this->x; + return $this->x; } public function getY():float{ - return (float)$this->y; + return $this->y; } public function getEstimatedModuleSize():float{