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));
        }
예제 #2
0
        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));
        }