Search in sources :

Example 46 with BitMatrix

use of com.google.zxing.common.BitMatrix in project zxing by zxing.

the class Detector method detect.

/**
   * <p>Detects a Data Matrix Code in an image.</p>
   *
   * @return {@link DetectorResult} encapsulating results of detecting a Data Matrix Code
   * @throws NotFoundException if no Data Matrix Code can be found
   */
public DetectorResult detect() throws NotFoundException {
    ResultPoint[] cornerPoints = rectangleDetector.detect();
    ResultPoint pointA = cornerPoints[0];
    ResultPoint pointB = cornerPoints[1];
    ResultPoint pointC = cornerPoints[2];
    ResultPoint pointD = cornerPoints[3];
    // Point A and D are across the diagonal from one another,
    // as are B and C. Figure out which are the solid black lines
    // by counting transitions
    List<ResultPointsAndTransitions> transitions = new ArrayList<>(4);
    transitions.add(transitionsBetween(pointA, pointB));
    transitions.add(transitionsBetween(pointA, pointC));
    transitions.add(transitionsBetween(pointB, pointD));
    transitions.add(transitionsBetween(pointC, pointD));
    Collections.sort(transitions, new ResultPointsAndTransitionsComparator());
    // Sort by number of transitions. First two will be the two solid sides; last two
    // will be the two alternating black/white sides
    ResultPointsAndTransitions lSideOne = transitions.get(0);
    ResultPointsAndTransitions lSideTwo = transitions.get(1);
    // Figure out which point is their intersection by tallying up the number of times we see the
    // endpoints in the four endpoints. One will show up twice.
    Map<ResultPoint, Integer> pointCount = new HashMap<>();
    increment(pointCount, lSideOne.getFrom());
    increment(pointCount, lSideOne.getTo());
    increment(pointCount, lSideTwo.getFrom());
    increment(pointCount, lSideTwo.getTo());
    ResultPoint maybeTopLeft = null;
    ResultPoint bottomLeft = null;
    ResultPoint maybeBottomRight = null;
    for (Map.Entry<ResultPoint, Integer> entry : pointCount.entrySet()) {
        ResultPoint point = entry.getKey();
        Integer value = entry.getValue();
        if (value == 2) {
            // this is definitely the bottom left, then -- end of two L sides
            bottomLeft = point;
        } else {
            // Otherwise it's either top left or bottom right -- just assign the two arbitrarily now
            if (maybeTopLeft == null) {
                maybeTopLeft = point;
            } else {
                maybeBottomRight = point;
            }
        }
    }
    if (maybeTopLeft == null || bottomLeft == null || maybeBottomRight == null) {
        throw NotFoundException.getNotFoundInstance();
    }
    // Bottom left is correct but top left and bottom right might be switched
    ResultPoint[] corners = { maybeTopLeft, bottomLeft, maybeBottomRight };
    // Use the dot product trick to sort them out
    ResultPoint.orderBestPatterns(corners);
    // Now we know which is which:
    ResultPoint bottomRight = corners[0];
    bottomLeft = corners[1];
    ResultPoint topLeft = corners[2];
    // Which point didn't we find in relation to the "L" sides? that's the top right corner
    ResultPoint topRight;
    if (!pointCount.containsKey(pointA)) {
        topRight = pointA;
    } else if (!pointCount.containsKey(pointB)) {
        topRight = pointB;
    } else if (!pointCount.containsKey(pointC)) {
        topRight = pointC;
    } else {
        topRight = pointD;
    }
    // Next determine the dimension by tracing along the top or right side and counting black/white
    // transitions. Since we start inside a black module, we should see a number of transitions
    // equal to 1 less than the code dimension. Well, actually 2 less, because we are going to
    // end on a black module:
    // The top right point is actually the corner of a module, which is one of the two black modules
    // adjacent to the white module at the top right. Tracing to that corner from either the top left
    // or bottom right should work here.
    int dimensionTop = transitionsBetween(topLeft, topRight).getTransitions();
    int dimensionRight = transitionsBetween(bottomRight, topRight).getTransitions();
    if ((dimensionTop & 0x01) == 1) {
        // it can't be odd, so, round... up?
        dimensionTop++;
    }
    dimensionTop += 2;
    if ((dimensionRight & 0x01) == 1) {
        // it can't be odd, so, round... up?
        dimensionRight++;
    }
    dimensionRight += 2;
    BitMatrix bits;
    ResultPoint correctedTopRight;
    // rectangular if the bigger side is at least 7/4 times the other:
    if (4 * dimensionTop >= 7 * dimensionRight || 4 * dimensionRight >= 7 * dimensionTop) {
        // The matrix is rectangular
        correctedTopRight = correctTopRightRectangular(bottomLeft, bottomRight, topLeft, topRight, dimensionTop, dimensionRight);
        if (correctedTopRight == null) {
            correctedTopRight = topRight;
        }
        dimensionTop = transitionsBetween(topLeft, correctedTopRight).getTransitions();
        dimensionRight = transitionsBetween(bottomRight, correctedTopRight).getTransitions();
        if ((dimensionTop & 0x01) == 1) {
            // it can't be odd, so, round... up?
            dimensionTop++;
        }
        if ((dimensionRight & 0x01) == 1) {
            // it can't be odd, so, round... up?
            dimensionRight++;
        }
        bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, correctedTopRight, dimensionTop, dimensionRight);
    } else {
        // The matrix is square
        int dimension = Math.min(dimensionRight, dimensionTop);
        // correct top right point to match the white module
        correctedTopRight = correctTopRight(bottomLeft, bottomRight, topLeft, topRight, dimension);
        if (correctedTopRight == null) {
            correctedTopRight = topRight;
        }
        // Redetermine the dimension using the corrected top right point
        int dimensionCorrected = Math.max(transitionsBetween(topLeft, correctedTopRight).getTransitions(), transitionsBetween(bottomRight, correctedTopRight).getTransitions());
        dimensionCorrected++;
        if ((dimensionCorrected & 0x01) == 1) {
            dimensionCorrected++;
        }
        bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, correctedTopRight, dimensionCorrected, dimensionCorrected);
    }
    return new DetectorResult(bits, new ResultPoint[] { topLeft, bottomLeft, bottomRight, correctedTopRight });
}
Also used : ResultPoint(com.google.zxing.ResultPoint) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) BitMatrix(com.google.zxing.common.BitMatrix) ResultPoint(com.google.zxing.ResultPoint) DetectorResult(com.google.zxing.common.DetectorResult) HashMap(java.util.HashMap) Map(java.util.Map)

