Beispiel #1
0
        private static void AddErrorCorrection(StringBuilder barPattern)
        {
            // Adds Reed-Solomon error correction.
            int dataCodewords = 0;

            byte[] eccBlocks  = new byte[4];
            byte[] dataBlocks = new byte[31];

            // Build the triples data blocks;
            for (int i = 0; i < barPattern.Length; i += 3, dataCodewords++)
            {
                dataBlocks[dataCodewords] = (byte)(ConvertPattern(barPattern[i], 4)
                                                   + ConvertPattern(barPattern[i + 1], 2)
                                                   + ConvertPattern(barPattern[i + 2], 0));
            }

            ReedSolomon.RSInitialise(0x43, 4, 1);
            ReedSolomon.RSEncode(dataCodewords, dataBlocks, eccBlocks);

            // Append error correction in reverse order.
            for (int i = 4; i > 0; i--)
            {
                barPattern.Append(AusBarTable[(int)eccBlocks[i - 1]]);
            }
        }
Beispiel #2
0
        private static void SecondaryDataCheckOdd(int eccLength, int[] maxiCodewords)
        {
            // Handles error correction of odd characters in secondary.
            int dataLength = 68;

            if (eccLength == 20)
            {
                dataLength = 84;
            }

            byte[] dataCodewords = new byte[dataLength];
            byte[] eccCodewords  = new byte[eccLength];

            for (int j = 0; j < dataLength; j++)
            {
                if ((j & 1) != 0)  // Odd
                {
                    dataCodewords[(j - 1) / 2] = (byte)maxiCodewords[j + 20];
                }
            }

            ReedSolomon.RSInitialise(0x43, eccLength, 1);
            ReedSolomon.RSEncode(dataLength / 2, dataCodewords, eccCodewords);

            for (int j = 0; j < eccLength; j++)
            {
                maxiCodewords[dataLength + (2 * j) + 1 + 20] = eccCodewords[eccLength - 1 - j];
            }
        }
        private static void PrimaryDataCheck(int[] maxiCodewords)
        {
            // Handles error correction of primary barcodeMessage.
            int dataLength = 10;
            int eccLength = 10;
            byte[] data = new byte[dataLength];
            byte[] result = new byte[eccLength];


            for (int j = 0; j < dataLength; j++)
                data[j] = (byte)maxiCodewords[j];

            ReedSolomon.RSInitialise(0x43, eccLength, 1);
            ReedSolomon.RSEncode(dataLength, data, result);

            for (int j = 0; j < eccLength; j++)
                maxiCodewords[dataLength + j] = result[eccLength - 1 - j];
        }
