1import std.stdio;
  2import std.file;
  3import std.format;
  4import std.string;
  5import std.range;
  6import std.algorithm;
  7import std.array;
  8import std.math;
  9
 10// BMP file header (14 bytes).
 11struct BitmapFileHeader {
 12	char[2] signature;      // "BM" signature
 13	uint fileSize;          // Size of the file in bytes
 14	ushort reserved1;       // Reserved (0)
 15	ushort reserved2;       // Reserved (0)
 16	uint dataOffset;        // Offset to the start of image data
 17}
 18
 19// BMP info header (40 bytes for BITMAPINFOHEADER).
 20struct BitmapInfoHeader {
 21	uint size;              // Size of this header (40 bytes)
 22	int width;              // Image width in pixels
 23	int height;             // Image height in pixels
 24	ushort planes;          // Number of color planes (must be 1)
 25	ushort bitsPerPixel;    // Bits per pixel (1, 4, 8, 16, 24, or 32)
 26	uint compression;       // Compression method (0 = none, 1 = RLE-8, 2 = RLE-4)
 27	uint imageSize;         // Size of the image data in bytes
 28	int xPixelsPerMeter;    // Horizontal resolution (pixels per meter)
 29	int yPixelsPerMeter;    // Vertical resolution (pixels per meter)
 30	uint colorsUsed;        // Number of colors in the palette
 31	uint importantColors;   // Number of important colors used (0 = all)
 32}
 33
 34// RGB pixel structure.
 35struct RGB {
 36	ubyte blue;
 37	ubyte green;
 38	ubyte red;
 39
 40	string toString() const {
 41		return format("RGB(%d, %d, %d)", red, green, blue);
 42	}
 43}
 44
 45void main(string[] args) {
 46	if (args.length < 2) {
 47		writeln("Usage: main <filename.bmp>");
 48		return;
 49	}
 50
 51	string fileName = args[1];
 52
 53	try {
 54		// Read the file.
 55		auto file = File(fileName, "rb");
 56
 57		// Read the BMP file header.
 58		BitmapFileHeader fileHeader;
 59		file.rawRead((&fileHeader)[0..1]);
 60
 61		// Check if it's a valid BMP file
 62		if (fileHeader.signature != "BM") {
 63			writeln("Error: Not a valid BMP file");
 64			return;
 65		}
 66
 67		// Read the BMP info header.
 68		BitmapInfoHeader infoHeader;
 69		file.rawRead((&infoHeader)[0..1]);
 70
 71		// Display header information.
 72		writeln("BMP File Header Information:");
 73		writefln("  Signature: %s", fileHeader.signature);
 74		writefln("  File Size: %d bytes", fileHeader.fileSize);
 75		writefln("  Data Offset: %d bytes", fileHeader.dataOffset);
 76
 77		writeln("\nBMP Info Header Information:");
 78		writefln("  Header Size: %d bytes", infoHeader.size);
 79		writefln("  Image Width: %d pixels", infoHeader.width);
 80		writefln("  Image Height: %d pixels", infoHeader.height);
 81		writefln("  Color Planes: %d", infoHeader.planes);
 82		writefln("  Bits Per Pixel: %d", infoHeader.bitsPerPixel);
 83
 84		// Display compression method.
 85		string compressionMethod;
 86		switch (infoHeader.compression) {
 87			case 0: compressionMethod = "None (BI_RGB)"; break;
 88			case 1: compressionMethod = "RLE-8 (BI_RLE8)"; break;
 89			case 2: compressionMethod = "RLE-4 (BI_RLE4)"; break;
 90			case 3: compressionMethod = "Bitfields (BI_BITFIELDS)"; break;
 91			default: compressionMethod = format("Unknown (%d)", infoHeader.compression);
 92		}
 93		writefln("  Compression: %s", compressionMethod);
 94
 95		writefln("  Image Size: %d bytes", infoHeader.imageSize);
 96		writefln("  Horizontal Resolution: %d pixels/meter", infoHeader.xPixelsPerMeter);
 97		writefln("  Vertical Resolution: %d pixels/meter", infoHeader.yPixelsPerMeter);
 98		writefln("  Colors Used: %d", infoHeader.colorsUsed);
 99		writefln("  Important Colors: %d", infoHeader.importantColors);
100
101		// Calculate color depth information.
102		int numColors = (infoHeader.bitsPerPixel <= 8) ? (1 << infoHeader.bitsPerPixel) : 0;
103		if (numColors > 0) {
104			writefln("  Color Palette: %d colors", numColors);
105		} else {
106			writefln("  Color Palette: None (direct color)");
107		}
108	} catch (Exception e) {
109		writefln("Error reading BMP file: %s", e.msg);
110	}
111}