| <?php |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| namespace Zxing\Qrcode\Decoder; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| final class FormatInformation |
| { |
| public static $FORMAT_INFO_MASK_QR; |
|
|
| |
| |
| |
| public static $FORMAT_INFO_DECODE_LOOKUP; |
| |
| |
| |
| private static $BITS_SET_IN_HALF_BYTE; |
|
|
| private $errorCorrectionLevel; |
| private $dataMask; |
|
|
| private function __construct($formatInfo) |
| { |
| |
| $this->errorCorrectionLevel = ErrorCorrectionLevel::forBits(($formatInfo >> 3) & 0x03); |
| |
| $this->dataMask = ($formatInfo & 0x07); |
| } |
|
|
| public static function Init() |
| { |
| self::$FORMAT_INFO_MASK_QR = 0x5412; |
| self::$BITS_SET_IN_HALF_BYTE = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4]; |
| self::$FORMAT_INFO_DECODE_LOOKUP = [ |
| [0x5412, 0x00], |
| [0x5125, 0x01], |
| [0x5E7C, 0x02], |
| [0x5B4B, 0x03], |
| [0x45F9, 0x04], |
| [0x40CE, 0x05], |
| [0x4F97, 0x06], |
| [0x4AA0, 0x07], |
| [0x77C4, 0x08], |
| [0x72F3, 0x09], |
| [0x7DAA, 0x0A], |
| [0x789D, 0x0B], |
| [0x662F, 0x0C], |
| [0x6318, 0x0D], |
| [0x6C41, 0x0E], |
| [0x6976, 0x0F], |
| [0x1689, 0x10], |
| [0x13BE, 0x11], |
| [0x1CE7, 0x12], |
| [0x19D0, 0x13], |
| [0x0762, 0x14], |
| [0x0255, 0x15], |
| [0x0D0C, 0x16], |
| [0x083B, 0x17], |
| [0x355F, 0x18], |
| [0x3068, 0x19], |
| [0x3F31, 0x1A], |
| [0x3A06, 0x1B], |
| [0x24B4, 0x1C], |
| [0x2183, 0x1D], |
| [0x2EDA, 0x1E], |
| [0x2BED, 0x1F], |
| ]; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| public static function decodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2) |
| { |
| $formatInfo = self::doDecodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2); |
| if ($formatInfo != null) { |
| return $formatInfo; |
| } |
| |
| |
| |
| return self::doDecodeFormatInformation($maskedFormatInfo1 ^ self::$FORMAT_INFO_MASK_QR, |
| $maskedFormatInfo2 ^ self::$FORMAT_INFO_MASK_QR); |
| } |
|
|
| private static function doDecodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2) |
| { |
| |
| $bestDifference = PHP_INT_MAX; |
| $bestFormatInfo = 0; |
| foreach (self::$FORMAT_INFO_DECODE_LOOKUP as $decodeInfo) { |
| $targetInfo = $decodeInfo[0]; |
| if ($targetInfo == $maskedFormatInfo1 || $targetInfo == $maskedFormatInfo2) { |
| |
| return new FormatInformation($decodeInfo[1]); |
| } |
| $bitsDifference = self::numBitsDiffering($maskedFormatInfo1, $targetInfo); |
| if ($bitsDifference < $bestDifference) { |
| $bestFormatInfo = $decodeInfo[1]; |
| $bestDifference = $bitsDifference; |
| } |
| if ($maskedFormatInfo1 != $maskedFormatInfo2) { |
| |
| $bitsDifference = self::numBitsDiffering($maskedFormatInfo2, $targetInfo); |
| if ($bitsDifference < $bestDifference) { |
| $bestFormatInfo = $decodeInfo[1]; |
| $bestDifference = $bitsDifference; |
| } |
| } |
| } |
| |
| |
| if ($bestDifference <= 3) { |
| return new FormatInformation($bestFormatInfo); |
| } |
|
|
| return null; |
| } |
|
|
| public static function numBitsDiffering($a, $b) |
| { |
| $a ^= $b; |
| |
| return self::$BITS_SET_IN_HALF_BYTE[$a & 0x0F] + |
| self::$BITS_SET_IN_HALF_BYTE[(int)(uRShift($a, 4) & 0x0F)] + |
| self::$BITS_SET_IN_HALF_BYTE[(uRShift($a, 8) & 0x0F)] + |
| self::$BITS_SET_IN_HALF_BYTE[(uRShift($a, 12) & 0x0F)] + |
| self::$BITS_SET_IN_HALF_BYTE[(uRShift($a, 16) & 0x0F)] + |
| self::$BITS_SET_IN_HALF_BYTE[(uRShift($a, 20) & 0x0F)] + |
| self::$BITS_SET_IN_HALF_BYTE[(uRShift($a, 24) & 0x0F)] + |
| self::$BITS_SET_IN_HALF_BYTE[(uRShift($a, 28) & 0x0F)]; |
| } |
|
|
| public function getErrorCorrectionLevel() |
| { |
| return $this->errorCorrectionLevel; |
| } |
|
|
| public function getDataMask() |
| { |
| return $this->dataMask; |
| } |
|
|
| |
| public function hashCode() |
| { |
| return ($this->errorCorrectionLevel->ordinal() << 3) | (int)($this->dataMask); |
| } |
|
|
| |
| public function equals($o) |
| { |
| if (!($o instanceof FormatInformation)) { |
| return false; |
| } |
| $other = $o; |
|
|
| return $this->errorCorrectionLevel == $other->errorCorrectionLevel && |
| $this->dataMask == $other->dataMask; |
| } |
| } |
|
|
| FormatInformation::Init(); |
|
|