Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements for big Aztec barcodes #23

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@
*/
public final class AztecReader implements Reader {

private void reportFoundResultPoints(Map<DecodeHintType, ?> hints, ResultPoint[] points) {
if (hints != null) {
ResultPointCallback rpcb = (ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK);
if (rpcb != null) {
for (ResultPoint point : points) {
rpcb.foundPossibleResultPoint(point);
}
}
}
}

/**
* Locates and decodes a Data Matrix code in an image.
*
Expand All @@ -64,6 +75,7 @@ public Result decode(BinaryBitmap image, Map<DecodeHintType,?> hints)
try {
AztecDetectorResult detectorResult = detector.detect(false);
points = detectorResult.getPoints();
reportFoundResultPoints(hints, points);
decoderResult = new Decoder().decode(detectorResult);
} catch (NotFoundException e) {
notFoundException = e;
Expand All @@ -74,6 +86,7 @@ public Result decode(BinaryBitmap image, Map<DecodeHintType,?> hints)
try {
AztecDetectorResult detectorResult = detector.detect(true);
points = detectorResult.getPoints();
reportFoundResultPoints(hints, points);
decoderResult = new Decoder().decode(detectorResult);
} catch (NotFoundException | FormatException e) {
if (notFoundException != null) {
Expand All @@ -86,22 +99,13 @@ public Result decode(BinaryBitmap image, Map<DecodeHintType,?> hints)
}
}

if (hints != null) {
ResultPointCallback rpcb = (ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK);
if (rpcb != null) {
for (ResultPoint point : points) {
rpcb.foundPossibleResultPoint(point);
}
}
}

Result result = new Result(decoderResult.getText(),
decoderResult.getRawBytes(),
decoderResult.getNumBits(),
points,
BarcodeFormat.AZTEC,
System.currentTimeMillis());

List<byte[]> byteSegments = decoderResult.getByteSegments();
if (byteSegments != null) {
result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments);
Expand All @@ -110,7 +114,7 @@ public Result decode(BinaryBitmap image, Map<DecodeHintType,?> hints)
if (ecLevel != null) {
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
}

return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.google.zxing.aztec.AztecDetectorResult;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.GridSampler;
import com.google.zxing.common.detector.CornerDetector;
import com.google.zxing.common.detector.MathUtils;
import com.google.zxing.common.detector.WhiteRectangleDetector;
import com.google.zxing.common.reedsolomon.GenericGF;
Expand Down Expand Up @@ -76,17 +77,17 @@ public AztecDetectorResult detect(boolean isMirror) throws NotFoundException {

// 3. Get the size of the matrix and other parameters from the bull's eye
extractParameters(bullsEyeCorners);

// 4. Sample the grid

// 4. Get the corners of the matrix.
ResultPoint[] corners = getMatrixCornerPoints(pCenter, bullsEyeCorners, getDimension());

// 5. Sample the grid
BitMatrix bits = sampleGrid(image,
bullsEyeCorners[shift % 4],
bullsEyeCorners[(shift + 1) % 4],
bullsEyeCorners[(shift + 2) % 4],
bullsEyeCorners[(shift + 3) % 4]);

// 5. Get the corners of the matrix.
ResultPoint[] corners = getMatrixCornerPoints(bullsEyeCorners);

corners[(shift + 1) % 4],
corners[(shift + 2) % 4],
corners[(shift + 3) % 4],
corners[shift % 4]);

return new AztecDetectorResult(bits, corners, compact, nbDataBlocks, nbLayers);
}

Expand All @@ -105,13 +106,13 @@ private void extractParameters(ResultPoint[] bullsEyeCorners) throws NotFoundExc
// Get the bits around the bull's eye
int[] sides = {
sampleLine(bullsEyeCorners[0], bullsEyeCorners[1], length), // Right side
sampleLine(bullsEyeCorners[1], bullsEyeCorners[2], length), // Bottom
sampleLine(bullsEyeCorners[1], bullsEyeCorners[2], length), // Bottom
sampleLine(bullsEyeCorners[2], bullsEyeCorners[3], length), // Left side
sampleLine(bullsEyeCorners[3], bullsEyeCorners[0], length) // Top
sampleLine(bullsEyeCorners[3], bullsEyeCorners[0], length) // Top
};

// bullsEyeCorners[shift] is the corner of the bulls'eye that has three
// orientation marks.
// bullsEyeCorners[shift] is the corner of the bulls'eye that has three
// orientation marks.
// sides[shift] is the row/column that goes from the corner with three
// orientation marks to the corner with two.
shift = getRotation(sides, length);
Expand All @@ -130,11 +131,11 @@ private void extractParameters(ResultPoint[] bullsEyeCorners) throws NotFoundExc
parameterData += ((side >> 2) & (0x1f << 5)) + ((side >> 1) & 0x1F);
}
}

// Corrects parameter data using RS. Returns just the data portion
// without the error correction.
int correctedData = getCorrectedParameterData(parameterData, compact);

if (compact) {
// 8 bits: 2 bits layers and 6 bits data blocks
nbLayers = (correctedData >> 6) + 1;
Expand Down Expand Up @@ -222,26 +223,30 @@ private static int getCorrectedParameterData(long parameterData, boolean compact
}
return result;
}

/**
* Finds the corners of a bull-eye centered on the passed point.
* This returns the centers of the diagonal points just outside the bull's eye
* Returns [topRight, bottomRight, bottomLeft, topLeft]
*
*
* @param pCenter Center point
* @return The corners of the bull-eye
* @throws NotFoundException If no valid bull-eye can be found
*/
private ResultPoint[] getBullsEyeCorners(Point pCenter) throws NotFoundException {


float corr_factor = 1.0f;

Point pina = pCenter;
Point pinb = pCenter;
Point pinc = pCenter;
Point pind = pCenter;

boolean color = true;

for (nbCenterLayers = 1; nbCenterLayers < 9; nbCenterLayers++) {
float corr_tmp;

Point pouta = getFirstDifferent(pina, color, 1, -1);
Point poutb = getFirstDifferent(pinb, color, 1, 1);
Point poutc = getFirstDifferent(pinc, color, -1, 1);
Expand All @@ -252,10 +257,14 @@ private ResultPoint[] getBullsEyeCorners(Point pCenter) throws NotFoundException
//c b

if (nbCenterLayers > 2) {
corr_tmp = Math.max(distance(poutd, pouta) / ((float) (((this.nbCenterLayers * 2) - 1) * 2)), 1.0f);

float q = distance(poutd, pouta) * nbCenterLayers / (distance(pind, pina) * (nbCenterLayers + 2));
if (q < 0.75 || q > 1.25 || !isWhiteOrBlackRectangle(pouta, poutb, poutc, poutd)) {
if (q < 0.75 || q > 1.25 || !isWhiteOrBlackRectangle(pouta, poutb, poutc, poutd, (int) corr_tmp)) {
break;
}
} else {
corr_tmp = corr_factor;
}

pina = pouta;
Expand All @@ -264,14 +273,15 @@ private ResultPoint[] getBullsEyeCorners(Point pCenter) throws NotFoundException
pind = poutd;

color = !color;
corr_factor = corr_tmp;
}

if (nbCenterLayers != 5 && nbCenterLayers != 7) {
throw NotFoundException.getNotFoundInstance();
}

compact = nbCenterLayers == 5;

// Expand the square by .5 pixel in each direction so that we're on the border
// between the white square and the black square
ResultPoint pinax = new ResultPoint(pina.getX() + 0.5f, pina.getY() - 0.5f);
Expand Down Expand Up @@ -319,7 +329,7 @@ private Point getMatrixCenter() {
pointD = getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint();

}

//Compute the center of the rectangle
int cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0f);
int cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0f);
Expand All @@ -341,7 +351,7 @@ private Point getMatrixCenter() {
pointC = getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint();
pointD = getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint();
}

// Recompute the center of the rectangle
cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0f);
cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0f);
Expand All @@ -355,8 +365,21 @@ private Point getMatrixCenter() {
* @param bullsEyeCorners the array of bull's eye corners
* @return the array of aztec code corners
*/
private ResultPoint[] getMatrixCornerPoints(ResultPoint[] bullsEyeCorners) {
return expandSquare(bullsEyeCorners, 2 * nbCenterLayers, getDimension());
private ResultPoint[] getMatrixCornerPoints(Point pCenter, ResultPoint[] bullsEyeCorners, int targetMatrixSize) throws NotFoundException {
float maxX = 0.0f;
float minX = image.getWidth();
for (ResultPoint bullsEyeCorner : bullsEyeCorners) {
float tmpX = bullsEyeCorner.getX();
if (tmpX > maxX) {
maxX = tmpX;
}
if (tmpX < minX) {
minX = tmpX;
}
}

int initSize = (int) (maxX - minX); // we are looking for first white rectangle outside of bulls eye
return (new CornerDetector(image, initSize, pCenter.getX(), pCenter.getY(), targetMatrixSize)).detect();
}

/**
Expand All @@ -369,12 +392,12 @@ private BitMatrix sampleGrid(BitMatrix image,
ResultPoint topRight,
ResultPoint bottomRight,
ResultPoint bottomLeft) throws NotFoundException {

GridSampler sampler = GridSampler.getInstance();
int dimension = getDimension();

float low = dimension / 2.0f - nbCenterLayers;
float high = dimension / 2.0f + nbCenterLayers;
float low = 0.5f;
float high = (float) dimension - 0.5f;

return sampler.sampleGrid(image,
dimension,
Expand Down Expand Up @@ -421,9 +444,8 @@ private int sampleLine(ResultPoint p1, ResultPoint p2, int size) {
private boolean isWhiteOrBlackRectangle(Point p1,
Point p2,
Point p3,
Point p4) {

int corr = 3;
Point p4,
int corr) {

p1 = new Point(p1.getX() - corr, p1.getY() + corr);
p2 = new Point(p2.getX() - corr, p2.getY() - corr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public CameraManager(Context context) {
previewCallback = new PreviewCallback(configManager);
windowManager = (WindowManager) this.context.getSystemService(Context.WINDOW_SERVICE);
}

/**
* Opens the camera driver and initializes the hardware parameters.
*
Expand Down Expand Up @@ -247,9 +247,9 @@ public synchronized Rect getFramingRect() {
}
return framingRect;
}

private static int findDesiredDimensionInRange(int resolution, int hardMin, int hardMax) {
int dim = 5 * resolution / 8; // Target 5/8 of each dimension
int dim = 7 * resolution / 8; // Target 7/8 of each dimension
if (dim < hardMin) {
return hardMin;
}
Expand Down Expand Up @@ -300,7 +300,7 @@ public synchronized Rect getFramingRectInPreview() {
return framingRectInPreview;
}


/**
* Allows third party apps to specify the camera ID, rather than determine
* it automatically based on available cameras and their orientation.
Expand All @@ -310,7 +310,7 @@ public synchronized Rect getFramingRectInPreview() {
public synchronized void setManualCameraId(int cameraId) {
requestedCameraId = cameraId;
}

public synchronized void setTorchInitiallyOn(boolean on) {
torchInitiallyOn = on;
}
Expand Down
Loading