| <?php |
| |
| |
| |
| |
| |
| |
|
|
| namespace Zxing\Common\Detector; |
|
|
| use Zxing\BinaryBitmap; |
| use \Zxing\NotFoundException; |
| use \Zxing\ResultPoint; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| class MonochromeRectangleDetector |
| { |
| private static $MAX_MODULES = 32; |
| private $image; |
|
|
| public function __construct(BinaryBitmap $image) |
| { |
| $this->image = $image; |
|
|
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 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; |
|
|
| |
| $pointA = $this->findCornerFromCenter($halfWidth, 0, $left, $right, |
| $halfHeight, -$deltaY, $top, $bottom, $halfWidth / 4); |
|
|
| return new ResultPoint($pointA, $pointB, $pointC, $pointD); |
|
|
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 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) { |
| |
| $range = $this->blackWhiteRange($y, $maxWhiteRun, $left, $right, true); |
| } else { |
| |
| $range = $this->blackWhiteRange($x, $maxWhiteRun, $top, $bottom, false); |
| } |
| if ($range == null) { |
| if ($lastRange == null) { |
| throw NotFoundException::getNotFoundInstance(); |
| } |
| |
| if ($deltaX == 0) { |
| $lastY = $y - $deltaY; |
| if ($lastRange[0] < $centerX) { |
| if ($lastRange[1] > $centerX) { |
| |
| 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(); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| private function blackWhiteRange($fixedDimension, $maxWhiteRun, $minDim, $maxDim, $horizontal) |
| { |
| $center = ($minDim + $maxDim) / 2; |
|
|
| |
| $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++; |
|
|
| |
| $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; |
| } |
| } |