mirror of https://github.com/NekoX-Dev/NekoX.git
217 lines
8.2 KiB
Java
Executable File
217 lines
8.2 KiB
Java
Executable File
/*
|
|
* 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.
|
|
*/
|
|
|
|
package com.google.zxing.common.detector;
|
|
|
|
import com.google.zxing.NotFoundException;
|
|
import com.google.zxing.ResultPoint;
|
|
import com.google.zxing.common.BitMatrix;
|
|
|
|
/**
|
|
* <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
|
|
* @deprecated without replacement since 3.3.0
|
|
*/
|
|
@Deprecated
|
|
public final class MonochromeRectangleDetector {
|
|
|
|
private static final int MAX_MODULES = 32;
|
|
|
|
private final BitMatrix image;
|
|
|
|
public MonochromeRectangleDetector(BitMatrix 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 ResultPoint[] detect() throws NotFoundException {
|
|
int height = image.getHeight();
|
|
int width = image.getWidth();
|
|
int halfHeight = height / 2;
|
|
int halfWidth = width / 2;
|
|
int deltaY = Math.max(1, height / (MAX_MODULES * 8));
|
|
int deltaX = Math.max(1, width / (MAX_MODULES * 8));
|
|
|
|
int top = 0;
|
|
int bottom = height;
|
|
int left = 0;
|
|
int right = width;
|
|
ResultPoint pointA = findCornerFromCenter(halfWidth, 0, left, right,
|
|
halfHeight, -deltaY, top, bottom, halfWidth / 2);
|
|
top = (int) pointA.getY() - 1;
|
|
ResultPoint pointB = findCornerFromCenter(halfWidth, -deltaX, left, right,
|
|
halfHeight, 0, top, bottom, halfHeight / 2);
|
|
left = (int) pointB.getX() - 1;
|
|
ResultPoint pointC = findCornerFromCenter(halfWidth, deltaX, left, right,
|
|
halfHeight, 0, top, bottom, halfHeight / 2);
|
|
right = (int) pointC.getX() + 1;
|
|
ResultPoint pointD = findCornerFromCenter(halfWidth, 0, left, right,
|
|
halfHeight, deltaY, top, bottom, halfWidth / 2);
|
|
bottom = (int) pointD.getY() + 1;
|
|
|
|
// Go try to find point A again with better information -- might have been off at first.
|
|
pointA = 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 centerX center's x component (horizontal)
|
|
* @param deltaX same as deltaY but change in x per step instead
|
|
* @param left minimum value of x
|
|
* @param right maximum value of x
|
|
* @param centerY center's y component (vertical)
|
|
* @param deltaY change in y per step. If scanning up this is negative; down, positive;
|
|
* left or right, 0
|
|
* @param top minimum value of y to search through (meaningless when di == 0)
|
|
* @param bottom maximum value of y
|
|
* @param maxWhiteRun maximum run of white pixels that can still be considered to be within
|
|
* the barcode
|
|
* @return a {@link ResultPoint} encapsulating the corner that was found
|
|
* @throws NotFoundException if such a point cannot be found
|
|
*/
|
|
private ResultPoint findCornerFromCenter(int centerX,
|
|
int deltaX,
|
|
int left,
|
|
int right,
|
|
int centerY,
|
|
int deltaY,
|
|
int top,
|
|
int bottom,
|
|
int maxWhiteRun) throws NotFoundException {
|
|
int[] lastRange = null;
|
|
for (int y = centerY, x = centerX;
|
|
y < bottom && y >= top && x < right && x >= left;
|
|
y += deltaY, x += deltaX) {
|
|
int[] range;
|
|
if (deltaX == 0) {
|
|
// horizontal slices, up and down
|
|
range = blackWhiteRange(y, maxWhiteRun, left, right, true);
|
|
} else {
|
|
// vertical slices, left and right
|
|
range = blackWhiteRange(x, maxWhiteRun, top, bottom, false);
|
|
}
|
|
if (range == null) {
|
|
if (lastRange == null) {
|
|
throw NotFoundException.getNotFoundInstance();
|
|
}
|
|
// lastRange was found
|
|
if (deltaX == 0) {
|
|
int lastY = y - deltaY;
|
|
if (lastRange[0] < centerX) {
|
|
if (lastRange[1] > centerX) {
|
|
// straddle, choose one or the other based on direction
|
|
return new ResultPoint(lastRange[deltaY > 0 ? 0 : 1], lastY);
|
|
}
|
|
return new ResultPoint(lastRange[0], lastY);
|
|
} else {
|
|
return new ResultPoint(lastRange[1], lastY);
|
|
}
|
|
} else {
|
|
int lastX = x - deltaX;
|
|
if (lastRange[0] < centerY) {
|
|
if (lastRange[1] > centerY) {
|
|
return new ResultPoint(lastX, lastRange[deltaX < 0 ? 0 : 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 int[] blackWhiteRange(int fixedDimension, int maxWhiteRun, int minDim, int maxDim, boolean horizontal) {
|
|
|
|
int center = (minDim + maxDim) / 2;
|
|
|
|
// Scan left/up first
|
|
int start = center;
|
|
while (start >= minDim) {
|
|
if (horizontal ? image.get(start, fixedDimension) : image.get(fixedDimension, start)) {
|
|
start--;
|
|
} else {
|
|
int whiteRunStart = start;
|
|
do {
|
|
start--;
|
|
} while (start >= minDim && !(horizontal ? image.get(start, fixedDimension) :
|
|
image.get(fixedDimension, start)));
|
|
int whiteRunSize = whiteRunStart - start;
|
|
if (start < minDim || whiteRunSize > maxWhiteRun) {
|
|
start = whiteRunStart;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
start++;
|
|
|
|
// Then try right/down
|
|
int end = center;
|
|
while (end < maxDim) {
|
|
if (horizontal ? image.get(end, fixedDimension) : image.get(fixedDimension, end)) {
|
|
end++;
|
|
} else {
|
|
int whiteRunStart = end;
|
|
do {
|
|
end++;
|
|
} while (end < maxDim && !(horizontal ? image.get(end, fixedDimension) :
|
|
image.get(fixedDimension, end)));
|
|
int whiteRunSize = end - whiteRunStart;
|
|
if (end >= maxDim || whiteRunSize > maxWhiteRun) {
|
|
end = whiteRunStart;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
end--;
|
|
|
|
return end > start ? new int[]{start, end} : null;
|
|
}
|
|
|
|
} |