/**
  * <p>Convenience method that can decode a QR Code represented as a 2D array of booleans.
  * "true" is taken to mean a black module.</p>
  *
  * @param image booleans representing white/black QR Code modules
  * @param hints decoding hints that should be used to influence decoding
  * @return text and bytes encoded within the QR Code
  * @throws FormatException if the QR Code cannot be decoded
  * @throws ChecksumException if error correction fails
  */
 public function decodeImage($image, $hints = null)
 {
     $dimension = count($image);
     $bits = new BitMatrix($dimension);
     for ($i = 0; $i < $dimension; $i++) {
         for ($j = 0; $j < $dimension; $j++) {
             if ($image[$i][$j]) {
                 $bits->set($j, $i);
             }
         }
     }
     return $this->decode($bits, $hints);
 }
 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 = (double) $y + 0.5;
         for ($x = 0; $x < $max; $x += 2) {
             $points[$x] = (double) ($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;
 }
 /**
  * This method detects a code in a "pure" image -- that is, pure monochrome image
  * which contains only an unrotated, unskewed, image of a code, with some white border
  * around it. This is a specialized method that works exceptionally fast in this special
  * case.
  *
  * @see com.google.zxing.datamatrix.DataMatrixReader#extractPureBits(BitMatrix)
  */
 private static function extractPureBits($image)
 {
     $leftTopBlack = $image->getTopLeftOnBit();
     $rightBottomBlack = $image->getBottomRightOnBit();
     if ($leftTopBlack == null || $rightBottomBlack == null) {
         throw NotFoundException::getNotFoundInstance();
     }
     $moduleSize = self::moduleSize($leftTopBlack, $image);
     $top = $leftTopBlack[1];
     $bottom = $rightBottomBlack[1];
     $left = $leftTopBlack[0];
     $right = $rightBottomBlack[0];
     // Sanity check!
     if ($left >= $right || $top >= $bottom) {
         throw NotFoundException::getNotFoundInstance();
     }
     if ($bottom - $top != $right - $left) {
         // Special case, where bottom-right module wasn't black so we found something else in the last row
         // Assume it's a square, so use height as the width
         $right = $left + ($bottom - $top);
     }
     $matrixWidth = round(($right - $left + 1) / $moduleSize);
     $matrixHeight = round(($bottom - $top + 1) / $moduleSize);
     if ($matrixWidth <= 0 || $matrixHeight <= 0) {
         throw NotFoundException::getNotFoundInstance();
     }
     if ($matrixHeight != $matrixWidth) {
         // Only possibly decode square regions
         throw NotFoundException::getNotFoundInstance();
     }
     // Push in the "border" by half the module width so that we start
     // sampling in the middle of the module. Just in case the image is a
     // little off, this will help recover.
     $nudge = (int) ($moduleSize / 2.0);
     // $nudge = (int) ($moduleSize / 2.0f);
     $top += $nudge;
     $left += $nudge;
     // But careful that this does not sample off the edge
     // "right" is the farthest-right valid pixel location -- right+1 is not necessarily
     // This is positive by how much the inner x loop below would be too large
     $nudgedTooFarRight = $left + (int) (($matrixWidth - 1) * $moduleSize) - $right;
     if ($nudgedTooFarRight > 0) {
         if ($nudgedTooFarRight > $nudge) {
             // Neither way fits; abort
             throw NotFoundException::getNotFoundInstance();
         }
         $left -= $nudgedTooFarRight;
     }
     // See logic above
     $nudgedTooFarDown = $top + (int) (($matrixHeight - 1) * $moduleSize) - $bottom;
     if ($nudgedTooFarDown > 0) {
         if ($nudgedTooFarDown > $nudge) {
             // Neither way fits; abort
             throw NotFoundException::getNotFoundInstance();
         }
         $top -= $nudgedTooFarDown;
     }
     // Now just read off the bits
     $bits = new BitMatrix($matrixWidth, $matrixHeight);
     for ($y = 0; $y < $matrixHeight; $y++) {
         $iOffset = $top + (int) ($y * $moduleSize);
         for ($x = 0; $x < $matrixWidth; $x++) {
             if ($image->get($left + (int) ($x * $moduleSize), $iOffset)) {
                 $bits->set($x, $y);
             }
         }
     }
     return $bits;
 }
 /**
  * See ISO 18004:2006 Annex E
  */
 function buildFunctionPattern()
 {
     $dimension = self::getDimensionForVersion();
     $bitMatrix = new BitMatrix($dimension);
     // Top left finder pattern + separator + format
     $bitMatrix->setRegion(0, 0, 9, 9);
     // Top right finder pattern + separator + format
     $bitMatrix->setRegion($dimension - 8, 0, 8, 9);
     // Bottom left finder pattern + separator + format
     $bitMatrix->setRegion(0, $dimension - 8, 9, 8);
     // Alignment patterns
     $max = count($this->alignmentPatternCenters);
     for ($x = 0; $x < $max; $x++) {
         $i = $this->alignmentPatternCenters[$x] - 2;
         for ($y = 0; $y < $max; $y++) {
             if ($x == 0 && ($y == 0 || $y == $max - 1) || $x == $max - 1 && $y == 0) {
                 // No alignment patterns near the three finder paterns
                 continue;
             }
             $bitMatrix->setRegion($this->alignmentPatternCenters[$y] - 2, $i, 5, 5);
         }
     }
     // Vertical timing pattern
     $bitMatrix->setRegion(6, 9, 1, $dimension - 17);
     // Horizontal timing pattern
     $bitMatrix->setRegion(9, 6, $dimension - 17, 1);
     if ($this->versionNumber > 6) {
         // Version info, top right
         $bitMatrix->setRegion($dimension - 11, 0, 3, 6);
         // Version info, bottom left
         $bitMatrix->setRegion(0, $dimension - 11, 6, 3);
     }
     return $bitMatrix;
 }
 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 = intval($height * $y / 5);
         $localLuminances = $source->getRow($row, $this->luminances);
         $right = intval($width * 4 / 5);
         for ($x = intval($width / 5); $x < $right; $x++) {
             $pixel = intval32bits($localLuminances[intval($x)] & 0xff);
             $localBuckets[intval32bits($pixel >> self::$LUMINANCE_SHIFT)]++;
         }
     }
     $blackPoint = $this->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 = intval($localLuminances[$offset + $x] & 0xff);
             if ($pixel < $blackPoint) {
                 $matrix->set($x, $y);
             }
         }
     }
     return $matrix;
 }