Beispiel #1
0
        /// <summary>
        /// The calculate method.
        /// </summary>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="numEcc">
        /// The number of <c>ecc</c> codes.
        /// </param>
        /// <returns>
        /// The <see cref="byte"/> array.
        /// </returns>
        public byte[] Calculate(Poly message, int numEcc)
        {
            // Get message poly coefficients
            int[] messageCoefficients = new int[message.Terms.Length];

            for (int i = 0; i < message.Terms.Length; i++)
            {
                messageCoefficients[i] = message.Terms[i].Coefficient;
            }

            // Convert message poly coefficients into Galois Field (get a coefficients from numbers)
            QrGaloisFieldPoly info = new QrGaloisFieldPoly(this.field, messageCoefficients);

            // Increase level of the poly by number of ECC
            info = info.MultiplyByMonomial(numEcc, 1);

            // Get generator poly
            QrGaloisFieldPoly generatorPoly = this.BuildGeneratorPolynomial(numEcc);

            // Divite by generator poly
            QrGaloisFieldPoly remainder = info.Divide(generatorPoly)[1];

            // Return remainder coefficients in bytes
            int[] coefficients = remainder.GetCoefficients();

            byte[] eccCodes = new byte[coefficients.Length];

            for (int i = 0; i < coefficients.Length; i++)
            {
                eccCodes[i] = Convert.ToByte(coefficients[i]);
            }

            return eccCodes;
        }
Beispiel #2
0
        /// <summary>
        /// this will Create a new Poly by the Value of 1 and Plus it to the First Poly.
        /// </summary>
        /// <param name="p1">Polynomial expression to increase</param>
        /// <returns>Increased polynomial expression</returns>
        public static Poly operator ++(Poly p1)
        {
            Poly p2 = new Poly("1");

            p1 = p1 + p2;
            return(p1);
        }