Beispiel #4
0
        private void Mailmark()
        {
            int    inputLength   = barcodeData.Length;
            char   barcodeType   = 'C';
            int    formatId      = 0;
            int    versionId     = 0;
            int    classId       = 0;
            int    supplyChainId = 0;
            int    itemId        = 0;
            string postcode      = String.Empty;
            int    postcodeType  = 0;
            string pattern       = String.Empty;

            short[] destinationPostcode = new short[112];
            short[] aRegister           = new short[112];
            short[] bRegister           = new short[112];
            short[] tempRegister        = new short[112];
            short[] cdvRegister         = new short[112];
            byte[]  data = new byte[26];
            int     dataTop, dataStep;

            byte[]        check    = new byte[7];
            short[]       extender = new short[27];
            int           checkCount;
            StringBuilder barPattern = new StringBuilder();
            bool          result;

            if (inputLength > 26)
            {
                throw new InvalidDataLengthException("Mailmark: Input data too long.");
            }

            if (inputLength <= 22)
            {
                for (int i = inputLength; i < 22; i++)
                {
                    barcodeData = ArrayExtensions.Insert(barcodeData, inputLength, ' ');
                }

                inputLength = barcodeData.Length;
                barcodeType = 'C';
            }


            if (inputLength > 22 && inputLength <= 26)
            {
                for (int i = inputLength; i < 26; i++)
                {
                    barcodeData = ArrayExtensions.Insert(barcodeData, inputLength, ' ');
                }

                inputLength = barcodeData.Length;
                barcodeType = 'L';
            }

            for (int i = 0; i < inputLength; i++)
            {
                barcodeData[i] = Char.ToUpper(barcodeData[i], CultureInfo.CurrentCulture);  // Make sure all characters are uppercase.
                if (CharacterSets.Mailmark.IndexOf(barcodeData[i]) == -1)
                {
                    throw new InvalidDataException("Mailmark: Invalid character in input data.");
                }
            }

            // Format is in the range 0-4.
            result = int.TryParse((new string(barcodeData, 0, 1)), out formatId);
            if (!result || formatId < 0 || formatId > 4)
            {
                throw new InvalidDataException("Mailmark: Invalid Format character in input data.");
            }

            // Version ID is in the range 1-4.
            result = int.TryParse((new string(barcodeData, 1, 1)), out versionId);
            versionId--;    // Internal field value of 0-3.
            if (!result || versionId < 0 || versionId > 3)
            {
                throw new InvalidDataException("Mailmark: Invalid Version ID character in input data.");
            }

            // Class is in the range 0-9 & A-E.
            result = int.TryParse((new string(barcodeData, 2, 1)), NumberStyles.HexNumber, null, out classId);
            if (!result || classId < 0 || classId > 14)
            {
                throw new InvalidDataException("Mailmark: Invalid Class ID character in input data.");
            }

            // Supply Chain ID is 2 digits for barcode C and 6 digits for barcode L
            int supplyChainLength = (barcodeType == 'C') ? 2 : 6;

            result = int.TryParse(new string(barcodeData, 3, supplyChainLength), out supplyChainId);
            if (!result)
            {
                throw new InvalidDataException("Mailmark: Invalid Supply Chain ID character in input data.");
            }

            // Item ID is 8 digits.
            result = int.TryParse(new string(barcodeData, 3 + supplyChainLength, 8), out itemId);
            if (!result)
            {
                throw new InvalidDataException("Mailmark: Invalid Item ID character in input data.");
            }

            // Seperate Destination Post Code plus DPS field.
            postcode = new string(barcodeData, 3 + supplyChainLength + 8, 9);

            // Detect postcode type

            /* Postcode type is used to select which format of postcode
             *
             * 1 = FNFNLLNLS
             * 2 = FFNNLLNLS
             * 3 = FFNNNLLNL
             * 4 = FFNFNLLNL
             * 5 = FNNLLNLSS
             * 6 = FNNNLLNLS
             * 7 = International designation*/

            if (postcode == "XY11     ")
            {
                postcodeType = 7;
            }

            else
            {
                if (postcode[7] == ' ')
                {
                    postcodeType = 5;
                }

                else
                {
                    if (postcode[8] == ' ')
                    {
                        // Types 1, 2 and 6
                        if (Char.IsDigit(postcode[1]))
                        {
                            if (Char.IsDigit(postcode[2]))
                            {
                                postcodeType = 6;
                            }

                            else
                            {
                                postcodeType = 1;
                            }
                        }

                        else
                        {
                            postcodeType = 2;
                        }
                    }

                    else
                    {
                        // Types 3 and 4
                        if (Char.IsDigit(postcode[3]))
                        {
                            postcodeType = 3;
                        }

                        else
                        {
                            postcodeType = 4;
                        }
                    }
                }
            }

            // Verify postcode type
            if (postcodeType != 7)
            {
                if (!VerifyPostcode(postcode, postcodeType))
                {
                    throw new InvalidDataException("Mailmark: Invalid Postcode in input data.");
                }
            }

            // Convert postcode to internal user field.
            if (postcodeType != 7)
            {
                pattern = postcodeFormat[postcodeType - 1];
                BinaryMath.BinaryLoad(bRegister, "0");
                for (int i = 0; i < 9; i++)
                {
                    switch (pattern[i])
                    {
                    case 'F':
                        BinaryMath.BinaryMultiply(bRegister, "26");
                        BinaryMath.BinaryLoad(tempRegister, "0");
                        for (int j = 0; j < 5; j++)
                        {
                            if ((SetF.IndexOf(postcode[i]) & (0x01 << j)) > 0)
                            {
                                tempRegister[j] = 1;
                            }
                        }

                        BinaryMath.BinaryAdd(bRegister, tempRegister);
                        break;

                    case 'L':
                        BinaryMath.BinaryMultiply(bRegister, "20");
                        BinaryMath.BinaryLoad(tempRegister, "0");
                        for (int j = 0; j < 5; j++)
                        {
                            if ((SetL.IndexOf(postcode[i]) & (0x01 << j)) > 0)
                            {
                                tempRegister[j] = 1;
                            }
                        }

                        BinaryMath.BinaryAdd(bRegister, tempRegister);
                        break;

                    case 'N':
                        BinaryMath.BinaryMultiply(bRegister, "10");
                        BinaryMath.BinaryLoad(tempRegister, "0");
                        for (int j = 0; j < 5; j++)
                        {
                            if ((SetN.IndexOf(postcode[i]) & (0x01 << j)) > 0)
                            {
                                tempRegister[j] = 1;
                            }
                        }

                        BinaryMath.BinaryAdd(bRegister, tempRegister);
                        break;
                    }
                }

                // Destination postcode = accumulatorA + accumulatorB.
                BinaryMath.BinaryLoad(destinationPostcode, "0");
                BinaryMath.BinaryAdd(destinationPostcode, bRegister);

                BinaryMath.BinaryLoad(aRegister, "1");
                if (postcodeType == 1)
                {
                    BinaryMath.BinaryAdd(destinationPostcode, aRegister);
                }

                BinaryMath.BinaryLoad(tempRegister, "5408000000");
                BinaryMath.BinaryAdd(aRegister, tempRegister);

                if (postcodeType == 2)
                {
                    BinaryMath.BinaryAdd(destinationPostcode, aRegister);
                }

                BinaryMath.BinaryLoad(tempRegister, "5408000000");
                BinaryMath.BinaryAdd(aRegister, tempRegister);

                if (postcodeType == 3)
                {
                    BinaryMath.BinaryAdd(destinationPostcode, aRegister);
                }

                BinaryMath.BinaryLoad(tempRegister, "54080000000");
                BinaryMath.BinaryAdd(aRegister, tempRegister);

                if (postcodeType == 4)
                {
                    BinaryMath.BinaryAdd(destinationPostcode, aRegister);
                }

                BinaryMath.BinaryLoad(tempRegister, "140608000000");
                BinaryMath.BinaryAdd(aRegister, tempRegister);

                if (postcodeType == 5)
                {
                    BinaryMath.BinaryAdd(destinationPostcode, aRegister);
                }

                BinaryMath.BinaryLoad(tempRegister, "208000000");
                BinaryMath.BinaryAdd(aRegister, tempRegister);

                if (postcodeType == 6)
                {
                    BinaryMath.BinaryAdd(destinationPostcode, aRegister);
                }
            }

            // Conversion from Internal User Fields to Consolidated Data Value
            // Set CDV to 0
            BinaryMath.BinaryLoad(cdvRegister, "0");

            // Add Destination Post Code plus DPS
            BinaryMath.BinaryAdd(cdvRegister, destinationPostcode);

            // Multiply by 100,000,000
            BinaryMath.BinaryMultiply(cdvRegister, "100000000");

            // Add Item ID
            BinaryMath.BinaryLoad(tempRegister, "0");
            for (int i = 0; i < 32; i++)

            {
                if ((0x01 & (itemId >> i)) > 0)
                {
                    tempRegister[i] = 1;
                }
            }

            BinaryMath.BinaryAdd(cdvRegister, tempRegister);

            if (barcodeType == 'C')
            {
                BinaryMath.BinaryMultiply(cdvRegister, "100");  // Barcode C - Multiply by 100
            }
            else
            {
                BinaryMath.BinaryMultiply(cdvRegister, "1000000");  // Barcode L - Multiply by 1,000,000
            }
            // Add Supply Chain ID
            //int scCount = barcodeType == 'C' ? 7 : 20;
            BinaryMath.BinaryLoad(tempRegister, "0");
            for (int i = 0; i < 20; i++)
            {
                if ((0x01 & (supplyChainId >> i)) > 0)
                {
                    tempRegister[i] = 1;
                }
            }

            BinaryMath.BinaryAdd(cdvRegister, tempRegister);

            // Multiply by 15
            BinaryMath.BinaryMultiply(cdvRegister, "15");

            // Add Class
            BinaryMath.BinaryLoad(tempRegister, "0");
            for (int i = 0; i < 4; i++)
            {
                if ((0x01 & (classId >> i)) > 0)
                {
                    tempRegister[i] = 1;
                }
            }

            BinaryMath.BinaryAdd(cdvRegister, tempRegister);
            // Multiply by 5
            BinaryMath.BinaryMultiply(cdvRegister, "5");

            // Add Format
            BinaryMath.BinaryLoad(tempRegister, "0");
            for (int i = 0; i < 4; i++)
            {
                if ((0x01 & (formatId >> i)) > 0)
                {
                    tempRegister[i] = 1;
                }
            }

            BinaryMath.BinaryAdd(cdvRegister, tempRegister);

            // Multiply by 4
            BinaryMath.BinaryMultiply(cdvRegister, "4");
            // Add Version ID
            BinaryMath.BinaryLoad(tempRegister, "0");
            for (int i = 0; i < 4; i++)
            {
                if ((0x01 & (versionId >> i)) > 0)
                {
                    tempRegister[i] = 1;
                }
            }

            BinaryMath.BinaryAdd(cdvRegister, tempRegister);
            if (barcodeType == 'C')
            {
                dataTop    = 15;
                dataStep   = 8;
                checkCount = 6;
            }

            else
            {
                dataTop    = 18;
                dataStep   = 10;
                checkCount = 7;
            }

            // Conversion from Consolidated Data Value to Data Numbers
            for (int i = 0; i < 112; i++)
            {
                bRegister[i] = cdvRegister[i];
            }

            for (int j = dataTop; j >= (dataStep + 1); j--)
            {
                for (int i = 0; i < 112; i++)
                {
                    cdvRegister[i] = bRegister[i];
                    bRegister[i]   = 0;
                    aRegister[i]   = 0;
                }

                aRegister[96] = 1;
                for (int i = 91; i >= 0; i--)
                {
                    bRegister[i] = BinaryMath.IsLarger(cdvRegister, aRegister);
                    if (bRegister[i] == 1)
                    {
                        BinaryMath.BinarySubtract(cdvRegister, aRegister);
                    }

                    BinaryMath.ShiftDown(aRegister);
                }

                data[j] = (byte)((cdvRegister[5] * 32) + (cdvRegister[4] * 16) + (cdvRegister[3] * 8) + (cdvRegister[2] * 4) + (cdvRegister[1] * 2) + cdvRegister[0]);
            }

            for (int j = dataStep; j >= 0; j--)
            {
                for (int i = 0; i < 112; i++)
                {
                    cdvRegister[i] = bRegister[i];
                    bRegister[i]   = 0;
                    aRegister[i]   = 0;
                }

                aRegister[95] = 1;
                aRegister[94] = 1;
                aRegister[93] = 1;
                aRegister[92] = 1;
                for (int i = 91; i >= 0; i--)
                {
                    bRegister[i] = BinaryMath.IsLarger(cdvRegister, aRegister);
                    if (bRegister[i] == 1)
                    {
                        BinaryMath.BinarySubtract(cdvRegister, aRegister);
                    }

                    BinaryMath.ShiftDown(aRegister);
                }

                data[j] = (byte)((cdvRegister[5] * 32) + (cdvRegister[4] * 16) + (cdvRegister[3] * 8) + (cdvRegister[2] * 4) + (cdvRegister[1] * 2) + cdvRegister[0]);
            }

            ReedSolomon.RSInitialise(0x25, checkCount, 1);
            ReedSolomon.RSEncode(dataTop + 1, data, check);
            // Append check digits to data.
            for (int i = 1; i <= checkCount; i++)
            {
                data[dataTop + i] = check[checkCount - i];
            }

            // Conversion from Data Numbers and Check Numbers to Data Symbols and Check Symbols
            for (int i = 0; i <= dataStep; i++)
            {
                data[i] = dataSymbolEven[data[i]];
            }

            for (int i = dataStep + 1; i <= (dataTop + checkCount); i++)
            {
                data[i] = dataSymbolOdd[data[i]];
            }

            // Conversion from Data Symbols and Check Symbols to Extender Groups
            for (int i = 0; i < inputLength; i++)
            {
                if (barcodeType == 'C')
                {
                    extender[extenderGroupC[i]] = data[i];
                }

                else
                {
                    extender[extenderGroupL[i]] = data[i];
                }
            }

            // Conversion from Extender Groups to Bar Identifiers
            for (int i = 0; i < inputLength; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    switch (extender[i] & 0x24)
                    {
                    case 0x24:
                        barPattern.Append("F");
                        break;

                    case 0x20:
                        if (i % 2 > 0)
                        {
                            barPattern.Append("D");
                        }

                        else
                        {
                            barPattern.Append("A");
                        }

                        break;

                    case 0x04:
                        if (i % 2 > 0)
                        {
                            barPattern.Append("A");
                        }

                        else
                        {
                            barPattern.Append("D");
                        }

                        break;

                    default:
                        barPattern.Append("T");
                        break;
                    }

                    extender[i] = (short)(extender[i] << 1);
                }
            }

            BuildSymbol(barPattern);
            barcodeText = new string(barcodeData);
        }