/// <summary> /// shortens an image by a 2 ratio /// </summary> public void ReduceSize(int ratio) { Crop(image.GetLength(0) - image.GetLength(0) % ratio, image.GetLength(1) - image.GetLength(1) % ratio); Pixel[,] imageTemp = new Pixel[image.GetLength(0) / ratio, image.GetLength(1) / ratio]; for (int i = 0; i < imageTemp.GetLength(0); i++) { for (int j = 0; j < imageTemp.GetLength(1); j++) { int R = 0, G = 0, B = 0; for (int k = 0; k < ratio; k++) { for (int l = 0; l < ratio; l++) { R += image[i * ratio + k, j *ratio + l].R; G += image[i * ratio + k, j *ratio + l].G; B += image[i * ratio + k, j *ratio + l].B; } } Pixel pixel = new Pixel((byte)(R / (ratio * ratio)), (byte)(G / (ratio * ratio)), (byte)(B / (ratio * ratio))); imageTemp[i, j] = pixel; //Console.WriteLine(i / ratio + " " + j / ratio + " " + imageTemp.GetLength(0) + " " + imageTemp.GetLength(1)); } } image = imageTemp; }
//----------------------- Convolution matrix ------------------------------- /// <summary> /// Does a convolution with an image /// </summary> /// <param name="a">the kernel</param> public void Convolution(float[,] a) { Pixel[,] imageTemp = new Pixel[image.GetLength(0), image.GetLength(1)]; float norm = Normalization(a); for (int i = 0; i < imageTemp.GetLength(0); i++) { for (int j = 0; j < imageTemp.GetLength(1); j++) { Pixel[,] subArray = Subarray(image, i, j, (a.GetLength(1) - 1) / 2); imageTemp[i, j] = Convolution(a, subArray, norm); } } image = imageTemp; }
/// <summary> /// Crop an image with padding from Left Top Right and Left /// </summary> /// <param name="left"></param> /// <param name="top"></param> /// <param name="right"></param> /// <param name="bottom"></param> public void CropFromLTRB(int left, int top, int right, int bottom) { // Check if it can crop with these values if (image.GetLength(0) - top - bottom > 0 && image.GetLength(1) - left - right > 0) { Pixel[,] imageTemp = new Pixel[image.GetLength(0) - top - bottom, image.GetLength(1) - left - right]; for (int i = 0; i < imageTemp.GetLength(0); i++) { for (int j = 0; j < imageTemp.GetLength(1); j++) { imageTemp[i, j] = image[i + top, j + left]; } } image = imageTemp; } }
/// <summary> /// Creates an histogram based on the image /// </summary> /// <param name="filename">specify the folder and filename</param> /// <returns> /// returns a string with the filename /// itcan vary because of existing file in the folder /// </returns> public string Histogram(string filename) { imageType = "BM"; offsetSize = 54; int[,] histogram = this.histogram; int max = 0; foreach (int n in histogram) { if (n > max) { max = n; } } float ratio = 100f / (float)max; Pixel[,] imageTemp = new Pixel[100, 256]; for (int i = 0; i < imageTemp.GetLength(1); i++) { for (int j = 0; j < imageTemp.GetLength(0); j++) { imageTemp[imageTemp.GetLength(0) - j - 1, imageTemp.GetLength(1) - i - 1] = Pixel.Black; if (histogram[0, i] * ratio >= j) { imageTemp[imageTemp.GetLength(0) - j - 1, imageTemp.GetLength(1) - i - 1].AddRed(); } if (histogram[1, i] * ratio >= j) { imageTemp[imageTemp.GetLength(0) - j - 1, imageTemp.GetLength(1) - i - 1].AddGreen(); } if (histogram[2, i] * ratio >= j) { imageTemp[imageTemp.GetLength(0) - j - 1, imageTemp.GetLength(1) - i - 1].AddBlue(); } } } MyImage histo = new MyImage(imageTemp); string[] split = filename.Split('\\'); filename = ""; for (int i = 0; i < split.Length - 1; i++) { filename += split[i] + '\\'; } filename += "histogram-" + split.Last(); return(histo.Save(filename)); }
/// <summary> /// Create the QRCode and the image corresponding /// </summary> /// <param name="message">message to encode in the QRCode</param> private QRCode(string message) { offsetSize = 54; imageType = "BM"; this.message = message.ToUpper(); encoding = "0010"; //Alphanumeric length = Int_To_Bits(message.Length, 9); messageBits = Encode_Message(); int eccCount = 0; if (type == 1) { eccCount = 7; } else { eccCount = 10; } byte[] error = ReedSolomonAlgorithm.Encode(BitsToByte(encoding + length + messageBits), eccCount, ErrorCorrectionCodeType.QRCode); this.error = ByteToBit(error); Console.WriteLine(encoding.Length + length.Length + messageBits.Length + this.error.Length); Console.WriteLine(encoding + length + messageBits + this.error); DrawCanvas(); WriteData(); DrawErrorCorrection(); int size = 6; image = new Pixel[size * (code.GetLength(0) + 2), size *(code.GetLength(1) + 2)]; for (int i = 0; i < image.GetLength(0); i++) { for (int j = 0; j < image.GetLength(1); j++) { if (i < size || j < size || i >= code.GetLength(0) * size + size || j >= code.GetLength(1) * size + size) { image[i, j] = Pixel.White; } else if (code[i / size - 1, j / size - 1] == 0) { image[i, j] = Pixel.White; } else { image[i, j] = Pixel.Black; } } } }
/// <summary> /// Uses an algorithm to create the mandelbrot fractal /// </summary> /// <param name="zoom">the amount of zoom in the mandelbrot fractal (default 1)</param> private void MandelbrotFractal(int zoom = 1) { float x1 = -2.1f; float x2 = 0.6f; float y1 = -1.2f; float y2 = 1.2f; float zoomf = zoom * 100; int max = 255; image = new Pixel[(int)((y2 - y1) * zoomf), (int)((x2 - x1) * zoomf)]; for (int y = 0; y < image.GetLength(0); y++) { for (int x = 0; x < image.GetLength(1); x++) { float c_r = (float)x / zoomf + x1; float c_i = (float)y / zoomf + y1; float z_r = 0; float z_i = 0; int i = 0; do { float temp = z_r; z_r = z_r * z_r - z_i * z_i + c_r; z_i = 2 * z_i * temp + c_i; i++; } while (z_r * z_r + z_i * z_i < 4 && i < max); if (i == max) { image[y, x] = Pixel.Black; } else { image[y, x] = new Pixel(0, 0, (byte)(i * 255 / max)); } } } }
/// <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); }