Файловый менеджер - Редактировать - /home/lakoyani/lakoyani.com.fj/Common.tar
Назад
Detector/MathUtils.php 0000777 00000002663 14711036717 0010765 0 ustar 00 <?php /* * Copyright 2012 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common\Detector; final class MathUtils { private function __construct() { } /** * Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its * argument to the nearest int, where x.5 rounds up to x+1. Semantics of this shortcut * differ slightly from {@link Math#round(float)} in that half rounds down for negative * values. -2.5 rounds to -3, not -2. For purposes here it makes no difference. * * @param float $d real value to round * * @return int $nearest {@code int} */ public static function round($d) { return (int)($d + ($d < 0.0 ? -0.5 : 0.5)); } public static function distance($aX, $aY, $bX, $bY) { $xDiff = $aX - $bX; $yDiff = $aY - $bY; return (float)sqrt($xDiff * $xDiff + $yDiff * $yDiff); } } Detector/MonochromeRectangleDetector.php 0000777 00000022125 14711036717 0014473 0 ustar 00 <?php /** * Created by PhpStorm. * User: Ashot * Date: 3/24/15 * Time: 21:23 */ namespace Zxing\Common\Detector; use Zxing\BinaryBitmap; use \Zxing\NotFoundException; use \Zxing\ResultPoint; /* * * import com.google.zxing.NotFoundException; import com.google.zxing.ResultPoint; import com.google.zxing.common.BitMatrix; */ //require_once('./lib/NotFoundException.php'); //require_once('./lib/ResultPoint.php'); //require_once('./lib/common/BitMatrix.php'); /** * <p>A somewhat generic detector that looks for a barcode-like rectangular region within an image. * It looks within a mostly white region of an image for a region of black and white, but mostly * black. It returns the four corners of the region, as best it can determine.</p> * * @author Sean Owen * @port Ashot Khanamiryan */ class MonochromeRectangleDetector { private static $MAX_MODULES = 32; private $image; public function __construct(BinaryBitmap $image) { $this->image = $image; } /** * <p>Detects a rectangular region of black and white -- mostly black -- with a region of mostly * white, in an image.</p> * * @return {@link ResultPoint}[] describing the corners of the rectangular region. The first and * last points are opposed on the diagonal, as are the second and third. The first point will be * the topmost point and the last, the bottommost. The second point will be leftmost and the * third, the rightmost * @throws NotFoundException if no Data Matrix Code can be found */ public function detect() { $height = $this->image->getHeight(); $width = $this->image->getWidth(); $halfHeight = $height / 2; $halfWidth = $width / 2; $deltaY = max(1, $height / (self::$MAX_MODULES * 8)); $deltaX = max(1, $width / (self::$MAX_MODULES * 8)); $top = 0; $bottom = $height; $left = 0; $right = $width; $pointA = $this->findCornerFromCenter($halfWidth, 0, $left, $right, $halfHeight, -$deltaY, $top, $bottom, $halfWidth / 2); $top = (int)$pointA->getY() - 1; $pointB = $this->findCornerFromCenter($halfWidth, -$deltaX, $left, $right, $halfHeight, 0, $top, $bottom, $halfHeight / 2); $left = (int)$pointB->getX() - 1; $pointC = $this->findCornerFromCenter($halfWidth, $deltaX, $left, $right, $halfHeight, 0, $top, $bottom, $halfHeight / 2); $right = (int)$pointC->getX() + 1; $pointD = $this->findCornerFromCenter($halfWidth, 0, $left, $right, $halfHeight, $deltaY, $top, $bottom, $halfWidth / 2); $bottom = (int)$pointD->getY() + 1; // Go try to find po$A again with better information -- might have been off at first. $pointA = $this->findCornerFromCenter($halfWidth, 0, $left, $right, $halfHeight, -$deltaY, $top, $bottom, $halfWidth / 4); return new ResultPoint($pointA, $pointB, $pointC, $pointD); } /** * Attempts to locate a corner of the barcode by scanning up, down, left or right from a center * point which should be within the barcode. * * @param float $centerX center's x component (horizontal) * @param float $deltaX same as deltaY but change in x per step instead * @param float $left minimum value of x * @param float $right maximum value of x * @param float $centerY center's y component (vertical) * @param float $deltaY change in y per step. If scanning up this is negative; down, positive; * left or right, 0 * @param float $top minimum value of y to search through (meaningless when di == 0) * @param float $bottom maximum value of y * @param float $maxWhiteRun maximum run of white pixels that can still be considered to be within * the barcode * * @return ResultPoint $a {@link com.google.zxing.ResultPoint} encapsulating the corner that was found * @throws NotFoundException if such a point cannot be found */ private function findCornerFromCenter($centerX, $deltaX, $left, $right, $centerY, $deltaY, $top, $bottom, $maxWhiteRun) { $lastRange = null; for ($y = $centerY, $x = $centerX; $y < $bottom && $y >= $top && $x < $right && $x >= $left; $y += $deltaY, $x += $deltaX) { $range = 0; if ($deltaX == 0) { // horizontal slices, up and down $range = $this->blackWhiteRange($y, $maxWhiteRun, $left, $right, true); } else { // vertical slices, left and right $range = $this->blackWhiteRange($x, $maxWhiteRun, $top, $bottom, false); } if ($range == null) { if ($lastRange == null) { throw NotFoundException::getNotFoundInstance(); } // lastRange was found if ($deltaX == 0) { $lastY = $y - $deltaY; if ($lastRange[0] < $centerX) { if ($lastRange[1] > $centerX) { // straddle, choose one or the other based on direction return new ResultPoint($deltaY > 0 ? $lastRange[0] : $lastRange[1], $lastY); } return new ResultPoint($lastRange[0], $lastY); } else { return new ResultPoint($lastRange[1], $lastY); } } else { $lastX = $x - $deltaX; if ($lastRange[0] < $centerY) { if ($lastRange[1] > $centerY) { return new ResultPoint($lastX, $deltaX < 0 ? $lastRange[0] : $lastRange[1]); } return new ResultPoint($lastX, $lastRange[0]); } else { return new ResultPoint($lastX, $lastRange[1]); } } } $lastRange = $range; } throw NotFoundException::getNotFoundInstance(); } /** * Computes the start and end of a region of pixels, either horizontally or vertically, that could * be part of a Data Matrix barcode. * * @param fixedDimension if scanning horizontally, this is the row (the fixed vertical location) * where we are scanning. If scanning vertically it's the column, the fixed horizontal location * @param maxWhiteRun largest run of white pixels that can still be considered part of the * barcode region * @param minDim minimum pixel location, horizontally or vertically, to consider * @param maxDim maximum pixel location, horizontally or vertically, to consider * @param horizontal if true, we're scanning left-right, instead of up-down * * @return int[] with start and end of found range, or null if no such range is found * (e.g. only white was found) */ private function blackWhiteRange($fixedDimension, $maxWhiteRun, $minDim, $maxDim, $horizontal) { $center = ($minDim + $maxDim) / 2; // Scan left/up first $start = $center; while ($start >= $minDim) { if ($horizontal ? $this->image->get($start, $fixedDimension) : $this->image->get($fixedDimension, $start)) { $start--; } else { $whiteRunStart = $start; do { $start--; } while ($start >= $minDim && !($horizontal ? $this->image->get($start, $fixedDimension) : $this->image->get($fixedDimension, $start))); $whiteRunSize = $whiteRunStart - $start; if ($start < $minDim || $whiteRunSize > $maxWhiteRun) { $start = $whiteRunStart; break; } } } $start++; // Then try right/down $end = $center; while ($end < $maxDim) { if ($horizontal ? $this->image->get($end, $fixedDimension) : $this->image->get($fixedDimension, $end)) { $end++; } else { $whiteRunStart = $end; do { $end++; } while ($end < $maxDim && !($horizontal ? $this->image->get($end, $fixedDimension) : $this->image->get($fixedDimension, $end))); $whiteRunSize = $end - $whiteRunStart; if ($end >= $maxDim || $whiteRunSize > $maxWhiteRun) { $end = $whiteRunStart; break; } } } $end--; return $end > $start ? [$start, $end] : null; } } CharacterSetECI.php 0000777 00000010571 14711036717 0010170 0 ustar 00 <?php namespace Zxing\Common; /** * Encapsulates a Character Set ECI, according to "Extended Channel * Interpretations" 5.3.1.1 of ISO 18004. */ final class CharacterSetECI { /**#@+ * Character set constants. */ const CP437 = 0; const ISO8859_1 = 1; const ISO8859_2 = 4; const ISO8859_3 = 5; const ISO8859_4 = 6; const ISO8859_5 = 7; const ISO8859_6 = 8; const ISO8859_7 = 9; const ISO8859_8 = 10; const ISO8859_9 = 11; const ISO8859_10 = 12; const ISO8859_11 = 13; const ISO8859_12 = 14; const ISO8859_13 = 15; const ISO8859_14 = 16; const ISO8859_15 = 17; const ISO8859_16 = 18; const SJIS = 20; const CP1250 = 21; const CP1251 = 22; const CP1252 = 23; const CP1256 = 24; const UNICODE_BIG_UNMARKED = 25; const UTF8 = 26; const ASCII = 27; const BIG5 = 28; const GB18030 = 29; const EUC_KR = 30; /** * Map between character names and their ECI values. * * @var array */ protected static $nameToEci = [ 'ISO-8859-1' => self::ISO8859_1, 'ISO-8859-2' => self::ISO8859_2, 'ISO-8859-3' => self::ISO8859_3, 'ISO-8859-4' => self::ISO8859_4, 'ISO-8859-5' => self::ISO8859_5, 'ISO-8859-6' => self::ISO8859_6, 'ISO-8859-7' => self::ISO8859_7, 'ISO-8859-8' => self::ISO8859_8, 'ISO-8859-9' => self::ISO8859_9, 'ISO-8859-10' => self::ISO8859_10, 'ISO-8859-11' => self::ISO8859_11, 'ISO-8859-12' => self::ISO8859_12, 'ISO-8859-13' => self::ISO8859_13, 'ISO-8859-14' => self::ISO8859_14, 'ISO-8859-15' => self::ISO8859_15, 'ISO-8859-16' => self::ISO8859_16, 'SHIFT-JIS' => self::SJIS, 'WINDOWS-1250' => self::CP1250, 'WINDOWS-1251' => self::CP1251, 'WINDOWS-1252' => self::CP1252, 'WINDOWS-1256' => self::CP1256, 'UTF-16BE' => self::UNICODE_BIG_UNMARKED, 'UTF-8' => self::UTF8, 'ASCII' => self::ASCII, 'GBK' => self::GB18030, 'EUC-KR' => self::EUC_KR, ]; /**#@-*/ /** * Additional possible values for character sets. * * @var array */ protected static $additionalValues = [ self::CP437 => 2, self::ASCII => 170, ]; private static $name = null; /** * Gets character set ECI by value. * * @param string $name * * @return CharacterSetEci|null */ public static function getCharacterSetECIByValue($value) { if ($value < 0 || $value >= 900) { throw new \InvalidArgumentException('Value must be between 0 and 900'); } if (false !== ($key = array_search($value, self::$additionalValues))) { $value = $key; } array_search($value, self::$nameToEci); try { self::setName($value); return new self($value); } catch (\UnexpectedValueException $e) { return null; } } private static function setName($value) { foreach (self::$nameToEci as $name => $key) { if ($key == $value) { self::$name = $name; return true; } } if (self::$name == null) { foreach (self::$additionalValues as $name => $key) { if ($key == $value) { self::$name = $name; return true; } } } } /** * Gets character set ECI name. * * @return character set ECI name|null */ public static function name() { return self::$name; } /** * Gets character set ECI by name. * * @param string $name * * @return CharacterSetEci|null */ public static function getCharacterSetECIByName($name) { $name = strtoupper($name); if (isset(self::$nameToEci[$name])) { return new self(self::$nameToEci[$name]); } return null; } } BitSource.php 0000777 00000007423 14711036717 0007200 0 ustar 00 <?php /* * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common; /** * <p>This provides an easy abstraction to read bits at a time from a sequence of bytes, where the * number of bits read is not often a multiple of 8.</p> * * <p>This class is thread-safe but not reentrant -- unless the caller modifies the bytes array * it passed in, in which case all bets are off.</p> * * @author Sean Owen */ final class BitSource { private $bytes; private $byteOffset = 0; private $bitOffset = 0; /** * @param bytes bytes from which this will read bits. Bits will be read from the first byte first. * Bits are read within a byte from most-significant to least-significant bit. */ public function __construct($bytes) { $this->bytes = $bytes; } /** * @return index of next bit in current byte which would be read by the next call to {@link #readBits(int)}. */ public function getBitOffset() { return $this->bitOffset; } /** * @return index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}. */ public function getByteOffset() { return $this->byteOffset; } /** * @param numBits number of bits to read * * @return int representing the bits read. The bits will appear as the least-significant * bits of the int * @throws InvalidArgumentException if numBits isn't in [1,32] or more than is available */ public function readBits($numBits) { if ($numBits < 1 || $numBits > 32 || $numBits > $this->available()) { throw new \InvalidArgumentException(strval($numBits)); } $result = 0; // First, read remainder from current byte if ($this->bitOffset > 0) { $bitsLeft = 8 - $this->bitOffset; $toRead = $numBits < $bitsLeft ? $numBits : $bitsLeft; $bitsToNotRead = $bitsLeft - $toRead; $mask = (0xFF >> (8 - $toRead)) << $bitsToNotRead; $result = ($this->bytes[$this->byteOffset] & $mask) >> $bitsToNotRead; $numBits -= $toRead; $this->bitOffset += $toRead; if ($this->bitOffset == 8) { $this->bitOffset = 0; $this->byteOffset++; } } // Next read whole bytes if ($numBits > 0) { while ($numBits >= 8) { $result = ($result << 8) | ($this->bytes[$this->byteOffset] & 0xFF); $this->byteOffset++; $numBits -= 8; } // Finally read a partial byte if ($numBits > 0) { $bitsToNotRead = 8 - $numBits; $mask = (0xFF >> $bitsToNotRead) << $bitsToNotRead; $result = ($result << $numBits) | (($this->bytes[$this->byteOffset] & $mask) >> $bitsToNotRead); $this->bitOffset += $numBits; } } return $result; } /** * @return number of bits that can be read successfully */ public function available() { return 8 * (count($this->bytes) - $this->byteOffset) - $this->bitOffset; } } AbstractEnum.php 0000777 00000004051 14711036717 0007663 0 ustar 00 <?php namespace Zxing\Common; use \Zxing\NotFoundException; use ReflectionClass; /** * A general enum implementation until we got SplEnum. */ final class AbstractEnum { /** * Default value. */ const __default = null; /** * Current value. * * @var mixed */ protected $value; /** * Cache of constants. * * @var array */ protected $constants; /** * Whether to handle values strict or not. * * @var boolean */ protected $strict; /** * Creates a new enum. * * @param mixed $initialValue * @param boolean $strict */ public function __construct($initialValue = null, $strict = false) { $this->strict = $strict; $this->change($initialValue); } /** * Changes the value of the enum. * * @param mixed $value * * @return void */ public function change($value) { if (!in_array($value, $this->getConstList(), $this->strict)) { throw new \UnexpectedValueException('Value not a const in enum ' . get_class($this)); } $this->value = $value; } /** * Gets all constants (possible values) as an array. * * @param boolean $includeDefault * * @return array */ public function getConstList($includeDefault = true) { if ($this->constants === null) { $reflection = new ReflectionClass($this); $this->constants = $reflection->getConstants(); } if ($includeDefault) { return $this->constants; } $constants = $this->constants; unset($constants['__default']); return $constants; } /** * Gets current value. * * @return mixed */ public function get() { return $this->value; } /** * Gets the name of the enum. * * @return string */ public function __toString() { return (string)array_search($this->value, $this->getConstList()); } } BitMatrix.php 0000777 00000070560 14711036717 0007206 0 ustar 00 <?php namespace Zxing\Common; final class BitMatrix { private $width; private $height; private $rowSize; private $bits; public function __construct($width, $height = false, $rowSize = false, $bits = false) { if (!$height) { $height = $width; } if (!$rowSize) { $rowSize = (int)(($width + 31) / 32); } if (!$bits) { $bits = fill_array(0, $rowSize * $height, 0); // [];//new int[rowSize * height]; } $this->width = $width; $this->height = $height; $this->rowSize = $rowSize; $this->bits = $bits; } public static function parse($stringRepresentation, $setString, $unsetString) { if (!$stringRepresentation) { throw new \InvalidArgumentException(); } $bits = []; $bitsPos = 0; $rowStartPos = 0; $rowLength = -1; $nRows = 0; $pos = 0; while ($pos < strlen($stringRepresentation)) { if ($stringRepresentation[$pos] == '\n' || $stringRepresentation->{$pos} == '\r') { if ($bitsPos > $rowStartPos) { if ($rowLength == -1) { $rowLength = $bitsPos - $rowStartPos; } else if ($bitsPos - $rowStartPos != $rowLength) { throw new \InvalidArgumentException("row lengths do not match"); } $rowStartPos = $bitsPos; $nRows++; } $pos++; } else if (substr($stringRepresentation, $pos, strlen($setString)) == $setString) { $pos += strlen($setString); $bits[$bitsPos] = true; $bitsPos++; } else if (substr($stringRepresentation, $pos + strlen($unsetString)) == $unsetString) { $pos += strlen($unsetString); $bits[$bitsPos] = false; $bitsPos++; } else { throw new \InvalidArgumentException( "illegal character encountered: " . substr($stringRepresentation, $pos)); } } // no EOL at end? if ($bitsPos > $rowStartPos) { if ($rowLength == -1) { $rowLength = $bitsPos - $rowStartPos; } else if ($bitsPos - $rowStartPos != $rowLength) { throw new \InvalidArgumentException("row lengths do not match"); } $nRows++; } $matrix = new BitMatrix($rowLength, $nRows); for ($i = 0; $i < $bitsPos; $i++) { if ($bits[$i]) { $matrix->set($i % $rowLength, $i / $rowLength); } } return $matrix; } /** * <p>Sets the given bit to true.</p> * * @param $x ; The horizontal component (i.e. which column) * @param $y ; The vertical component (i.e. which row) */ public function set($x, $y) { $offset = (int)($y * $this->rowSize + ($x / 32)); if (!isset($this->bits[$offset])) { $this->bits[$offset] = 0; } //$this->bits[$offset] = $this->bits[$offset]; // if($this->bits[$offset]>200748364){ //$this->bits= array(0,0,-16777216,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,-16777216,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,-16777216,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,-16777216,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,-16777216,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,-16777216,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,-16777216,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,-16777216,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,-16777216,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,-16777216,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,-16777216,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,-1090519040,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,1056964608,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,-1358954496,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,117440512,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,50331648,-1,-1,-1,-1,65535,0,0,0,0,0,0,0,33554432,-1,-1,536870911,-4096,65279,0,0,0,0,0,0,0,0,-1,-1,65535,-4096,65535,0,0,0,0,0,0,0,0,-193,536870911,0,-4096,65279,0,0,0,0,0,0,0,0,-254,32767,0,-4096,61951,0,0,0,0,0,0,0,0,20913920,0,0,-4096,50175,0,0,0,0,0,0,0,0,0,0,0,-4096,60159,0,0,0,0,0,0,0,0,0,0,0,-4096,64255,0,0,0,0,0,0,0,0,0,0,0,-8192,56319,0,0,0,0,0,0,0,0,0,0,0,-4096,16777215,0,0,0,0,0,0,0,0,0,0,0,-4096,16777215,0,0,0,0,0,0,0,0,0,0,0,-4096,16777215,0,0,0,0,0,0,0,0,0,0,0,-4096,16777215,0,0,0,0,0,0,0,0,0,0,0,-4096,16777215,0,0,0,0,0,0,0,0,0,0,0,-4096,16777215,0,0,0,0,0,0,0,0,0,0,0,-4096,16777215,0,0,0,0,0,0,0,0,0,0,0,-4096,16777215,0,0,0,0,0,0,0,251658240,0,0,0,-4096,-1,255,0,256,0,0,0,0,117440512,0,0,0,-4096,-1,255,0,512,0,0,0,0,117440512,0,0,0,-4096,-1,255,0,1024,0,0,0,0,117440512,0,0,0,-4096,-1,223,0,256,0,0,0,0,117440512,0,0,33030144,-4096,-1,191,0,256,0,0,0,0,117440512,0,0,33554428,-4096,-1,255,0,768,0,0,0,0,117440512,0,402849792,67108862,-8192,-1,255,0,768,0,0,0,0,117440512,0,470278396,63045630,-8192,-1,255,0,256,0,0,0,0,251658240,-8388608,470278399,58720286,-8192,-1,2686975,0,3842,0,0,0,0,251658240,-131072,1007149567,58720286,-8192,-1,2031615,0,3879,0,0,0,0,251658240,536739840,1007092192,58720286,-8192,-1,851967,0,3840,0,0,0,0,251658240,917504,1007092192,58720284,-8192,-1,2031615,0,3968,0,0,0,0,251658240,917504,1007092160,59244060,-8192,-1,65535,0,7936,0,0,0,0,251658240,917504,1009779136,59244060,-8192,-1,9371647,0,1792,0,0,0,0,251658240,917504,946921920,59244060,-8192,-1,8585215,0,1792,0,0,0,0,117440512,-15859712,477159875,59244060,-8192,-1,65535,0,12032,0,0,0,0,251658240,-15859712,52490691,59244060,-8192,-1,-1,0,65408,0,0,0,0,251658240,-15859712,58778051,59244060,-8192,-1,-1,0,65473,0,0,0,0,251658240,-15859712,125886915,59244060,-8192,-1,-1,0,65472,0,0,0,0,251658240,-15859712,58778051,59244060,-8192,-1,-1,0,65408,0,0,0,0,251658240,-15859712,8380867,59244060,-8192,-1,-1,0,65473,0,0,0,0,251658240,-15859712,8380867,59244060,-8192,-1,-1,0,131011,0,0,0,0,251658240,-15859712,8380867,58720284,-8192,-1,-1,0,130947,0,0,0,0,251658240,-15859712,2089411,58720284,-8192,-1,-1,0,130947,0,0,0,0,251658240,-32636928,449,58720284,-8192,-1,-1,33554431,131015,0,0,0,0,251658240,786432,448,62914588,-8192,-1,-1,16777215,131015,0,0,0,0,251658240,786432,448,67108860,-8192,-1,-1,553648127,131015,0,0,0,0,251658240,786432,946864576,67108860,-8192,-1,-1,32505855,131015,0,0,0,0,251658240,786432,946921976,8388604,-8192,-1,-1,8191999,131015,0,0,0,0,251658240,-262144,946921983,248,-8192,-1,-1,8126463,196551,0,0,0,0,251658240,-262144,7397887,0,-8192,-1,-1,16777215,262087,0,0,0,0,251658240,-262144,8257543,0,-8192,-1,-1,-2121269249,262095,0,0,0,0,520093696,0,8257536,0,-8192,-1,-1,-201326593,262095,0,0,0,0,520290304,0,8257536,117963776,-8192,-1,-1,-201326593,262095,0,0,0,0,520093696,0,-2140143616,118488579,-8192,-1,-1,-201326593,131023,0,0,0,0,520093696,0,-2131697280,118488579,-8192,-1,-1,-503316481,131023,0,0,0,0,520093696,2145386496,-2131631232,118484995,-16384,-1,-1,-469762049,262095,0,0,0,0,520093696,2147221504,552649600,118481344,-16384,-1,-1,-469762049,131023,0,0,0,0,520290304,2147221504,2029002240,118481344,-16384,-1,-1,-469762049,262031,0,0,0,0,520290304,-266600448,2029001791,125952960,-16384,-1,-1,-469762049,262031,0,0,0,0,1057423360,-266600448,2027953215,133177312,-16384,-1,-1,-134217729,262111,0,0,0,0,1058471936,-266600448,-119531393,133177343,-16384,-1,-1,-134217729,262111,0,0,0,0,1058471936,-2145648640,-253754369,66068479,-16384,-1,-1,-134217729,262111,0,0,0,0,1058471936,236716032,-253754369,15729663,-16384,-1,-1,-134217729,262095,0,0,0,0,1057947648,236716032,-253754369,6348807,-16384,-1,-1,-134217729,262095,0,0,0,0,524222464,236716032,-253690305,6348803,-16384,-1,-1,-134217729,262111,0,0,0,0,521076736,2115764224,-253625344,14737411,-16384,-1,-1,-134217729,262095,0,0,0,0,522125312,2115764224,-253625344,14743555,-16384,-1,-1,-134217729,262111,0,0,16772608,0,1073676288,-31719424,-2014283776,14810115,-16384,-1,-1,-1,262143,0,0,16776704,0,1065287680,-1642594304,-1879178880,14810115,-16384,-1,-1,-1,524287,0,0,16776192,0,2139029504,264241152,-2013396089,14809091,-16384,-1,-1,-1,262095,0,0,16776192,0,2139029504,264241152,-2080636025,14803335,-16384,-1,-1,-1,262087,0,0,16776192,0,2147418112,264241152,-2132803581,14803847,-16384,-1,-1,-402653185,524259,0,0,8386048,0,2147418112,0,-2132688896,123783,-16384,-1,-1,1207959551,262112,0,0,16775168,0,2147418112,0,14794752,1046535,-16384,-1,-1,268435455,262128,0,0,16775168,0,2147418112,0,14712832,1047615,-16384,-1,-1,536870911,524284,0,0,16776705,0,2147418112,0,14680832,1047615,-16384,-1,-1,-1,524287,0,0,16776704,0,2147418112,-1048576,14681087,1046591,-32768,-1,-1,-1,524287,0,0,16776704,0,2147418112,-524288,-2132802561,2080831,-32768,-1,-1,-1,524287,0,0,16776705,0,2147418112,-524288,-31718401,2080831,-32768,-1,-1,-1,1048575,0,0,16776193,0,2147418112,3670016,-31718528,2080831,-32768,-1,-1,-1,524287,0,0,16776195,0,2147418112,3670016,-31718528,134086719,-32768,-1,-1,-1,524287,0,0,16776195,0,2147418112,3670016,253494144,268173368,-32768,-1,-1,-1,524287,0,0,16775171,0,2147418112,3670016,268174208,268173368,-32768,-1,-1,-1,1048575,0,0,16771072,0,2147418112,-63438848,268174223,31457328,-32768,-1,-1,-1,1048575,0,0,10418176,0,-65536,-63438848,133957519,14807040,-32768,-1,-1,-1,2097151,0,0,15923200,0,2147418112,-63438848,1968015,14809095,-32768,-1,-1,-1,1048575,0,0,12808192,0,2147418112,-63438848,2082703,12711943,-32768,-1,-1,-1,2097151,0,0,6420480,0,2147418112,-63438848,2082703,14343,-32768,-1,-1,-1,2097151,0,0,15202304,0,-65536,-63438848,2082703,1849351,-32768,-1,-1,-1,2097151,0,0,15464448,0,-65536,-63438848,264472335,1849351,-32768,-1,-1,-1,4194303,0,0,16371712,0,-65536,-63438848,264472335,14343,-32768,-1,-1,-1,8388607,0,0,0,0,-65536,-63438848,532907791,235010048,-32768,-1,-1,-1,16777215,0,0,0,0,-65536,-63438848,-1603833,235010160,-32768,-1,-1,-1,16777215,0,0,0,0,-65536,3670016,-30976,67238000,-32768,-1,-1,-1,16777215,0,0,0,0,-65536,3670016,-30976,48,-32768,-1,-1,-1,16777215,0,0,0,0,-65536,3670016,-29391104,768,-32768,-1,-1,-1,16777215,0,0,0,0,-65536,3670016,-29391104,768,-32768,-1,-1,-1,16777215,0,0,0,0,-65536,-524287,-65042433,768,-32768,-1,-1,-1,16777215,0,0,0,0,-65536,-524287,2082441215,0,-65536,-1,-1,-1,16777215,0,0,0,0,-13697024,-524287,511,0,-65536,-1,-1,-1,16777215,0,0,0,0,-12648448,1,0,0,-65536,-1,-1,-1,14680063,0,0,0,0,-12648448,1,0,0,-65536,-1,-1,-1,16777215,0,0,0,0,-65536,1,0,0,-65536,-1,-1,-1,14680063,0,0,0,0,-8454144,1,0,0,-65536,-1,-1,-1,12582911,0,0,0,0,-12648448,1,0,0,-65536,-1,-1,-1,2097151,0,0,0,0,-12648448,1,0,0,-65536,-1,-1,-1,1048575,0,0,0,0,-14745600,1,0,0,-65536,-1,-1,-1,3145727,0,0,0,0,1056964608,1,0,0,-65536,-1,-1,-1,1048575,0,0,0,0,1056964608,1,0,0,-65536,-1,-1,-1,1048575,0,0,0,0,1056964608,1,0,0,-65536,-1,-1,-1,524287,0,0,0,0,2130706432,1,0,0,-65536,-1,-1,-1,1048575,0,0,0,0,1056964608,1,0,0,-65536,-1,-1,-1,524287,0,0,0,0,2130706432,1,0,0,-65536,-1,-1,-1,524287,0,0,0,0,2130706432,1,0,0,-65536,-1,-1,-1,1048575,0,0,0,0,2130706432,1,0,0,-65536,-1,-1,-1,1048575,0,0,0,0,50331648,1,0,0,-65536,-1,-1,-1,1048575,0,0,0,0,117440512,1,0,-268435456,-1,-1,-1,-1,524287,0,0,0,0,251658240,1,0,-320,-1,-1,-1,-1,262143,0,0,0,0,520093696,1,-2048,-1,-1,-1,-1,-1,262143,0,0,0,0,1056964608,-16777213,-1,-1,-1,-1,-1,-1,131071,0,0,0,0,-16777216,-121,-1,-1,-1,-1,-1,-1,131071,0,0,0,0,-16777216,-1,-1,-1,-1,-1,-1,-1,131071,0,0,0,0,-16777216,-1,-1,-1,-1,-1,-1,-1,131071,0,0,0,0,-16777216,-1,-1,-1,-1,-1,-1,-1,131071,0,0,0,0,-16777216,-1,-1,-1,-1,-1,-1,-1,65535,0,0,0,0,-16777216,-1,-1,-1,-1,-1,-1,-1,65535,0,0,0,0,-16777216,-1,-1,-1,-1,-1,-1,-1,131071,0,0,0,0,-16777216,-1,-1,-1,-1,-1,-1,-1,262143,0,0,0,0,-16777216,-1,-1,-1,-1,-1,-1,-1,524287,0,0,0,0,-16777216,-1,-1,-1,-1,-1,-1,-1,524287,0,0,0,0,-16777216,-1,-1,-1,-1,-1,-1,-1,589823,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,8179,0,0,0,0,50331648,-1,-1,-1,-1,-1,-1,-1,4080,0,0,0,0,117440512,-1,-1,-1,-1,-1,-1,-1,1016,0,0,0,0,251658240,-1,-1,-1,-1,-1,-1,1073741823,1020,0,0,0,0,50331648,-1,-1,-1,-1,-1,-1,536870911,254,0,0,0,0,50331648,-1,-1,-1,-1,-1,-1,536870911,255,0,0,0,0,50331648,-1,-1,-1,-1,-1,-1,-1879048193,127,0,0,0,0,50331648,-1,-1,-1,-1,-1,-1,-469762049,63,0,0,0,0,1191182336,-1,-1,-1,-1,1023999,0,-520093712,15,0,0,0,0,-218103808,-1,-1,-1,-1,0,-8454144,-260046849,7,0,0,0,0,0,-193,-1,-1,-1057947649,-2147483648,-1,-58720257,1,0,0,0,0,0,-251,-1,-1,-1057423361,-2074,-1,-1,0,0,0,0,0,0,-59648,-1,-1,-1,-1,-1,1073741823,0,0,0,0,0,0,-65536,-1,-1,-1,-1,-1,268435455,0,0,0,0,0,0,-65536,-1,-1,-1,-1,-1,67108863,0,0,0,0,0,0,-65536,-1,-1,-1,-1,-1,8388607,0,0,0,0,0,0,0,-403603456,-1,-1,-1,-1,262143,0,0,0,8388656,0,0,0,-1891434496,-1,-1,-1,-1,16383,0,0,0,8388608,0,0,0,-1612513280,-1,-1,-1,-1,63,0,0,0,0,0,0,0,-24320,-1,-1,-1,8388607,0,0,0,0,0,0,0,0,-256,-1,-1,1073741823,1,0,0,0,0,0,0,0,1610612736,-15,-1,-1,16383,0,0,0,0,0,0,0,0,-16646144,-1,-1,251658239,0,0,0,0,0,0,0,0,0,-51200,-1,-1,40959,0,0,0,0,0,0,268419584,103809024,-12713984,-1,-2147483137,4194303,0,0,0,0,0,0,0,402620416,-2144010240,-13631487,-32513,3,20480,0,0,0,0,0,0,0,419299328,0,-262144,-1,0,0,0,0,0,0,0,0,0,0,0,-5832704,268049407,0,0,0,0,0,0,0,0,0,0,0,0,33030144,0,0,0,0,0,0,0,0,0,0,0,0,3670016,0,0,0,0,0,0,0,0,0,0,0,0,1572864,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,458752,0,0,0,0,0,0,0,0,0,0,0,0,229376,0,0,0,0,0,0,0,0,0,0,0,0,32768,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8192,0,0,0,0,0,0,0,0,0,0,0,0,8192,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31744,0,0,0,0,0,0,0,0,0,0,0,0,31744,0,0,0,0,0,0,0,0,0,0,0,0,64512,0,0,0,0,0,0,0,0,0,0,0,0,15872,0,0,0,0,0,0,0,0,0,0,0,0,3584,0,0,0,0,0,0,0,0,0,0,0,0,7680,0,0,0,0,0,0,0,0,0,0,0,0,512,0,0,0,0,0,0,0,0,0,0,0,0,3968,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3840,0,0,0,0,0,0,0,0,0,0,0,0,1855,0,0,0,0,0,0,0,0,0,0,0,0,63,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,134217728,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,124,0,0,0,0,0,0,0,0,0,0,0,-260046848,63,0,0,0,0,0,0,0,0,0,0,0,-17301504,127,0,0,0,0,0,0,0,0,0,0,0,-524288,127,0,0,0,0,0,0,0,0,0,0,0,-262144,127,0,0,0,0,0,0,0,0,0,0,0,-262144,63,0,0,0,0,0,0,0,0,0,0,0,-262144,63,0,0,0,0,0,0,0,0,0,0,0,-262144,63,0,0,0,0,0,0,0,0,0,0,0,-262144,31,0,0,0,0,0,0,0,0,0,0,0,-262144,63,0,0,0,0,3,0,0,0,0,0,0,-262144,63,0,0,0,0,7,0,0,0,0,0,0,-262144,63,0,0,0,0,63,0,0,0,0,0,0,-262144,63,0,0,0,0,511,0,0,0,0,0,0,-524288,31,0,0,0,0,8191,0,0,0,0,0,0,-1048576,63,0,0,0,0,131071,0,0,0,0,0,0,-524288,63,0,0,0,0,262143,0,0,0,0,0,0,-524288,63,0,0,0,0,131071,0,0,0,0,0,0,-1048576,63,0,0,0,0,262143,0,0,0,0,0,0,-1048576,63,0,0,0,0,262143,0,0,0,0,0,0,-1048576,63,0,0,0,0,262143,0,0,0,0,0,0,-1048576,63,0,0,0,0,262143,0,0,0,0,0,0,-2097152,127,0,0,0,0,262143,0,0,0,0,0,0,-2097152,127,0,0,0,0,262143,0,0,0,0,0,0,-1048576,127,0,0,0,0,262143,0,0,0,0,0,0,-1048576,127,0,0,0,0,262143,0,0,0,0,0,0,-2097152,255,0,0,0,0,262143,0,0,0,0,0,0,-2097152,255,0,0,0,0,262142,0,0,0,0,0,0,-2097152,255,0,0,0,0,262142,0,0,0,0,0,0,-2097152,255,0,0,0,0,262142,0,0,0,0,0,0,-2097152,255,0,0,0,0,262140,0,0,0,0,0,0,-2097152,255,0,0,0,0,131068,0,0,0,0,0,0,-4194304,255,0,0,0,0,131068,0,0,0,0,0,0,-4194304,255,0,0,0,0,65528,0,0,0,0,0,0,-8388608,255,0,0,0,0,65528,0,0,0,0,0,0,-8388608,255,0,0,0,0,65528,0,0,0,0,0,0,-8388608,255,0,0,0,0,32760,0,0,0,0,0,0,-8388608,255,0,0,0,0,32760,0,0,0,0,0,0,-16777216,255,0,0,-2147483648,255,16368,0,0,0,0,0,0,-16777216,255,0,0,-536870912,1023,16368,0,0,0,0,0,0,-33554432,255,0,0,-16777216,4095,16352,0,0,0,0,0,0,-33554432,255,0,0,-8388608,262143,16352,0,0,0,0,0,0,-33554432,255,0,0,-1048576,2097151,16352,0,0,0,0,0,0,-67108864,255,0,0,-524288,8388607,16352,0,0,0,0,0,0,-67108864,255,0,0,-262144,16777215,16320,0,0,0,0,0,0,-67108864,255,0,0,-131072,16777215,100679648,0,0,0,0,0,0,-67108864,255,0,0,-16384,16776959,125861824,0,0,0,0,0,0,-134217728,255,0,0,-4096,16773121,62930880,0,0,0,0,0,0,-134217728,127,0,0,2147482624,16252928,32704,0,0,0,0,0,0,-134217728,127,0,0,268435200,14680064,16320,0,0,0,0,0,0,-134217728,127,0,0,134217600,0,32704,0,0,0,0,0,0,-33554432,127,0,1056964608,67108736,0,32704,0,0,0,0,0,0,-33554432,127,0,2130706432,33554368,0,65408,0,0,0,0,0,0,-33554432,127,0,-16777216,8388576,0,32640,0,0,0,0,0,0,-134217728,127,0,-16777216,2097136,0,32640,0,0,0,0,0,0,-134217728,63,0,-16776960,1048573,0,32640,0,0,0,0,0,0,-536870912,63,0,-16776448,1048575,0,32640,0,0,0,0,0,0,-536870912,63,0,-33553664,6291455,66752,32640,0,0,0,0,0,0,-536870912,63,0,2013266688,2097148,229376,32640,0,0,0,0,0,0,-536870912,63,0,256,4194300,229376,32640,0,0,0,0,0,0,-536870912,63,0,0,524280,196608,32512,0,0,8,0,0,0,-1073741824,63,0,0,-200,15,65280,0,0,24,0,0,0,-1073741824,63,0,0,-1867768,127,32512,0,0,56,0,0,0,-1073741824,63,0,0,-1056768,4095,32512,0,0,124,0,0,0,-1073741824,63,0,0,-1050624,8191,32512,0,0,508,0,0,0,-2147483648,31,0,0,-7866368,8191,32512,0,0,1020,0,0,0,-2147483648,31,0,0,-33030656,8095,32512,0,0,2046,0,0,0,-2147483648,63,0,0,-66586624,771,32512,0,0,4094,0,0,0,0,63,0,0,-134184960,1,32256,0,0,8190,0,0,0,0,63,0,0,1610612736,0,32256,0,0,16382,0,0,0,-2147483648,63,0,0,0,0,15872,0,0,32767,0,0,0,-2147483648,31,0,0,0,0,15872,0,-2147483648,65535,0,0,0,-2147483648,31,0,0,0,0,7680,0,0,65535,0,0,0,-2147483648,31,0,0,134217728,0,7680,0,-2147483648,65535,0,0,0,-2147483648,31,0,0,0,0,7680,0,-2147483648,65535,0,0,0,-2147483648,31,0,0,0,0,7680,0,-1073741824,65535,0,0,0,-2147483648,31,0,0,0,0,3072,0,-1073741824,65535,0,0,0,-2147483648,31,0,0,0,0,3072,0,-1073741824,65535,0,0,0,-2147483648,31,0,0,0,0,0,0,-2147483648,65535,0,0,0,-2147483648,31,0,0,0,0,0,0,-1073741824,65535,0,0,0,0,31,0,0,0,0,0,0,-1073741824,65535,0,0,0,0,31,0,0,0,0,0,0,-2147483648,65535,0,0,0,0,30,0,0,0,0,0,0,-1073741824,65535,0,0,0,0,30,0,0,0,0,0,0,-2147483648,65535,0,0,0,0,30,0,0,0,0,0,0,0,65535,0,0,0,0,28,0,0,0,0,0,0,0,65535,0,0,0,0,28,0,0,0,0,0,0,0,65535,0,0,0,0,28,0,0,0,0,0,0,0,65535,0,0,0,0,24,0,0,0,0,0,0,-2147483648,65535,0,0,0,0,0,0,0,0,0,0,0,-536870912,65535);//[$offset] |= intval32bits(1 << ($x & 0x1f)); $bob = $this->bits[$offset]; $bob |= 1 << ($x & 0x1f); $this->bits[$offset] |= ($bob); //$this->bits[$offset] = intval32bits($this->bits[$offset]); //} //16777216 } public function _unset($x, $y) {//было unset, php не позволяет использовать unset $offset = (int)($y * $this->rowSize + ($x / 32)); $this->bits[$offset] &= ~(1 << ($x & 0x1f)); } /**1 << (249 & 0x1f) * <p>Flips the given bit.</p> * * @param $x ; The horizontal component (i.e. which column) * @param $y ; The vertical component (i.e. which row) */ public function flip($x, $y) { $offset = $y * $this->rowSize + (int)($x / 32); $this->bits[$offset] = ($this->bits[$offset] ^ (1 << ($x & 0x1f))); } /** * Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding * mask bit is set. * * @param $mask ; XOR mask */ public function _xor($mask) {//было xor, php не позволяет использовать xor if ($this->width != $mask->getWidth() || $this->height != $mask->getHeight() || $this->rowSize != $mask->getRowSize()) { throw new \InvalidArgumentException("input matrix dimensions do not match"); } $rowArray = new BitArray($this->width / 32 + 1); for ($y = 0; $y < $this->height; $y++) { $offset = $y * $this->rowSize; $row = $mask->getRow($y, $rowArray)->getBitArray(); for ($x = 0; $x < $this->rowSize; $x++) { $this->bits[$offset + $x] ^= $row[$x]; } } } /** * Clears all bits (sets to false). */ public function clear() { $max = count($this->bits); for ($i = 0; $i < $max; $i++) { $this->bits[$i] = 0; } } /** * <p>Sets a square region of the bit matrix to true.</p> * * @param $left ; The horizontal position to begin at (inclusive) * @param $top ; The vertical position to begin at (inclusive) * @param $width ; The width of the region * @param $height ; The height of the region */ public function setRegion($left, $top, $width, $height) { if ($top < 0 || $left < 0) { throw new \InvalidArgumentException("Left and top must be nonnegative"); } if ($height < 1 || $width < 1) { throw new \InvalidArgumentException("Height and width must be at least 1"); } $right = $left + $width; $bottom = $top + $height; if ($bottom > $this->height || $right > $this->width) { //> this.height || right > this.width throw new \InvalidArgumentException("The region must fit inside the matrix"); } for ($y = $top; $y < $bottom; $y++) { $offset = $y * $this->rowSize; for ($x = $left; $x < $right; $x++) { $this->bits[$offset + (int)($x / 32)] = ($this->bits[$offset + (int)($x / 32)] |= 1 << ($x & 0x1f)); } } } /** * Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees */ public function rotate180() { $width = $this->getWidth(); $height = $this->getHeight(); $topRow = new BitArray($width); $bottomRow = new BitArray($width); for ($i = 0; $i < ($height + 1) / 2; $i++) { $topRow = $this->getRow($i, $topRow); $bottomRow = $this->getRow($height - 1 - $i, $bottomRow); $topRow->reverse(); $bottomRow->reverse(); $this->setRow($i, $bottomRow); $this->setRow($height - 1 - $i, $topRow); } } /** * @return The width of the matrix */ public function getWidth() { return $this->width; } /** * A fast method to retrieve one row of data from the matrix as a BitArray. * * @param $y ; The row to retrieve * @param $row ; An optional caller-allocated BitArray, will be allocated if null or too small * * @return The resulting BitArray - this reference should always be used even when passing * your own row */ public function getRow($y, $row) { if ($row == null || $row->getSize() < $this->width) { $row = new BitArray($this->width); } else { $row->clear(); } $offset = $y * $this->rowSize; for ($x = 0; $x < $this->rowSize; $x++) { $row->setBulk($x * 32, $this->bits[$offset + $x]); } return $row; } /** * @param $y ; row to set * @param $row ; {@link BitArray} to copy from */ public function setRow($y, $row) { $this->bits = arraycopy($row->getBitArray(), 0, $this->bits, $y * $this->rowSize, $this->rowSize); } /** * This is useful in detecting the enclosing rectangle of a 'pure' barcode. * * @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white */ public function getEnclosingRectangle() { $left = $this->width; $top = $this->height; $right = -1; $bottom = -1; for ($y = 0; $y < $this->height; $y++) { for ($x32 = 0; $x32 < $this->rowSize; $x32++) { $theBits = $this->bits[$y * $this->rowSize + $x32]; if ($theBits != 0) { if ($y < $top) { $top = $y; } if ($y > $bottom) { $bottom = $y; } if ($x32 * 32 < $left) { $bit = 0; while (($theBits << (31 - $bit)) == 0) { $bit++; } if (($x32 * 32 + $bit) < $left) { $left = $x32 * 32 + $bit; } } if ($x32 * 32 + 31 > $right) { $bit = 31; while ((sdvig3($theBits, $bit)) == 0) {//>>> $bit--; } if (($x32 * 32 + $bit) > $right) { $right = $x32 * 32 + $bit; } } } } } $width = $right - $left; $height = $bottom - $top; if ($width < 0 || $height < 0) { return null; } return [$left, $top, $width, $height]; } /** * This is useful in detecting a corner of a 'pure' barcode. * * @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white */ public function getTopLeftOnBit() { $bitsOffset = 0; while ($bitsOffset < count($this->bits) && $this->bits[$bitsOffset] == 0) { $bitsOffset++; } if ($bitsOffset == count($this->bits)) { return null; } $y = $bitsOffset / $this->rowSize; $x = ($bitsOffset % $this->rowSize) * 32; $theBits = $this->bits[$bitsOffset]; $bit = 0; while (($theBits << (31 - $bit)) == 0) { $bit++; } $x += $bit; return [$x, $y]; } public function getBottomRightOnBit() { $bitsOffset = count($this->bits) - 1; while ($bitsOffset >= 0 && $this->bits[$bitsOffset] == 0) { $bitsOffset--; } if ($bitsOffset < 0) { return null; } $y = $bitsOffset / $this->rowSize; $x = ($bitsOffset % $this->rowSize) * 32; $theBits = $this->bits[$bitsOffset]; $bit = 31; while ((sdvig3($theBits, $bit)) == 0) {//>>> $bit--; } $x += $bit; return [$x, $y]; } /** * @return The height of the matrix */ public function getHeight() { return $this->height; } /** * @return The row size of the matrix */ public function getRowSize() { return $this->rowSize; } public function equals($o) { if (!($o instanceof BitMatrix)) { return false; } $other = $o; return $this->width == $other->width && $this->height == $other->height && $this->rowSize == $other->rowSize && $this->bits === $other->bits; } //@Override public function hashCode() { $hash = $this->width; $hash = 31 * $hash + $this->width; $hash = 31 * $hash + $this->height; $hash = 31 * $hash + $this->rowSize; $hash = 31 * $hash + hashCode($this->bits); return $hash; } //@Override public function toString($setString = '', $unsetString = '', $lineSeparator = '') { if (!$setString || !$unsetString) { return (string)'X ' . ' '; } if ($lineSeparator && $lineSeparator !== "\n") { return $this->toString_($setString, $unsetString, $lineSeparator); } return (string)($setString . $unsetString . "\n"); } public function toString_($setString, $unsetString, $lineSeparator) { //$result = new StringBuilder(height * (width + 1)); $result = ''; for ($y = 0; $y < $this->height; $y++) { for ($x = 0; $x < $this->width; $x++) { $result .= ($this->get($x, $y) ? $setString : $unsetString); } $result .= ($lineSeparator); } return (string)$result; } /** * @deprecated call {@link #toString(String,String)} only, which uses \n line separator always */ // @Deprecated /** * <p>Gets the requested bit, where true means black.</p> * * @param $x ; The horizontal component (i.e. which column) * @param $y ; The vertical component (i.e. which row) * * @return value of given bit in matrix */ public function get($x, $y) { $offset = (int)($y * $this->rowSize + ($x / 32)); if (!isset($this->bits[$offset])) { $this->bits[$offset] = 0; } // return (($this->bits[$offset] >> ($x & 0x1f)) & 1) != 0; return (uRShift($this->bits[$offset], ($x & 0x1f)) & 1) != 0;//было >>> вместо >>, не знаю как эмулировать беззнаковый сдвиг } // @Override public function _clone() { return new BitMatrix($this->width, $this->height, $this->rowSize, $this->bits); } } DecoderResult.php 0000777 00000005562 14711036717 0010047 0 ustar 00 <?php /* * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common; /** * <p>Encapsulates the result of decoding a matrix of bits. This typically * applies to 2D barcode formats. For now it contains the raw bytes obtained, * as well as a String interpretation of those bytes, if applicable.</p> * * @author Sean Owen */ final class DecoderResult { private $rawBytes; private $text; private $byteSegments; private $ecLevel; private $errorsCorrected; private $erasures; private $other; private $structuredAppendParity; private $structuredAppendSequenceNumber; public function __construct( $rawBytes, $text, $byteSegments, $ecLevel, $saSequence = -1, $saParity = -1 ) { $this->rawBytes = $rawBytes; $this->text = $text; $this->byteSegments = $byteSegments; $this->ecLevel = $ecLevel; $this->structuredAppendParity = $saParity; $this->structuredAppendSequenceNumber = $saSequence; } public function getRawBytes() { return $this->rawBytes; } public function getText() { return $this->text; } public function getByteSegments() { return $this->byteSegments; } public function getECLevel() { return $this->ecLevel; } public function getErrorsCorrected() { return $this->errorsCorrected; } public function setErrorsCorrected($errorsCorrected) { $this->errorsCorrected = $errorsCorrected; } public function getErasures() { return $this->erasures; } public function setErasures($erasures) { $this->erasures = $erasures; } public function getOther() { return $this->other; } public function setOther($other) { $this->other = $other; } public function hasStructuredAppend() { return $this->structuredAppendParity >= 0 && $this->structuredAppendSequenceNumber >= 0; } public function getStructuredAppendParity() { return $this->structuredAppendParity; } public function getStructuredAppendSequenceNumber() { return $this->structuredAppendSequenceNumber; } } DetectorResult.php 0000777 00000002374 14711036717 0010251 0 ustar 00 <?php /* * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common; /** * <p>Encapsulates the result of detecting a barcode in an image. This includes the raw * matrix of black/white pixels corresponding to the barcode, and possibly points of interest * in the image, like the location of finder patterns or corners of the barcode in the image.</p> * * @author Sean Owen */ class DetectorResult { private $bits; private $points; public function __construct($bits, $points) { $this->bits = $bits; $this->points = $points; } public final function getBits() { return $this->bits; } public final function getPoints() { return $this->points; } } GridSampler.php 0000777 00000015761 14711036717 0007516 0 ustar 00 <?php /* * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common; use Zxing\NotFoundException; /** * Implementations of this class can, given locations of finder patterns for a QR code in an * image, sample the right points in the image to reconstruct the QR code, accounting for * perspective distortion. It is abstracted since it is relatively expensive and should be allowed * to take advantage of platform-specific optimized implementations, like Sun's Java Advanced * Imaging library, but which may not be available in other environments such as J2ME, and vice * versa. * * The implementation used can be controlled by calling {@link #setGridSampler(GridSampler)} * with an instance of a class which implements this interface. * * @author Sean Owen */ abstract class GridSampler { private static $gridSampler; /** * Sets the implementation of GridSampler used by the library. One global * instance is stored, which may sound problematic. But, the implementation provided * ought to be appropriate for the entire platform, and all uses of this library * in the whole lifetime of the JVM. For instance, an Android activity can swap in * an implementation that takes advantage of native platform libraries. * * @param newGridSampler The platform-specific object to install. */ public static function setGridSampler($newGridSampler) { self::$gridSampler = $newGridSampler; } /** * @return the current implementation of GridSampler */ public static function getInstance() { if (!self::$gridSampler) { self::$gridSampler = new DefaultGridSampler(); } return self::$gridSampler; } /** * <p>Checks a set of points that have been transformed to sample points on an image against * the image's dimensions to see if the point are even within the image.</p> * * <p>This method will actually "nudge" the endpoints back onto the image if they are found to be * barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder * patterns in an image where the QR Code runs all the way to the image border.</p> * * <p>For efficiency, the method will check points from either end of the line until one is found * to be within the image. Because the set of points are assumed to be linear, this is valid.</p> * * @param image image into which the points should map * @param points actual points in x1,y1,...,xn,yn form * * @throws NotFoundException if an endpoint is lies outside the image boundaries */ protected static function checkAndNudgePoints( $image, $points ) { $width = $image->getWidth(); $height = $image->getHeight(); // Check and nudge points from start until we see some that are OK: $nudged = true; for ($offset = 0; $offset < count($points) && $nudged; $offset += 2) { $x = (int)$points[$offset]; $y = (int)$points[$offset + 1]; if ($x < -1 || $x > $width || $y < -1 || $y > $height) { throw NotFoundException::getNotFoundInstance(); } $nudged = false; if ($x == -1) { $points[$offset] = 0.0; $nudged = true; } else if ($x == $width) { $points[$offset] = $width - 1; $nudged = true; } if ($y == -1) { $points[$offset + 1] = 0.0; $nudged = true; } else if ($y == $height) { $points[$offset + 1] = $height - 1; $nudged = true; } } // Check and nudge points from end: $nudged = true; for ($offset = count($points) - 2; $offset >= 0 && $nudged; $offset -= 2) { $x = (int)$points[$offset]; $y = (int)$points[$offset + 1]; if ($x < -1 || $x > $width || $y < -1 || $y > $height) { throw NotFoundException::getNotFoundInstance(); } $nudged = false; if ($x == -1) { $points[$offset] = 0.0; $nudged = true; } else if ($x == $width) { $points[$offset] = $width - 1; $nudged = true; } if ($y == -1) { $points[$offset + 1] = 0.0; $nudged = true; } else if ($y == $height) { $points[$offset + 1] = $height - 1; $nudged = true; } } } /** * Samples an image for a rectangular matrix of bits of the given dimension. The sampling * transformation is determined by the coordinates of 4 points, in the original and transformed * image space. * * @param image image to sample * @param dimensionX width of {@link BitMatrix} to sample from image * @param dimensionY height of {@link BitMatrix} to sample from image * @param p1ToX point 1 preimage X * @param p1ToY point 1 preimage Y * @param p2ToX point 2 preimage X * @param p2ToY point 2 preimage Y * @param p3ToX point 3 preimage X * @param p3ToY point 3 preimage Y * @param p4ToX point 4 preimage X * @param p4ToY point 4 preimage Y * @param p1FromX point 1 image X * @param p1FromY point 1 image Y * @param p2FromX point 2 image X * @param p2FromY point 2 image Y * @param p3FromX point 3 image X * @param p3FromY point 3 image Y * @param p4FromX point 4 image X * @param p4FromY point 4 image Y * * @return {@link BitMatrix} representing a grid of points sampled from the image within a region * defined by the "from" parameters * @throws NotFoundException if image can't be sampled, for example, if the transformation defined * by the given points is invalid or results in sampling outside the image boundaries */ public abstract function sampleGrid( $image, $dimensionX, $dimensionY, $p1ToX, $p1ToY, $p2ToX, $p2ToY, $p3ToX, $p3ToY, $p4ToX, $p4ToY, $p1FromX, $p1FromY, $p2FromX, $p2FromY, $p3FromX, $p3FromY, $p4FromX, $p4FromY ); public abstract function sampleGrid_( $image, $dimensionX, $dimensionY, $transform ); } customFunctions.php 0000777 00000003762 14711036717 0010506 0 ustar 00 <?php if (!function_exists('arraycopy')) { function arraycopy($srcArray, $srcPos, $destArray, $destPos, $length) { $srcArrayToCopy = array_slice($srcArray, $srcPos, $length); array_splice($destArray, $destPos, $length, $srcArrayToCopy); return $destArray; } } if (!function_exists('hashCode')) { function hashCode($s) { $h = 0; $len = strlen($s); for ($i = 0; $i < $len; $i++) { $h = (31 * $h + ord($s[$i])); } return $h; } } if (!function_exists('numberOfTrailingZeros')) { function numberOfTrailingZeros($i) { if ($i == 0) return 32; $num = 0; while (($i & 1) == 0) { $i >>= 1; $num++; } return $num; } } if (!function_exists('uRShift')) { function uRShift($a, $b) { static $mask = (8 * PHP_INT_SIZE - 1); if ($b === 0) { return $a; } return ($a >> $b) & ~(1 << $mask >> ($b - 1)); } } /* function sdvig3($num,$count=1){//>>> 32 bit $s = decbin($num); $sarray = str_split($s,1); $sarray = array_slice($sarray,-32);//32bit for($i=0;$i<=1;$i++) { array_pop($sarray); array_unshift($sarray, '0'); } return bindec(implode($sarray)); } */ if (!function_exists('sdvig3')) { function sdvig3($a, $b) { if ($a >= 0) { return bindec(decbin($a >> $b)); //simply right shift for positive number } $bin = decbin($a >> $b); $bin = substr($bin, $b); // zero fill on the left side return bindec($bin); } } if (!function_exists('floatToIntBits')) { function floatToIntBits($float_val) { $int = unpack('i', pack('f', $float_val)); return $int[1]; } } if (!function_exists('fill_array')) { function fill_array($index, $count, $value) { if ($count <= 0) { return [0]; } return array_fill($index, $count, $value); } } DefaultGridSampler.php 0000777 00000006320 14711036717 0011012 0 ustar 00 <?php /* * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common; use Zxing\NotFoundException; /** * @author Sean Owen */ final class DefaultGridSampler extends GridSampler { //@Override public function sampleGrid( $image, $dimensionX, $dimensionY, $p1ToX, $p1ToY, $p2ToX, $p2ToY, $p3ToX, $p3ToY, $p4ToX, $p4ToY, $p1FromX, $p1FromY, $p2FromX, $p2FromY, $p3FromX, $p3FromY, $p4FromX, $p4FromY ) { $transform = PerspectiveTransform::quadrilateralToQuadrilateral( $p1ToX, $p1ToY, $p2ToX, $p2ToY, $p3ToX, $p3ToY, $p4ToX, $p4ToY, $p1FromX, $p1FromY, $p2FromX, $p2FromY, $p3FromX, $p3FromY, $p4FromX, $p4FromY); return $this->sampleGrid_($image, $dimensionX, $dimensionY, $transform); } //@Override public function sampleGrid_( $image, $dimensionX, $dimensionY, $transform ) { if ($dimensionX <= 0 || $dimensionY <= 0) { throw NotFoundException::getNotFoundInstance(); } $bits = new BitMatrix($dimensionX, $dimensionY); $points = fill_array(0, 2 * $dimensionX, 0.0); for ($y = 0; $y < $dimensionY; $y++) { $max = count($points); $iValue = (float)$y + 0.5; for ($x = 0; $x < $max; $x += 2) { $points[$x] = (float)($x / 2) + 0.5; $points[$x + 1] = $iValue; } $transform->transformPoints($points); // Quick check to see if points transformed to something inside the image; // sufficient to check the endpoints $this->checkAndNudgePoints($image, $points); try { for ($x = 0; $x < $max; $x += 2) { if ($image->get((int)$points[$x], (int)$points[$x + 1])) { // Black(-ish) pixel $bits->set($x / 2, $y); } } } catch (\Exception $aioobe) {//ArrayIndexOutOfBoundsException // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting // transform gets "twisted" such that it maps a straight line of points to a set of points // whose endpoints are in bounds, but others are not. There is probably some mathematical // way to detect this about the transformation that I don't know yet. // This results in an ugly runtime exception despite our clever checks above -- can't have // that. We could check each point's coordinates but that feels duplicative. We settle for // catching and wrapping ArrayIndexOutOfBoundsException. throw NotFoundException::getNotFoundInstance(); } } return $bits; } } Reedsolomon/ReedSolomonDecoder.php 0000777 00000017377 14711036717 0013314 0 ustar 00 <?php /* * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common\Reedsolomon; /** * <p>Implements Reed-Solomon decoding, as the name implies.</p> * * <p>The algorithm will not be explained here, but the following references were helpful * in creating this implementation:</p> * * <ul> * <li>Bruce Maggs. * <a href="http://www.cs.cmu.edu/afs/cs.cmu.edu/project/pscico-guyb/realworld/www/rs_decode.ps"> * "Decoding Reed-Solomon Codes"</a> (see discussion of Forney's Formula)</li> * <li>J.I. Hall. <a href="www.mth.msu.edu/~jhall/classes/codenotes/GRS.pdf"> * "Chapter 5. Generalized Reed-Solomon Codes"</a> * (see discussion of Euclidean algorithm)</li> * </ul> * * <p>Much credit is due to William Rucklidge since portions of this code are an indirect * port of his C++ Reed-Solomon implementation.</p> * * @author Sean Owen * @author William Rucklidge * @author sanfordsquires */ final class ReedSolomonDecoder { private $field; public function __construct($field) { $this->field = $field; } /** * <p>Decodes given set of received codewords, which include both data and error-correction * codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place, * in the input.</p> * * @param received data and error-correction codewords * @param twoS number of error-correction codewords available * * @throws ReedSolomonException if decoding fails for any reason */ public function decode(&$received, $twoS) { $poly = new GenericGFPoly($this->field, $received); $syndromeCoefficients = fill_array(0, $twoS, 0); $noError = true; for ($i = 0; $i < $twoS; $i++) { $eval = $poly->evaluateAt($this->field->exp($i + $this->field->getGeneratorBase())); $syndromeCoefficients[count($syndromeCoefficients) - 1 - $i] = $eval; if ($eval != 0) { $noError = false; } } if ($noError) { return; } $syndrome = new GenericGFPoly($this->field, $syndromeCoefficients); $sigmaOmega = $this->runEuclideanAlgorithm($this->field->buildMonomial($twoS, 1), $syndrome, $twoS); $sigma = $sigmaOmega[0]; $omega = $sigmaOmega[1]; $errorLocations = $this->findErrorLocations($sigma); $errorMagnitudes = $this->findErrorMagnitudes($omega, $errorLocations); $errorLocationsCount = count($errorLocations); for ($i = 0; $i < $errorLocationsCount; $i++) { $position = count($received) - 1 - $this->field->log($errorLocations[$i]); if ($position < 0) { throw new ReedSolomonException("Bad error location"); } $received[$position] = GenericGF::addOrSubtract($received[$position], $errorMagnitudes[$i]); } } private function runEuclideanAlgorithm($a, $b, $R) { // Assume a's degree is >= b's if ($a->getDegree() < $b->getDegree()) { $temp = $a; $a = $b; $b = $temp; } $rLast = $a; $r = $b; $tLast = $this->field->getZero(); $t = $this->field->getOne(); // Run Euclidean algorithm until r's degree is less than R/2 while ($r->getDegree() >= $R / 2) { $rLastLast = $rLast; $tLastLast = $tLast; $rLast = $r; $tLast = $t; // Divide rLastLast by rLast, with quotient in q and remainder in r if ($rLast->isZero()) { // Oops, Euclidean algorithm already terminated? throw new ReedSolomonException("r_{i-1} was zero"); } $r = $rLastLast; $q = $this->field->getZero(); $denominatorLeadingTerm = $rLast->getCoefficient($rLast->getDegree()); $dltInverse = $this->field->inverse($denominatorLeadingTerm); while ($r->getDegree() >= $rLast->getDegree() && !$r->isZero()) { $degreeDiff = $r->getDegree() - $rLast->getDegree(); $scale = $this->field->multiply($r->getCoefficient($r->getDegree()), $dltInverse); $q = $q->addOrSubtract($this->field->buildMonomial($degreeDiff, $scale)); $r = $r->addOrSubtract($rLast->multiplyByMonomial($degreeDiff, $scale)); } $t = $q->multiply($tLast)->addOrSubtract($tLastLast); if ($r->getDegree() >= $rLast->getDegree()) { throw new ReedSolomonException("Division algorithm failed to reduce polynomial?"); } } $sigmaTildeAtZero = $t->getCoefficient(0); if ($sigmaTildeAtZero == 0) { throw new ReedSolomonException("sigmaTilde(0) was zero"); } $inverse = $this->field->inverse($sigmaTildeAtZero); $sigma = $t->multiply($inverse); $omega = $r->multiply($inverse); return [$sigma, $omega]; } private function findErrorLocations($errorLocator) { // This is a direct application of Chien's search $numErrors = $errorLocator->getDegree(); if ($numErrors == 1) { // shortcut return [$errorLocator->getCoefficient(1)]; } $result = fill_array(0, $numErrors, 0); $e = 0; for ($i = 1; $i < $this->field->getSize() && $e < $numErrors; $i++) { if ($errorLocator->evaluateAt($i) == 0) { $result[$e] = $this->field->inverse($i); $e++; } } if ($e != $numErrors) { throw new ReedSolomonException("Error locator degree does not match number of roots"); } return $result; } private function findErrorMagnitudes($errorEvaluator, $errorLocations) { // This is directly applying Forney's Formula $s = count($errorLocations); $result = fill_array(0, $s, 0); for ($i = 0; $i < $s; $i++) { $xiInverse = $this->field->inverse($errorLocations[$i]); $denominator = 1; for ($j = 0; $j < $s; $j++) { if ($i != $j) { //denominator = field.multiply(denominator, // GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse))); // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug. // Below is a funny-looking workaround from Steven Parkes $term = $this->field->multiply($errorLocations[$j], $xiInverse); $termPlus1 = ($term & 0x1) == 0 ? $term | 1 : $term & ~1; $denominator = $this->field->multiply($denominator, $termPlus1); } } $result[$i] = $this->field->multiply($errorEvaluator->evaluateAt($xiInverse), $this->field->inverse($denominator)); if ($this->field->getGeneratorBase() != 0) { $result[$i] = $this->field->multiply($result[$i], $xiInverse); } } return $result; } } Reedsolomon/ReedSolomonException.php 0000777 00000001512 14711036717 0013665 0 ustar 00 <?php /* * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common\Reedsolomon; /** * <p>Thrown when an exception occurs during Reed-Solomon decoding, such as when * there are too many errors to correct.</p> * * @author Sean Owen */ final class ReedSolomonException extends \Exception { } Reedsolomon/GenericGF.php 0000777 00000013141 14711036717 0011352 0 ustar 00 <?php /* * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common\Reedsolomon; /** * <p>This class contains utility methods for performing mathematical operations over * the Galois Fields. Operations use a given primitive polynomial in calculations.</p> * * <p>Throughout this package, elements of the GF are represented as an {@code int} * for convenience and speed (but at the cost of memory). * </p> * * @author Sean Owen * @author David Olivier */ final class GenericGF { public static $AZTEC_DATA_12; public static $AZTEC_DATA_10; public static $AZTEC_DATA_6; public static $AZTEC_PARAM; public static $QR_CODE_FIELD_256; public static $DATA_MATRIX_FIELD_256; public static $AZTEC_DATA_8; public static $MAXICODE_FIELD_64; private $expTable; private $logTable; private $zero; private $one; private $size; private $primitive; private $generatorBase; /** * Create a representation of GF(size) using the given primitive polynomial. * * @param primitive irreducible polynomial whose coefficients are represented by * the bits of an int, where the least-significant bit represents the constant * coefficient * @param size the size of the field * @param b the factor b in the generator polynomial can be 0- or 1-based * (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))). * In most cases it should be 1, but for QR code it is 0. */ public function __construct($primitive, $size, $b) { $this->primitive = $primitive; $this->size = $size; $this->generatorBase = $b; $this->expTable = []; $this->logTable = []; $x = 1; for ($i = 0; $i < $size; $i++) { $this->expTable[$i] = $x; $x *= 2; // we're assuming the generator alpha is 2 if ($x >= $size) { $x ^= $primitive; $x &= $size - 1; } } for ($i = 0; $i < $size - 1; $i++) { $this->logTable[$this->expTable[$i]] = $i; } // logTable[0] == 0 but this should never be used $this->zero = new GenericGFPoly($this, [0]); $this->one = new GenericGFPoly($this, [1]); } public static function Init() { self::$AZTEC_DATA_12 = new GenericGF(0x1069, 4096, 1); // x^12 + x^6 + x^5 + x^3 + 1 self::$AZTEC_DATA_10 = new GenericGF(0x409, 1024, 1); // x^10 + x^3 + 1 self::$AZTEC_DATA_6 = new GenericGF(0x43, 64, 1); // x^6 + x + 1 self::$AZTEC_PARAM = new GenericGF(0x13, 16, 1); // x^4 + x + 1 self::$QR_CODE_FIELD_256 = new GenericGF(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1 self::$DATA_MATRIX_FIELD_256 = new GenericGF(0x012D, 256, 1); // x^8 + x^5 + x^3 + x^2 + 1 self::$AZTEC_DATA_8 = self::$DATA_MATRIX_FIELD_256; self::$MAXICODE_FIELD_64 = self::$AZTEC_DATA_6; } /** * Implements both addition and subtraction -- they are the same in GF(size). * * @return sum/difference of a and b */ public static function addOrSubtract($a, $b) { return $a ^ $b; } public function getZero() { return $this->zero; } public function getOne() { return $this->one; } /** * @return the monomial representing coefficient * x^degree */ public function buildMonomial($degree, $coefficient) { if ($degree < 0) { throw new \InvalidArgumentException(); } if ($coefficient == 0) { return $this->zero; } $coefficients = fill_array(0, $degree + 1, 0);//new int[degree + 1]; $coefficients[0] = $coefficient; return new GenericGFPoly($this, $coefficients); } /** * @return 2 to the power of a in GF(size) */ public function exp($a) { return $this->expTable[$a]; } /** * @return base 2 log of a in GF(size) */ public function log($a) { if ($a == 0) { throw new \InvalidArgumentException(); } return $this->logTable[$a]; } /** * @return multiplicative inverse of a */ public function inverse($a) { if ($a == 0) { throw new \Exception(); } return $this->expTable[$this->size - $this->logTable[$a] - 1]; } /** * @return int product of a and b in GF(size) */ public function multiply($a, $b) { if ($a == 0 || $b == 0) { return 0; } return $this->expTable[($this->logTable[$a] + $this->logTable[$b]) % ($this->size - 1)]; } public function getSize() { return $this->size; } public function getGeneratorBase() { return $this->generatorBase; } // @Override public function toString() { return "GF(0x" . dechex((int)($this->primitive)) . ',' . $this->size . ')'; } } GenericGF::Init(); Reedsolomon/GenericGFPoly.php 0000777 00000023442 14711036717 0012223 0 ustar 00 <?php /* * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common\Reedsolomon; /** * <p>Represents a polynomial whose coefficients are elements of a GF. * Instances of this class are immutable.</p> * * <p>Much credit is due to William Rucklidge since portions of this code are an indirect * port of his C++ Reed-Solomon implementation.</p> * * @author Sean Owen */ final class GenericGFPoly { private $field; private $coefficients; /** * @param field the {@link GenericGF} instance representing the field to use * to perform computations * @param coefficients array coefficients as ints representing elements of GF(size), arranged * from most significant (highest-power term) coefficient to least significant * * @throws InvalidArgumentException if argument is null or empty, * or if leading coefficient is 0 and this is not a * constant polynomial (that is, it is not the monomial "0") */ public function __construct($field, $coefficients) { if (count($coefficients) == 0) { throw new \InvalidArgumentException(); } $this->field = $field; $coefficientsLength = count($coefficients); if ($coefficientsLength > 1 && $coefficients[0] == 0) { // Leading term must be non-zero for anything except the constant polynomial "0" $firstNonZero = 1; while ($firstNonZero < $coefficientsLength && $coefficients[$firstNonZero] == 0) { $firstNonZero++; } if ($firstNonZero == $coefficientsLength) { $this->coefficients = [0]; } else { $this->coefficients = fill_array(0, $coefficientsLength - $firstNonZero, 0); $this->coefficients = arraycopy($coefficients, $firstNonZero, $this->coefficients, 0, count($this->coefficients)); } } else { $this->coefficients = $coefficients; } } public function getCoefficients() { return $this->coefficients; } /** * @return evaluation of this polynomial at a given point */ public function evaluateAt($a) { if ($a == 0) { // Just return the x^0 coefficient return $this->getCoefficient(0); } $size = count($this->coefficients); if ($a == 1) { // Just the sum of the coefficients $result = 0; foreach ($this->coefficients as $coefficient) { $result = GenericGF::addOrSubtract($result, $coefficient); } return $result; } $result = $this->coefficients[0]; for ($i = 1; $i < $size; $i++) { $result = GenericGF::addOrSubtract($this->field->multiply($a, $result), $this->coefficients[$i]); } return $result; } /** * @return coefficient of x^degree term in this polynomial */ public function getCoefficient($degree) { return $this->coefficients[count($this->coefficients) - 1 - $degree]; } public function multiply($other) { if (is_int($other)) { return $this->multiply_($other); } if ($this->field !== $other->field) { throw new \InvalidArgumentException("GenericGFPolys do not have same GenericGF field"); } if ($this->isZero() || $other->isZero()) { return $this->field->getZero(); } $aCoefficients = $this->coefficients; $aLength = count($aCoefficients); $bCoefficients = $other->coefficients; $bLength = count($bCoefficients); $product = fill_array(0, $aLength + $bLength - 1, 0); for ($i = 0; $i < $aLength; $i++) { $aCoeff = $aCoefficients[$i]; for ($j = 0; $j < $bLength; $j++) { $product[$i + $j] = GenericGF::addOrSubtract($product[$i + $j], $this->field->multiply($aCoeff, $bCoefficients[$j])); } } return new GenericGFPoly($this->field, $product); } public function multiply_($scalar) { if ($scalar == 0) { return $this->field->getZero(); } if ($scalar == 1) { return $this; } $size = count($this->coefficients); $product = fill_array(0, $size, 0); for ($i = 0; $i < $size; $i++) { $product[$i] = $this->field->multiply($this->coefficients[$i], $scalar); } return new GenericGFPoly($this->field, $product); } /** * @return true iff this polynomial is the monomial "0" */ public function isZero() { return $this->coefficients[0] == 0; } public function multiplyByMonomial($degree, $coefficient) { if ($degree < 0) { throw new \InvalidArgumentException(); } if ($coefficient == 0) { return $this->field->getZero(); } $size = count($this->coefficients); $product = fill_array(0, $size + $degree, 0); for ($i = 0; $i < $size; $i++) { $product[$i] = $this->field->multiply($this->coefficients[$i], $coefficient); } return new GenericGFPoly($this->field, $product); } public function divide($other) { if ($this->field !== $other->field) { throw new \InvalidArgumentException("GenericGFPolys do not have same GenericGF field"); } if ($other->isZero()) { throw new \InvalidArgumentException("Divide by 0"); } $quotient = $this->field->getZero(); $remainder = $this; $denominatorLeadingTerm = $other->getCoefficient($other->getDegree()); $inverseDenominatorLeadingTerm = $this->field->inverse($denominatorLeadingTerm); while ($remainder->getDegree() >= $other->getDegree() && !$remainder->isZero()) { $degreeDifference = $remainder->getDegree() - $other->getDegree(); $scale = $this->field->multiply($remainder->getCoefficient($remainder->getDegree()), $inverseDenominatorLeadingTerm); $term = $other->multiplyByMonomial($degreeDifference, $scale); $iterationQuotient = $this->field->buildMonomial($degreeDifference, $scale); $quotient = $quotient->addOrSubtract($iterationQuotient); $remainder = $remainder->addOrSubtract($term); } return [$quotient, $remainder]; } /** * @return degree of this polynomial */ public function getDegree() { return count($this->coefficients) - 1; } public function addOrSubtract($other) { if ($this->field !== $other->field) { throw new \InvalidArgumentException("GenericGFPolys do not have same GenericGF field"); } if ($this->isZero()) { return $other; } if ($other->isZero()) { return $this; } $smallerCoefficients = $this->coefficients; $largerCoefficients = $other->coefficients; if (count($smallerCoefficients) > count($largerCoefficients)) { $temp = $smallerCoefficients; $smallerCoefficients = $largerCoefficients; $largerCoefficients = $temp; } $sumDiff = fill_array(0, count($largerCoefficients), 0); $lengthDiff = count($largerCoefficients) - count($smallerCoefficients); // Copy high-order terms only found in higher-degree polynomial's coefficients $sumDiff = arraycopy($largerCoefficients, 0, $sumDiff, 0, $lengthDiff); $countLargerCoefficients = count($largerCoefficients); for ($i = $lengthDiff; $i < $countLargerCoefficients; $i++) { $sumDiff[$i] = GenericGF::addOrSubtract($smallerCoefficients[$i - $lengthDiff], $largerCoefficients[$i]); } return new GenericGFPoly($this->field, $sumDiff); } //@Override public function toString() { $result = ''; for ($degree = $this->getDegree(); $degree >= 0; $degree--) { $coefficient = $this->getCoefficient($degree); if ($coefficient != 0) { if ($coefficient < 0) { $result .= " - "; $coefficient = -$coefficient; } else { if (strlen($result) > 0) { $result .= " + "; } } if ($degree == 0 || $coefficient != 1) { $alphaPower = $this->field->log($coefficient); if ($alphaPower == 0) { $result .= '1'; } else if ($alphaPower == 1) { $result .= 'a'; } else { $result .= "a^"; $result .= ($alphaPower); } } if ($degree != 0) { if ($degree == 1) { $result .= 'x'; } else { $result .= "x^"; $result .= $degree; } } } } return $result; } } HybridBinarizer.php 0000777 00000025573 14711036717 0010376 0 ustar 00 <?php /* * Copyright 2009 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common; use Zxing\Binarizer; use Zxing\LuminanceSource; use Zxing\NotFoundException; /** * This class implements a local thresholding algorithm, which while slower than the * GlobalHistogramBinarizer, is fairly efficient for what it does. It is designed for * high frequency images of barcodes with black data on white backgrounds. For this application, * it does a much better job than a global blackpoint with severe shadows and gradients. * However it tends to produce artifacts on lower frequency images and is therefore not * a good general purpose binarizer for uses outside ZXing. * * This class extends GlobalHistogramBinarizer, using the older histogram approach for 1D readers, * and the newer local approach for 2D readers. 1D decoding using a per-row histogram is already * inherently local, and only fails for horizontal gradients. We can revisit that problem later, * but for now it was not a win to use local blocks for 1D. * * This Binarizer is the default for the unit tests and the recommended class for library users. * * @author dswitkin@google.com (Daniel Switkin) */ final class HybridBinarizer extends GlobalHistogramBinarizer { // 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 static $BLOCK_SIZE_POWER = 3; private static $BLOCK_SIZE = 8; // ...0100...00 private static $BLOCK_SIZE_MASK = 7; // ...0011...11 private static $MINIMUM_DIMENSION = 40; private static $MIN_DYNAMIC_RANGE = 24; private $matrix; public function __construct($source) { parent::__construct($source); self::$BLOCK_SIZE_POWER = 3; self::$BLOCK_SIZE = 1 << self::$BLOCK_SIZE_POWER; // ...0100...00 self::$BLOCK_SIZE_MASK = self::$BLOCK_SIZE - 1; // ...0011...11 self::$MINIMUM_DIMENSION = self::$BLOCK_SIZE * 5; self::$MIN_DYNAMIC_RANGE = 24; } /** * Calculates the final BitMatrix once for all requests. This could be called once from the * constructor instead, but there are some advantages to doing it lazily, such as making * profiling easier, and not doing heavy lifting when callers don't expect it. */ public function getBlackMatrix() { if ($this->matrix !== null) { return $this->matrix; } $source = $this->getLuminanceSource(); $width = $source->getWidth(); $height = $source->getHeight(); if ($width >= self::$MINIMUM_DIMENSION && $height >= self::$MINIMUM_DIMENSION) { $luminances = $source->getMatrix(); $subWidth = $width >> self::$BLOCK_SIZE_POWER; if (($width & self::$BLOCK_SIZE_MASK) != 0) { $subWidth++; } $subHeight = $height >> self::$BLOCK_SIZE_POWER; if (($height & self::$BLOCK_SIZE_MASK) != 0) { $subHeight++; } $blackPoints = self::calculateBlackPoints($luminances, $subWidth, $subHeight, $width, $height); $newMatrix = new BitMatrix($width, $height); self::calculateThresholdForBlock($luminances, $subWidth, $subHeight, $width, $height, $blackPoints, $newMatrix); $this->matrix = $newMatrix; } else { // If the image is too small, fall back to the global histogram approach. $this->matrix = parent::getBlackMatrix(); } return $this->matrix; } /** * Calculates a single black point for each block of pixels and saves it away. * See the following thread for a discussion of this algorithm: * http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0 */ private static function calculateBlackPoints( $luminances, $subWidth, $subHeight, $width, $height ) { $blackPoints = fill_array(0, $subHeight, 0); foreach ($blackPoints as $key => $point) { $blackPoints[$key] = fill_array(0, $subWidth, 0); } for ($y = 0; $y < $subHeight; $y++) { $yoffset = ($y << self::$BLOCK_SIZE_POWER); $maxYOffset = $height - self::$BLOCK_SIZE; if ($yoffset > $maxYOffset) { $yoffset = $maxYOffset; } for ($x = 0; $x < $subWidth; $x++) { $xoffset = ($x << self::$BLOCK_SIZE_POWER); $maxXOffset = $width - self::$BLOCK_SIZE; if ($xoffset > $maxXOffset) { $xoffset = $maxXOffset; } $sum = 0; $min = 0xFF; $max = 0; 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); $sum += $pixel; // still looking for good contrast if ($pixel < $min) { $min = $pixel; } if ($pixel > $max) { $max = $pixel; } } // short-circuit min/max tests once dynamic range is met if ($max - $min > self::$MIN_DYNAMIC_RANGE) { // 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 += ($luminances[$offset + $xx] & 0xFF); } } } } // The default estimate is the average of the values in the block. $average = ($sum >> (self::$BLOCK_SIZE_POWER * 2)); if ($max - $min <= self::$MIN_DYNAMIC_RANGE) { // If variation within the block is low, assume this is a block with only light or only // dark pixels. In that case we do not want to use the average, as it would divide this // low contrast area into black and white pixels, essentially creating data out of noise. // // The default assumption is that the block is light/background. Since no estimate for // the level of dark pixels exists locally, use half the min for the block. $average = (int)($min / 2); if ($y > 0 && $x > 0) { // Correct the "white background" assumption for blocks that have neighbors by comparing // the pixels in this block to the previously calculated black points. This is based on // the fact that dark barcode symbology is always surrounded by some amount of light // background for which reasonable black point estimates were made. The bp estimated at // 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); if ($min < $averageNeighborBlackPoint) { $average = $averageNeighborBlackPoint; } } } $blackPoints[$y][$x] = (int)($average); } } return $blackPoints; } /** * For each block in the image, calculate the average black point using a 5x5 grid * 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 static function calculateThresholdForBlock( $luminances, $subWidth, $subHeight, $width, $height, $blackPoints, $matrix ) { for ($y = 0; $y < $subHeight; $y++) { $yoffset = ($y << self::$BLOCK_SIZE_POWER); $maxYOffset = $height - self::$BLOCK_SIZE; if ($yoffset > $maxYOffset) { $yoffset = $maxYOffset; } for ($x = 0; $x < $subWidth; $x++) { $xoffset = ($x << self::$BLOCK_SIZE_POWER); $maxXOffset = $width - self::$BLOCK_SIZE; if ($xoffset > $maxXOffset) { $xoffset = $maxXOffset; } $left = self::cap($x, 2, $subWidth - 3); $top = self::cap($y, 2, $subHeight - 3); $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]; } $average = (int)($sum / 25); self::thresholdBlock($luminances, $xoffset, $yoffset, $average, $width, $matrix); } } } private static function cap($value, $min, $max) { if ($value < $min) { return $min; } elseif ($value > $max) { return $max; } else { return $value; } } /** * Applies a single threshold to a block of pixels. */ private static function thresholdBlock( $luminances, $xoffset, $yoffset, $threshold, $stride, $matrix ) { for ($y = 0, $offset = $yoffset * $stride + $xoffset; $y < self::$BLOCK_SIZE; $y++, $offset += $stride) { for ($x = 0; $x < self::$BLOCK_SIZE; $x++) { // Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0. if (($luminances[$offset + $x] & 0xFF) <= $threshold) { $matrix->set($xoffset + $x, $yoffset + $y); } } } } public function createBinarizer($source) { return new HybridBinarizer($source); } } GlobalHistogramBinarizer.php 0000777 00000016505 14711036717 0012226 0 ustar 00 <?php /* * Copyright 2009 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common; use Zxing\Binarizer; use Zxing\LuminanceSource; use Zxing\NotFoundException; /** * This Binarizer implementation uses the old ZXing global histogram approach. It is suitable * for low-end mobile devices which don't have enough CPU or memory to use a local thresholding * algorithm. However, because it picks a global black point, it cannot handle difficult shadows * and gradients. * * Faster mobile devices and all desktop applications should probably use HybridBinarizer instead. * * @author dswitkin@google.com (Daniel Switkin) * @author Sean Owen */ class GlobalHistogramBinarizer extends Binarizer { private static $LUMINANCE_BITS = 5; private static $LUMINANCE_SHIFT = 3; private static $LUMINANCE_BUCKETS = 32; private static $EMPTY = []; private $luminances = []; private $buckets = []; private $source = []; public function __construct($source) { self::$LUMINANCE_SHIFT = 8 - self::$LUMINANCE_BITS; self::$LUMINANCE_BUCKETS = 1 << self::$LUMINANCE_BITS; parent::__construct($source); $this->luminances = self::$EMPTY; $this->buckets = fill_array(0, self::$LUMINANCE_BUCKETS, 0); $this->source = $source; } // Applies simple sharpening to the row data to improve performance of the 1D Readers. public function getBlackRow($y, $row = null) { $this->source = $this->getLuminanceSource(); $width = $this->source->getWidth(); if ($row == null || $row->getSize() < $width) { $row = new BitArray($width); } else { $row->clear(); } $this->initArrays($width); $localLuminances = $this->source->getRow($y, $this->luminances); $localBuckets = $this->buckets; for ($x = 0; $x < $width; $x++) { $pixel = $localLuminances[$x] & 0xff; $localBuckets[$pixel >> self::$LUMINANCE_SHIFT]++; } $blackPoint = self::estimateBlackPoint($localBuckets); $left = $localLuminances[0] & 0xff; $center = $localLuminances[1] & 0xff; for ($x = 1; $x < $width - 1; $x++) { $right = $localLuminances[$x + 1] & 0xff; // A simple -1 4 -1 box filter with a weight of 2. $luminance = (($center * 4) - $left - $right) / 2; if ($luminance < $blackPoint) { $row->set($x); } $left = $center; $center = $right; } return $row; } // Does not sharpen the data, as this call is intended to only be used by 2D Readers. private function initArrays($luminanceSize) { if (count($this->luminances) < $luminanceSize) { $this->luminances = []; } for ($x = 0; $x < self::$LUMINANCE_BUCKETS; $x++) { $this->buckets[$x] = 0; } } private static function estimateBlackPoint($buckets) { // Find the tallest peak in the histogram. $numBuckets = count($buckets); $maxBucketCount = 0; $firstPeak = 0; $firstPeakSize = 0; for ($x = 0; $x < $numBuckets; $x++) { if ($buckets[$x] > $firstPeakSize) { $firstPeak = $x; $firstPeakSize = $buckets[$x]; } if ($buckets[$x] > $maxBucketCount) { $maxBucketCount = $buckets[$x]; } } // Find the second-tallest peak which is somewhat far from the tallest peak. $secondPeak = 0; $secondPeakScore = 0; for ($x = 0; $x < $numBuckets; $x++) { $distanceToBiggest = $x - $firstPeak; // Encourage more distant second peaks by multiplying by square of distance. $score = $buckets[$x] * $distanceToBiggest * $distanceToBiggest; if ($score > $secondPeakScore) { $secondPeak = $x; $secondPeakScore = $score; } } // Make sure firstPeak corresponds to the black peak. if ($firstPeak > $secondPeak) { $temp = $firstPeak; $firstPeak = $secondPeak; $secondPeak = $temp; } // If there is too little contrast in the image to pick a meaningful black point, throw rather // than waste time trying to decode the image, and risk false positives. if ($secondPeak - $firstPeak <= $numBuckets / 16) { throw NotFoundException::getNotFoundInstance(); } // Find a valley between them that is low and closer to the white peak. $bestValley = $secondPeak - 1; $bestValleyScore = -1; for ($x = $secondPeak - 1; $x > $firstPeak; $x--) { $fromFirst = $x - $firstPeak; $score = $fromFirst * $fromFirst * ($secondPeak - $x) * ($maxBucketCount - $buckets[$x]); if ($score > $bestValleyScore) { $bestValley = $x; $bestValleyScore = $score; } } return ($bestValley << self::$LUMINANCE_SHIFT); } public function getBlackMatrix() { $source = $this->getLuminanceSource(); $width = $source->getWidth(); $height = $source->getHeight(); $matrix = new BitMatrix($width, $height); // Quickly calculates the histogram by sampling four rows from the image. This proved to be // more robust on the blackbox tests than sampling a diagonal as we used to do. $this->initArrays($width); $localBuckets = $this->buckets; for ($y = 1; $y < 5; $y++) { $row = (int)($height * $y / 5); $localLuminances = $source->getRow($row, $this->luminances); $right = (int)(($width * 4) / 5); for ($x = (int)($width / 5); $x < $right; $x++) { $pixel = ($localLuminances[(int)($x)] & 0xff); $localBuckets[($pixel >> self::$LUMINANCE_SHIFT)]++; } } $blackPoint = self::estimateBlackPoint($localBuckets); // 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 = $source->getMatrix(); for ($y = 0; $y < $height; $y++) { $offset = $y * $width; for ($x = 0; $x < $width; $x++) { $pixel = (int)($localLuminances[$offset + $x] & 0xff); if ($pixel < $blackPoint) { $matrix->set($x, $y); } } } return $matrix; } public function createBinarizer($source) { return new GlobalHistogramBinarizer($source); } } BitArray.php 0000777 00000031470 14711036717 0007015 0 ustar 00 <?php /** * Created by PhpStorm. * User: Ashot * Date: 3/25/15 * Time: 11:51 */ /* * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common; /** * <p>A simple, fast array of bits, represented compactly by an array of ints internally.</p> * * @author Sean Owen */ final class BitArray { private $bits; private $size; public function __construct($bits = [], $size = 0) { if (!$bits && !$size) { $this->$size = 0; $this->bits = []; } elseif ($bits && !$size) { $this->size = $bits; $this->bits = $this->makeArray($bits); } else { $this->bits = $bits; $this->size = $size; } } private static function makeArray($size) { return []; } public function getSize() { return $this->size; } public function getSizeInBytes() { return ($this->size + 7) / 8; } /** * Sets bit i. * * @param i bit to set */ public function set($i) { $this->bits[(int)($i / 32)] |= 1 << ($i & 0x1F); $this->bits[(int)($i / 32)] = ($this->bits[(int)($i / 32)]); } /** * Flips bit i. * * @param i bit to set */ public function flip($i) { $this->bits[(int)($i / 32)] ^= 1 << ($i & 0x1F); $this->bits[(int)($i / 32)] = ($this->bits[(int)($i / 32)]); } /** * @param from first bit to check * * @return index of first bit that is set, starting from the given index, or size if none are set * at or beyond this given index * @see #getNextUnset(int) */ public function getNextSet($from) { if ($from >= $this->size) { return $this->size; } $bitsOffset = (int)($from / 32); $currentBits = (int)$this->bits[$bitsOffset]; // mask off lesser bits first $currentBits &= ~((1 << ($from & 0x1F)) - 1); while ($currentBits == 0) { if (++$bitsOffset == count($this->bits)) { return $this->size; } $currentBits = $this->bits[$bitsOffset]; } $result = ($bitsOffset * 32) + numberOfTrailingZeros($currentBits); //numberOfTrailingZeros return $result > $this->size ? $this->size : $result; } /** * @param from index to start looking for unset bit * * @return index of next unset bit, or {@code size} if none are unset until the end * @see #getNextSet(int) */ public function getNextUnset($from) { if ($from >= $this->size) { return $this->size; } $bitsOffset = (int)($from / 32); $currentBits = ~$this->bits[$bitsOffset]; // mask off lesser bits first $currentBits &= ~((1 << ($from & 0x1F)) - 1); while ($currentBits == 0) { if (++$bitsOffset == count($this->bits)) { return $this->size; } $currentBits = (~$this->bits[$bitsOffset]); } $result = ($bitsOffset * 32) + numberOfTrailingZeros($currentBits); return $result > $this->size ? $this->size : $result; } /** * Sets a block of 32 bits, starting at bit i. * * @param i first bit to set * @param newBits the new value of the next 32 bits. Note again that the least-significant bit * corresponds to bit i, the next-least-significant to i+1, and so on. */ public function setBulk($i, $newBits) { $this->bits[(int)($i / 32)] = $newBits; } /** * Sets a range of bits. * * @param start start of range, inclusive. * @param end end of range, exclusive */ public function setRange($start, $end) { if ($end < $start) { throw new \InvalidArgumentException(); } if ($end == $start) { return; } $end--; // will be easier to treat this as the last actually set bit -- inclusive $firstInt = (int)($start / 32); $lastInt = (int)($end / 32); for ($i = $firstInt; $i <= $lastInt; $i++) { $firstBit = $i > $firstInt ? 0 : $start & 0x1F; $lastBit = $i < $lastInt ? 31 : $end & 0x1F; $mask = 0; if ($firstBit == 0 && $lastBit == 31) { $mask = -1; } else { $mask = 0; for ($j = $firstBit; $j <= $lastBit; $j++) { $mask |= 1 << $j; } } $this->bits[$i] = ($this->bits[$i] | $mask); } } /** * Clears all bits (sets to false). */ public function clear() { $max = count($this->bits); for ($i = 0; $i < $max; $i++) { $this->bits[$i] = 0; } } /** * Efficient method to check if a range of bits is set, or not set. * * @param start start of range, inclusive. * @param end end of range, exclusive * @param value if true, checks that bits in range are set, otherwise checks that they are not set * * @return true iff all bits are set or not set in range, according to value argument * @throws InvalidArgumentException if end is less than or equal to start */ public function isRange($start, $end, $value) { if ($end < $start) { throw new \InvalidArgumentException(); } if ($end == $start) { return true; // empty range matches } $end--; // will be easier to treat this as the last actually set bit -- inclusive $firstInt = (int)($start / 32); $lastInt = (int)($end / 32); for ($i = $firstInt; $i <= $lastInt; $i++) { $firstBit = $i > $firstInt ? 0 : $start & 0x1F; $lastBit = $i < $lastInt ? 31 : $end & 0x1F; $mask = 0; if ($firstBit == 0 && $lastBit == 31) { $mask = -1; } else { $mask = 0; for ($j = $firstBit; $j <= $lastBit; $j++) { $mask = ($mask | (1 << $j)); } } // Return false if we're looking for 1s and the masked bits[i] isn't all 1s (that is, // equals the mask, or we're looking for 0s and the masked portion is not all 0s if (($this->bits[$i] & $mask) != ($value ? $mask : 0)) { return false; } } return true; } /** * Appends the least-significant bits, from value, in order from most-significant to * least-significant. For example, appending 6 bits from 0x000001E will append the bits * 0, 1, 1, 1, 1, 0 in that order. * * @param value {@code int} containing bits to append * @param numBits bits from value to append */ public function appendBits($value, $numBits) { if ($numBits < 0 || $numBits > 32) { throw new \InvalidArgumentException("Num bits must be between 0 and 32"); } $this->ensureCapacity($this->size + $numBits); for ($numBitsLeft = $numBits; $numBitsLeft > 0; $numBitsLeft--) { $this->appendBit((($value >> ($numBitsLeft - 1)) & 0x01) == 1); } } private function ensureCapacity($size) { if ($size > count($this->bits) * 32) { $newBits = $this->makeArray($size); $newBits = arraycopy($this->bits, 0, $newBits, 0, count($this->bits)); $this->bits = $newBits; } } public function appendBit($bit) { $this->ensureCapacity($this->size + 1); if ($bit) { $this->bits[(int)($this->size / 32)] |= 1 << ($this->size & 0x1F); } $this->size++; } public function appendBitArray($other) { $otherSize = $other->size; $this->ensureCapacity($this->size + $otherSize); for ($i = 0; $i < $otherSize; $i++) { $this->appendBit($other->get($i)); } } public function _xor($other) { if (count($this->bits) !== count($other->bits)) { throw new \InvalidArgumentException("Sizes don't match"); } $count = count($this->bits); for ($i = 0; $i < $count; $i++) { // The last byte could be incomplete (i.e. not have 8 bits in // it) but there is no problem since 0 XOR 0 == 0. $this->bits[$i] ^= $other->bits[$i]; } } /** * * @param bitOffset first bit to start writing * @param array array to write into. Bytes are written most-significant byte first. This is the opposite * of the internal representation, which is exposed by {@link #getBitArray()} * @param offset position in array to start writing * @param numBytes how many bytes to write */ public function toBytes($bitOffset, &$array, $offset, $numBytes) { for ($i = 0; $i < $numBytes; $i++) { $theByte = 0; for ($j = 0; $j < 8; $j++) { if ($this->get($bitOffset)) { $theByte |= 1 << (7 - $j); } $bitOffset++; } $array[(int)($offset + $i)] = $theByte; } } /** * @param $i ; bit to get * * @return true iff bit i is set */ public function get($i) { $key = (int)($i / 32); return ($this->bits[$key] & (1 << ($i & 0x1F))) != 0; } /** * @return array underlying array of ints. The first element holds the first 32 bits, and the least * significant bit is bit 0. */ public function getBitArray() { return $this->bits; } /** * Reverses all bits in the array. */ public function reverse() { $newBits = []; // reverse all int's first $len = (($this->size - 1) / 32); $oldBitsLen = $len + 1; for ($i = 0; $i < $oldBitsLen; $i++) { $x = $this->bits[$i];/* $x = (($x >> 1) & 0x55555555L) | (($x & 0x55555555L) << 1); $x = (($x >> 2) & 0x33333333L) | (($x & 0x33333333L) << 2); $x = (($x >> 4) & 0x0f0f0f0fL) | (($x & 0x0f0f0f0fL) << 4); $x = (($x >> 8) & 0x00ff00ffL) | (($x & 0x00ff00ffL) << 8); $x = (($x >> 16) & 0x0000ffffL) | (($x & 0x0000ffffL) << 16);*/ $x = (($x >> 1) & 0x55555555) | (($x & 0x55555555) << 1); $x = (($x >> 2) & 0x33333333) | (($x & 0x33333333) << 2); $x = (($x >> 4) & 0x0f0f0f0f) | (($x & 0x0f0f0f0f) << 4); $x = (($x >> 8) & 0x00ff00ff) | (($x & 0x00ff00ff) << 8); $x = (($x >> 16) & 0x0000ffff) | (($x & 0x0000ffff) << 16); $newBits[(int)$len - $i] = (int)$x; } // now correct the int's if the bit size isn't a multiple of 32 if ($this->size != $oldBitsLen * 32) { $leftOffset = $oldBitsLen * 32 - $this->size; $mask = 1; for ($i = 0; $i < 31 - $leftOffset; $i++) { $mask = ($mask << 1) | 1; } $currentInt = ($newBits[0] >> $leftOffset) & $mask; for ($i = 1; $i < $oldBitsLen; $i++) { $nextInt = $newBits[$i]; $currentInt |= $nextInt << (32 - $leftOffset); $newBits[(int)($i) - 1] = $currentInt; $currentInt = ($nextInt >> $leftOffset) & $mask; } $newBits[(int)($oldBitsLen) - 1] = $currentInt; } // $bits = $newBits; } public function equals($o) { if (!($o instanceof BitArray)) { return false; } $other = $o; return $this->size == $other->size && $this->bits === $other->bits; } public function hashCode() { return 31 * $this->size + hashCode($this->bits); } public function toString() { $result = ''; for ($i = 0; $i < $this->size; $i++) { if (($i & 0x07) == 0) { $result .= ' '; } $result .= ($this->get($i) ? 'X' : '.'); } return (string)$result; } public function _clone() { return new BitArray($this->bits, $this->size); } } PerspectiveTransform.php 0000777 00000013752 14711036717 0011470 0 ustar 00 <?php /* * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common; /** * <p>This class implements a perspective transform in two dimensions. Given four source and four * destination points, it will compute the transformation implied between them. The code is based * directly upon section 3.4.2 of George Wolberg's "Digital Image Warping"; see pages 54-56.</p> * * @author Sean Owen */ final class PerspectiveTransform { private $a11; private $a12; private $a13; private $a21; private $a22; private $a23; private $a31; private $a32; private $a33; private function __construct( $a11, $a21, $a31, $a12, $a22, $a32, $a13, $a23, $a33 ) { $this->a11 = $a11; $this->a12 = $a12; $this->a13 = $a13; $this->a21 = $a21; $this->a22 = $a22; $this->a23 = $a23; $this->a31 = $a31; $this->a32 = $a32; $this->a33 = $a33; } public static function quadrilateralToQuadrilateral( $x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3, $x0p, $y0p, $x1p, $y1p, $x2p, $y2p, $x3p, $y3p ) { $qToS = self::quadrilateralToSquare($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3); $sToQ = self::squareToQuadrilateral($x0p, $y0p, $x1p, $y1p, $x2p, $y2p, $x3p, $y3p); return $sToQ->times($qToS); } public static function quadrilateralToSquare( $x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3 ) { // Here, the adjoint serves as the inverse: return self::squareToQuadrilateral($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3)->buildAdjoint(); } public function buildAdjoint() { // Adjoint is the transpose of the cofactor matrix: return new PerspectiveTransform($this->a22 * $this->a33 - $this->a23 * $this->a32, $this->a23 * $this->a31 - $this->a21 * $this->a33, $this->a21 * $this->a32 - $this->a22 * $this->a31, $this->a13 * $this->a32 - $this->a12 * $this->a33, $this->a11 * $this->a33 - $this->a13 * $this->a31, $this->a12 * $this->a31 - $this->a11 * $this->a32, $this->a12 * $this->a23 - $this->a13 * $this->a22, $this->a13 * $this->a21 - $this->a11 * $this->a23, $this->a11 * $this->a22 - $this->a12 * $this->a21); } public static function squareToQuadrilateral( $x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3 ) { $dx3 = $x0 - $x1 + $x2 - $x3; $dy3 = $y0 - $y1 + $y2 - $y3; if ($dx3 == 0.0 && $dy3 == 0.0) { // Affine return new PerspectiveTransform($x1 - $x0, $x2 - $x1, $x0, $y1 - $y0, $y2 - $y1, $y0, 0.0, 0.0, 1.0); } else { $dx1 = $x1 - $x2; $dx2 = $x3 - $x2; $dy1 = $y1 - $y2; $dy2 = $y3 - $y2; $denominator = $dx1 * $dy2 - $dx2 * $dy1; $a13 = ($dx3 * $dy2 - $dx2 * $dy3) / $denominator; $a23 = ($dx1 * $dy3 - $dx3 * $dy1) / $denominator; return new PerspectiveTransform($x1 - $x0 + $a13 * $x1, $x3 - $x0 + $a23 * $x3, $x0, $y1 - $y0 + $a13 * $y1, $y3 - $y0 + $a23 * $y3, $y0, $a13, $a23, 1.0); } } public function times($other) { return new PerspectiveTransform($this->a11 * $other->a11 + $this->a21 * $other->a12 + $this->a31 * $other->a13, $this->a11 * $other->a21 + $this->a21 * $other->a22 + $this->a31 * $other->a23, $this->a11 * $other->a31 + $this->a21 * $other->a32 + $this->a31 * $other->a33, $this->a12 * $other->a11 + $this->a22 * $other->a12 + $this->a32 * $other->a13, $this->a12 * $other->a21 + $this->a22 * $other->a22 + $this->a32 * $other->a23, $this->a12 * $other->a31 + $this->a22 * $other->a32 + $this->a32 * $other->a33, $this->a13 * $other->a11 + $this->a23 * $other->a12 + $this->a33 * $other->a13, $this->a13 * $other->a21 + $this->a23 * $other->a22 + $this->a33 * $other->a23, $this->a13 * $other->a31 + $this->a23 * $other->a32 + $this->a33 * $other->a33); } public function transformPoints(&$points, &$yValues = 0) { if ($yValues) { $this->transformPoints_($points, $yValues); return; } $max = count($points); $a11 = $this->a11; $a12 = $this->a12; $a13 = $this->a13; $a21 = $this->a21; $a22 = $this->a22; $a23 = $this->a23; $a31 = $this->a31; $a32 = $this->a32; $a33 = $this->a33; for ($i = 0; $i < $max; $i += 2) { $x = $points[$i]; $y = $points[$i + 1]; $denominator = $a13 * $x + $a23 * $y + $a33; $points[$i] = ($a11 * $x + $a21 * $y + $a31) / $denominator; $points[$i + 1] = ($a12 * $x + $a22 * $y + $a32) / $denominator; } } public function transformPoints_(&$xValues, &$yValues) { $n = count($xValues); for ($i = 0; $i < $n; $i++) { $x = $xValues[$i]; $y = $yValues[$i]; $denominator = $this->a13 * $x + $this->a23 * $y + $this->a33; $xValues[$i] = ($this->a11 * $x + $this->a21 * $y + $this->a31) / $denominator; $yValues[$i] = ($this->a12 * $x + $this->a22 * $y + $this->a32) / $denominator; } } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка