Exemplo n.º 1
0
		private FormatInformation(int formatInfo)
		{
			// Bits 3,4
			errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03);
			// Bottom 3 bits
			_dataMask = (sbyte) (formatInfo & 0x07);
		}
Exemplo n.º 2
0
        /// <summary> <p>Decodes a QR Code represented as a {@link BitMatrix}. A 1 or "true" is taken to mean a black module.</p>
        ///
        /// </summary>
        /// <param name="bits">booleans representing white/black QR Code modules
        /// </param>
        /// <returns> text and bytes encoded within the QR Code
        /// </returns>
        /// <throws>  ReaderException if the QR Code cannot be decoded </throws>
        public DecoderResult decode(BitMatrix bits)
        {
            // Construct a parser and read version, error-correction level
            BitMatrixParser      parser  = new BitMatrixParser(bits);
            Version              version = parser.readVersion();
            ErrorCorrectionLevel ecLevel = parser.readFormatInformation().ErrorCorrectionLevel;

            // Read codewords
            sbyte[] codewords = parser.readCodewords();
            // Separate into data blocks
            DataBlock[] dataBlocks = DataBlock.getDataBlocks(codewords, version, ecLevel);

            // Count total number of data bytes
            int totalBytes = 0;

            for (int i = 0; i < dataBlocks.Length; i++)
            {
                totalBytes += dataBlocks[i].NumDataCodewords;
            }
            sbyte[] resultBytes  = new sbyte[totalBytes];
            int     resultOffset = 0;

            // Error-correct and copy data blocks together into a stream of bytes
            for (int j = 0; j < dataBlocks.Length; j++)
            {
                DataBlock dataBlock        = dataBlocks[j];
                sbyte[]   codewordBytes    = dataBlock.Codewords;
                int       numDataCodewords = dataBlock.NumDataCodewords;
                correctErrors(codewordBytes, numDataCodewords);
                for (int i = 0; i < numDataCodewords; i++)
                {
                    resultBytes[resultOffset++] = codewordBytes[i];
                }
            }

            // Decode the contents of that stream of bytes
            return(DecodedBitStreamParser.decode(resultBytes, version, ecLevel));
        }
Exemplo n.º 3
0
		public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel)
		{
			return _ecBlocks[ecLevel.Ordinal()];
		}
Exemplo n.º 4
0
        /// <summary> <p>When QR Codes use multiple data blocks, they are actually interleaved.
        /// That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This
        /// method will separate the data into original blocks.</p>
        ///
        /// </summary>
        /// <param name="rawCodewords">bytes as read directly from the QR Code
        /// </param>
        /// <param name="version">version of the QR Code
        /// </param>
        /// <param name="ecLevel">error-correction level of the QR Code
        /// </param>
        /// <returns> {@link DataBlock}s containing original bytes, "de-interleaved" from representation in the
        /// QR Code
        /// </returns>
        internal static DataBlock[] getDataBlocks(sbyte[] rawCodewords, Version version, ErrorCorrectionLevel ecLevel)
        {
            if (rawCodewords.Length != version.TotalCodewords)
            {
                throw new System.ArgumentException();
            }

            // Figure out the number and size of data blocks used by this version and
            // error correction level
            Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);

            // First count the total number of data blocks
            int totalBlocks = 0;

            Version.ECB[] ecBlockArray = ecBlocks.getECBlocks();
            for (int i = 0; i < ecBlockArray.Length; i++)
            {
                totalBlocks += ecBlockArray[i].Count;
            }

            // Now establish DataBlocks of the appropriate size and number of data codewords
            DataBlock[] result          = new DataBlock[totalBlocks];
            int         numResultBlocks = 0;

            for (int j = 0; j < ecBlockArray.Length; j++)
            {
                Version.ECB ecBlock = ecBlockArray[j];
                for (int i = 0; i < ecBlock.Count; i++)
                {
                    int numDataCodewords  = ecBlock.DataCodewords;
                    int numBlockCodewords = ecBlocks.ECCodewordsPerBlock + numDataCodewords;
                    result[numResultBlocks++] = new DataBlock(numDataCodewords, new sbyte[numBlockCodewords]);
                }
            }

            // All blocks have the same amount of data, except that the last n
            // (where n may be 0) have 1 more byte. Figure out where these start.
            int shorterBlocksTotalCodewords = result[0].codewords.Length;
            int longerBlocksStartAt         = result.Length - 1;

            while (longerBlocksStartAt >= 0)
            {
                int numCodewords = result[longerBlocksStartAt].codewords.Length;
                if (numCodewords == shorterBlocksTotalCodewords)
                {
                    break;
                }
                longerBlocksStartAt--;
            }
            longerBlocksStartAt++;

            int shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.ECCodewordsPerBlock;
            // The last elements of result may be 1 element longer;
            // first fill out as many elements as all of them have
            int rawCodewordsOffset = 0;

            for (int i = 0; i < shorterBlocksNumDataCodewords; i++)
            {
                for (int j = 0; j < numResultBlocks; j++)
                {
                    result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];
                }
            }
            // Fill out the last data block in the longer ones
            for (int j = longerBlocksStartAt; j < numResultBlocks; j++)
            {
                result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++];
            }
            // Now add in error correction blocks
            int max = result[0].codewords.Length;

            for (int i = shorterBlocksNumDataCodewords; i < max; i++)
            {
                for (int j = 0; j < numResultBlocks; j++)
                {
                    int iOffset = j < longerBlocksStartAt?i:i + 1;
                    result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];
                }
            }
            return(result);
        }
	    internal static DecoderResult decode(sbyte[] bytes, Version version, ErrorCorrectionLevel ecLevel)
		{
			BitSource bits = new BitSource(bytes);
			System.Text.StringBuilder result = new System.Text.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 (System.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);
		}
