private static EditableImage ReadPaletteBmp(byte[] buffer, Color[] palette, BmpInfoHeader header, int bpp) { int ppb = 8 / bpp; // Pixels per byte (bits per pixel) int width = (header.Width + ppb - 1) / ppb; int alignment = width % 4; // Rows are aligned on 4 byte boundaries int mask = (0xFF >> (8 - bpp)); // Bit mask int rowbase; int colbase; int offset; int realRow; Color color; EditableImage image = new EditableImage(header.Width, header.Height); if (alignment != 0) { alignment = 4 - alignment; // Calculate row padding } for (int row = 0; row < header.Height; row++) { rowbase = (row * (width + alignment)); for (int col = 0; col < width; col++) { offset = rowbase + col; colbase = col * ppb; realRow = header.Height - row - 1; // Reverse row for (int shift = 0; ((shift < ppb) && ((colbase + shift) < header.Width)); shift++) { color = palette[((buffer[offset]) >> (8 - bpp - (shift * bpp))) & mask]; image.SetPixel(colbase + shift, realRow, color.R, color.G, color.B, 255); } } } return image; }
private static EditableImage Read8BitBmp(byte[] buffer, Color[] palette, BmpInfoHeader header) { int alignment = header.Width % 4; // Rows are aligned on 4 byte boundaries int rowbase = 0; int offset; int realRow; Color color; EditableImage image = new EditableImage(header.Width, header.Height); if (alignment != 0) { alignment = 4 - alignment; // Calculate row padding } for (int row = 0; row < header.Height; row++) { rowbase = (row * (header.Width + alignment)); for (int col = 0; col < header.Width; col++) { offset = rowbase + col; realRow = header.Height - row - 1; // Reverse row color = palette[buffer[offset]]; image.SetPixel(col, realRow, color.R, color.G, color.B, color.A); } } return image; }
private static EditableImage Read565Bmp(byte[] buffer, BmpInfoHeader header) { int rowbase = 0; int offset; int realRow; short color; byte red; byte green; byte blue; int scaleR = 256 / 32; int scaleG = 256 / 64; EditableImage image = new EditableImage(header.Width, header.Height); for (int row = 0; row < header.Height; row++) { rowbase = (row * header.Width * 2); for (int col = 0; col < header.Width; col++) { offset = rowbase + (col * 2); realRow = header.Height - row - 1; // Reverse row // Get color and convert color = BitConverter.ToInt16(buffer, offset); red = (byte)(((color & _REDMASK) >> 11) * scaleR); green = (byte)(((color & _GREENMASK) >> 5) * scaleG); blue = (byte)(((color & _BLUEMASK)) * scaleR); // Set pixel image.SetPixel(col, realRow, red, green, blue, 255); } } return image; }
private static EditableImage Read4BitBmp(byte[] buffer, Color[] palette, BmpInfoHeader header) { int width = (header.Width + 1) / 2; int alignment = width % 4; // Rows are aligned on 4 byte boundaries int rowbase = 0; int colbase = 0; int offset; int realRow; Color color1; Color color2; EditableImage image = new EditableImage(header.Width, header.Height); if (alignment != 0) { alignment = 4 - alignment; // Calculate row padding } for (int row = 0; row < header.Height; row++) { rowbase = (row * (width + alignment)); for (int col = 0; col < width; col++) { colbase = col * 2; offset = rowbase + col; realRow = header.Height - row - 1; // Reverse row color1 = palette[(buffer[offset]) >> 4]; color2 = palette[(buffer[offset]) & 0x0F]; image.SetPixel(colbase, realRow, color1.R, color1.G, color1.B, 255); image.SetPixel(colbase + 1, realRow, color2.R, color2.G, color2.B, 255); } } return image; }
private static EditableImage Read24BitBmp(byte[] buffer, BmpInfoHeader header) { int alignment = (header.Width * 3) % 4; // Rows are aligned on 4 byte boundaries int rowbase = 0; int offset; int realRow; EditableImage image = new EditableImage(header.Width, header.Height); if (alignment != 0) { alignment = 4 - alignment; // Calculate row padding } for (int row = 0; row < header.Height; row++) { rowbase = (row * ((header.Width * 3) + alignment)); for (int col = 0; col < header.Width; col++) { offset = rowbase + (col * 3); realRow = header.Height - row - 1; // Reverse row if (offset >= buffer.Length) { HtmlPage.Window.Alert("Error - outside of bounds and not sure why"); } image.SetPixel(col, realRow, buffer[offset + 2], buffer[offset + 1], buffer[offset], 255); } } return image; }
/// <summary> /// /// </summary> /// <param name="stream"></param> /// <returns></returns> public static BmpInfoHeader FillFromStream(Stream stream) { byte[] buffer = new byte[_SIZE]; BmpInfoHeader header = new BmpInfoHeader(); stream.Read(buffer, 0, _SIZE); // Fill header.HeaderSize = BitConverter.ToInt32(buffer, 0); header.Width = BitConverter.ToInt32(buffer, 4); header.Height = BitConverter.ToInt32(buffer, 8); header.BitsPerPixel = BitConverter.ToInt16(buffer, 14); header.Compression = BitConverter.ToInt32(buffer, 16); header.ImageSize = BitConverter.ToInt32(buffer, 20); header.ColorCount = BitConverter.ToInt32(buffer, 32); // Fix for no ImageSize in the header if (header.ImageSize == 0) { int rowSize = 4 * (int)Math.Ceiling(header.Width * (header.BitsPerPixel / 32)); int fileSize = header.HeaderSize + (4 * (int)Math.Pow(2, header.BitsPerPixel)) + rowSize + header.Height; header.ImageSize = (int)fileSize; } if (header.ColorCount == 0) { header.ColorCount = (1 << header.BitsPerPixel); } // Return results return header; }