private void parseImageArray(byte[] imageArray, ref image24BitBMP image) { int i = fileSizeOffset; image.fileSize = getFourByteNumber(imageArray[i], imageArray[i + 1], imageArray[i + 2], imageArray[i + 3]); i = imageDataOffset; image.imageDataOffset = getFourByteNumber(imageArray[i], imageArray[i + 1], imageArray[i + 2], imageArray[i + 3]); i = widthOffset; image.imageWidthPixels = getFourByteNumber(imageArray[i], imageArray[i + 1], imageArray[i + 2], imageArray[i + 3]); i = heightOffset; image.imageHeightPixels = getFourByteNumber(imageArray[i], imageArray[i + 1], imageArray[i + 2], imageArray[i + 3]); i = colorPlanesOffset; image.numColorPlanes = getFourByteNumber(imageArray[i], imageArray[i + 1], imageArray[i + 2], imageArray[i + 3]); i = bitsPerPixelOffset; image.bitsPerPixel = getFourByteNumber(imageArray[i], imageArray[i + 1], imageArray[i + 2], imageArray[i + 3]); i = compressionOffset; image.compressionType = getFourByteNumber(imageArray[i], imageArray[i + 1], imageArray[i + 2], imageArray[i + 3]); i = pxPerMeterHorizontalOffset; image.pixelsPerMMHorizontal = getFourByteNumber(imageArray[i], imageArray[i + 1], imageArray[i + 2], imageArray[i + 3]) / 1000; i = pxPerMeterVerticalOffset; image.pixelsPerMMVertical = getFourByteNumber(imageArray[i], imageArray[i + 1], imageArray[i + 2], imageArray[i + 3]) / 1000; image.imageData = new byte[imageArray.Length - (int)image.imageDataOffset]; Array.Copy(imageArray, (int)image.imageDataOffset, image.imageData, 0, image.imageData.Length); image.grayScaleImageData = new byte[(int)image.imageWidthPixels * (int)image.imageHeightPixels]; }
private void processImageData(ref image24BitBMP image) { // Declare useful variables int numPixels = (int)image.imageHeightPixels * (int)image.imageWidthPixels; int currentTile = 0; int currentGrayscalePixel = 0; int row = 0, column = 0; // Convert image to grayscale. Average the three bytes (R, G, B) for each pixel int padding = ((int)image.imageWidthPixels * 3) % 4; // Rows are padded with '0's to make the row count divisible by 4 if (padding != 0) { padding = 4 - padding; } // Grayscale conversion currentGrayscalePixel = 0; for (row = 0; row < (int)image.imageHeightPixels; row++) { for (column = 0; column < (int)image.imageWidthPixels; column++) { int i = row * (((int)image.imageWidthPixels) * 3 + padding) + column * 3; image.grayScaleImageData[currentGrayscalePixel] = (byte)(((int)image.imageData[i] + (int)image.imageData[i + 1] + (int)image.imageData[i + 2]) / 3); currentGrayscalePixel++; } } // Scale image, assuming image's vertical and horizontal resolution are equal // Image height exceeds screen limits if ((double)image.imageHeightPixels / image.pixelsPerMMVertical > screenHeightMM) { image.pixelsPerMMVertical = (ulong)((double)image.imageHeightPixels / screenHeightMM); image.pixelsPerMMHorizontal = image.pixelsPerMMVertical; } // Image width exceeds screen limits if ((double)image.imageWidthPixels / image.pixelsPerMMHorizontal > screenWidthMM) { image.pixelsPerMMHorizontal = (ulong)((double)image.imageWidthPixels / screenWidthMM); image.pixelsPerMMVertical = image.pixelsPerMMHorizontal; } // Crop image to make image dimensions in pixels divisible by the tile size in pixels int numStrayHorzPixels = (int)image.imageWidthPixels % ((int)image.pixelsPerMMHorizontal * tileSizeMM); int numStrayVertPixels = (int)image.imageHeightPixels % ((int)image.pixelsPerMMVertical * tileSizeMM); if (numStrayHorzPixels > 0 || numStrayVertPixels > 0) { currentGrayscalePixel = 0; image.imageHeightPixels -= (ulong)numStrayVertPixels; image.imageWidthPixels -= (ulong)numStrayHorzPixels; numPixels = (int)image.imageHeightPixels * (int)image.imageWidthPixels; image.grayScaleImageDataCorrectSize = new byte[image.imageWidthPixels * image.imageHeightPixels]; for (row = 0; row < (int)image.imageHeightPixels; row++) { for (column = 0; column < (int)image.imageWidthPixels; column++) { int i = row * ((int)image.imageWidthPixels + numStrayHorzPixels) + column; image.grayScaleImageDataCorrectSize[currentGrayscalePixel] = image.grayScaleImageData[i]; currentGrayscalePixel++; } } } else { image.grayScaleImageDataCorrectSize = new byte[image.grayScaleImageData.Length]; Array.Copy(image.grayScaleImageData, image.grayScaleImageDataCorrectSize, image.grayScaleImageData.Length); } // Calculate pixels per tile int tileWidthPx = (int)image.pixelsPerMMHorizontal * tileSizeMM; int tileHeightPx = (int)image.pixelsPerMMVertical * tileSizeMM; // Calculate image size in tiles image.imageWidthTiles = image.imageWidthPixels / image.pixelsPerMMHorizontal / (ulong)tileSizeMM; image.imageHeightTiles = image.imageHeightPixels / image.pixelsPerMMVertical / (ulong)tileSizeMM; // Create draw byte array image.commandBytes = new byte[image.imageHeightTiles * image.imageWidthTiles]; currentTile = 0; int currentTileValue = 0; for (row = 0; row < (int)image.imageHeightTiles; row++) { for (column = 0; column < (int)image.imageWidthTiles; column++) { // Calculate top left tile number int i = (row) * (int)image.imageWidthPixels * tileHeightPx + column * tileWidthPx; // Sum pixels in each tile int pixelRow = 0, pixelColumn = 0; for (pixelRow = 0; pixelRow < tileHeightPx; pixelRow++) { for (pixelColumn = 0; pixelColumn < tileWidthPx; pixelColumn++) { currentTileValue += image.grayScaleImageDataCorrectSize[i + pixelColumn]; } } currentTileValue /= (tileWidthPx * tileHeightPx); image.commandBytes[currentTile] = (byte)currentTileValue; currentTile++; currentTileValue = 0; } } currentTileValue = 0; }
private void button_Upload_Click(object sender, EventArgs e) { // Provide user feedback textBox_Status.Text = "Processing image"; // Display image pictureBox1.ImageLocation = imageLocation; pictureBox1.SizeMode = PictureBoxSizeMode.Zoom; // Determine resolution of print if (comboBox_Resolution.Text == "Low") { tileSizeMM = lowResTileSizeMM; } else if (comboBox_Resolution.Text == "Medium") { tileSizeMM = mediumResTileSizeMM; } else if (comboBox_Resolution.Text == "High") { tileSizeMM = highResTileSizeMM; } // Convert image to byte array Image imageIn = Image.FromFile(imageLocation); byte[] byteArray; MemoryStream ms = new MemoryStream(); imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); byteArray = ms.ToArray(); // Create image class currentImage = new image24BitBMP(); // Parse image parseImageArray(byteArray, ref currentImage); // Process image array processImageData(ref currentImage); // Add command bytes to draw queue int columnCount = 0; foreach (byte tileByte in currentImage.commandBytes) { // Enqueue tile byte switch (tileByte) { case 255: drawQueue.Enqueue(254); break; case 0: drawQueue.Enqueue(1); break; default: drawQueue.Enqueue(tileByte); break; } columnCount++; // Enqueue newline character '0' at end of row if (columnCount == (int)currentImage.imageWidthTiles) { columnCount = 0; drawQueue.Enqueue(0); } } textBox_Status.Text = "Image processing complete"; ////Print out the image //int currentTile = 0; //foreach (byte currentByte in currentImage.commandBytes) //{ // richTextBox_debug.AppendText(currentByte.ToString() + " "); // if ((currentTile + 1) % (int)currentImage.imageWidthTiles == 0) // { // richTextBox_debug.AppendText(Environment.NewLine); // } // currentTile++; //} }