internal static DecoderResult Decode(byte[] bytes, Version version, ErrorCorrectionLevel ecLevel) { var bits = new BitSource(bytes); var result = new StringBuilder(50); var byteSegments = new List <byte[]>(1); var symbolSequence = -1; var parityData = -1; try { CharacterSetECI currentCharacterSetECI = null; bool fc1InEffect = false; Mode mode; do { // While still another segment to read... if (bits.Available() < 4) { // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here mode = Mode.TERMINATOR; } else { try { mode = Mode.ForBits(bits.ReadBits(4)); // mode is encoded by 4 bits } catch (ArgumentException) { return(null); } } switch (mode.Name) { case Mode.Names.TERMINATOR: break; case Mode.Names.FNC1_FIRST_POSITION: case Mode.Names.FNC1_SECOND_POSITION: // We do little with FNC1 except alter the parsed result a bit according to the spec fc1InEffect = true; break; case Mode.Names.STRUCTURED_APPEND: if (bits.Available() < 16) { return(null); } // not really supported; but sequence number and parity is added later to the result metadata // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue symbolSequence = bits.ReadBits(8); parityData = bits.ReadBits(8); break; case Mode.Names.ECI: // Count doesn't apply to ECI int value = ParseECIValue(bits); currentCharacterSetECI = CharacterSetECI.GetCharacterSetECIByValue(value); if (currentCharacterSetECI == null) { return(null); } break; case Mode.Names.HANZI: // First handle Hanzi mode which does not start with character count //chinese mode contains a sub set indicator right after mode indicator int subset = bits.ReadBits(4); int countHanzi = bits.ReadBits(mode.GetCharacterCountBits(version)); if (subset == GB2312_SUBSET) { if (!DecodeHanziSegment(bits, result, countHanzi)) { return(null); } } break; default: // "Normal" QR code modes: // How many characters will follow, encoded in this mode? int count = bits.ReadBits(mode.GetCharacterCountBits(version)); switch (mode.Name) { case Mode.Names.NUMERIC: if (!DecodeNumericSegment(bits, result, count)) { return(null); } break; case Mode.Names.ALPHANUMERIC: if (!DecodeAlphanumericSegment(bits, result, count, fc1InEffect)) { return(null); } break; case Mode.Names.BYTE: if (!DecodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments)) { return(null); } break; case Mode.Names.KANJI: if (!DecodeKanjiSegment(bits, result, count)) { return(null); } break; default: return(null); } break; } } while (mode != Mode.TERMINATOR); } catch (ArgumentException) { // from readBits() calls return(null); } var resultString = result.ToString().Replace("\r\n", "\n").Replace("\n", Environment.NewLine); return(new DecoderResult(bytes, resultString)); }
internal static DecoderResult Decode(sbyte[] bytes, Version version, ErrorCorrectionLevel ecLevel) { BitSource bits = new BitSource(bytes); StringBuilder result = new StringBuilder(50); CharacterSetECI currentCharacterSetECI = null; bool fc1InEffect = false; System.Collections.ArrayList byteSegments = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(1)); Mode mode; do { // While still another segment to read... if (bits.Available() < 4) { // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here mode = Mode.TERMINATOR; } else { try { mode = Mode.ForBits(bits.ReadBits(4)); // mode is encoded by 4 bits } catch (ArgumentException) { throw ReaderException.Instance; } } if (!mode.Equals(Mode.TERMINATOR)) { if (mode.Equals(Mode.FNC1_FIRST_POSITION) || mode.Equals(Mode.FNC1_SECOND_POSITION)) { // We do little with FNC1 except alter the parsed result a bit according to the spec fc1InEffect = true; } else if (mode.Equals(Mode.STRUCTURED_APPEND)) { // not really supported; all we do is ignore it // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue bits.ReadBits(16); } else if (mode.Equals(Mode.ECI)) { // Count doesn't apply to ECI int value_Renamed = ParseECIValue(bits); currentCharacterSetECI = CharacterSetECI.GetCharacterSetECIByValue(value_Renamed); if (currentCharacterSetECI == null) { throw ReaderException.Instance; } } else { // How many characters will follow, encoded in this mode? int count = bits.ReadBits(mode.GetCharacterCountBits(version)); if (mode.Equals(Mode.NUMERIC)) { DecodeNumericSegment(bits, result, count); } else if (mode.Equals(Mode.ALPHANUMERIC)) { DecodeAlphanumericSegment(bits, result, count, fc1InEffect); } else if (mode.Equals(Mode.BYTE)) { DecodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments); } else if (mode.Equals(Mode.KANJI)) { DecodeKanjiSegment(bits, result, count); } else { throw ReaderException.Instance; } } } }while (!mode.Equals(Mode.TERMINATOR)); return(new DecoderResult(bytes, result.ToString(), (byteSegments.Count == 0)?null:byteSegments, ecLevel)); }