public static BitList GenerateCheckWords(BitList bits, int totalBits, int wordSize) { var rs = new ReedSolomonEncoder(GetGaloisField(wordSize)); // bits is guaranteed to be a multiple of the wordSize, so no padding needed int messageWordCount = bits.Length / wordSize; int totalWordCount = totalBits / wordSize; int eccWordCount = totalWordCount - messageWordCount; int[] messageWords = BitsToWords(bits, wordSize, messageWordCount); int[] eccWords = rs.Encode(messageWords, eccWordCount); int startPad = totalBits % wordSize; var messageBits = new BitList(); messageBits.AddBits(0, (byte)startPad); foreach (var messageWord in messageWords) { messageBits.AddBits((uint)messageWord, (byte)wordSize); } foreach (var eccWord in eccWords) { messageBits.AddBits((uint)eccWord, (byte)wordSize); } return(messageBits); }
public static byte[] CalculateEcc(byte[] data, CodeSize size) { var dataSize = data.Length; var result = new byte[data.Length + size.EccCount]; Array.Copy(data, result, data.Length); for (int block = 0; block < size.BlockCount; block++) { var dataCnt = size.DataCodewordsForBlock(block); var buff = new int[dataCnt]; // copy the data for the current block to buff var j = 0; for (int i = block; i < dataSize; i += size.BlockCount) { buff[j] = result[i]; j++; } // calc the error correction codes var ecc = ReedSolomonEncoder.Encode(buff, size.ErrorCorrectionCodewordsPerBlock); // and append them to the result j = 0; for (int i = block; i < size.ErrorCorrectionCodewordsPerBlock * size.BlockCount; i += size.BlockCount) { result[dataSize + i] = (byte)ecc[j]; j++; } } return(result); }
private void TestOneCase(byte[] data, int ecLength, byte[] expectResult) { byte[] result = ReedSolomonEncoder.Encode(data, ecLength, m_cacheGeneratorPoly); if (!PolynomialExtensions.isEqual(result, expectResult)) { Assert.Fail("Remainder not same. result {0}, expect {1}", result.Length, expectResult.Length); } }
public static byte[] CalculateEcc(byte[] data, byte eccCount) { if (data == null) { throw new ArgumentNullException(nameof(data)); } var dataInts = data.Select(x => (int)x).ToArray(); int[] res = ReedSolomonEncoder.Encode(dataInts, eccCount); return(res.Select(x => (byte)x).ToArray()); }
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> /// 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); }
public void Encode(int[] plainData, int erasures) { var rse = new ReedSolomonEncoder(_field); rse.Encode(plainData, erasures); }