Example 47 with BitMatrix

use of com.google.zxing.common.BitMatrix in project zxing by zxing.

the class MaxiCodeReader method extractPureBits.

/**
   * 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)
   * @see com.google.zxing.qrcode.QRCodeReader#extractPureBits(BitMatrix)
   */
private static BitMatrix extractPureBits(BitMatrix image) throws NotFoundException {
    int[] enclosingRectangle = image.getEnclosingRectangle();
    if (enclosingRectangle == null) {
        throw NotFoundException.getNotFoundInstance();
    }
    int left = enclosingRectangle[0];
    int top = enclosingRectangle[1];
    int width = enclosingRectangle[2];
    int height = enclosingRectangle[3];
    // Now just read off the bits
    BitMatrix bits = new BitMatrix(MATRIX_WIDTH, MATRIX_HEIGHT);
    for (int y = 0; y < MATRIX_HEIGHT; y++) {
        int iy = top + (y * height + height / 2) / MATRIX_HEIGHT;
        for (int x = 0; x < MATRIX_WIDTH; x++) {
            int ix = left + (x * width + width / 2 + (y & 0x01) * width / 2) / MATRIX_WIDTH;
            if (image.get(ix, iy)) {
                bits.set(x, y);
            }
        }
    }
    return bits;
}
Also used : BitMatrix(com.google.zxing.common.BitMatrix) ResultPoint(com.google.zxing.ResultPoint)

Example 48 with BitMatrix

use of com.google.zxing.common.BitMatrix in project zxing by zxing.

the class MaxiCodeReader method decode.

@Override
public Result decode(BinaryBitmap image, Map<DecodeHintType, ?> hints) throws NotFoundException, ChecksumException, FormatException {
    DecoderResult decoderResult;
    if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE)) {
        BitMatrix bits = extractPureBits(image.getBlackMatrix());
        decoderResult = decoder.decode(bits, hints);
    } else {
        throw NotFoundException.getNotFoundInstance();
    }
    Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), NO_POINTS, BarcodeFormat.MAXICODE);
    String ecLevel = decoderResult.getECLevel();
    if (ecLevel != null) {
        result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
    }
    return result;
}
Also used : DecoderResult(com.google.zxing.common.DecoderResult) BitMatrix(com.google.zxing.common.BitMatrix) Result(com.google.zxing.Result) DecoderResult(com.google.zxing.common.DecoderResult)

