X-Git-Url: http://git.rot13.org/?p=zxing.git;a=blobdiff_plain;f=core%2Fsrc%2Fcom%2Fgoogle%2Fzxing%2Fqrcode%2FQRCodeReader.java;h=52002ae7c547eaa6b22b8b8104e37c3281c9b131;hp=adc53b3cff02625d9e7931b17020b73c75c9227d;hb=de6f57f5cfd923b42c2c9665b2db381c3a7a3f53;hpb=9dc2a42f1e2a05cd525d4e583e6127eda8e7c4de diff --git a/core/src/com/google/zxing/qrcode/QRCodeReader.java b/core/src/com/google/zxing/qrcode/QRCodeReader.java index adc53b3c..52002ae7 100644 --- a/core/src/com/google/zxing/qrcode/QRCodeReader.java +++ b/core/src/com/google/zxing/qrcode/QRCodeReader.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 Google Inc. + * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,23 +16,36 @@ package com.google.zxing.qrcode; +import com.google.zxing.BarcodeFormat; import com.google.zxing.DecodeHintType; -import com.google.zxing.MonochromeBitmapSource; import com.google.zxing.Reader; import com.google.zxing.ReaderException; import com.google.zxing.Result; import com.google.zxing.ResultPoint; +import com.google.zxing.ResultMetadataType; +import com.google.zxing.BinaryBitmap; import com.google.zxing.common.BitMatrix; +import com.google.zxing.common.DecoderResult; +import com.google.zxing.common.DetectorResult; import com.google.zxing.qrcode.decoder.Decoder; import com.google.zxing.qrcode.detector.Detector; -import com.google.zxing.qrcode.detector.DetectorResult; import java.util.Hashtable; /** - * @author srowen@google.com (Sean Owen) + * This implementation can detect and decode QR Codes in an image. + * + * @author Sean Owen */ -public final class QRCodeReader implements Reader { +public class QRCodeReader implements Reader { + + private static final ResultPoint[] NO_POINTS = new ResultPoint[0]; + + private final Decoder decoder = new Decoder(); + + protected Decoder getDecoder() { + return decoder; + } /** * Locates and decodes a QR code in an image. @@ -40,49 +53,84 @@ public final class QRCodeReader implements Reader { * @return a String representing the content encoded by the QR code * @throws ReaderException if a QR code cannot be found, or cannot be decoded */ - public Result decode(MonochromeBitmapSource image) throws ReaderException { + public Result decode(BinaryBitmap image) throws ReaderException { return decode(image, null); } - public Result decode(MonochromeBitmapSource image, Hashtable hints) + public Result decode(BinaryBitmap image, Hashtable hints) throws ReaderException { - String text; + DecoderResult decoderResult; ResultPoint[] points; if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE)) { - BitMatrix bits = extractPureBits(image); - text = Decoder.decode(bits); - points = new ResultPoint[0]; + BitMatrix bits = extractPureBits(image.getBlackMatrix()); + decoderResult = decoder.decode(bits, hints); + points = NO_POINTS; } else { - DetectorResult result = new Detector(image).detect(); - text = Decoder.decode(result.getBits()); - points = result.getPoints(); + DetectorResult detectorResult = new Detector(image.getBlackMatrix()).detect(hints); + decoderResult = decoder.decode(detectorResult.getBits(), hints); + points = detectorResult.getPoints(); } - return new Result(text, points); + + Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.QR_CODE); + if (decoderResult.getByteSegments() != null) { + result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, decoderResult.getByteSegments()); + } + if (decoderResult.getECLevel() != null) { + result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult.getECLevel().toString()); + } + return result; } - private static BitMatrix extractPureBits(MonochromeBitmapSource image) - throws ReaderException { + public void reset() { + // do nothing + } + + /** + * This method detects a barcode in a "pure" image -- that is, pure monochrome image + * which contains only an unrotated, unskewed, image of a barcode, with some white border + * around it. This is a specialized method that works exceptionally fast in this special + * case. + */ + private static BitMatrix extractPureBits(BitMatrix image) throws ReaderException { // Now need to determine module size in pixels - // First, skip white border + + int height = image.getHeight(); + int width = image.getWidth(); + int minDimension = Math.min(height, width); + + // First, skip white border by tracking diagonally from the top left down and to the right: int borderWidth = 0; - while (!image.isBlack(borderWidth, borderWidth)) { + while (borderWidth < minDimension && !image.get(borderWidth, borderWidth)) { borderWidth++; } + if (borderWidth == minDimension) { + throw ReaderException.getInstance(); + } + + // And then keep tracking across the top-left black module to determine module size int moduleEnd = borderWidth; - while (image.isBlack(moduleEnd, moduleEnd)) { + while (moduleEnd < minDimension && image.get(moduleEnd, moduleEnd)) { moduleEnd++; } + if (moduleEnd == minDimension) { + throw ReaderException.getInstance(); + } + int moduleSize = moduleEnd - borderWidth; - int rowEndOfSymbol = image.getWidth() - 1; - while (!image.isBlack(rowEndOfSymbol, borderWidth)) { + // And now find where the rightmost black module on the first row ends + int rowEndOfSymbol = width - 1; + while (rowEndOfSymbol >= 0 && !image.get(rowEndOfSymbol, borderWidth)) { rowEndOfSymbol--; } + if (rowEndOfSymbol < 0) { + throw ReaderException.getInstance(); + } rowEndOfSymbol++; + // Make sure width of barcode is a multiple of module size if ((rowEndOfSymbol - borderWidth) % moduleSize != 0) { - throw new ReaderException("Bad module size / width: " + moduleSize + - " / " + (rowEndOfSymbol - borderWidth)); + throw ReaderException.getInstance(); } int dimension = (rowEndOfSymbol - borderWidth) / moduleSize; @@ -91,12 +139,18 @@ public final class QRCodeReader implements Reader { // little off, this will help recover. borderWidth += moduleSize >> 1; + int sampleDimension = borderWidth + (dimension - 1) * moduleSize; + if (sampleDimension >= width || sampleDimension >= height) { + throw ReaderException.getInstance(); + } + + // Now just read off the bits BitMatrix bits = new BitMatrix(dimension); for (int i = 0; i < dimension; i++) { int iOffset = borderWidth + i * moduleSize; for (int j = 0; j < dimension; j++) { - if (image.isBlack(borderWidth + j * moduleSize, iOffset)) { - bits.set(i, j); + if (image.get(borderWidth + j * moduleSize, iOffset)) { + bits.set(j, i); } } }