/** * 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.application.food.zxing.pdf417.PDF417Reader#extractPureBits(com.application.food.zxing.common.BitMatrix) * @see * com.application.food.zxing.datamatrix.DataMatrixReader#extractPureBits(com.application.food.zxing.common.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(); } float moduleSize = moduleSize(leftTopBlack, image); int top = leftTopBlack[1]; int bottom = rightBottomBlack[1]; int left = leftTopBlack[0]; int right = rightBottomBlack[0]; if (bottom - top != right - left) { // Special case, where bottom-right module wasn't black so we found something else in the last // row // Assume it's a square, so use height as the width right = left + (bottom - top); } int matrixWidth = Math.round((right - left + 1) / moduleSize); int matrixHeight = Math.round((bottom - top + 1) / moduleSize); if (matrixWidth <= 0 || matrixHeight <= 0) { throw NotFoundException.getNotFoundInstance(); } if (matrixHeight != matrixWidth) { // Only possibly decode square regions 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 = Math.round(moduleSize / 2.0f); 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 + (int) (y * moduleSize); for (int x = 0; x < matrixWidth; x++) { if (image.get(left + (int) (x * moduleSize), iOffset)) { bits.set(x, y); } } } return bits; }
protected static int parseFinderValue(int[] counters, int[][] finderPatterns) throws NotFoundException { for (int value = 0; value < finderPatterns.length; value++) { if (patternMatchVariance(counters, finderPatterns[value], MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { return value; } } throw NotFoundException.getNotFoundInstance(); }
/** * @return the 3 best {@link FinderPattern}s from our list of candidates. The "best" are those * that have been detected at least {@link #CENTER_QUORUM} times, and whose module size * differs from the average among those patterns the least * @throws com.application.food.zxing.NotFoundException if 3 such finder patterns do not exist */ private FinderPattern[] selectBestPatterns() throws NotFoundException { int startSize = possibleCenters.size(); if (startSize < 3) { // Couldn't find enough finder patterns throw NotFoundException.getNotFoundInstance(); } // Filter outlier possibilities whose module size is too different if (startSize > 3) { // But we can only afford to do so if we have at least 4 possibilities to choose from float totalModuleSize = 0.0f; float square = 0.0f; for (FinderPattern center : possibleCenters) { float size = center.getEstimatedModuleSize(); totalModuleSize += size; square += size * size; } float average = totalModuleSize / (float) startSize; float stdDev = (float) Math.sqrt(square / startSize - average * average); Collections.sort(possibleCenters, new FurthestFromAverageComparator(average)); float limit = Math.max(0.2f * average, stdDev); for (int i = 0; i < possibleCenters.size() && possibleCenters.size() > 3; i++) { FinderPattern pattern = possibleCenters.get(i); if (Math.abs(pattern.getEstimatedModuleSize() - average) > limit) { possibleCenters.remove(i); i--; } } } if (possibleCenters.size() > 3) { // Throw away all but those first size candidate points we found. float totalModuleSize = 0.0f; for (FinderPattern possibleCenter : possibleCenters) { totalModuleSize += possibleCenter.getEstimatedModuleSize(); } float average = totalModuleSize / (float) possibleCenters.size(); Collections.sort(possibleCenters, new CenterComparator(average)); possibleCenters.subList(3, possibleCenters.size()).clear(); } return new FinderPattern[] { possibleCenters.get(0), possibleCenters.get(1), possibleCenters.get(2) }; }
private static float moduleSize(int[] leftTopBlack, BitMatrix image) throws NotFoundException { int height = image.getHeight(); int width = image.getWidth(); int x = leftTopBlack[0]; int y = leftTopBlack[1]; boolean inBlack = true; int transitions = 0; while (x < width && y < height) { if (inBlack != image.get(x, y)) { if (++transitions == 5) { break; } inBlack = !inBlack; } x++; y++; } if (x == width || y == height) { throw NotFoundException.getNotFoundInstance(); } return (x - leftTopBlack[0]) / 7.0f; }