Last active
June 12, 2024 08:46
-
-
Save macromaniac/a64a68f39041158d5f22959f91f9fb49 to your computer and use it in GitHub Desktop.
Low level C# Bitmap Serializer. Surprisingly 5x faster than the commonly used .net BitmapData (tested on 100x100 images). Mostly for when you want finer tune control over your bitmaps than .net gives you.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
public class BitmapBytes | |
{ | |
/// <summary> | |
/// 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)); | |
/// </summary> | |
/// <param name="rgba">array of r,g,b,a pixels, must be divisible by 4</param> | |
/// <param name="width">the image width, in pixels, height is omitted as it gets calculated</param> | |
/// <returns>a byte array in bmp format</returns> | |
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 | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ex usage (generating and displaying static):