/// <summary> /// Decode a QRCode /// </summary> /// <param name="img">image containing the QRCode</param> private QRCode(MyImage img) { // Copy image on this object image = new Pixel[img.image.GetLength(0), img.image.GetLength(1)]; for (int i = 0; i < image.GetLength(0); i++) { for (int j = 0; j < image.GetLength(1); j++) { image[i, j] = new Pixel(img.image[i, j]); } } /* https://www.researchgate.net/publication/221337868_Fast_QR_Code_Detection_in_Arbitrarily_Acquired_Images */ //Assume image is flat on the surface //Find the size of a finder and the size of a code to determine the version //and the size of a bit to be accurate while reading // plus save the start index of QRCode; // Different size horizontal and vertical (if image is warped int sizeOfFinderHorizontal = 0; int sizeOfCodeHorizontal = 0; int sizeOfFinderVertical = 0; int sizeOfCodeVertical = 0; bool b = true; int line = 0; int column = 0; int startLine = 0; int startColumn = 0; //Searching while (b) { column = 0; while (column < image.GetLength(1) && !image[line, column].isCloseToBlack) { column++; } startColumn = column; startLine = line; // For horizontal size while (column < image.GetLength(1) && image[startLine, column].isCloseToBlack) { b = false; sizeOfFinderHorizontal++; column++; } // For Vertical size while (!b && line < image.GetLength(0) && image[line, startColumn].isCloseToBlack) { sizeOfFinderVertical++; line++; } if (!b) { // Horizontal size for (int j = image.GetLength(1) - 1; j >= 0 && sizeOfCodeHorizontal == 0; j--) { if (image[startLine, j].isCloseToBlack) { sizeOfCodeHorizontal = j - startColumn; } } // Vertical Size for (int j = image.GetLength(0) - 1; j >= 0 && sizeOfCodeVertical == 0; j--) { if (image[j, startColumn].isCloseToBlack) { sizeOfCodeVertical = j - startLine; } } } line++; } //Compute the size of a bit (finder is 7 pixels wide) int bitSizeHorizontal = sizeOfFinderHorizontal / 7; int bitSizeVertical = sizeOfFinderVertical / 7; int approxSize = sizeOfCodeHorizontal / bitSizeHorizontal; //Determine the version of QR based on the size if (approxSize < 23) { type = 1; } else { type = 2; } //Now read the QRCode but first Draw the Canvas DrawCanvas(); //Read DAta string messageBits = ReadData(bitSizeHorizontal, bitSizeVertical, startLine, startColumn); // Get rid of the last seven bits if type 2 if (type == 2) { messageBits = messageBits.Substring(0, 352); } Console.WriteLine(messageBits); // Get The Error count int eccCount = 7 * 8; if (type == 2) { eccCount = 10 * 8; } //Split error bits and message bits string errorBits = messageBits.Substring(messageBits.Length - eccCount, eccCount); messageBits = messageBits.Substring(0, messageBits.Length - eccCount); // Decode with Reed Solomon Algorithm byte[] messageBytes = BitsToByte(messageBits); byte[] errorBytes = BitsToByte(errorBits); byte[] finalMessage = ReedSolomonAlgorithm.Decode(messageBytes, errorBytes, ErrorCorrectionCodeType.QRCode); messageBits = ByteToBit(finalMessage); // Assume the image is alphanumeric and get rid of the length messageBits = messageBits.Substring(4, messageBits.Length - 4); Decode_Message(messageBits); }