public getNextSet ( int from ) : int | ||
from | int | first bit to check |
return | int |
public void testGetNextSet5() { Random r = new Random((int)DateTime.Now.Ticks); for (int i = 0; i < 10; i++) { BitArray array = new BitArray(1 + r.Next(100)); int numSet = r.Next(20); for (int j = 0; j < numSet; j++) { array[r.Next(array.Size)] = true; } int numQueries = r.Next(20); for (int j = 0; j < numQueries; j++) { int query = r.Next(array.Size); int expected = query; while (expected < array.Size && !array[expected]) { expected++; } int actual = array.getNextSet(query); if (actual != expected) { array.getNextSet(query); } Assert.AreEqual(expected, actual); } } }
public void testGetNextSet1() { BitArray array = new BitArray(32); for (int i = 0; i < array.Size; i++) { Assert.AreEqual(32, array.getNextSet(i)); } array = new BitArray(33); for (int i = 0; i < array.Size; i++) { Assert.AreEqual(33, array.getNextSet(i)); } }
public void testGetNextSet2() { BitArray array = new BitArray(33); array[31] = true; for (int i = 0; i < array.Size; i++) { Assert.AreEqual(i <= 31 ? 31 : 33, array.getNextSet(i)); } array = new BitArray(33); array[32] = true; for (int i = 0; i < array.Size; i++) { Assert.AreEqual(32, array.getNextSet(i)); } }
public void testGetNextSet3() { BitArray array = new BitArray(63); array[31] = true; array[32] = true; for (int i = 0; i < array.Size; i++) { int expected; if (i <= 31) { expected = 31; } else if (i == 32) { expected = 32; } else { expected = 63; } Assert.AreEqual(expected, array.getNextSet(i)); } }
public void testGetNextSet4() { BitArray array = new BitArray(63); array[33] = true; array[40] = true; for (int i = 0; i < array.Size; i++) { int expected; if (i <= 33) { expected = 33; } else if (i <= 40) { expected = 40; } else { expected = 63; } Assert.AreEqual(expected, array.getNextSet(i)); } }
/// <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><see cref="Result"/>containing encoded string and start/end of barcode</returns> override public Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints) { for (var index = 0; index < counters.Length; index++) counters[index] = 0; decodeRowResult.Length = 0; int[] start = findAsteriskPattern(row); if (start == null) return null; // Read off white space int nextStart = row.getNextSet(start[1]); int end = row.Size; char decodedChar; int lastStart; do { if (!recordPattern(row, nextStart, counters)) return null; int pattern = toPattern(counters); if (pattern < 0) { return null; } if (!patternToChar(pattern, out decodedChar)) return null; decodeRowResult.Append(decodedChar); lastStart = nextStart; foreach (int counter in counters) { nextStart += counter; } // Read off white space nextStart = row.getNextSet(nextStart); } while (decodedChar != '*'); decodeRowResult.Remove(decodeRowResult.Length - 1, 1); // remove asterisk // Should be at least one more black module if (nextStart == end || !row[nextStart]) { return null; } if (decodeRowResult.Length < 2) { // false positive -- need at least 2 checksum digits return null; } if (!checkChecksums(decodeRowResult)) return null; // Remove checksum digits decodeRowResult.Length = decodeRowResult.Length - 2; String resultString = decodeExtended(decodeRowResult); if (resultString == null) return null; float left = (start[1] + start[0])/2.0f; float right = (nextStart + lastStart)/2.0f; var resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) ? null : (ResultPointCallback) hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; if (resultPointCallback != null) { resultPointCallback(new ResultPoint(left, rowNumber)); resultPointCallback(new ResultPoint(right, rowNumber)); } return new Result( resultString, null, new[] { new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber) }, BarcodeFormat.CODE_93); }
private int[] findAsteriskPattern(BitArray row) { int width = row.Size; int rowOffset = row.getNextSet(0); for (var index = 0; index < counters.Length; index++) counters[index] = 0; int counterPosition = 0; int patternStart = rowOffset; bool isWhite = false; int patternLength = counters.Length; for (int i = rowOffset; i < width; i++) { if (row[i] ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { if (toPattern(counters) == ASTERISK_ENCODING) { return new int[] { patternStart, i }; } 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; } } return null; }
/// <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><see cref="Result"/>containing encoded string and start/end of barcode</returns> override public Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints) { for (var index = 0; index < counters.Length; index++) counters[index] = 0; decodeRowResult.Length = 0; int[] start = findAsteriskPattern(row, counters); if (start == null) return null; // Read off white space int nextStart = row.getNextSet(start[1]); int end = row.Size; char decodedChar; int lastStart; do { if (!recordPattern(row, nextStart, counters)) return null; int pattern = toNarrowWidePattern(counters); if (pattern < 0) { return null; } if (!patternToChar(pattern, out decodedChar)) return null; decodeRowResult.Append(decodedChar); lastStart = nextStart; foreach (int counter in counters) { nextStart += counter; } // Read off white space nextStart = row.getNextSet(nextStart); } while (decodedChar != '*'); decodeRowResult.Length = decodeRowResult.Length - 1; // remove asterisk // Look for whitespace after pattern: int lastPatternSize = 0; foreach (int counter in counters) { lastPatternSize += counter; } 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 >> 1) < lastPatternSize) { return null; } // overriding constructor value is possible bool useCode39CheckDigit = usingCheckDigit; if (hints != null && hints.ContainsKey(DecodeHintType.ASSUME_CODE_39_CHECK_DIGIT)) { useCode39CheckDigit = (bool) hints[DecodeHintType.ASSUME_CODE_39_CHECK_DIGIT]; } if (useCode39CheckDigit) { int max = decodeRowResult.Length - 1; int total = 0; for (int i = 0; i < max; i++) { total += ALPHABET_STRING.IndexOf(decodeRowResult[i]); } if (decodeRowResult[max] != ALPHABET[total % 43]) { return null; } decodeRowResult.Length = max; } if (decodeRowResult.Length == 0) { // false positive return null; } // overriding constructor value is possible bool useCode39ExtendedMode = extendedMode; if (hints != null && hints.ContainsKey(DecodeHintType.USE_CODE_39_EXTENDED_MODE)) { useCode39ExtendedMode = (bool)hints[DecodeHintType.USE_CODE_39_EXTENDED_MODE]; } String resultString; if (useCode39ExtendedMode) { resultString = decodeExtended(decodeRowResult.ToString()); if (resultString == null) { if (hints != null && hints.ContainsKey(DecodeHintType.RELAXED_CODE_39_EXTENDED_MODE) && Convert.ToBoolean(hints[DecodeHintType.RELAXED_CODE_39_EXTENDED_MODE])) resultString = decodeRowResult.ToString(); else return null; } } else { resultString = decodeRowResult.ToString(); } float left = (float) (start[1] + start[0])/2.0f; float right = (float) (nextStart + lastStart)/2.0f; var resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) ? null : (ResultPointCallback) hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; if (resultPointCallback != null) { resultPointCallback(new ResultPoint(left, rowNumber)); resultPointCallback(new ResultPoint(right, rowNumber)); } return new Result( resultString, null, new[] { new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber) }, BarcodeFormat.CODE_39); }
private static int[] findAsteriskPattern(BitArray row, int[] counters) { int width = row.Size; int rowOffset = row.getNextSet(0); int counterPosition = 0; int patternStart = rowOffset; bool isWhite = false; int patternLength = counters.Length; for (int i = rowOffset; i < width; i++) { if (row[i] ^ 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(Math.Max(0, patternStart - ((i - patternStart) >> 1)), patternStart, false)) { return new int[] { patternStart, i }; } } 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; } } return null; }
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[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; } } if (bestMatch >= 0) { // Look for whitespace before start pattern, >= 50% of width of start pattern if (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; } } return null; }
/// <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><see cref="Result"/>containing encoded string and start/end of barcode</returns> override public Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints) { int[] counters = new int[9]; int[] start = findAsteriskPattern(row, counters); if (start == null) return null; // Read off white space int nextStart = row.getNextSet(start[1]); int end = row.Size; StringBuilder result = new StringBuilder(20); char decodedChar; int lastStart; do { if (!recordPattern(row, nextStart, counters)) return null; int pattern = toNarrowWidePattern(counters); if (pattern < 0) { return null; } if (!patternToChar(pattern, out decodedChar)) return null; result.Append(decodedChar); lastStart = nextStart; foreach (int counter in counters) { nextStart += counter; } // Read off white space nextStart = row.getNextSet(nextStart); } while (decodedChar != '*'); result.Length = result.Length - 1; // remove asterisk // Look for whitespace after pattern: int lastPatternSize = 0; foreach (int counter in counters) { lastPatternSize += counter; } 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 >> 1) < lastPatternSize) { return null; } if (usingCheckDigit) { int max = result.Length - 1; int total = 0; for (int i = 0; i < max; i++) { total += ALPHABET_STRING.IndexOf(result[i]); } if (result[max] != ALPHABET[total%43]) { return null; } result.Length = max; } if (result.Length == 0) { // false positive return null; } String resultString; if (extendedMode) { resultString = decodeExtended(result.ToString()); if (resultString == null) return null; } else { resultString = result.ToString(); } float left = (float) (start[1] + start[0])/2.0f; float right = (float) (nextStart + lastStart)/2.0f; var resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) ? null : (ResultPointCallback) hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; if (resultPointCallback != null) { resultPointCallback(new ResultPoint(left, rowNumber)); resultPointCallback(new ResultPoint(right, rowNumber)); } return new Result( resultString, null, new[] { new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber) }, BarcodeFormat.CODE_39); }
/// <summary> /// </summary> /// <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/...</param> /// pixel counts, otherwise, it is interpreted as black/white/black/... /// <param name="pattern">pattern of counts of number of black and white pixels that are being</param> /// searched for as a pattern /// <param name="counters">array of counters, as long as pattern, to re-use</param> /// <returns>start/end horizontal offset of guard pattern, as an array of two ints</returns> internal static int[] findGuardPattern(BitArray row, int rowOffset, bool whiteFirst, int[] pattern, int[] counters) { int patternLength = pattern.Length; int width = row.Size; bool isWhite = whiteFirst; rowOffset = whiteFirst ? row.getNextUnset(rowOffset) : row.getNextSet(rowOffset); int counterPosition = 0; int patternStart = rowOffset; for (int x = rowOffset; x < width; x++) { if (row[x] ^ 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]; Array.Copy(counters, 2, counters, 0, patternLength - 2); counters[patternLength - 2] = 0; counters[patternLength - 1] = 0; counterPosition--; } else { counterPosition++; } counters[counterPosition] = 1; isWhite = !isWhite; } } return null; }
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 checkParity = 0; for (int x = 0; x < 2 && rowOffset < end; x++) { int bestMatch; if (!UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_AND_G_PATTERNS, out bestMatch)) return -1; resultString.Append((char)('0' + bestMatch % 10)); foreach (int counter in counters) { rowOffset += counter; } if (bestMatch >= 10) { checkParity |= 1 << (1 - x); } if (x != 1) { // Read off separator if not last rowOffset = row.getNextSet(rowOffset); rowOffset = row.getNextUnset(rowOffset); } } if (resultString.Length != 2) { return -1; } if (int.Parse(resultString.ToString()) % 4 != checkParity) { return -1; } return rowOffset; }
private int[] findStartPattern(BitArray row, int[] counters) { const int patternLength = 2; int width = row.Size; int rowOffset = row.getNextSet(0); int counterPosition = 0; int patternStart = rowOffset; bool isWhite = false; counters[0] = 0; counters[1] = 0; for (int i = rowOffset; i < width; i++) { if (row[i] ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { // narrow and wide areas should be as near as possible to factor 2 // lets say we will check 1.5 <= factor <= 5 var factorNarrowToWide = ((float)counters[0]) / ((float)counters[1]); if (factorNarrowToWide >= 1.5 && factorNarrowToWide <= 5) { calculateAverageCounterWidth(counters, patternLength); if (toPattern(counters, patternLength) == START_ENCODING) { // Look for whitespace before start pattern, >= 50% of width of start pattern if (row.isRange(Math.Max(0, patternStart - ((i - patternStart) >> 1)), patternStart, false)) { return new int[] {patternStart, i}; } } } 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; } } return null; }
private int isIMB(BitArray row, ref int pixelStartOffset, ref int pixelStopOffset, ref int pixelBarLength) { int width = row.Size; int rowOffset = row.getNextSet(0); pixelStartOffset = rowOffset; int previousPixelOffset = pixelStartOffset; const bool isWhite = false; int countBars = 0; bool insideBar = false; int currBarLength = 0; int prevBarLength = 0; bool insideWS = false; int numWSBetween = 0; int currWSLength = 0; int prevWSLength = 0; for (int i = rowOffset; i < width; i++) { if (row[i] ^ isWhite) // if current pixel is black { insideWS = false; if (!insideBar) { if (countBars <= 1) { prevWSLength = currWSLength; } else { if (prevWSLength != currWSLength) { numWSBetween = 1; prevWSLength = currWSLength; countBars = 1; pixelStartOffset = previousPixelOffset; } } countBars++; insideBar = true; previousPixelOffset = i; } currWSLength = 0; currBarLength++; } else // if current pixel is white { insideBar = false; if (!insideWS) { numWSBetween++; insideWS = true; if (countBars <= 1) prevBarLength = currBarLength; else { if (prevBarLength != currBarLength) { countBars = 1; numWSBetween = 1; prevWSLength = 0; pixelStartOffset = previousPixelOffset; prevBarLength = currBarLength; } else { if (countBars == 65) // made it this far, so break { pixelStopOffset = i; //pixelBarLength = prevBarLength; break; } } } currBarLength = 0; } currWSLength++; } } pixelBarLength = prevBarLength; return (countBars); }
/// <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><see cref="Result"/>containing encoded string and start/end of barcode</returns> override public Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints) { for (var index = 0; index < counters.Length; index++) counters[index] = 0; decodeRowResult.Length = 0; int[] start = findStartPattern(row, counters); if (start == null) return null; // Read off white space int nextStart = row.getNextSet(start[1]); char decodedChar; int lastStart = nextStart; int pattern; do { if (!recordPattern(row, nextStart, counters, 8)) { // not enough bars for a number but perhaps enough for the end pattern var endPattern = findEndPattern(row, nextStart, counters); if (endPattern == null) return null; lastStart = nextStart; nextStart = endPattern[1]; break; } pattern = toPattern(counters, 8); if (!patternToChar(pattern, out decodedChar)) { // pattern doesn't result in an encoded number // but it could be the end pattern followed by some black areas var endPattern = findEndPattern(row, nextStart, counters); if (endPattern == null) return null; lastStart = nextStart; nextStart = endPattern[1]; break; } decodeRowResult.Append(decodedChar); lastStart = nextStart; foreach (int counter in counters) { nextStart += counter; } // Read off white space nextStart = row.getNextSet(nextStart); } while (decodedChar != '*'); // at least 3 digits to prevent false positives within other kind // of codes like PDF417 if (decodeRowResult.Length < 3) { return null; } var rawBytes = Encoding.UTF8.GetBytes(decodeRowResult.ToString()); var resultString = decodeRowResult.ToString(); if (usingCheckDigit) { var resultStringWithoutChecksum = resultString.Substring(0, resultString.Length - 1); int checkSum = CalculateChecksumLuhn(resultStringWithoutChecksum); if ((char)(checkSum + 48) != resultString[resultStringWithoutChecksum.Length]) { return null; } } float left = (float)(start[1] + start[0]) / 2.0f; float right = (float)(nextStart + lastStart) / 2.0f; var resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) ? null : (ResultPointCallback)hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; if (resultPointCallback != null) { resultPointCallback(new ResultPoint(left, rowNumber)); resultPointCallback(new ResultPoint(right, rowNumber)); } return new Result( resultString, rawBytes, new[] { new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber) }, BarcodeFormat.MSI); }
private static int getNextSecondBar(BitArray row, int initialPos) { int currentPos; if (row[initialPos]) { currentPos = row.getNextUnset(initialPos); currentPos = row.getNextSet(currentPos); } else { currentPos = row.getNextSet(initialPos); currentPos = row.getNextUnset(currentPos); } return currentPos; }
/// <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 or -1 if no black lines are found in the row.</returns> private static int skipWhiteSpace(BitArray row) { int width = row.Size; int endStart = row.getNextSet(0); if (endStart == width) { return -1; } return endStart; }
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 < 5 && rowOffset < end; x++) { int bestMatch; if (!UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_AND_G_PATTERNS, out bestMatch)) return -1; resultString.Append((char)('0' + bestMatch % 10)); foreach (int counter in counters) { rowOffset += counter; } if (bestMatch >= 10) { lgPatternFound |= 1 << (4 - x); } if (x != 4) { // Read off separator if not last rowOffset = row.getNextSet(rowOffset); rowOffset = row.getNextUnset(rowOffset); } } if (resultString.Length != 5) { return -1; } int checkDigit; if (!determineCheckDigit(lgPatternFound, out checkDigit)) return -1; if (extensionChecksum(resultString.ToString()) != checkDigit) { return -1; } return rowOffset; }