Beispiel #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Poly"/> class. 
        /// Constructor which creates new instance of poly from existing poly.
        /// Meant for copying polys.
        /// </summary>
        /// <param name="p">
        /// Polynomial instance
        /// </param>
        public Poly(Poly p)
        {
            this.terms = new TermCollection();

            for (int i = 0; i < p.Terms.Length; i++)
            {
                Term t = new Term(p.Terms[i].Power, p.Terms[i].Coefficient);

                this.terms.Add(t);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Poly"/> class.
        /// Constructor which creates new instance of poly from existing poly.
        /// Meant for copying polys.
        /// </summary>
        /// <param name="p">
        /// Polynomial instance
        /// </param>
        public Poly(Poly p)
        {
            this.terms = new TermCollection();

            for (int i = 0; i < p.Terms.Length; i++)
            {
                Term t = new Term(p.Terms[i].Power, p.Terms[i].Coefficient);

                this.terms.Add(t);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Plus Operator:
        /// Add Method of TermsCollection will Check the Power of each Term And if it's already
        /// exists in the Collection Just Plus the Coefficient of the Term and This Mean Plus Operation.
        /// So We Simply Add the Terms of Second Poly to the First one.
        /// </summary>
        /// <param name="p1">Polynomial one</param>
        /// <param name="p2">Polynomial two</param>
        /// <returns>Sum of both polynomials</returns>
        public static Poly operator +(Poly p1, Poly p2)
        {
            Poly result = new Poly(p1.ToString());

            foreach (Term t in p2.Terms)
            {
                result.Terms.Add(t);
            }

            return(result);
        }
Beispiel #6
0
        /// <summary>
        /// Minus Operation: Like Plus Operation but at first we just Make the Second Poly to the Negative Value.
        /// </summary>
        /// <param name="p1">Polynomial one</param>
        /// <param name="p2">Polynomial two</param>
        /// <returns>Subtracted polynomial expression</returns>
        public static Poly operator -(Poly p1, Poly p2)
        {
            Poly result     = new Poly(p1.ToString());
            Poly negetiveP2 = new Poly(p2.ToString());

            foreach (Term t in negetiveP2.Terms)
            {
                t.Coefficient *= -1;
            }

            return(result + negetiveP2);
        }
Beispiel #7
0
        /// <summary>
        /// Division operator
        /// </summary>
        /// <param name="p1">Polynomial one</param>
        /// <param name="p2">Polynomial two</param>
        /// <returns>Divided polynomial</returns>
        public static Poly operator /(Poly p1, Poly p2)
        {
            p1.Terms.Sort(TermCollection.SortType.Des);
            p2.Terms.Sort(TermCollection.SortType.Des);
            TermCollection resultTerms = new TermCollection();

            if (p1.Terms[0].Power < p2.Terms[0].Power)
            {
                throw new Exception("Invalid Division: P1.MaxPower is Lower than P2.MaxPower");
            }

            while (p1.Terms[0].Power > p2.Terms[0].Power)
            {
                Term nextResult = new Term(
                    p1.Terms[0].Power - p2.Terms[0].Power, p1.Terms[0].Coefficient / p2.Terms[0].Coefficient);
                resultTerms.Add(nextResult);
                Poly tempPoly = nextResult;

                Poly newPoly = tempPoly * p2;
                p1 = p1 - newPoly;
            }

            return(new Poly(resultTerms));
        }
Beispiel #8
0
        /// <summary>
        /// The process.
        /// </summary>
        /// <exception cref="ArgumentException">
        /// Throws argument exception if wrong type or version are selected
        /// </exception>
        /// <exception cref="Exception">
        /// Throws exception if text is too long for the matrix
        /// </exception>
        private void Process()
        {
            // Preprocess
            // -> one of the parameters was not set, simple mode
            // -> create structure of QR Image
            this.ChooseVersions();

            if (this.debugData != null)
            {
                this.img = new QrImage(this.version, this.mask, this.breakPoint);

                this.debugData.Append(this.img.GetDebugData());
            }
            else
            {
                this.img = new QrImage(this.version, this.mask);
            }

            if ((this.breakPoint == QrBreakPoint.CreatedMatrix) && (this.debugData != null))
            {
                this.debugData.Append("------- Breakpoint reached: Step 1 -------");

                return;
            }

            // Step one - sending type to output
            if (this.debugData != null)
            {
                this.debugData.Append(
                    "------------------ Step 1 ------------------\n- Sending type bits (4) to output ...\n");
            }

            switch (this.type)
            {
                case QrType.Numeric:
                    this.output.Enqueue(false);
                    this.output.Enqueue(false);
                    this.output.Enqueue(false);
                    this.output.Enqueue(true);

                    break;

                case QrType.AlphaNumeric:
                    this.output.Enqueue(false);
                    this.output.Enqueue(false);
                    this.output.Enqueue(true);
                    this.output.Enqueue(false);

                    break;

                case QrType.Binary:
                    this.output.Enqueue(false);
                    this.output.Enqueue(true);
                    this.output.Enqueue(false);
                    this.output.Enqueue(false);

                    break;
                case QrType.Japanese:
                    this.output.Enqueue(true);
                    this.output.Enqueue(false);
                    this.output.Enqueue(false);
                    this.output.Enqueue(false);

                    break;
                default:
                    throw new ArgumentException("Wrong QRType selected.");
            }

            if (this.debugData != null)
            {
                this.debugData.Append(
                    "- Sent 4 bytes of output: " + BinaryExtensions.BinaryToString(this.output) + "\n\n");
            }

            if ((this.breakPoint == QrBreakPoint.OutputTypeBits) && (this.debugData != null))
            {
                this.debugData.Append("------- Breakpoint reached: Step 2 -------");

                return;
            }

            // Step two - write length of string
            if (this.debugData != null)
            {
                this.debugData.Append(
                    "------------------ Step 2 ------------------\n- Calculating bit size for data length ...\n");
            }

            byte strLength;

            if ((this.version.Version >= 1) && (this.version.Version <= 9))
            {
                switch (this.type)
                {
                    case QrType.Numeric:
                        strLength = 10;
                        break;
                    case QrType.AlphaNumeric:
                        strLength = 9;
                        break;
                    case QrType.Binary:
                        strLength = 8;
                        break;
                    case QrType.Japanese:
                        strLength = 8;
                        break;
                    default:
                        strLength = 0;
                        break;
                }
            }
            else if ((this.version.Version >= 10) && (this.version.Version <= 26))
            {
                switch (this.type)
                {
                    case QrType.Numeric:
                        strLength = 12;
                        break;
                    case QrType.AlphaNumeric:
                        strLength = 11;
                        break;
                    case QrType.Binary:
                        strLength = 16;
                        break;
                    case QrType.Japanese:
                        strLength = 10;
                        break;
                    default:
                        strLength = 0;
                        break;
                }
            }
            else if ((this.version.Version >= 27) && (this.version.Version <= 40))
            {
                switch (this.type)
                {
                    case QrType.Numeric:
                        strLength = 14;
                        break;
                    case QrType.AlphaNumeric:
                        strLength = 13;
                        break;
                    case QrType.Binary:
                        strLength = 16;
                        break;
                    case QrType.Japanese:
                        strLength = 12;
                        break;
                    default:
                        strLength = 0;
                        break;
                }
            }
            else
            {
                throw new ArgumentException("Wrong QRVersion selected.");
            }

            if (this.debugData != null)
            {
                this.debugData.Append(
                    "- QR Type: " + this.type + ", QR Version: " + this.version.Version + ", Bit size: " + strLength
                    + " bits.\n");
            }

            // Write length to output
            int length = this.text.Length;

            this.ToOutput(BinaryExtensions.DecToBin(length, strLength));

            if (this.debugData != null)
            {
                this.debugData.Append(
                    "- Stored data length to output: "
                    + BinaryExtensions.BinaryToString(BinaryExtensions.DecToBin(length, strLength)) + "\n");
                this.debugData.Append(
                    "- Data stored in output: " + BinaryExtensions.BinaryToString(this.output) + "\n\n");
            }

            if ((this.breakPoint == QrBreakPoint.OutputDataLength) && (this.debugData != null))
            {
                this.debugData.Append("------- Breakpoint reached: Step 3 -------");

                return;
            }

            // Step 3 - encoding entry text
            if (this.debugData != null)
            {
                this.debugData.Append(
                    "------------------ Step 3 ------------------\n- Creating code table for input ...\n");
            }

            QrCodeTable table = new QrCodeTable(this.type);

            if (this.debugData != null)
            {
                this.debugData.Append("- Checking for odd input length.\n");
            }

            // Odd text length handling
            if (length % 2 == 1)
            {
                if (this.debugData != null)
                {
                    this.debugData.Append(" - Text length is odd, reducing size for one character.\n");
                }

                length = length - 1;
            }

            if (this.debugData != null)
            {
                this.debugData.Append("- Writing characters ...\n");
            }

            for (int i = 0; i < length; i += 2)
            {
                // Get number
                int calc = (table.GetCharCount() * table.GetCodeByChar(this.text[i]))
                           + table.GetCodeByChar(this.text[i + 1]);

                if (this.debugData != null)
                {
                    this.debugData.Append(
                        " - Characters: " + this.text[i] + ", " + this.text[i + 1] + ": (" + table.GetCharCount()
                        + " * " + table.GetCodeByChar(this.text[i]) + ") + " + table.GetCodeByChar(this.text[i + 1])
                        + " = " + calc + "\n");
                }

                // Write number, why 11 bits for each sign?????
                // Experimental: strLength as calculated for size.
                this.ToOutput(BinaryExtensions.DecToBin(calc, 11));
            }

            // Handling last 6 bits for odd length
            if (this.text.Length % 2 == 1)
            {
                if (this.debugData != null)
                {
                    this.debugData.Append(
                        "- Writing last (odd) character " + this.text[this.text.Length - 1] + " with " + 6 + " bits: "
                        + table.GetCodeByChar(this.text[this.text.Length - 1]) + "\n");
                }

                this.ToOutput(BinaryExtensions.DecToBin(table.GetCodeByChar(this.text[this.text.Length - 1]), 6));
            }

            if (this.debugData != null)
            {
                this.debugData.Append("- Input successfully encoded to binary.\n\n");
            }

            if ((this.breakPoint == QrBreakPoint.EncodedDataToBinary) && (this.debugData != null))
            {
                this.debugData.Append("------- Breakpoint reached: Step 4 -------");

                return;
            }

            // Step 4 - finishing binary string
            if (this.debugData != null)
            {
                this.debugData.Append("------------------ Step 4 ------------------\n- Finishing binary string ...\n");
            }

            // Calculate maximum bit length
            int maxBits = this.version.DataSize * 8;

            if (this.debugData != null)
            {
                this.debugData.Append(
                    "- Maximum bits for current version: " + maxBits + " current bits: " + this.output.Count + "\n");
            }

            // Add zeros to end of bit string, if we are missing them
            int bitOverflow = 0;

            while (this.output.Count < maxBits)
            {
                this.output.Enqueue(false);

                bitOverflow++;

                if (bitOverflow >= 4)
                {
                    break;
                }
            }

            if (this.debugData != null)
            {
                this.debugData.Append(
                    "- Added " + bitOverflow + " bits to binary output. Total: " + this.output.Count + " bits.\n\n");
            }

            if ((this.breakPoint == QrBreakPoint.FinishedBinary) && (this.debugData != null))
            {
                this.debugData.Append("------- Breakpoint reached: Step 5 -------");

                return;
            }

            // Step 5 - breaking the bit string into bytes
            if (this.debugData != null)
            {
                this.debugData.Append(
                    "------------------ Step 5 ------------------\n- Dividing bits into bytes (8 bits per byte) ...\n");
                this.debugData.Append("- Current output size: " + this.output.Count + " bits\n");
            }

            // For now we will just make sure it is divided by 8, we will not convert to bytes unless required.
            while (this.output.Count % 8 != 0)
            {
                this.output.Enqueue(false);
            }

            if (this.debugData != null)
            {
                this.debugData.Append(
                    "- Added zeros to output, current size: " + this.output.Count + " bits, "
                    + (this.output.Count / 8) + " bytes.\n\n");
            }

            if ((this.breakPoint == QrBreakPoint.BrokenBinary) && (this.debugData != null))
            {
                this.debugData.Append("------- Breakpoint reached: Step 6 -------");

                return;
            }

            // Step 6 - inserting characters
            if (this.debugData != null)
            {
                this.debugData.Append(
                    "------------------ Step 6 ------------------\n- Inserting characters to fill missing data string ...\n");
            }

            // If we have too many bits
            if ((this.output.Count / 8) > this.version.DataSize)
            {
                throw new Exception("Text is too long for current matrix.");
            }

            // If we have less or exact number of bits
            List<bool> defaultBlock1 = BinaryExtensions.DecToBin(236, 8);
            List<bool> defaultBlock2 = BinaryExtensions.DecToBin(17, 8);

            // Fill matrix until it is full as specified in version
            int fillCount = 0;

            if (this.debugData != null)
            {
                this.debugData.Append(
                    "- Current output size: " + (this.output.Count / 8) + ", missing: "
                    + (this.version.DataSize - (this.output.Count / 8)) + " bytes.\n");
                this.debugData.Append("- Added bytes: ");
            }

            while ((this.output.Count / 8) < this.version.DataSize)
            {
                if ((fillCount % 2) == 0)
                {
                    if (this.debugData != null)
                    {
                        this.debugData.Append("236, ");
                    }

                    this.ToOutput(defaultBlock1);
                }
                else
                {
                    if (this.debugData != null)
                    {
                        this.debugData.Append("17, ");
                    }

                    this.ToOutput(defaultBlock2);
                }

                fillCount++;
            }

            if (this.debugData != null)
            {
                this.debugData.Append(
                    "\n- Output size filled to match data size: " + (this.output.Count / 8) + "/"
                    + this.version.DataSize + " bytes\n\n");
            }

            if ((this.breakPoint == QrBreakPoint.MissingBytes) && (this.debugData != null))
            {
                this.debugData.Append("------- Breakpoint reached: Step 7 -------");

                return;
            }

            // Step 7 - generating error code correction (ECC) by Reed-Solomon procedure

            // Convert bits from output to byte array
            byte[] bytes = BinaryExtensions.BitArrayToByteArray(new BitArray(this.output.ToArray()));

            if (this.debugData != null)
            {
                this.debugData.Append(
                    "------------------ Step 7 ------------------\n- Calculating error code correction ...\n");
                this.debugData.Append(
                    "- Dividing data words into blocks: " + this.version.GetBlockCount() + " total.\n");
                this.debugData.Append("- Creating message polynomial for each block ...\n");
            }

            // Divide bytes into blocks
            QrBlock[] blocks = new QrBlock[this.version.GetBlockCount()];

            for (int x = 0; x < this.version.GetBlockCount(); x++)
            {
                // Creating message polynominal system (F(x)) for current block

                // Calculate block length and starting position
                int blockLength;
                int blockStart;

                if (x >= this.version.BlockOneCount)
                {
                    blockLength = this.version.BlockTwoSize;

                    blockStart = (this.version.BlockOneSize * this.version.BlockOneCount)
                                 + ((x - this.version.BlockOneCount) * this.version.BlockTwoSize);
                }
                else
                {
                    blockLength = this.version.BlockOneSize;

                    blockStart = this.version.BlockOneSize * x;
                }

                if (this.debugData != null)
                {
                    this.debugData.Append(
                        "----------------------------------\n- Block " + (x + 1) + ", data from: " + blockStart
                        + ", length: " + blockLength + "\n- Message polynomial:\n\n");
                }

                Poly message = new Poly();

                int messageLevel = this.version.BlockOneSize
                                   + (this.version.ErrorSize / this.version.GetBlockCount()) - 1;

                for (int i = 0; i < blockLength; i++)
                {
                    if (this.debugData != null)
                    {
                        this.debugData.Append("(" + bytes[i + blockStart] + "x ^ " + messageLevel + ")");

                        if (i != blockLength - 1)
                        {
                            this.debugData.Append(" + ");
                        }
                    }

                    Term ter = new Term(messageLevel, bytes[i + blockStart]);
                    message.Terms.Add(ter);

                    messageLevel--;
                }

                if (this.debugData != null)
                {
                    this.debugData.Append(
                        "\n\n- Calculating "
                        + ((int)Math.Floor(this.version.ErrorSize / (double)this.version.GetBlockCount()))
                        + " error codes using Reed-Solomon algorithm.\n");
                }

                // Calculate Error codes of desired block
                blocks[x] = new QrBlock { MessagePoly = new Poly(message) };

                // Create Reed Solomon algorithm class
                QrReedSolomon ecc = new QrReedSolomon();

                // Experimental bugfix: rounding the result, so we can choose correct ECC
                blocks[x].EccCoefficients = ecc.Calculate(
                    message, (int)Math.Floor(this.version.ErrorSize / (double)this.version.GetBlockCount()));

                if (this.debugData != null)
                {
                    this.debugData.Append(
                        "- Calculated error codes: " + BinaryExtensions.ArrayToString(blocks[x].EccCoefficients)
                        + "\n\n");
                }
            }

            // Write error codes to bit stream

            // Clear current output
            this.output.Clear();

            // Writing data bits
            if (this.debugData != null)
            {
                this.debugData.Append("- Writing data bits into output:\n- ");
            }

            // Blocks might not be the same size...
            for (int i = 0; i < Math.Max(this.version.BlockOneSize, this.version.BlockTwoSize); i++)
            {
                foreach (QrBlock t in blocks)
                {
                    if (i < t.MessagePoly.Terms.Length)
                    {
                        this.ToOutput(BinaryExtensions.DecToBin(t.MessagePoly.Terms[i].Coefficient, 8));

                        if (this.debugData != null)
                        {
                            this.debugData.Append(t.MessagePoly.Terms[i].Coefficient + ", ");
                        }
                    }
                }
            }

            if (this.debugData != null)
            {
                this.debugData.Append("\n\n- Writing ECC bits to output:\n- ");
            }

            // Writting ECC bits
            for (int i = 0; i < blocks[0].EccCoefficients.Length; i++)
            {
                if (i == 17)
                {
                    if (this.debugData != null)
                    {
                        this.debugData.Append(",");
                    }
                }

                foreach (QrBlock t in blocks)
                {
                    this.ToOutput(BinaryExtensions.DecToBin(t.EccCoefficients[i], 8));

                    if (this.debugData != null)
                    {
                        this.debugData.Append(t.EccCoefficients[i] + ", ");
                    }
                }
            }

            if (this.debugData != null)
            {
                this.debugData.Append("\n\n");
            }

            // Step 8, 9, 10 - Handled by QRImage class
            if ((this.breakPoint == QrBreakPoint.ErrorCode) && (this.debugData != null))
            {
                this.debugData.Append("------- Breakpoint reached: Step 8 -------");

                return;
            }

            this.img.CreateImage(this.output);

            if (this.debugData != null)
            {
                this.debugData.Append(this.img.GetDebugData());
            }
        }
Beispiel #9
0
 /// <summary>
 /// this will Create a new Poly by the Value of -1 and Plus it to the First Poly.
 /// </summary>
 /// <param name="p1">Polynomial expression</param>
 /// <returns>Decreased polynomial by 1</returns>
 public static Poly operator --(Poly p1)
 {
     Poly p2 = new Poly("-1");
     p1 = p1 + p2;
     return p1;
 }
Beispiel #10
0
        /// <summary>
        /// Minus Operation: Like Plus Operation but at first we just Make the Second Poly to the Negative Value.
        /// </summary>
        /// <param name="p1">Polynomial one</param>
        /// <param name="p2">Polynomial two</param>
        /// <returns>Subtracted polynomial expression</returns>
        public static Poly operator -(Poly p1, Poly p2)
        {
            Poly result = new Poly(p1.ToString());
            Poly negetiveP2 = new Poly(p2.ToString());
            foreach (Term t in negetiveP2.Terms)
            {
                t.Coefficient *= -1;
            }

            return result + negetiveP2;
        }
Beispiel #11
0
        /// <summary>
        /// Plus Operator: 
        /// Add Method of TermsCollection will Check the Power of each Term And if it's already 
        /// exists in the Collection Just Plus the Coefficient of the Term and This Mean Plus Operation.
        /// So We Simply Add the Terms of Second Poly to the First one.
        /// </summary>
        /// <param name="p1">Polynomial one</param>
        /// <param name="p2">Polynomial two</param>
        /// <returns>Sum of both polynomials</returns>
        public static Poly operator +(Poly p1, Poly p2)
        {
            Poly result = new Poly(p1.ToString());
            foreach (Term t in p2.Terms)
            {
                result.Terms.Add(t);
            }

            return result;
        }