/// <summary>
    /// Encode an array of data codeword with GaloisField 256.
    /// </summary>
    /// <param name="dataBytes">Array of data codewords for a single block.</param>
    /// <param name="numECBytes">Number of error correction codewords for data codewords</param>
    /// <param name="generatorPoly">Cached or newly create GeneratorPolynomial</param>
    /// <returns>Return error correction codewords array</returns>
    internal static byte[] Encode(byte[] dataBytes, int numECBytes, GeneratorPolynomial generatorPoly)
    {
        int dataLength = dataBytes.Length;

        Guard.NotNull(nameof(generatorPoly), generatorPoly);

        if (dataLength == 0)
        {
            throw new ArgumentException("There is no data bytes to encode.");
        }

        if (numECBytes <= 0)
        {
            throw new ArgumentException("No Error Correction bytes.");
        }

        int[] toEncode = ConvertToIntArray(dataBytes, dataLength, numECBytes);

        Polynomial generator = generatorPoly.GetGenerator(numECBytes);

        Polynomial dataPoly = new(generator.GField, toEncode);

        PolyDivideStruct divideResult = dataPoly.Divide(generator);

        int[] remainderCoeffs = divideResult.Remainder.Coefficients;

        return(ConvertTosByteArray(remainderCoeffs, numECBytes));
    }
示例#2
0
        public void PerformanceTest()
        {
            Random randomizer = new Random();

            sbyte[] zxTestCase = PolynomialExtensions.GenerateSbyteArray(40, randomizer);
            int     ecBytes    = 50;

            byte[] testCase = PolynomialExtensions.ToByteArray(zxTestCase);

            Stopwatch sw          = new Stopwatch();
            int       timesofTest = 10000;

            string[] timeElapsed = new string[2];

            sw.Start();
            GaloisField256      gf256     = GaloisField256.QRCodeGaloisField;
            GeneratorPolynomial generator = new GeneratorPolynomial(gf256);

            for (int i = 0; i < timesofTest; i++)
            {
                ReedSolomonEncoder.Encode(testCase, ecBytes, generator);
            }

            sw.Stop();

            timeElapsed[0] = sw.ElapsedMilliseconds.ToString();

            sw.Reset();

            sw.Start();

            for (int i = 0; i < timesofTest; i++)
            {
                EncoderInternal.generateECBytes(zxTestCase, ecBytes);
            }
            sw.Stop();

            timeElapsed[1] = sw.ElapsedMilliseconds.ToString();


            Assert.Pass("ReedSolomon performance {0} Tests~ QrCode.Net: {1} ZXing: {2}", timesofTest, timeElapsed[0], timeElapsed[1]);
        }
        /// <summary>
        /// Encode an array of data codeword with GaloisField 256.
        /// </summary>
        /// <param name="dataBytes">Array of data codewords for a single block.</param>
        /// <param name="numECBytes">Number of error correction codewords for data codewords</param>
        /// <param name="generatorPoly">Cached or newly create GeneratorPolynomial</param>
        /// <returns>Return error correction codewords array</returns>
        /// <remarks></remarks>
        internal static byte[] Encode(byte[] dataBytes, int numECBytes, GeneratorPolynomial generatorPoly)
        {
            int dataLength = dataBytes.Length;
            if (generatorPoly == null)
                throw new ArgumentNullException("generator", "GeneratorPolynomial var is null");
            if (dataLength == 0)
                throw new ArgumentException("There is no data bytes to encode");
            if (numECBytes <= 0)
                throw new ArgumentException("No Error Correction bytes");
            int[] toEncode = ConvertToIntArray(dataBytes, dataLength, numECBytes);

            Polynomial generator = generatorPoly.GetGenerator(numECBytes);

            var dataPoly = new Polynomial(generator.GField, toEncode);

            PolyDivideStruct divideResult = dataPoly.Divide(generator);

            int[] remainderCoeffs = divideResult.Remainder.Coefficients;

            return ConvertTosByteArray(remainderCoeffs, numECBytes);
        }
