using System;
public class BitmapBytes
{
///
/// Converts RGBA bytes into an RGBA Bitmap.
/// Pixels go left to right, bottom to top.
/// Can write to file with, e.g:
/// File.WriteAllBytes("example.bmp", BitmapBytes.FromRGBABytes(imageData, width));
///
/// array of r,g,b,a pixels, must be divisible by 4
/// the image width, in pixels, height is omitted as it gets calculated
/// a byte array in bmp format
public static byte[] FromRGBABytes(byte[] rgba, int width)
{
int height = (rgba.Length / 4) / width;
var bytes = new byte[rgba.Length + bmpHeader.Length];
//write header
Buffer.BlockCopy(bmpHeader, 0, bytes, 0, bmpHeader.Length);
//write filesize to offset 2
Buffer.BlockCopy(BitConverter.GetBytes(bytes.Length), 0, bytes, 2, 4);
//write width to offset 18
Buffer.BlockCopy(BitConverter.GetBytes(width), 0, bytes, 18, 4);
//write height to offset 22
Buffer.BlockCopy(BitConverter.GetBytes(height), 0, bytes, 22, 4);
//write image size to offset 34
Buffer.BlockCopy(BitConverter.GetBytes(width * height * 4), 0, bytes, 34, 4);
//finally, write the image data
Buffer.BlockCopy(rgba, 0, bytes, bmpHeader.Length, rgba.Length);
return bytes;
}
static byte[] bmpHeader = new byte[] // All values are little-endian
{
0x42, 0x4D, // Signature 'BM'
0xaa, 0x00, 0x00, 0x00, // Size: e.g. 170 bytes
0x00, 0x00, // Unused
0x00, 0x00, // Unused
0x8a, 0x00, 0x00, 0x00, // Offset to image data
0x7c, 0x00, 0x00, 0x00, // DIB header size (124 bytes)
0x04, 0x00, 0x00, 0x00, // Width (e.g. 4px)
0x02, 0x00, 0x00, 0x00, // Height (e.g. 2px)
0x01, 0x00, // Planes (1)
0x20, 0x00, // Bits per pixel (32)
0x03, 0x00, 0x00, 0x00, // Format (bitfield = use bitfields | no compression)
0x20, 0x00, 0x00, 0x00, // Image raw size (32 bytes)
0x13, 0x0B, 0x00, 0x00, // Horizontal print resolution (2835 = 72dpi * 39.3701)
0x13, 0x0B, 0x00, 0x00, // Vertical print resolution (2835 = 72dpi * 39.3701)
0x00, 0x00, 0x00, 0x00, // Colors in palette (none)
0x00, 0x00, 0x00, 0x00, // Important colors (0 = all)
0xFF, 0x00, 0x00, 0x00, // R bitmask (00FF0000)
0x00, 0xFF, 0x00, 0x00, // G bitmask (0000FF00)
0x00, 0x00, 0xFF, 0x00, // B bitmask (000000FF)
0x00, 0x00, 0x00, 0xFF, // A bitmask (FF000000)
0x42, 0x47, 0x52, 0x73, // sRGB color space
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Unused R, G, B entries for color space
0x00, 0x00, 0x00, 0x00, // Unused Gamma X entry for color space
0x00, 0x00, 0x00, 0x00, // Unused Gamma Y entry for color space
0x00, 0x00, 0x00, 0x00, // Unused Gamma Z entry for color space
0x00, 0x00, 0x00, 0x00, // Unknown
0x00, 0x00, 0x00, 0x00, // Unknown
0x00, 0x00, 0x00, 0x00, // Unknown
0x00, 0x00, 0x00, 0x00, // Unknown
};
}