$MAX_MODULES
$MAX_MODULES
<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.
findCornerFromCenter(float $centerX, float $deltaX, float $left, float $right, float $centerY, float $deltaY, float $top, float $bottom, float $maxWhiteRun) : \Zxing\ResultPoint
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.
float | $centerX | center's x component (horizontal) |
float | $deltaX | same as deltaY but change in x per step instead |
float | $left | minimum value of x |
float | $right | maximum value of x |
float | $centerY | center's y component (vertical) |
float | $deltaY | change in y per step. If scanning up this is negative; down, positive; left or right, 0 |
float | $top | minimum value of y to search through (meaningless when di == 0) |
float | $bottom | maximum value of y |
float | $maxWhiteRun | maximum run of white pixels that can still be considered to be within the barcode |
if such a point cannot be found
$a {@link com.google.zxing.ResultPoint} encapsulating the corner that was found
blackWhiteRange(mixed $fixedDimension, mixed $maxWhiteRun, mixed $minDim, mixed $maxDim, mixed $horizontal) : int[]
Computes the start and end of a region of pixels, either horizontally or vertically, that could be part of a Data Matrix barcode.
mixed | $fixedDimension | |
mixed | $maxWhiteRun | |
mixed | $minDim | |
mixed | $maxDim | |
mixed | $horizontal |
with start and end of found range, or null if no such range is found (e.g. only white was found)
<?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;
}
}