示例#4
0
        /// <summary>
        /// Generate error correction blocks. Then out put with codewords BitList
        /// ISO/IEC 18004/2006 P45, 46. Chapter 6.6 Constructing final message codewords sequence.
        /// </summary>
        /// <param name="dataCodewords">Datacodewords from DataEncodation.DataEncode</param>
        /// <param name="numTotalBytes">Total number of bytes</param>
        /// <param name="numDataBytes">Number of data bytes</param>
        /// <param name="numECBlocks">Number of Error Correction blocks</param>
        /// <returns>codewords BitList contain datacodewords and ECCodewords</returns>
        internal static BitList FillECCodewords(BitList dataCodewords, VersionDetail vd)
        {
            List <byte> dataCodewordsByte  = dataCodewords.List;
            int         ecBlockGroup2      = vd.ECBlockGroup2;
            int         ecBlockGroup1      = vd.ECBlockGroup1;
            int         numDataBytesGroup1 = vd.NumDataBytesGroup1;
            int         numDataBytesGroup2 = vd.NumDataBytesGroup2;

            int ecBytesPerBlock = vd.NumECBytesPerBlock;

            int dataBytesOffset = 0;

            byte[][] dByteJArray  = new byte[vd.NumECBlocks][];
            byte[][] ecByteJArray = new byte[vd.NumECBlocks][];

            GaloisField256      gf256     = GaloisField256.QRCodeGaloisField;
            GeneratorPolynomial generator = new GeneratorPolynomial(gf256);

            for (int blockID = 0; blockID < vd.NumECBlocks; blockID++)
            {
                if (blockID < ecBlockGroup1)
                {
                    dByteJArray[blockID] = new byte[numDataBytesGroup1];
                    for (int index = 0; index < numDataBytesGroup1; index++)
                    {
                        dByteJArray[blockID][index] = dataCodewordsByte[dataBytesOffset + index];
                    }
                    dataBytesOffset += numDataBytesGroup1;
                }
                else
                {
                    dByteJArray[blockID] = new byte[numDataBytesGroup2];
                    for (int index = 0; index < numDataBytesGroup2; index++)
                    {
                        dByteJArray[blockID][index] = dataCodewordsByte[dataBytesOffset + index];
                    }
                    dataBytesOffset += numDataBytesGroup2;
                }

                ecByteJArray[blockID] = ReedSolomonEncoder.Encode(dByteJArray[blockID], ecBytesPerBlock, generator);
            }
            if (vd.NumDataBytes != dataBytesOffset)
            {
                throw new ArgumentException("Data bytes does not match offset");
            }

            BitList codewords = new BitList();

            int maxDataLength = ecBlockGroup1 == vd.NumECBlocks ? numDataBytesGroup1 : numDataBytesGroup2;

            for (int dataID = 0; dataID < maxDataLength; dataID++)
            {
                for (int blockID = 0; blockID < vd.NumECBlocks; blockID++)
                {
                    if (!(dataID == numDataBytesGroup1 && blockID < ecBlockGroup1))
                    {
                        codewords.Add((int)dByteJArray[blockID][dataID], 8);
                    }
                }
            }

            for (int ECID = 0; ECID < ecBytesPerBlock; ECID++)
            {
                for (int blockID = 0; blockID < vd.NumECBlocks; blockID++)
                {
                    codewords.Add((int)ecByteJArray[blockID][ECID], 8);
                }
            }

            if (vd.NumTotalBytes != codewords.Count >> 3)
            {
                throw new ArgumentException(string.Format("total bytes: {0}, actual bits: {1}", vd.NumTotalBytes, codewords.Count));
            }

            return(codewords);
        }
示例#5
0
        /// <summary>
        /// Generate error correction blocks. Then out put with codewords BitList
        /// ISO/IEC 18004/2006 P45, 46. Chapter 6.6 Constructing final message codewords sequence.
        /// </summary>
        /// <param name="dataCodewords">Datacodewords from DataEncodation.DataEncode</param>
        /// <param name="vd">The vd.</param>
        /// <returns>codewords BitList contain datacodewords and ECCodewords</returns>
        /// <remarks></remarks>
        internal static BitList FillECCodewords(BitList dataCodewords, VersionDetail vd)
        {
            List<byte> dataCodewordsByte = dataCodewords.List;
            int ecBlockGroup2 = vd.ECBlockGroup2;
            int ecBlockGroup1 = vd.ECBlockGroup1;
            int numDataBytesGroup1 = vd.NumDataBytesGroup1;
            int numDataBytesGroup2 = vd.NumDataBytesGroup2;

            int ecBytesPerBlock = vd.NumECBytesPerBlock;

            int dataBytesOffset = 0;
            var dByteJArray = new byte[vd.NumECBlocks][];
            var ecByteJArray = new byte[vd.NumECBlocks][];

            GaloisField256 gf256 = GaloisField256.QRCodeGaloisField;
            var generator = new GeneratorPolynomial(gf256);

            for (int blockID = 0; blockID < vd.NumECBlocks; blockID++)
            {
                if (blockID < ecBlockGroup1)
                {
                    dByteJArray[blockID] = new byte[numDataBytesGroup1];
                    for (int index = 0; index < numDataBytesGroup1; index++)
                    {
                        dByteJArray[blockID][index] = dataCodewordsByte[dataBytesOffset + index];
                    }
                    dataBytesOffset += numDataBytesGroup1;
                }
                else
                {
                    dByteJArray[blockID] = new byte[numDataBytesGroup2];
                    for (int index = 0; index < numDataBytesGroup2; index++)
                    {
                        dByteJArray[blockID][index] = dataCodewordsByte[dataBytesOffset + index];
                    }
                    dataBytesOffset += numDataBytesGroup2;
                }

                ecByteJArray[blockID] = ReedSolomonEncoder.Encode(dByteJArray[blockID], ecBytesPerBlock, generator);
            }
            if (vd.NumDataBytes != dataBytesOffset)
                throw new ArgumentException("Data bytes does not match offset");

            var codewords = new BitList();

            int maxDataLength = ecBlockGroup1 == vd.NumECBlocks ? numDataBytesGroup1 : numDataBytesGroup2;

            for (int dataID = 0; dataID < maxDataLength; dataID++)
            {
                for (int blockID = 0; blockID < vd.NumECBlocks; blockID++)
                {
                    if (!(dataID == numDataBytesGroup1 && blockID < ecBlockGroup1))
                        codewords.Add(dByteJArray[blockID][dataID], 8);
                }
            }

            for (int ECID = 0; ECID < ecBytesPerBlock; ECID++)
            {
                for (int blockID = 0; blockID < vd.NumECBlocks; blockID++)
                {
                    codewords.Add(ecByteJArray[blockID][ECID], 8);
                }
            }

            if (vd.NumTotalBytes != codewords.Count >> 3)
                throw new ArgumentException(string.Format("total bytes: {0}, actual bits: {1}", vd.NumTotalBytes,
                                                          codewords.Count));

            return codewords;
        }