See ISO 18004:2006, 6.4.1, Tables 2 and 3. This enum encapsulates the various modes in which data can be encoded to bits in the QR code standard.
/// <summary> /// Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits". /// </summary> /// <param name="content">The content.</param> /// <param name="mode">The mode.</param> /// <param name="bits">The bits.</param> /// <param name="encoding">The encoding.</param> internal static void appendBytes(String content, Mode mode, BitArray bits, String encoding) { if (mode.Equals(Mode.NUMERIC)) appendNumericBytes(content, bits); else if (mode.Equals(Mode.ALPHANUMERIC)) appendAlphanumericBytes(content, bits); else if (mode.Equals(Mode.BYTE)) append8BitBytes(content, bits, encoding); else if (mode.Equals(Mode.KANJI)) appendKanjiBytes(content, bits); else throw new WriterException("Invalid mode: " + mode); }
/// <summary> /// Append length info. On success, store the result in "bits". /// </summary> /// <param name="numLetters">The num letters.</param> /// <param name="version">The version.</param> /// <param name="mode">The mode.</param> /// <param name="bits">The bits.</param> internal static void appendLengthInfo(int numLetters, Version version, Mode mode, BitArray bits) { int numBits = mode.getCharacterCountBits(version); if (numLetters >= (1 << numBits)) { throw new WriterException(numLetters + " is bigger than " + ((1 << numBits) - 1)); } bits.appendBits(numLetters, numBits); }
/// <summary> /// Append mode info. On success, store the result in "bits". /// </summary> /// <param name="mode">The mode.</param> /// <param name="bits">The bits.</param> internal static void appendModeInfo(Mode mode, BitArray bits) { bits.appendBits(mode.Bits, 4); }
/// <summary> /// Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits". /// </summary> /// <param name="content">The content.</param> /// <param name="mode">The mode.</param> /// <param name="bits">The bits.</param> /// <param name="encoding">The encoding.</param> internal static void appendBytes(String content, Mode mode, BitArray bits, String encoding) { // TODO: check the purpose of this .Equals(obj) if (mode == Mode.BYTE) append8BitBytes(content, bits, encoding); else throw new WriterException("Invalid mode: " + mode); }
/// <summary> /// Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits". /// </summary> /// <param name="content">The content.</param> /// <param name="mode">The mode.</param> /// <param name="bits">The bits.</param> /// <param name="encoding">The encoding.</param> internal static void appendBytes(String content, Mode mode, BitArray bits, String encoding) { if (mode.Equals(Mode.BYTE)) append8BitBytes(content, bits, encoding); else throw new WriterException("Invalid mode: " + mode); }
internal static DecoderResult decode(byte[] bytes, Version version, ErrorCorrectionLevel ecLevel, IDictionary <DecodeHintType, object> hints) { var bits = new BitSource(bytes); var result = new StringBuilder(50); var byteSegments = new List <byte[]>(1); var symbolSequence = -1; var parityData = -1; int symbologyModifier; try { CharacterSetECI currentCharacterSetECI = null; bool fc1InEffect = false; bool hasFNC1first = false; bool hasFNC1second = 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: hasFNC1first = true; // symbology detection // We do little with FNC1 except alter the parsed result a bit according to the spec fc1InEffect = true; break; case Mode.Names.FNC1_SECOND_POSITION: hasFNC1second = true; // symbology detection // 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, hints)) { return(null); } break; case Mode.Names.KANJI: if (!decodeKanjiSegment(bits, result, count)) { return(null); } break; default: return(null); } break; } } while (mode != Mode.TERMINATOR); if (currentCharacterSetECI != null) { if (hasFNC1first) { symbologyModifier = 4; } else if (hasFNC1second) { symbologyModifier = 6; } else { symbologyModifier = 2; } } else { if (hasFNC1first) { symbologyModifier = 3; } else if (hasFNC1second) { symbologyModifier = 5; } else { symbologyModifier = 1; } } } catch (ArgumentException) { // from readBits() calls return(null); } return(new DecoderResult(bytes, result.ToString(), byteSegments.Count == 0 ? null : byteSegments, ecLevel == null ? null : ecLevel.ToString(), symbolSequence, parityData, symbologyModifier)); }