Exemplo n.º 6
0
		/// <summary> <p>When QR Codes use multiple data blocks, they are actually interleaved.
		/// That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This
		/// method will separate the data into original blocks.</p>
		/// 
		/// </summary>
		/// <param name="rawCodewords">bytes as read directly from the QR Code
		/// </param>
		/// <param name="version">version of the QR Code
		/// </param>
		/// <param name="ecLevel">error-correction level of the QR Code
		/// </param>
		/// <returns> {@link DataBlock}s containing original bytes, "de-interleaved" from representation in the
		/// QR Code
		/// </returns>
		internal static DataBlock[] getDataBlocks(sbyte[] rawCodewords, Version version, ErrorCorrectionLevel ecLevel)
		{
			
			if (rawCodewords.Length != version.TotalCodewords)
			{
				throw new System.ArgumentException();
			}
			
			// Figure out the number and size of data blocks used by this version and
			// error correction level
			Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);
			
			// First count the total number of data blocks
			int totalBlocks = 0;
			Version.ECB[] ecBlockArray = ecBlocks.getECBlocks();
			for (int i = 0; i < ecBlockArray.Length; i++)
			{
				totalBlocks += ecBlockArray[i].Count;
			}
			
			// Now establish DataBlocks of the appropriate size and number of data codewords
			DataBlock[] result = new DataBlock[totalBlocks];
			int numResultBlocks = 0;
			for (int j = 0; j < ecBlockArray.Length; j++)
			{
				Version.ECB ecBlock = ecBlockArray[j];
				for (int i = 0; i < ecBlock.Count; i++)
				{
					int numDataCodewords = ecBlock.DataCodewords;
					int numBlockCodewords = ecBlocks.ECCodewordsPerBlock + numDataCodewords;
					result[numResultBlocks++] = new DataBlock(numDataCodewords, new sbyte[numBlockCodewords]);
				}
			}
			
			// All blocks have the same amount of data, except that the last n
			// (where n may be 0) have 1 more byte. Figure out where these start.
			int shorterBlocksTotalCodewords = result[0].codewords.Length;
			int longerBlocksStartAt = result.Length - 1;
			while (longerBlocksStartAt >= 0)
			{
				int numCodewords = result[longerBlocksStartAt].codewords.Length;
				if (numCodewords == shorterBlocksTotalCodewords)
				{
					break;
				}
				longerBlocksStartAt--;
			}
			longerBlocksStartAt++;
			
			int shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.ECCodewordsPerBlock;
			// The last elements of result may be 1 element longer;
			// first fill out as many elements as all of them have
			int rawCodewordsOffset = 0;
			for (int i = 0; i < shorterBlocksNumDataCodewords; i++)
			{
				for (int j = 0; j < numResultBlocks; j++)
				{
					result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];
				}
			}
			// Fill out the last data block in the longer ones
			for (int j = longerBlocksStartAt; j < numResultBlocks; j++)
			{
				result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++];
			}
			// Now add in error correction blocks
			int max = result[0].codewords.Length;
			for (int i = shorterBlocksNumDataCodewords; i < max; i++)
			{
				for (int j = 0; j < numResultBlocks; j++)
				{
					int iOffset = j < longerBlocksStartAt?i:i + 1;
					result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];
				}
			}
			return result;
		}
Exemplo n.º 7
0
        internal static DecoderResult decode(sbyte[] bytes, Version version, ErrorCorrectionLevel ecLevel)
        {
            BitSource bits = new BitSource(bytes);

            System.Text.StringBuilder result = new System.Text.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 (System.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));
        }
Exemplo n.º 8
0
 public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel)
 {
     return(_ecBlocks[ecLevel.Ordinal()]);
 }