/// <summary> Based on pattern of odd-even ('L' and 'G') patterns used to encoded the explicitly-encoded /// digits in a barcode, determines the implicitly encoded first digit and adds it to the /// result string. /// /// </summary> /// <param name="resultString">string to insert decoded first digit into /// </param> /// <param name="lgPatternFound">int whose bits indicates the pattern of odd/even L/G patterns used to /// encode digits /// </param> /// <throws> ReaderException if first digit cannot be determined </throws> private static void determineFirstDigit(StringBuilder resultString, int lgPatternFound) { for (int d = 0; d < 10; d++) { if (lgPatternFound == FIRST_DIGIT_ENCODINGS[d]) { string s = resultString.ToString().Insert(0, (Int32Extend.ToChar(CharExtend.ToInt32('0') + d)).ToString()); resultString.Clear(); resultString.Append(s); return ; } } throw new Exception("ReaderException"); }
/// <summary> See ISO 16022:2006, 5.2.3 and Annex C, Table C.2</summary> private static int decodeAsciiSegment(BitSource bits, StringBuilder result, StringBuilder resultTrailer) { bool upperShift = false; do { int oneByte = bits.readBits(8); if (oneByte == 0) { throw new Exception("ReaderException"); } else if (oneByte <= 128) { // ASCII data (ASCII value + 1) oneByte = upperShift?(oneByte + 128):oneByte; upperShift = false; result.Append((char) (oneByte - 1)); return ASCII_ENCODE; } else if (oneByte == 129) { // Pad return PAD_ENCODE; } else if (oneByte <= 229) { // 2-digit data 00-99 (Numeric Value + 130) int value_Renamed = oneByte - 130; if (value_Renamed < 10) { // padd with '0' for single digit values result.Append('0'); } result.Append(value_Renamed); } else if (oneByte == 230) { // Latch to C40 encodation return C40_ENCODE; } else if (oneByte == 231) { // Latch to Base 256 encodation return BASE256_ENCODE; } else if (oneByte == 232) { // FNC1 //throw ReaderException.getInstance(); // Ignore this symbol for now } else if (oneByte == 233) { // Structured Append //throw ReaderException.getInstance(); // Ignore this symbol for now } else if (oneByte == 234) { // Reader Programming //throw ReaderException.getInstance(); // Ignore this symbol for now } else if (oneByte == 235) { // Upper Shift (shift to Extended ASCII) upperShift = true; } else if (oneByte == 236) { // 05 Macro result.Append("[)>\u001E05\u001D"); string s = resultTrailer.ToString().Insert(0, "\u001E\u0004"); resultTrailer.Clear(); resultTrailer.Append(s); } else if (oneByte == 237) { // 06 Macro result.Append("[)>\u001E06\u001D"); string s = resultTrailer.ToString().Insert(0, "\u001E\u0004"); resultTrailer.Clear(); resultTrailer.Append(s); } else if (oneByte == 238) { // Latch to ANSI X12 encodation return ANSIX12_ENCODE; } else if (oneByte == 239) { // Latch to Text encodation return TEXT_ENCODE; } else if (oneByte == 240) { // Latch to EDIFACT encodation return EDIFACT_ENCODE; } else if (oneByte == 241) { // ECI Character // TODO(bbrown): I think we need to support ECI //throw ReaderException.getInstance(); // Ignore this symbol for now } else if (oneByte >= 242) { // Not to be used in ASCII encodation throw new Exception("ReaderException"); } } while (bits.available() > 0); return ASCII_ENCODE; }
private static void decodeAlphanumericSegment(BitSource bits, StringBuilder result, int count, bool fc1InEffect) { // Read two characters at a time int start = result.ToString().Length; while (count > 1) { int nextTwoCharsBits = bits.readBits(11); result.Append(ALPHANUMERIC_CHARS[Math.Floor(nextTwoCharsBits / 45)]); result.Append(ALPHANUMERIC_CHARS[nextTwoCharsBits % 45]); count -= 2; } if (count == 1) { // special case: one character left result.Append(ALPHANUMERIC_CHARS[bits.readBits(6)]); } char[] c = new char[result.ToString().Length]; SupportClass.GetCharsFromString(result.ToString(), 0, result.ToString().Length, c, 0); List<char> list = new List<char>(c); // See section 6.4.8.1, 6.4.8.2 if (fc1InEffect) { // We need to massage the result a bit if in an FNC1 mode: for (int i = start; i < list.Count; i++) { if (list[i] == '%') { if (i < list.Count - 1 && list[i + 1] == '%') { // %% is rendered as % list = list.RemoveRange(i + 1, 1); } else { // In alpha mode, % should be converted to FNC1 separator 0x1D list[i] = Int32Extend.ToChar(0x1D); } } } result.Clear(); result.Append(list.Join()); } }
public override Result decodeRow2(int rowNumber, BitArray row, Dictionary<object, 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 new Exception("ReaderException"); } bool done = false; bool isNextShifted = false; StringBuilder result = new StringBuilder(); 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 new Exception("ReaderException"); } 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, Math.Min(width, nextStart + Math.Floor((nextStart - lastStart) / 2)), false)) { throw new Exception("ReaderException"); } // Pull out from sum the value of the penultimate check code checksumTotal -= multiplier * lastCode; // lastCode is the checksum then: if (checksumTotal % 103 != lastCode) { throw new Exception("ReaderException"); } // Need to pull out the check digits from string int resultLength = result.ToString().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) { string s = result.ToString().Remove(resultLength - 2, resultLength - (resultLength - 2)); result.Clear(); result.Append(s); } else { string s = result.ToString().Remove(resultLength - 1, resultLength - (resultLength - 1)); result.Clear(); result.Append(s); } } String resultString = result.ToString(); if (resultString.Length == 0) { // Almost surely a false positive throw new Exception("ReaderException"); } //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); }
private static void determineNumSysAndCheckDigit(StringBuilder resultString, int lgPatternFound) { for (int numSys = 0; numSys <= 1; numSys++) { for (int d = 0; d < 10; d++) { if (lgPatternFound == NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) { string s = Int32Extend.ToChar(CharExtend.ToInt32('0') + numSys) + resultString.ToString() + Int32Extend.ToChar(CharExtend.ToInt32('0') + d); resultString.Clear(); resultString.Append(s); //resultString.Insert(0, (char) ('0' + numSys)); //resultString.Append((char) ('0' + d)); return ; } } } throw new Exception("ReaderException"); }
/// <summary> Add two numbers which are represented as strings. /// /// </summary> /// <param name="value1"> /// </param> /// <param name="value2"> /// </param> /// <returns> the result of value1 + value2 /// </returns> private static StringBuilder add(String value1, String value2) { StringBuilder temp1 = new StringBuilder(); StringBuilder temp2 = new StringBuilder(); //System.StringBuilder result = new System.StringBuilder(); char[] result = new char[value1.Length]; for (int i = 0; i < value1.Length; i++) { // Put zeros into the result. result[i] = '0'; } int carry = 0; for (int i = value1.Length - 3; i > - 1; i -= 3) { temp1.Clear(); temp1.Append(value1.CharAt(i)); temp1.Append(value1.CharAt(i + 1)); temp1.Append(value1.CharAt(i + 2)); temp2.Clear(); temp2.Append(value2.CharAt(i)); temp2.Append(value2.CharAt(i + 1)); temp2.Append(value2.CharAt(i + 2)); int intValue1 = Int32.Parse(temp1.ToString()); int intValue2 = Int32.Parse(temp2.ToString()); int sumval = (intValue1 + intValue2 + carry) % 1000; carry = Math.Floor((intValue1 + intValue2 + carry) / 1000); result[i + 2] = Int32Extend.ToChar((sumval % 10) + CharExtend.ToInt32('0')); result[i + 1] = Int32Extend.ToChar((Math.Floor(sumval / 10) % 10) + CharExtend.ToInt32('0')); result[i] = Int32Extend.ToChar(Math.Floor(sumval / 100) + CharExtend.ToInt32('0')); } return new StringBuilder(result.Join()); }
/// <summary> Creates a reader that can be configured to check the last character as a check digit, /// or optionally attempt to decode "extended Code 39" sequences that are used to encode /// the full ASCII character set. /// /// </summary> /// <param name="usingCheckDigit">if true, treat the last data character as a check digit, not /// data, and verify that the checksum passes. /// </param> /// <param name="extendedMode">if true, will attempt to decode extended Code 39 sequences in the /// text. /// </param> //public Code39Reader(bool usingCheckDigit, bool extendedMode) //{ // this.usingCheckDigit = usingCheckDigit; // this.extendedMode = extendedMode; //} public override Result decodeRow2(int rowNumber, BitArray row, Dictionary<object, object> 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++; } StringBuilder result = new StringBuilder(); int[] counters = new int[9]; char decodedChar; int lastStart; do { recordPattern(row, nextStart, counters); int pattern = toNarrowWidePattern(counters); if (pattern < 0) { throw new Exception("ReaderException"); } 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 != '*'); string s = result.ToString().Remove(result.ToString().Length - 1, 1); result.Clear(); result.Append(s); // 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 && Math.Floor(whiteSpaceAfterEnd / 2) < lastPatternSize) { throw new Exception("ReaderException"); } if (usingCheckDigit) { int max = result.ToString().Length - 1; int total = 0; for (int i = 0; i < max; i++) { total += ALPHABET_STRING.IndexOf(result.ToString().CharAt(i)); } if (total % 43 != ALPHABET_STRING.IndexOf(result.ToString().CharAt(max))) { throw new Exception("ReaderException"); } s = result.ToString().Remove(max, 1); result.Clear(); result.Append(s); } String resultString = result.ToString(); if (extendedMode) { resultString = decodeExtended(resultString); } if (resultString.Length == 0) { // Almost surely a false positive throw new Exception("ReaderException"); } //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 static List<string> SeparateTokens(string input) { var result = new List<string>(); var number = new StringBuilder(); for (int i = 0; i < input.Length; i++) { if (input[i] == '-' && (i == 0 || input[i - 1] == ',' || input[i - 1] == '(')) { number.Append('-'); } else if (char.IsDigit(input[i]) || input[i] == '.') { number.Append(input[i]); } else if (!char.IsDigit(input[i]) && input[i] != '.' && number.Length != 0) { result.Add(number.ToString()); number.Clear(); i--; } else if (brackets.Contains(input[i])) { result.Add(input[i].ToString()); } else if (arithmeticOperations.Contains(input[i])) { result.Add(input[i].ToString()); } else if (input[i] == ',') { result.Add(","); } else if (i + 1 < input.Length && input.Substring(i, 2).ToLower() == "ln") { result.Add("ln"); i++; } else if (i + 2 < input.Length && input.Substring(i, 3).ToLower() == "pow") { result.Add("pow"); i += 2; } else if (i + 3 < input.Length && input.Substring(i, 4).ToLower() == "sqrt") { result.Add("sqrt"); i += 3; } else { throw new ArgumentException("Invalid input"); } } if (number.Length != 0) { result.Add(number.ToString()); } return result; }