/// <summary> Identify where the end of the middle / payload section ends. /// /// </summary> /// <param name="row">row of black/white values to search /// </param> /// <returns> Array, containing index of start of 'end block' and end of 'end /// block' /// </returns> /// <throws> ReaderException </throws> internal int[] decodeEnd(BitArray row) { // For convenience, reverse the row and then // search from 'the start' for the end block row.reverse(); try { int endStart = skipWhiteSpace(row); int[] endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED); // 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 recalculate the indices of where the 'endblock' starts & stops to // accommodate // the reversed nature of the search int temp = endPattern[0]; endPattern[0] = row.Size - endPattern[1]; endPattern[1] = row.Size - temp; return(endPattern); } finally { // Put the row back the right way. row.reverse(); } }
protected internal override int decodeMiddle(BitArray row, int[] startRange, System.Text.StringBuilder result) { int[] counters = decodeMiddleCounters; counters[0] = 0; counters[1] = 0; counters[2] = 0; counters[3] = 0; int end = row.Size; int rowOffset = startRange[1]; int lgPatternFound = 0; for (int x = 0; x < 6 && rowOffset < end; x++) { int bestMatch = decodeDigit(row, counters, rowOffset, L_AND_G_PATTERNS); result.Append((char)('0' + bestMatch % 10)); for (int i = 0; i < counters.Length; i++) { rowOffset += counters[i]; } if (bestMatch >= 10) { lgPatternFound |= 1 << (5 - x); } } determineNumSysAndCheckDigit(result, lgPatternFound); return(rowOffset); }
/// <summary> Attempts to decode a single UPC/EAN-encoded digit. /// /// </summary> /// <param name="row">row of black/white values to decode /// </param> /// <param name="counters">the counts of runs of observed black/white/black/... values /// </param> /// <param name="rowOffset">horizontal offset to start decoding from /// </param> /// <param name="patterns">the set of patterns to use to decode -- sometimes different encodings /// for the digits 0-9 are used, and this indicates the encodings for 0 to 9 that should /// be used /// </param> /// <returns> horizontal offset of first pixel beyond the decoded digit /// </returns> /// <throws> ReaderException if digit cannot be decoded </throws> internal static int decodeDigit(BitArray row, int[] counters, int rowOffset, int[][] patterns) { recordPattern(row, rowOffset, counters); int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept int bestMatch = -1; int max = patterns.Length; for (int i = 0; i < max; i++) { int[] pattern = patterns[i]; int variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); if (variance < bestVariance) { bestVariance = variance; bestMatch = i; } } if (bestMatch >= 0) { return(bestMatch); } else { throw ReaderException.Instance; } }
protected internal override int decodeMiddle(BitArray row, int[] startRange, System.Text.StringBuilder result) { int[] counters = decodeMiddleCounters; counters[0] = 0; counters[1] = 0; counters[2] = 0; counters[3] = 0; int end = row.Size; int rowOffset = startRange[1]; int lgPatternFound = 0; for (int x = 0; x < 6 && rowOffset < end; x++) { int bestMatch = decodeDigit(row, counters, rowOffset, L_AND_G_PATTERNS); result.Append((char) ('0' + bestMatch % 10)); for (int i = 0; i < counters.Length; i++) { rowOffset += counters[i]; } if (bestMatch >= 10) { lgPatternFound |= 1 << (5 - x); } } determineNumSysAndCheckDigit(result, lgPatternFound); return rowOffset; }
protected internal override int decodeMiddle(BitArray row, int[] startRange, System.Text.StringBuilder result) { int[] counters = decodeMiddleCounters; counters[0] = 0; counters[1] = 0; counters[2] = 0; counters[3] = 0; int end = row.Size; int rowOffset = startRange[1]; for (int x = 0; x < 4 && rowOffset < end; x++) { int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS); result.Append((char)('0' + bestMatch)); for (int i = 0; i < counters.Length; i++) { rowOffset += counters[i]; } } int[] middleRange = findGuardPattern(row, rowOffset, true, MIDDLE_PATTERN); rowOffset = middleRange[1]; for (int x = 0; x < 4 && rowOffset < end; x++) { int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS); result.Append((char)('0' + bestMatch)); for (int i = 0; i < counters.Length; i++) { rowOffset += counters[i]; } } return(rowOffset); }
private static int decodeCode(BitArray row, int[] counters, int rowOffset) { recordPattern(row, rowOffset, counters); int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept int bestMatch = -1; for (int d = 0; d < CODE_PATTERNS.Length; d++) { int[] pattern = CODE_PATTERNS[d]; int variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); if (variance < bestVariance) { bestVariance = variance; bestMatch = d; } } // TODO We're overlooking the fact that the STOP pattern has 7 values, not 6. if (bestMatch >= 0) { return(bestMatch); } else { throw ReaderException.Instance; } }
/// <param name="row"> row of black/white values to search /// </param> /// <param name="payloadStart">offset of start pattern /// </param> /// <param name="resultString">{@link StringBuffer} to append decoded chars to /// </param> /// <throws> ReaderException if decoding could not complete successfully </throws> private static void decodeMiddle(BitArray row, int payloadStart, int payloadEnd, System.Text.StringBuilder resultString) { // Digits are interleaved in pairs - 5 black lines for one digit, and the // 5 // interleaved white lines for the second digit. // Therefore, need to scan 10 lines and then // split these into two arrays int[] counterDigitPair = new int[10]; int[] counterBlack = new int[5]; int[] counterWhite = new int[5]; while (payloadStart < payloadEnd) { // Get 10 runs of black/white. recordPattern(row, payloadStart, counterDigitPair); // Split them into each array for (int k = 0; k < 5; k++) { int twoK = k << 1; counterBlack[k] = counterDigitPair[twoK]; counterWhite[k] = counterDigitPair[twoK + 1]; } int bestMatch = decodeDigit(counterBlack); resultString.Append((char)('0' + bestMatch)); bestMatch = decodeDigit(counterWhite); resultString.Append((char)('0' + bestMatch)); for (int i = 0; i < counterDigitPair.Length; i++) { payloadStart += counterDigitPair[i]; } } }
protected internal override int decodeMiddle(BitArray row, int[] startRange, System.Text.StringBuilder result) { int[] counters = decodeMiddleCounters; counters[0] = 0; counters[1] = 0; counters[2] = 0; counters[3] = 0; int end = row.Size; int rowOffset = startRange[1]; for (int x = 0; x < 4 && rowOffset < end; x++) { int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS); result.Append((char) ('0' + bestMatch)); for (int i = 0; i < counters.Length; i++) { rowOffset += counters[i]; } } int[] middleRange = findGuardPattern(row, rowOffset, true, MIDDLE_PATTERN); rowOffset = middleRange[1]; for (int x = 0; x < 4 && rowOffset < end; x++) { int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS); result.Append((char) ('0' + bestMatch)); for (int i = 0; i < counters.Length; i++) { rowOffset += counters[i]; } } return rowOffset; }
private static int[] findAsteriskPattern(BitArray row) { int width = row.Size; int rowOffset = 0; while (rowOffset < width) { if (row.get_Renamed(rowOffset)) { break; } rowOffset++; } int counterPosition = 0; int[] counters = new int[9]; int patternStart = rowOffset; bool isWhite = false; int patternLength = counters.Length; for (int i = rowOffset; i < width; i++) { bool pixel = row.get_Renamed(i); if (pixel ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { if (toNarrowWidePattern(counters) == ASTERISK_ENCODING) { // Look for whitespace before start pattern, >= 50% of width of start pattern if (row.isRange(System.Math.Max(0, patternStart - (i - patternStart) / 2), patternStart, false)) { return(new int[] { patternStart, i }); } } patternStart += counters[0] + counters[1]; for (int y = 2; y < patternLength; y++) { counters[y - 2] = counters[y]; } counters[patternLength - 2] = 0; counters[patternLength - 1] = 0; counterPosition--; } else { counterPosition++; } counters[counterPosition] = 1; isWhite = !isWhite; } } throw ReaderException.Instance; }
/// <param name="row">row of black/white values to search /// </param> /// <param name="rowOffset">position to start search /// </param> /// <param name="whiteFirst">if true, indicates that the pattern specifies white/black/white/... /// pixel counts, otherwise, it is interpreted as black/white/black/... /// </param> /// <param name="pattern">pattern of counts of number of black and white pixels that are being /// searched for as a pattern /// </param> /// <returns> start/end horizontal offset of guard pattern, as an array of two ints /// </returns> /// <throws> ReaderException if pattern is not found </throws> internal static int[] findGuardPattern(BitArray row, int rowOffset, bool whiteFirst, int[] pattern) { int patternLength = pattern.Length; int[] counters = new int[patternLength]; int width = row.Size; bool isWhite = false; while (rowOffset < width) { isWhite = !row.get_Renamed(rowOffset); if (whiteFirst == isWhite) { break; } rowOffset++; } int counterPosition = 0; int patternStart = rowOffset; for (int x = rowOffset; x < width; x++) { bool pixel = row.get_Renamed(x); if (pixel ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { return(new int[] { patternStart, x }); } patternStart += counters[0] + counters[1]; for (int y = 2; y < patternLength; y++) { counters[y - 2] = counters[y]; } counters[patternLength - 2] = 0; counters[patternLength - 1] = 0; counterPosition--; } else { counterPosition++; } counters[counterPosition] = 1; isWhite = !isWhite; } } throw ReaderException.Instance; }
/// <summary> <p>Like {@link #decodeRow(int, BitArray, java.util.Hashtable)}, but /// allows caller to inform method about where the UPC/EAN start pattern is /// found. This allows this to be computed once and reused across many implementations.</p> /// </summary> // public virtual Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange, System.Collections.Hashtable hints) // commented by .net follower (http://dotnetfollower.com) public virtual Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange, System.Collections.Generic.Dictionary <Object, Object> hints) // added by .net follower (http://dotnetfollower.com) { // ResultPointCallback resultPointCallback = hints == null?null:(ResultPointCallback) hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; // commented by .net follower (http://dotnetfollower.com) ResultPointCallback resultPointCallback = null; // added by .net follower (http://dotnetfollower.com) if (hints != null && hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK)) // added by .net follower (http://dotnetfollower.com) { resultPointCallback = (ResultPointCallback)hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; // added by .net follower (http://dotnetfollower.com) } if (resultPointCallback != null) { resultPointCallback.foundPossibleResultPoint(new ResultPoint((startGuardRange[0] + startGuardRange[1]) / 2.0f, rowNumber)); } System.Text.StringBuilder result = decodeRowStringBuffer; result.Length = 0; int endStart = decodeMiddle(row, startGuardRange, result); if (resultPointCallback != null) { resultPointCallback.foundPossibleResultPoint(new ResultPoint(endStart, rowNumber)); } int[] endRange = decodeEnd(row, endStart); if (resultPointCallback != null) { resultPointCallback.foundPossibleResultPoint(new ResultPoint((endRange[0] + endRange[1]) / 2.0f, rowNumber)); } // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The // spec might want more whitespace, but in practice this is the maximum we can count on. int end = endRange[1]; int quietEnd = end + (end - endRange[0]); if (quietEnd >= row.Size || !row.isRange(end, quietEnd, false)) { throw ReaderException.Instance; } System.String resultString = result.ToString(); if (!checkChecksum(resultString)) { throw ReaderException.Instance; } //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" float left = (float)(startGuardRange[1] + startGuardRange[0]) / 2.0f; //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" float right = (float)(endRange[1] + endRange[0]) / 2.0f; //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" return(new Result(resultString, null, new ResultPoint[] { new ResultPoint(left, (float)rowNumber), new ResultPoint(right, (float)rowNumber) }, BarcodeFormat)); }
// Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On // success, store the result in "matrix" and return true. //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: static void buildMatrix(com.google.zxing.common.BitArray dataBits, com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ecLevel, com.google.zxing.qrcode.decoder.Version version, int maskPattern, ByteMatrix matrix) throws com.google.zxing.WriterException internal static void buildMatrix(BitArray dataBits, ErrorCorrectionLevel ecLevel, Version version, int maskPattern, ByteMatrix matrix) { clearMatrix(matrix); embedBasicPatterns(version, matrix); // Type information appear with any version. embedTypeInfo(ecLevel, maskPattern, matrix); // Version info appear if version >= 7. maybeEmbedVersionInfo(version, matrix); // Data should be embedded at end. embedDataBits(dataBits, maskPattern, matrix); }
/// <summary> Identify where the start of the middle / payload section starts. /// /// </summary> /// <param name="row">row of black/white values to search /// </param> /// <returns> Array, containing index of start of 'start block' and end of /// 'start block' /// </returns> /// <throws> ReaderException </throws> internal int[] decodeStart(BitArray row) { int endStart = skipWhiteSpace(row); int[] startPattern = findGuardPattern(row, endStart, START_PATTERN); // Determine the width of a narrow line in pixels. We can do this by // getting the width of the start pattern and dividing by 4 because its // made up of 4 narrow lines. this.narrowLineWidth = (startPattern[1] - startPattern[0]) >> 2; validateQuietZone(row, startPattern[0]); return(startPattern); }
/// <summary> Records the size of successive runs of white and black pixels in a row, starting at a given point. /// The values are recorded in the given array, and the number of runs recorded is equal to the size /// of the array. If the row starts on a white pixel at the given start point, then the first count /// recorded is the run of white pixels starting from that point; likewise it is the count of a run /// of black pixels if the row begin on a black pixels at that point. /// /// </summary> /// <param name="row">row to count from /// </param> /// <param name="start">offset into row to start at /// </param> /// <param name="counters">array into which to record counts /// </param> /// <throws> ReaderException if counters cannot be filled entirely from row before running out </throws> /// <summary> of pixels /// </summary> internal static void recordPattern(BitArray row, int start, int[] counters) { int numCounters = counters.Length; for (int i = 0; i < numCounters; i++) { counters[i] = 0; } int end = row.Size; if (start >= end) { throw ReaderException.Instance; } bool isWhite = !row.get_Renamed(start); int counterPosition = 0; int i2 = start; while (i2 < end) { bool pixel = row.get_Renamed(i2); if (pixel ^ isWhite) { // that is, exactly one is true counters[counterPosition]++; } else { counterPosition++; if (counterPosition == numCounters) { break; } else { counters[counterPosition] = 1; isWhite ^= true; // isWhite = !isWhite; } } i2++; } // If we read fully the last section of pixels and filled up our counters -- or filled // the last counter but ran off the side of the image, OK. Otherwise, a problem. if (!(counterPosition == numCounters || (counterPosition == numCounters - 1 && i2 == end))) { throw ReaderException.Instance; } }
/// <param name="row"> row of black/white values to search /// </param> /// <param name="rowOffset">position to start search /// </param> /// <param name="pattern"> pattern of counts of number of black and white pixels that are /// being searched for as a pattern /// </param> /// <returns> start/end horizontal offset of guard pattern, as an array of two /// ints /// </returns> /// <throws> ReaderException if pattern is not found </throws> private static int[] findGuardPattern(BitArray row, int rowOffset, int[] pattern) { // TODO: This is very similar to implementation in UPCEANReader. Consider if they can be // merged to a single method. int patternLength = pattern.Length; int[] counters = new int[patternLength]; int width = row.Size; bool isWhite = false; int counterPosition = 0; int patternStart = rowOffset; for (int x = rowOffset; x < width; x++) { bool pixel = row.get_Renamed(x); if (pixel ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { return(new int[] { patternStart, x }); } patternStart += counters[0] + counters[1]; for (int y = 2; y < patternLength; y++) { counters[y - 2] = counters[y]; } counters[patternLength - 2] = 0; counters[patternLength - 1] = 0; counterPosition--; } else { counterPosition++; } counters[counterPosition] = 1; isWhite = !isWhite; } } throw ReaderException.Instance; }
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints) { int size = readers.Count; for (int i = 0; i < size; i++) { OneDReader reader = (OneDReader) readers[i]; try { return reader.decodeRow(rowNumber, row, hints); } catch (ReaderException re) { // continue } } throw ReaderException.Instance; }
/// <summary> 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. Scan back until /// we either get to the start of the barcode or match the necessary number of /// quiet zone pixels. /// /// Note: Its assumed the row is reversed when using this method to find /// quiet zone after the end pattern. /// /// ref: http://www.barcode-1.net/i25code.html /// /// </summary> /// <param name="row">bit array representing the scanned barcode. /// </param> /// <param name="startPattern">index into row of the start or end pattern. /// </param> /// <throws> ReaderException if the quiet zone cannot be found, a ReaderException is thrown. </throws> private void validateQuietZone(BitArray row, int startPattern) { int quietCount = this.narrowLineWidth * 10; // expect to find this many pixels of quiet zone for (int i = startPattern - 1; quietCount > 0 && i >= 0; i--) { if (row.get_Renamed(i)) { break; } quietCount--; } if (quietCount != 0) { // Unable to find the necessary number of quiet zone pixels. throw ReaderException.Instance; } }
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Generic.Dictionary <Object, Object> hints) { int size = readers.Count; for (int i = 0; i < size; i++) { OneDReader reader = (OneDReader)readers[i]; try { return(reader.decodeRow(rowNumber, row, hints)); } catch (ReaderException re) { // continue } } throw ReaderException.Instance; }
// public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints) // commented by .net follower (http://dotnetfollower.com) public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Generic.Dictionary <Object, Object> hints) // added by .net follower (http://dotnetfollower.com) { // Find out where the Middle section (payload) starts & ends int[] startRange = decodeStart(row); int[] endRange = decodeEnd(row); System.Text.StringBuilder result = new System.Text.StringBuilder(20); decodeMiddle(row, startRange[1], endRange[0], result); System.String resultString = result.ToString(); int[] allowedLengths = null; // if (hints != null) // commented by .net follower (http://dotnetfollower.com) if (hints != null && hints.ContainsKey(DecodeHintType.ALLOWED_LENGTHS)) // added by .net follower (http://dotnetfollower.com) { allowedLengths = (int[])hints[DecodeHintType.ALLOWED_LENGTHS]; } if (allowedLengths == null) { allowedLengths = DEFAULT_ALLOWED_LENGTHS; } // To avoid false positives with 2D barcodes (and other patterns), make // an assumption that the decoded string must be 6, 10 or 14 digits. int length = resultString.Length; bool lengthOK = false; for (int i = 0; i < allowedLengths.Length; i++) { if (length == allowedLengths[i]) { lengthOK = true; break; } } if (!lengthOK) { throw ReaderException.Instance; } //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" return(new Result(resultString, null, new ResultPoint[] { new ResultPoint(startRange[1], (float)rowNumber), new ResultPoint(endRange[0], (float)rowNumber) }, BarcodeFormat.ITF)); }
/// <summary> Skip all whitespace until we get to the first black line. /// /// </summary> /// <param name="row">row of black/white values to search /// </param> /// <returns> index of the first black line. /// </returns> /// <throws> ReaderException Throws exception if no black lines are found in the row </throws> private static int skipWhiteSpace(BitArray row) { int width = row.Size; int endStart = 0; while (endStart < width) { if (row.get_Renamed(endStart)) { break; } endStart++; } if (endStart == width) { throw ReaderException.Instance; } return(endStart); }
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints) { // Find out where the Middle section (payload) starts & ends int[] startRange = decodeStart(row); int[] endRange = decodeEnd(row); System.Text.StringBuilder result = new System.Text.StringBuilder(20); decodeMiddle(row, startRange[1], endRange[0], result); System.String resultString = result.ToString(); int[] allowedLengths = null; if (hints != null) { allowedLengths = (int[]) hints[DecodeHintType.ALLOWED_LENGTHS]; } if (allowedLengths == null) { allowedLengths = DEFAULT_ALLOWED_LENGTHS; } // To avoid false positives with 2D barcodes (and other patterns), make // an assumption that the decoded string must be 6, 10 or 14 digits. int length = resultString.Length; bool lengthOK = false; for (int i = 0; i < allowedLengths.Length; i++) { if (length == allowedLengths[i]) { lengthOK = true; break; } } if (!lengthOK) { throw ReaderException.Instance; } //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" return new Result(resultString, null, new ResultPoint[]{new ResultPoint(startRange[1], (float) rowNumber), new ResultPoint(endRange[0], (float) rowNumber)}, BarcodeFormat.ITF); }
internal static int[] findStartGuardPattern(BitArray row) { bool foundStart = false; int[] startRange = null; int nextStart = 0; while (!foundStart) { startRange = findGuardPattern(row, nextStart, false, START_END_PATTERN); int start = startRange[0]; nextStart = startRange[1]; // Make sure there is a quiet zone at least as big as the start pattern before the barcode. // If this check would run off the left edge of the image, do not accept this barcode, // as it is very likely to be a false positive. int quietStart = start - (nextStart - start); if (quietStart >= 0) { foundStart = row.isRange(quietStart, start, false); } } return startRange; }
public BitArray getBlackRow(int y, BitArray row, int startX, int getWidth) { if (row == null) { row = new BitArray(getWidth); } else { row.clear(); } //UPGRADE_ISSUE: Method 'java.awt.image.BufferedImage.getRGB' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javaawtimageBufferedImagegetRGB_int_int_int_int_int[]_int_int'" int[] pixelRow = getRGB(startX, y, getWidth); for (int i = 0; i < getWidth; i++) { if (computeRGBLuminance(pixelRow[i]) < blackPoint) { row.set(i); } } return(row); }
internal static int[] findStartGuardPattern(BitArray row) { bool foundStart = false; int[] startRange = null; int nextStart = 0; while (!foundStart) { startRange = findGuardPattern(row, nextStart, false, START_END_PATTERN); int start = startRange[0]; nextStart = startRange[1]; // Make sure there is a quiet zone at least as big as the start pattern before the barcode. // If this check would run off the left edge of the image, do not accept this barcode, // as it is very likely to be a false positive. int quietStart = start - (nextStart - start); if (quietStart >= 0) { foundStart = row.isRange(quietStart, start, false); } } return(startRange); }
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints) { // Compute this location once and reuse it on multiple implementations int[] startGuardPattern = UPCEANReader.findStartGuardPattern(row); int size = readers.Count; for (int i = 0; i < size; i++) { UPCEANReader reader = (UPCEANReader)readers[i]; Result result; try { result = reader.decodeRow(rowNumber, row, startGuardPattern, hints); } catch (ReaderException re) { continue; } // Special case: a 12-digit code encoded in UPC-A is identical to a "0" // followed by those 12 digits encoded as EAN-13. Each will recognize such a code, // UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with "0". // Individually these are correct and their readers will both read such a code // and correctly call it EAN-13, or UPC-A, respectively. // // In this case, if we've been looking for both types, we'd like to call it // a UPC-A code. But for efficiency we only run the EAN-13 decoder to also read // UPC-A. So we special case it here, and convert an EAN-13 result to a UPC-A // result if appropriate. if (result.BarcodeFormat.Equals(BarcodeFormat.EAN_13) && result.Text[0] == '0') { return(new Result(result.Text.Substring(1), null, result.ResultPoints, BarcodeFormat.UPC_A)); } return(result); } throw ReaderException.Instance; }
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints) { // Compute this location once and reuse it on multiple implementations int[] startGuardPattern = UPCEANReader.findStartGuardPattern(row); int size = readers.Count; for (int i = 0; i < size; i++) { UPCEANReader reader = (UPCEANReader) readers[i]; Result result; try { result = reader.decodeRow(rowNumber, row, startGuardPattern, hints); } catch (ReaderException re) { continue; } // Special case: a 12-digit code encoded in UPC-A is identical to a "0" // followed by those 12 digits encoded as EAN-13. Each will recognize such a code, // UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with "0". // Individually these are correct and their readers will both read such a code // and correctly call it EAN-13, or UPC-A, respectively. // // In this case, if we've been looking for both types, we'd like to call it // a UPC-A code. But for efficiency we only run the EAN-13 decoder to also read // UPC-A. So we special case it here, and convert an EAN-13 result to a UPC-A // result if appropriate. if (result.BarcodeFormat.Equals(BarcodeFormat.EAN_13) && result.Text[0] == '0') { return new Result(result.Text.Substring(1), null, result.ResultPoints, BarcodeFormat.UPC_A); } return result; } throw ReaderException.Instance; }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public com.google.zxing.Result decodeRow(int rowNumber, com.google.zxing.common.BitArray row, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.FormatException, com.google.zxing.ChecksumException public override Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints) { return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, hints)); }
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints) { return(maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, hints))); }
protected internal override int decodeMiddle(BitArray row, int[] startRange, System.Text.StringBuilder resultString) { return(ean13Reader.decodeMiddle(row, startRange, resultString)); }
protected internal override int decodeMiddle(BitArray row, int[] startRange, StringBuilder resultString) { int[] counters = decodeMiddleCounters; counters[0] = 0; counters[1] = 0; counters[2] = 0; counters[3] = 0; int end = row.Size; int rowOffset = startRange[1]; int lgPatternFound = 0; for (int x = 0; x < 6 && rowOffset < end; x++) { int bestMatch = decodeDigit(row, counters, rowOffset, L_AND_G_PATTERNS); resultString.Append(Int32Extend.ToChar(CharExtend.ToInt32('0') + bestMatch % 10)); for (int i = 0; i < counters.Length; i++) { rowOffset += counters[i]; } if (bestMatch >= 10) { lgPatternFound |= 1 << (5 - x); } } determineFirstDigit(resultString, lgPatternFound); int[] middleRange = findGuardPattern(row, rowOffset, true, MIDDLE_PATTERN); rowOffset = middleRange[1]; for (int x = 0; x < 6 && rowOffset < end; x++) { int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS); resultString.Append(Int32Extend.ToChar(CharExtend.ToInt32('0') + bestMatch)); for (int i = 0; i < counters.Length; i++) { rowOffset += counters[i]; } } return rowOffset; }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: private static int[] findStartPattern(com.google.zxing.common.BitArray row) throws com.google.zxing.NotFoundException private static int[] findStartPattern(BitArray row) { int width = row.Size; int rowOffset = row.getNextSet(0); int counterPosition = 0; int[] counters = new int[6]; int patternStart = rowOffset; bool isWhite = false; int patternLength = counters.Length; for (int i = rowOffset; i < width; i++) { if (row.get(i) ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { int bestVariance = MAX_AVG_VARIANCE; int bestMatch = -1; for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) { int variance = patternMatchVariance(counters, CODE_PATTERNS[startCode], MAX_INDIVIDUAL_VARIANCE); if (variance < bestVariance) { bestVariance = variance; bestMatch = startCode; } } // Look for whitespace before start pattern, >= 50% of width of start pattern if (bestMatch >= 0 && row.isRange(Math.Max(0, patternStart - (i - patternStart) / 2), patternStart, false)) { return new int[]{patternStart, i, bestMatch}; } patternStart += counters[0] + counters[1]; Array.Copy(counters, 2, counters, 0, patternLength - 2); counters[patternLength - 2] = 0; counters[patternLength - 1] = 0; counterPosition--; } else { counterPosition++; } counters[counterPosition] = 1; isWhite = !isWhite; } } throw NotFoundException.NotFoundInstance; }
protected internal override int decodeMiddle(BitArray row, int[] startRange, System.Text.StringBuilder resultString) { return ean13Reader.decodeMiddle(row, startRange, resultString); }
/// <summary> Identify where the end of the middle / payload section ends. /// /// </summary> /// <param name="row">row of black/white values to search /// </param> /// <returns> Array, containing index of start of 'end block' and end of 'end /// block' /// </returns> /// <throws> ReaderException </throws> internal int[] decodeEnd(BitArray row) { // For convenience, reverse the row and then // search from 'the start' for the end block row.reverse(); try { int endStart = skipWhiteSpace(row); int[] endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED); // 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 recalculate the indices of where the 'endblock' starts & stops to // accommodate // the reversed nature of the search int temp = endPattern[0]; endPattern[0] = row.Size - endPattern[1]; endPattern[1] = row.Size - temp; return endPattern; } finally { // Put the row back the right way. row.reverse(); } }
public BitArray getBlackColumn(int x, BitArray column, int startY, int getHeight) { return(null); }
/// <summary> /// Converts one row of luminance data to 1 bit data. May actually do the conversion, or return /// cached data. Callers should assume this method is expensive and call it as seldom as possible. /// This method is intended for decoding 1D barcodes and may choose to apply sharpening. /// For callers which only examine one row of pixels at a time, the same BitArray should be reused /// and passed in with each call for performance. However it is legal to keep more than one row /// at a time if needed. /// </summary> /// <param name="y"> The row to fetch, 0 <= y < bitmap height. </param> /// <param name="row"> An optional preallocated array. If null or too small, it will be ignored. /// If used, the Binarizer will call BitArray.clear(). Always use the returned object. </param> /// <returns> The array of bits for this row (true means black). </returns> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public abstract com.google.zxing.common.BitArray getBlackRow(int y, com.google.zxing.common.BitArray row) throws NotFoundException; public abstract BitArray getBlackRow(int y, BitArray row);
/// <summary> <p>Attempts to decode a one-dimensional barcode format given a single row of /// an image.</p> /// /// </summary> /// <param name="rowNumber">row number from top of the row /// </param> /// <param name="row">the black/white pixel data of the row /// </param> /// <param name="hints">decode hints /// </param> /// <returns> {@link Result} containing encoded string and start/end of barcode /// </returns> /// <throws> ReaderException if an error occurs or barcode cannot be found </throws> public abstract Result decodeRow(int rowNumber, BitArray row, Dictionary <object, object> hints);
/// <summary> 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". /// /// </summary> /// <param name="image">The image to decode /// </param> /// <param name="hints">Any hints that were requested /// </param> /// <returns> The contents of the decoded barcode /// </returns> /// <throws> ReaderException Any spontaneous errors which occur </throws> private Result doDecode(BinaryBitmap image, Dictionary <object, object> hints) { int width = image.Width; int height = image.Height; BitArray row = new BitArray(width); int middle = height >> 1; bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER); int rowStep = System.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 { row = image.getBlackRow(rowNumber, row); } catch (ReaderException) { continue; } // 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 // This means we will only ever draw result points *once* in the life of this method // since we want to avoid drawing the wrong points after flipping the row, and, // don't want to clutter with noise from every single row scan -- just the scans // that start on the center line. if (hints != null && hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK)) { Dictionary <object, object> newHints = new Dictionary <object, object>(); System.Collections.IEnumerator hintEnum = hints.Keys.GetEnumerator(); //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'" while (hintEnum.MoveNext()) { //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'" System.Object key = hintEnum.Current; if (!key.Equals(DecodeHintType.NEED_RESULT_POINT_CALLBACK)) { newHints[key] = hints[key]; } } hints = newHints; } } 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, (System.Object) 180); // And remember to flip the result points horizontally. ResultPoint[] points = result.ResultPoints; points[0] = new ResultPoint(width - points[0].X - 1, points[0].Y); points[1] = new ResultPoint(width - points[1].X - 1, points[1].Y); } return(result); } catch (ReaderException) { // continue -- just couldn't decode this row } } } throw ReaderException.Instance; }
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints) { int[] start = findAsteriskPattern(row); int nextStart = start[1]; int end = row.Size; // Read off white space while (nextStart < end && !row.get_Renamed(nextStart)) { nextStart++; } System.Text.StringBuilder result = new System.Text.StringBuilder(20); int[] counters = new int[9]; char decodedChar; int lastStart; do { recordPattern(row, nextStart, counters); int pattern = toNarrowWidePattern(counters); if (pattern < 0) { throw ReaderException.Instance; } decodedChar = patternToChar(pattern); result.Append(decodedChar); lastStart = nextStart; for (int i = 0; i < counters.Length; i++) { nextStart += counters[i]; } // Read off white space while (nextStart < end && !row.get_Renamed(nextStart)) { nextStart++; } }while (decodedChar != '*'); result.Remove(result.Length - 1, 1); // remove asterisk // Look for whitespace after pattern: int lastPatternSize = 0; for (int i = 0; i < counters.Length; i++) { lastPatternSize += counters[i]; } int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize; // If 50% of last pattern size, following last pattern, is not whitespace, fail // (but if it's whitespace to the very end of the image, that's OK) if (nextStart != end && whiteSpaceAfterEnd / 2 < lastPatternSize) { throw ReaderException.Instance; } if (usingCheckDigit) { int max = result.Length - 1; int total = 0; for (int i = 0; i < max; i++) { total += ALPHABET_STRING.IndexOf((System.Char)result[i]); } if (total % 43 != ALPHABET_STRING.IndexOf((System.Char)result[max])) { throw ReaderException.Instance; } result.Remove(max, 1); } System.String resultString = result.ToString(); if (extendedMode) { resultString = decodeExtended(resultString); } if (resultString.Length == 0) { // Almost surely a false positive throw ReaderException.Instance; } //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" float left = (float)(start[1] + start[0]) / 2.0f; //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" float right = (float)(nextStart + lastStart) / 2.0f; //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" return(new Result(resultString, null, new ResultPoint[] { new ResultPoint(left, (float)rowNumber), new ResultPoint(right, (float)rowNumber) }, BarcodeFormat.CODE_39)); }
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints) { return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, hints)); }
/// <param name="row"> row of black/white values to search /// </param> /// <param name="payloadStart">offset of start pattern /// </param> /// <param name="resultString">{@link StringBuffer} to append decoded chars to /// </param> /// <throws> ReaderException if decoding could not complete successfully </throws> private static void decodeMiddle(BitArray row, int payloadStart, int payloadEnd, System.Text.StringBuilder resultString) { // Digits are interleaved in pairs - 5 black lines for one digit, and the // 5 // interleaved white lines for the second digit. // Therefore, need to scan 10 lines and then // split these into two arrays int[] counterDigitPair = new int[10]; int[] counterBlack = new int[5]; int[] counterWhite = new int[5]; while (payloadStart < payloadEnd) { // Get 10 runs of black/white. recordPattern(row, payloadStart, counterDigitPair); // Split them into each array for (int k = 0; k < 5; k++) { int twoK = k << 1; counterBlack[k] = counterDigitPair[twoK]; counterWhite[k] = counterDigitPair[twoK + 1]; } int bestMatch = decodeDigit(counterBlack); resultString.Append((char) ('0' + bestMatch)); bestMatch = decodeDigit(counterWhite); resultString.Append((char) ('0' + bestMatch)); for (int i = 0; i < counterDigitPair.Length; i++) { payloadStart += counterDigitPair[i]; } } }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: private static int decodeCode(com.google.zxing.common.BitArray row, int[] counters, int rowOffset) throws com.google.zxing.NotFoundException private static int decodeCode(BitArray row, int[] counters, int rowOffset) { recordPattern(row, rowOffset, counters); int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept int bestMatch = -1; for (int d = 0; d < CODE_PATTERNS.Length; d++) { int[] pattern = CODE_PATTERNS[d]; int variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); if (variance < bestVariance) { bestVariance = variance; bestMatch = d; } } // TODO We're overlooking the fact that the STOP pattern has 7 values, not 6. if (bestMatch >= 0) { return bestMatch; } else { throw NotFoundException.NotFoundInstance; } }
/// <summary> Skip all whitespace until we get to the first black line. /// /// </summary> /// <param name="row">row of black/white values to search /// </param> /// <returns> index of the first black line. /// </returns> /// <throws> ReaderException Throws exception if no black lines are found in the row </throws> private static int skipWhiteSpace(BitArray row) { int width = row.Size; int endStart = 0; while (endStart < width) { if (row.get_Renamed(endStart)) { break; } endStart++; } if (endStart == width) { throw ReaderException.Instance; } return endStart; }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public com.google.zxing.Result decodeRow(int rowNumber, com.google.zxing.common.BitArray row, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.FormatException, com.google.zxing.ChecksumException public override Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints) { int[] startPatternInfo = findStartPattern(row); int startCode = startPatternInfo[2]; int codeSet; switch (startCode) { case CODE_START_A: codeSet = CODE_CODE_A; break; case CODE_START_B: codeSet = CODE_CODE_B; break; case CODE_START_C: codeSet = CODE_CODE_C; break; default: throw FormatException.FormatInstance; } bool done = false; bool isNextShifted = false; StringBuilder result = new StringBuilder(20); IList<sbyte> rawCodes = new List<sbyte>(20); int lastStart = startPatternInfo[0]; int nextStart = startPatternInfo[1]; int[] counters = new int[6]; int lastCode = 0; int code = 0; int checksumTotal = startCode; int multiplier = 0; bool lastCharacterWasPrintable = true; while (!done) { bool unshift = isNextShifted; isNextShifted = false; // Save off last code lastCode = code; // Decode another code from image code = decodeCode(row, counters, nextStart); rawCodes.Add((sbyte) code); // Remember whether the last code was printable or not (excluding CODE_STOP) if (code != CODE_STOP) { lastCharacterWasPrintable = true; } // Add to checksum computation (if not CODE_STOP of course) if (code != CODE_STOP) { multiplier++; checksumTotal += multiplier * code; } // Advance to where the next code will to start lastStart = nextStart; foreach (int counter in counters) { nextStart += counter; } // Take care of illegal start codes switch (code) { case CODE_START_A: case CODE_START_B: case CODE_START_C: throw FormatException.FormatInstance; } switch (codeSet) { case CODE_CODE_A: if (code < 64) { result.Append((char)(' ' + code)); } else if (code < 96) { result.Append((char)(code - 64)); } else { // Don't let CODE_STOP, which always appears, affect whether whether we think the last // code was printable or not. if (code != CODE_STOP) { lastCharacterWasPrintable = false; } switch (code) { case CODE_FNC_1: case CODE_FNC_2: case CODE_FNC_3: case CODE_FNC_4_A: // do nothing? break; case CODE_SHIFT: isNextShifted = true; codeSet = CODE_CODE_B; break; case CODE_CODE_B: codeSet = CODE_CODE_B; break; case CODE_CODE_C: codeSet = CODE_CODE_C; break; case CODE_STOP: done = true; break; } } break; case CODE_CODE_B: if (code < 96) { result.Append((char)(' ' + code)); } else { if (code != CODE_STOP) { lastCharacterWasPrintable = false; } switch (code) { case CODE_FNC_1: case CODE_FNC_2: case CODE_FNC_3: case CODE_FNC_4_B: // do nothing? break; case CODE_SHIFT: isNextShifted = true; codeSet = CODE_CODE_A; break; case CODE_CODE_A: codeSet = CODE_CODE_A; break; case CODE_CODE_C: codeSet = CODE_CODE_C; break; case CODE_STOP: done = true; break; } } break; case CODE_CODE_C: if (code < 100) { if (code < 10) { result.Append('0'); } result.Append(code); } else { if (code != CODE_STOP) { lastCharacterWasPrintable = false; } switch (code) { case CODE_FNC_1: // do nothing? break; case CODE_CODE_A: codeSet = CODE_CODE_A; break; case CODE_CODE_B: codeSet = CODE_CODE_B; break; case CODE_STOP: done = true; break; } } break; } // Unshift back to another code set if we were shifted if (unshift) { codeSet = codeSet == CODE_CODE_A ? CODE_CODE_B : CODE_CODE_A; } } // Check for ample whitespace following pattern, but, to do this we first need to remember that // we fudged decoding CODE_STOP since it actually has 7 bars, not 6. There is a black bar left // to read off. Would be slightly better to properly read. Here we just skip it: nextStart = row.getNextUnset(nextStart); if (!row.isRange(nextStart, Math.Min(row.Size, nextStart + (nextStart - lastStart) / 2), false)) { throw NotFoundException.NotFoundInstance; } // Pull out from sum the value of the penultimate check code checksumTotal -= multiplier * lastCode; // lastCode is the checksum then: if (checksumTotal % 103 != lastCode) { throw ChecksumException.ChecksumInstance; } // Need to pull out the check digits from string int resultLength = result.Length; if (resultLength == 0) { // false positive throw NotFoundException.NotFoundInstance; } // Only bother if the result had at least one character, and if the checksum digit happened to // be a printable character. If it was just interpreted as a control code, nothing to remove. if (resultLength > 0 && lastCharacterWasPrintable) { if (codeSet == CODE_CODE_C) { result.Remove(resultLength - 2, 2); } else { result.Remove(resultLength - 1, 1); } } float left = (float)(startPatternInfo[1] + startPatternInfo[0]) / 2.0f; float right = (float)(nextStart + lastStart) / 2.0f; int rawCodesSize = rawCodes.Count; sbyte[] rawBytes = new sbyte[rawCodesSize]; for (int i = 0; i < rawCodesSize; i++) { rawBytes[i] = rawCodes[i]; } return new Result(result.ToString(), rawBytes, new ResultPoint[]{new ResultPoint(left, (float) rowNumber), new ResultPoint(right, (float) rowNumber)}, BarcodeFormat.CODE_128); }
protected internal override int[] decodeEnd(BitArray row, int endStart) { return findGuardPattern(row, endStart, true, MIDDLE_END_PATTERN); }
/// <summary> 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". /// /// </summary> /// <param name="image">The image to decode /// </param> /// <param name="hints">Any hints that were requested /// </param> /// <returns> The contents of the decoded barcode /// </returns> /// <throws> ReaderException Any spontaneous errors which occur </throws> private Result doDecode(BinaryBitmap image, System.Collections.Hashtable hints) { int width = image.Width; int height = image.Height; BitArray row = new BitArray(width); int middle = height >> 1; bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER); int rowStep = System.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 { row = image.getBlackRow(rowNumber, row); } catch (ReaderException) { continue; } // 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 // This means we will only ever draw result points *once* in the life of this method // since we want to avoid drawing the wrong points after flipping the row, and, // don't want to clutter with noise from every single row scan -- just the scans // that start on the center line. if (hints != null && hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK)) { System.Collections.Hashtable newHints = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable()); // Can't use clone() in J2ME System.Collections.IEnumerator hintEnum = hints.Keys.GetEnumerator(); //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'" while (hintEnum.MoveNext()) { //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'" System.Object key = hintEnum.Current; if (!key.Equals(DecodeHintType.NEED_RESULT_POINT_CALLBACK)) { newHints[key] = hints[key]; } } hints = newHints; } } 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, (System.Object) 180); // And remember to flip the result points horizontally. ResultPoint[] points = result.ResultPoints; points[0] = new ResultPoint(width - points[0].X - 1, points[0].Y); points[1] = new ResultPoint(width - points[1].X - 1, points[1].Y); } return result; } catch (ReaderException) { // continue -- just couldn't decode this row } } } throw ReaderException.Instance; }
private static int[] findAsteriskPattern(BitArray row) { int width = row.Size; int rowOffset = 0; while (rowOffset < width) { if (row.get_Renamed(rowOffset)) { break; } rowOffset++; } int counterPosition = 0; int[] counters = new int[9]; int patternStart = rowOffset; bool isWhite = false; int patternLength = counters.Length; for (int i = rowOffset; i < width; i++) { bool pixel = row.get_Renamed(i); if (pixel ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { if (toNarrowWidePattern(counters) == ASTERISK_ENCODING) { // Look for whitespace before start pattern, >= 50% of width of start pattern if (row.isRange(System.Math.Max(0, patternStart - (i - patternStart) / 2), patternStart, false)) { return new int[]{patternStart, i}; } } patternStart += counters[0] + counters[1]; for (int y = 2; y < patternLength; y++) { counters[y - 2] = counters[y]; } counters[patternLength - 2] = 0; counters[patternLength - 1] = 0; counterPosition--; } else { counterPosition++; } counters[counterPosition] = 1; isWhite = !isWhite; } } throw ReaderException.Instance; }
public override Result decodeRow(int rowNumber, BitArray row, Dictionary <object, object> hints) { return(maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, hints))); }
/// <summary> <p>Attempts to decode a one-dimensional barcode format given a single row of /// an image.</p> /// /// </summary> /// <param name="rowNumber">row number from top of the row /// </param> /// <param name="row">the black/white pixel data of the row /// </param> /// <param name="hints">decode hints /// </param> /// <returns> {@link Result} containing encoded string and start/end of barcode /// </returns> /// <throws> ReaderException if an error occurs or barcode cannot be found </throws> public abstract Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints);
/// <summary> Converts one row of luminance data to 1 bit data. May actually do the conversion, or return /// cached data. Callers should assume this method is expensive and call it as seldom as possible. /// This method is intended for decoding 1D barcodes and may choose to apply sharpening. /// /// </summary> /// <param name="y">The row to fetch, 0 <= y < bitmap height. /// </param> /// <param name="row">An optional preallocated array. If null or too small, it will be ignored. /// If used, the Binarizer will call BitArray.clear(). Always use the returned object. /// </param> /// <returns> The array of bits for this row (true means black). /// </returns> public BitArray getBlackRow(int y, BitArray row) { return binarizer.getBlackRow(y, row); }
protected internal override int[] decodeEnd(BitArray row, int endStart) { return(findGuardPattern(row, endStart, true, MIDDLE_END_PATTERN)); }
/// <summary> Identify where the start of the middle / payload section starts. /// /// </summary> /// <param name="row">row of black/white values to search /// </param> /// <returns> Array, containing index of start of 'start block' and end of /// 'start block' /// </returns> /// <throws> ReaderException </throws> internal int[] decodeStart(BitArray row) { int endStart = skipWhiteSpace(row); int[] startPattern = findGuardPattern(row, endStart, START_PATTERN); // Determine the width of a narrow line in pixels. We can do this by // getting the width of the start pattern and dividing by 4 because its // made up of 4 narrow lines. this.narrowLineWidth = (startPattern[1] - startPattern[0]) >> 2; validateQuietZone(row, startPattern[0]); return startPattern; }
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints) { int[] startPatternInfo = findStartPattern(row); int startCode = startPatternInfo[2]; int codeSet; switch (startCode) { case CODE_START_A: codeSet = CODE_CODE_A; break; case CODE_START_B: codeSet = CODE_CODE_B; break; case CODE_START_C: codeSet = CODE_CODE_C; break; default: throw ReaderException.Instance; } bool done = false; bool isNextShifted = false; System.Text.StringBuilder result = new System.Text.StringBuilder(20); int lastStart = startPatternInfo[0]; int nextStart = startPatternInfo[1]; int[] counters = new int[6]; int lastCode = 0; int code = 0; int checksumTotal = startCode; int multiplier = 0; bool lastCharacterWasPrintable = true; while (!done) { bool unshift = isNextShifted; isNextShifted = false; // Save off last code lastCode = code; // Decode another code from image code = decodeCode(row, counters, nextStart); // Remember whether the last code was printable or not (excluding CODE_STOP) if (code != CODE_STOP) { lastCharacterWasPrintable = true; } // Add to checksum computation (if not CODE_STOP of course) if (code != CODE_STOP) { multiplier++; checksumTotal += multiplier * code; } // Advance to where the next code will to start lastStart = nextStart; for (int i = 0; i < counters.Length; i++) { nextStart += counters[i]; } // Take care of illegal start codes switch (code) { case CODE_START_A: case CODE_START_B: case CODE_START_C: throw ReaderException.Instance; } switch (codeSet) { case CODE_CODE_A: if (code < 64) { result.Append((char)(' ' + code)); } else if (code < 96) { result.Append((char)(code - 64)); } else { // Don't let CODE_STOP, which always appears, affect whether whether we think the last // code was printable or not. if (code != CODE_STOP) { lastCharacterWasPrintable = false; } switch (code) { case CODE_FNC_1: case CODE_FNC_2: case CODE_FNC_3: case CODE_FNC_4_A: // do nothing? break; case CODE_SHIFT: isNextShifted = true; codeSet = CODE_CODE_B; break; case CODE_CODE_B: codeSet = CODE_CODE_B; break; case CODE_CODE_C: codeSet = CODE_CODE_C; break; case CODE_STOP: done = true; break; } } break; case CODE_CODE_B: if (code < 96) { result.Append((char)(' ' + code)); } else { if (code != CODE_STOP) { lastCharacterWasPrintable = false; } switch (code) { case CODE_FNC_1: case CODE_FNC_2: case CODE_FNC_3: case CODE_FNC_4_B: // do nothing? break; case CODE_SHIFT: isNextShifted = true; codeSet = CODE_CODE_C; break; case CODE_CODE_A: codeSet = CODE_CODE_A; break; case CODE_CODE_C: codeSet = CODE_CODE_C; break; case CODE_STOP: done = true; break; } } break; case CODE_CODE_C: if (code < 100) { if (code < 10) { result.Append('0'); } result.Append(code); } else { if (code != CODE_STOP) { lastCharacterWasPrintable = false; } switch (code) { case CODE_FNC_1: // do nothing? break; case CODE_CODE_A: codeSet = CODE_CODE_A; break; case CODE_CODE_B: codeSet = CODE_CODE_B; break; case CODE_STOP: done = true; break; } } break; } // Unshift back to another code set if we were shifted if (unshift) { switch (codeSet) { case CODE_CODE_A: codeSet = CODE_CODE_C; break; case CODE_CODE_B: codeSet = CODE_CODE_A; break; case CODE_CODE_C: codeSet = CODE_CODE_B; break; } } } // Check for ample whitespace following pattern, but, to do this we first need to remember that // we fudged decoding CODE_STOP since it actually has 7 bars, not 6. There is a black bar left // to read off. Would be slightly better to properly read. Here we just skip it: int width = row.Size; while (nextStart < width && row.get_Renamed(nextStart)) { nextStart++; } if (!row.isRange(nextStart, System.Math.Min(width, nextStart + (nextStart - lastStart) / 2), false)) { throw ReaderException.Instance; } // Pull out from sum the value of the penultimate check code checksumTotal -= multiplier * lastCode; // lastCode is the checksum then: if (checksumTotal % 103 != lastCode) { throw ReaderException.Instance; } // Need to pull out the check digits from string int resultLength = result.Length; // Only bother if the result had at least one character, and if the checksum digit happened to // be a printable character. If it was just interpreted as a control code, nothing to remove. if (resultLength > 0 && lastCharacterWasPrintable) { if (codeSet == CODE_CODE_C) { result.Remove(resultLength - 2, resultLength - (resultLength - 2)); } else { result.Remove(resultLength - 1, resultLength - (resultLength - 1)); } } System.String resultString = result.ToString(); if (resultString.Length == 0) { // Almost surely a false positive throw ReaderException.Instance; } //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" float left = (float)(startPatternInfo[1] + startPatternInfo[0]) / 2.0f; //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" float right = (float)(nextStart + lastStart) / 2.0f; //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" return(new Result(resultString, null, new ResultPoint[] { new ResultPoint(left, (float)rowNumber), new ResultPoint(right, (float)rowNumber) }, BarcodeFormat.CODE_128)); }
/// <param name="row"> row of black/white values to search /// </param> /// <param name="rowOffset">position to start search /// </param> /// <param name="pattern"> pattern of counts of number of black and white pixels that are /// being searched for as a pattern /// </param> /// <returns> start/end horizontal offset of guard pattern, as an array of two /// ints /// </returns> /// <throws> ReaderException if pattern is not found </throws> private static int[] findGuardPattern(BitArray row, int rowOffset, int[] pattern) { // TODO: This is very similar to implementation in UPCEANReader. Consider if they can be // merged to a single method. int patternLength = pattern.Length; int[] counters = new int[patternLength]; int width = row.Size; bool isWhite = false; int counterPosition = 0; int patternStart = rowOffset; for (int x = rowOffset; x < width; x++) { bool pixel = row.get_Renamed(x); if (pixel ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { return new int[]{patternStart, x}; } patternStart += counters[0] + counters[1]; for (int y = 2; y < patternLength; y++) { counters[y - 2] = counters[y]; } counters[patternLength - 2] = 0; counters[patternLength - 1] = 0; counterPosition--; } else { counterPosition++; } counters[counterPosition] = 1; isWhite = !isWhite; } } throw ReaderException.Instance; }
private static int[] findStartPattern(BitArray row) { int width = row.Size; int rowOffset = 0; while (rowOffset < width) { if (row.get_Renamed(rowOffset)) { break; } rowOffset++; } int counterPosition = 0; int[] counters = new int[6]; int patternStart = rowOffset; bool isWhite = false; int patternLength = counters.Length; for (int i = rowOffset; i < width; i++) { bool pixel = row.get_Renamed(i); if (pixel ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { int bestVariance = MAX_AVG_VARIANCE; int bestMatch = -1; for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) { int variance = patternMatchVariance(counters, CODE_PATTERNS[startCode], MAX_INDIVIDUAL_VARIANCE); if (variance < bestVariance) { bestVariance = variance; bestMatch = startCode; } } if (bestMatch >= 0) { // Look for whitespace before start pattern, >= 50% of width of start pattern if (row.isRange(System.Math.Max(0, patternStart - (i - patternStart) / 2), patternStart, false)) { return(new int[] { patternStart, i, bestMatch }); } } patternStart += counters[0] + counters[1]; for (int y = 2; y < patternLength; y++) { counters[y - 2] = counters[y]; } counters[patternLength - 2] = 0; counters[patternLength - 1] = 0; counterPosition--; } else { counterPosition++; } counters[counterPosition] = 1; isWhite = !isWhite; } } throw ReaderException.Instance; }
// public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints) // commented by .net follower (http://dotnetfollower.com) public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Generic.Dictionary <Object, Object> hints) // added by .net follower (http://dotnetfollower.com) { return(maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, hints))); }
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints) { int[] start = findAsteriskPattern(row); int nextStart = start[1]; int end = row.Size; // Read off white space while (nextStart < end && !row.get_Renamed(nextStart)) { nextStart++; } System.Text.StringBuilder result = new System.Text.StringBuilder(20); int[] counters = new int[9]; char decodedChar; int lastStart; do { recordPattern(row, nextStart, counters); int pattern = toNarrowWidePattern(counters); if (pattern < 0) { throw ReaderException.Instance; } decodedChar = patternToChar(pattern); result.Append(decodedChar); lastStart = nextStart; for (int i = 0; i < counters.Length; i++) { nextStart += counters[i]; } // Read off white space while (nextStart < end && !row.get_Renamed(nextStart)) { nextStart++; } } while (decodedChar != '*'); result.Remove(result.Length - 1, 1); // remove asterisk // Look for whitespace after pattern: int lastPatternSize = 0; for (int i = 0; i < counters.Length; i++) { lastPatternSize += counters[i]; } int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize; // If 50% of last pattern size, following last pattern, is not whitespace, fail // (but if it's whitespace to the very end of the image, that's OK) if (nextStart != end && whiteSpaceAfterEnd / 2 < lastPatternSize) { throw ReaderException.Instance; } if (usingCheckDigit) { int max = result.Length - 1; int total = 0; for (int i = 0; i < max; i++) { total += ALPHABET_STRING.IndexOf((System.Char) result[i]); } if (total % 43 != ALPHABET_STRING.IndexOf((System.Char) result[max])) { throw ReaderException.Instance; } result.Remove(max, 1); } System.String resultString = result.ToString(); if (extendedMode) { resultString = decodeExtended(resultString); } if (resultString.Length == 0) { // Almost surely a false positive throw ReaderException.Instance; } //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" float left = (float) (start[1] + start[0]) / 2.0f; //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" float right = (float) (nextStart + lastStart) / 2.0f; //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" return new Result(resultString, null, new ResultPoint[]{new ResultPoint(left, (float) rowNumber), new ResultPoint(right, (float) rowNumber)}, BarcodeFormat.CODE_39); }
// added by .net follower (http://dotnetfollower.com) // public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints) // commented by .net follower (http://dotnetfollower.com) public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Generic.Dictionary<Object, Object> hints) { return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, hints)); }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public com.google.zxing.Result decodeRow(int rowNumber, com.google.zxing.common.BitArray row, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException public override Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints) { // Compute this location once and reuse it on multiple implementations int[] startGuardPattern = UPCEANReader.findStartGuardPattern(row); foreach (UPCEANReader reader in readers) { Result result; try { result = reader.decodeRow(rowNumber, row, startGuardPattern, hints); } catch (ReaderException re) { continue; } // Special case: a 12-digit code encoded in UPC-A is identical to a "0" // followed by those 12 digits encoded as EAN-13. Each will recognize such a code, // UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with "0". // Individually these are correct and their readers will both read such a code // and correctly call it EAN-13, or UPC-A, respectively. // // In this case, if we've been looking for both types, we'd like to call it // a UPC-A code. But for efficiency we only run the EAN-13 decoder to also read // UPC-A. So we special case it here, and convert an EAN-13 result to a UPC-A // result if appropriate. // // But, don't return UPC-A if UPC-A was not a requested format! bool ean13MayBeUPCA = result.BarcodeFormat == BarcodeFormat.EAN_13 && result.Text[0] == '0'; //ICollection<BarcodeFormat> possibleFormats = hints == null ? null : (ICollection<BarcodeFormat>) hints[DecodeHintType.POSSIBLE_FORMATS]; ICollection<BarcodeFormat> possibleFormats = null; if (hints != null && hints.ContainsKey(DecodeHintType.POSSIBLE_FORMATS)) { possibleFormats = (ICollection<BarcodeFormat>)hints[DecodeHintType.POSSIBLE_FORMATS]; } bool canReturnUPCA = possibleFormats == null || possibleFormats.Contains(BarcodeFormat.UPC_A); if (ean13MayBeUPCA && canReturnUPCA) { // Transfer the metdata across Result resultUPCA = new Result(result.Text.Substring(1), result.RawBytes, result.ResultPoints, BarcodeFormat.UPC_A); resultUPCA.putAllMetadata(result.ResultMetadata); return resultUPCA; } return result; } throw NotFoundException.NotFoundInstance; }