Example 49 with BitMatrix

use of com.google.zxing.common.BitMatrix in project zxing by zxing.

the class DataMatrixReader method extractPureBits.

/**
   * 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.qrcode.QRCodeReader#extractPureBits(BitMatrix)
   */
private static BitMatrix extractPureBits(BitMatrix image) throws NotFoundException {
    int[] leftTopBlack = image.getTopLeftOnBit();
    int[] rightBottomBlack = image.getBottomRightOnBit();
    if (leftTopBlack == null || rightBottomBlack == null) {
        throw NotFoundException.getNotFoundInstance();
    }
    int moduleSize = moduleSize(leftTopBlack, image);
    int top = leftTopBlack[1];
    int bottom = rightBottomBlack[1];
    int left = leftTopBlack[0];
    int right = rightBottomBlack[0];
    int matrixWidth = (right - left + 1) / moduleSize;
    int matrixHeight = (bottom - top + 1) / moduleSize;
    if (matrixWidth <= 0 || matrixHeight <= 0) {
        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.
    int nudge = moduleSize / 2;
    top += nudge;
    left += nudge;
    // Now just read off the bits
    BitMatrix bits = new BitMatrix(matrixWidth, matrixHeight);
    for (int y = 0; y < matrixHeight; y++) {
        int iOffset = top + y * moduleSize;
        for (int x = 0; x < matrixWidth; x++) {
            if (image.get(left + x * moduleSize, iOffset)) {
                bits.set(x, y);
            }
        }
    }
    return bits;
}
Also used : BitMatrix(com.google.zxing.common.BitMatrix) ResultPoint(com.google.zxing.ResultPoint)

Example 50 with BitMatrix

use of com.google.zxing.common.BitMatrix in project zxing by zxing.

the class DataMatrixReader method decode.

@Override
public Result decode(BinaryBitmap image, Map<DecodeHintType, ?> hints) throws NotFoundException, ChecksumException, FormatException {
    DecoderResult decoderResult;
    ResultPoint[] points;
    if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE)) {
        BitMatrix bits = extractPureBits(image.getBlackMatrix());
        decoderResult = decoder.decode(bits);
        points = NO_POINTS;
    } else {
        DetectorResult detectorResult = new Detector(image.getBlackMatrix()).detect();
        decoderResult = decoder.decode(detectorResult.getBits());
        points = detectorResult.getPoints();
    }
    Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.DATA_MATRIX);
    List<byte[]> byteSegments = decoderResult.getByteSegments();
    if (byteSegments != null) {
        result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments);
    }
    String ecLevel = decoderResult.getECLevel();
    if (ecLevel != null) {
        result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
    }
    return result;
}
Also used : ResultPoint(com.google.zxing.ResultPoint) Detector(com.google.zxing.datamatrix.detector.Detector) DecoderResult(com.google.zxing.common.DecoderResult) DetectorResult(com.google.zxing.common.DetectorResult) BitMatrix(com.google.zxing.common.BitMatrix) Result(com.google.zxing.Result) DetectorResult(com.google.zxing.common.DetectorResult) DecoderResult(com.google.zxing.common.DecoderResult)

Aggregations

BitMatrix (com.google.zxing.common.BitMatrix)114 ResultPoint (com.google.zxing.ResultPoint)26 EncodeHintType (com.google.zxing.EncodeHintType)23 Test (org.junit.Test)20 Bitmap (android.graphics.Bitmap)15 QRCodeWriter (com.google.zxing.qrcode.QRCodeWriter)14 DecoderResult (com.google.zxing.common.DecoderResult)12 WriterException (com.google.zxing.WriterException)10 DetectorResult (com.google.zxing.common.DetectorResult)10 MultiFormatWriter (com.google.zxing.MultiFormatWriter)9 Hashtable (java.util.Hashtable)9 AztecDetectorResult (com.google.zxing.aztec.AztecDetectorResult)8 EnumMap (java.util.EnumMap)8 Result (com.google.zxing.Result)7 ArrayList (java.util.ArrayList)6 Point (com.google.zxing.aztec.detector.Detector.Point)5 SymbolShapeHint (com.google.zxing.datamatrix.encoder.SymbolShapeHint)5 NotFoundException (com.google.zxing.NotFoundException)4 BitArray (com.google.zxing.common.BitArray)4 FinderPatternInfo (com.google.zxing.qrcode.detector.FinderPatternInfo)4