using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace HS_Core.ImageFormat2D { /// /// The Bitmap File Header /// struct BitmapFileHeader { public UInt16 bfType; public UInt32 bfSize; public UInt16 bfReserved1; public UInt16 bfReserved2; public UInt32 bfOffBits; } /// /// The Bitmap Info Header /// struct BitmapHeader { public UInt32 biSize; public UInt32 BiWidth; public UInt32 BiHeight; public UInt16 biPlanes; public UInt16 biBitCount; public UInt32 biCompression; public UInt32 biSizeImage; public UInt32 biXPelsPerMeter; public UInt32 biYPelsPerMeter; public UInt32 biClrUsed; public UInt32 biClrImportant; } /// /// a 24bit pixel (no alpha channel) /// struct BitmapPixel { public byte r; public byte g; public byte b; } /// /// Main Bitmap Class /// class HS_Bitmap { private BitmapPixel[,] Pixels; //pixel data for the image public int Width { get; private set; } //image width public int Height { get; private set; } //image height /// /// Constructor - Create a new Bitmap /// /// New Image Width /// New Image Height public HS_Bitmap(int Width, int Height) { this.Width = Width; this.Height = Height; Pixels = new BitmapPixel[Width, Height]; } /// /// Get pixel data of the bitmap surface /// /// 2D array of BitmapPixel public BitmapPixel[,] GetPixels() { return Pixels; } /// /// Set data for a single pixel /// /// X location on bitmap /// Y Location on bitmap /// Pixel data public void SetPixel(int x, int y, BitmapPixel pix) { if (x >= 0 && x < Width) { if (y >= 0 && y < Height) { Pixels[x, y] = pix; } } } /// /// Clear entire bitmap to a single colour /// /// Red Value /// Green Value /// Blue Value public void Clear(byte r, byte g, byte b) { for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { Pixels[x, y].r = r; Pixels[x, y].g = g; Pixels[x, y].b = b; } } } /// /// Set data for a single pixel /// /// X location on bitmap /// Y Location on bitmap /// Red Value /// Green Value /// Blue Value public void SetPixel(int x, int y, byte r, byte g, byte b) { if (x >= 0 && x < Width) { if (y >= 0 && y < Height) { Pixels[x, y].r = r; Pixels[x, y].g = g; Pixels[x, y].b = b; } } } /// /// Set multiple pixels at once /// /// X location in destination bitmap /// Y location in destination bitmap /// 2D Array of BitmapPixel to copy to destination bitmap public void SetPixels(int x, int y, BitmapPixel[,] pixels) { int p_width = pixels.GetLength(0); int p_height = pixels.GetLength(1); for (int x2 = 0; x2 < p_width; x2++) { for (int y2 = 0; y2 < p_height; y2++) { if (x + x2 >= 0 && x + x2 < Width) { if (y + y2 >= 0 && y + y2 < Height) { Pixels[x + x2, y + y2] = pixels[x2, y2]; } } } } } /// /// Copy another bitmap into this bitmap /// /// X location in destination bitmap /// Y location in destination bitmap /// Source bitmap to copy from public void SetPixels(int x, int y, HS_Bitmap bmp) { BitmapPixel[,] pixels = bmp.GetPixels(); SetPixels(x, y, pixels); } /// /// Provides bitmap image data in the correct format for storing in a file (.bmp) /// /// BMP formatted pixel data private byte[] GetBMPRawData() { //calculate padding and size of buffer int ScanlineSize = Width * 3; int BufferPadding = 0; while ((ScanlineSize + BufferPadding) % 4 != 0) BufferPadding++; int Combined = BufferPadding + ScanlineSize; byte[] Buffer = new byte[Height * Combined]; //now flip the orientation and reverse the rgb, because bitmaps. int BufferPos = 0; for (int y = 0; y < Height; y++) { for (int x = 0; x < Width; x++) { BufferPos = (Height - y - 1) * Combined + (x * 3); Buffer[BufferPos] = Pixels[x, y].b; Buffer[BufferPos + 1] = Pixels[x, y].g; Buffer[BufferPos + 2] = Pixels[x, y].r; } } return Buffer; } /// /// Save the current state of the bitmap to a file. /// /// Destination file to create (include path and .bmp extension) public void SaveBmp(string fn) { //this will only write 24bit bitmaps. BitmapFileHeader BmpFileHeader = new BitmapFileHeader(); BitmapHeader BmpHeader = new BitmapHeader(); byte[] BmpData = GetBMPRawData(); UInt32 BmpFileHeaderSize = (UInt32)System.Runtime.InteropServices.Marshal.SizeOf(BmpFileHeader); UInt32 BmpInfoHeaderSize = (UInt32)System.Runtime.InteropServices.Marshal.SizeOf(BmpHeader); BmpFileHeader.bfSize = (UInt32)(BmpFileHeaderSize + BmpInfoHeaderSize + BmpData.Length); BmpFileHeader.bfType = 0x4D42; BmpFileHeader.bfReserved1 = 0; BmpFileHeader.bfReserved2 = 0; BmpFileHeader.bfOffBits = 54; BmpHeader.biSize = BmpInfoHeaderSize; BmpHeader.BiWidth = (UInt32)Width; BmpHeader.BiHeight = (UInt32)Height; BmpHeader.biPlanes = 1; BmpHeader.biBitCount = 24; BmpHeader.biCompression = 0; BmpHeader.biSizeImage = 0; BmpHeader.biXPelsPerMeter = 3800; BmpHeader.biYPelsPerMeter = 3800; BmpHeader.biClrUsed = 0; BmpHeader.biClrImportant = 0; StreamWriter swriter = new StreamWriter(fn); BinaryWriter ImgStream = new BinaryWriter(swriter.BaseStream); //remember to write the file in binary you dofus :/ ImgStream.Write(BmpFileHeader.bfType); ImgStream.Write(BmpFileHeader.bfSize); ImgStream.Write(BmpFileHeader.bfReserved1); ImgStream.Write(BmpFileHeader.bfReserved2); ImgStream.Write(BmpFileHeader.bfOffBits); ImgStream.Write(BmpHeader.biSize); ImgStream.Write(BmpHeader.BiWidth); ImgStream.Write(BmpHeader.BiHeight); ImgStream.Write(BmpHeader.biPlanes); ImgStream.Write(BmpHeader.biBitCount); ImgStream.Write(BmpHeader.biCompression); ImgStream.Write(BmpHeader.biSizeImage); ImgStream.Write(BmpHeader.biXPelsPerMeter); ImgStream.Write(BmpHeader.biYPelsPerMeter); ImgStream.Write(BmpHeader.biClrUsed); ImgStream.Write(BmpHeader.biClrImportant); for (int n = 0; n < BmpData.Length; n++) { ImgStream.Write(BmpData[n]); } swriter.Dispose(); ImgStream.Dispose(); } } }