/** * Identify where the end of the middle / payload section ends. * * @param row row of black/white values to search * @return Array, containing index of start of 'end block' and end of 'end * block' * @throws ReaderException */ int[] decodeEnd(BitArray row) { // For convenience, reverse the row and then // search from 'the start' for the end block row.reverse(); int endStart = skipWhiteSpace(row); int[] endPattern; try { endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED); } catch (ReaderException e) { // Put our row of data back the right way before throwing row.reverse(); throw e; } // The start & end patterns must be pre/post fixed by a quiet zone. This // zone must be at least 10 times the width of a narrow line. // ref: http://www.barcode-1.net/i25code.html validateQuietZone(row, endPattern[0]); // Now recalc the indicies of where the 'endblock' starts & stops to // accomodate // the reversed nature of the search int temp = endPattern[0]; endPattern[0] = row.getSize() - endPattern[1]; endPattern[1] = row.getSize() - temp; // Put the row back the righ way. row.reverse(); return endPattern; }
/** * We're going to examine rows from the middle outward, searching alternately above and below the * middle, and farther out each time. rowStep is the number of rows between each successive * attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then * middle + rowStep, then middle - (2 * rowStep), etc. * rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily * decided that moving up and down by about 1/16 of the image is pretty good; we try more of the * image if "trying harder". * * @param image The image to decode * @param hints Any hints that were requested * @return The contents of the decoded barcode * @throws ReaderException Any spontaneous errors which occur */ private Result doDecode(MonochromeBitmapSource image, System.Collections.Hashtable hints) { int width = image.getWidth(); int height = image.getHeight(); BitArray row = new BitArray(width); int middle = height >> 1; bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER); int rowStep = Math.Max(1, height >> (tryHarder ? 7 : 4)); int MaxLines; if (tryHarder) { MaxLines = height; // Look at the whole image, not just the center } else { MaxLines = 9; // Nine rows spaced 1/16 apart is roughly the middle half of the image } for (int x = 0; x < MaxLines; x++) { // Scanning from the middle out. Determine which row we're looking at next: int rowStepsAboveOrBelow = (x + 1) >> 1; bool isAbove = (x & 0x01) == 0; // i.e. is x even? int rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow); if (rowNumber < 0 || rowNumber >= height) { // Oops, if we run off the top or bottom, stop break; } // Estimate black point for this row and load it: try { image.estimateBlackPoint(BlackPointEstimationMethod.ROW_SAMPLING, rowNumber); } catch (ReaderException re) { continue; } image.getBlackRow(rowNumber, row,0, width); // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to // handle decoding upside down barcodes. for (int attempt = 0; attempt < 2; attempt++) { if (attempt == 1) { // trying again? row.reverse(); // reverse the row and continue } try { // Look for a barcode Result result = decodeRow(rowNumber, row, hints); // We found our barcode if (attempt == 1) { // But it was upside down, so note that result.putMetadata(ResultMetadataType.ORIENTATION, 180); // And remember to flip the result points horizontally. ResultPoint[] points = result.getResultPoints(); points[0] = (ResultPoint) new GenericResultPoint(width - points[0].getX() - 1, points[0].getY()); points[1] = (ResultPoint)new GenericResultPoint(width - points[1].getX() - 1, points[1].getY()); } return result; } catch (ReaderException re) { // continue -- just couldn't decode this row } } } throw new ReaderException(); }