// See https://aka.ms/new-console-template for more information using System.Text; using System.Text.Encodings; namespace Ray { struct Vec3 { double x, y, z; } readonly struct Color { public readonly byte r, g, b; public Color(byte r, byte g, byte b) { this.r = r; this.g = g; this.b = b; } } class BitmapImage { public readonly UInt16 width, height; private Color[,] pixels; public BitmapImage(UInt16 width, UInt16 height) { this.width = width; this.height = height; this.pixels = new Color[width,height]; } public void setPixel(in UInt16 x, in UInt16 y, in Color c) { this.pixels[x,y] = c; } public void writeImage(in string path) { //Rows in BMP images must be divisibly by 4... for some reason. int padding = (4 - (width * 3) % 4) % 4; //8 bit color depth + 26 bytes for header and BITMAPCORE header Int32 bfSize = (width * height * 3) + (padding * this.height) + 26; using (FileStream fs = new FileStream(path, FileMode.Create)) using (BinaryWriter bw = new BinaryWriter(fs)) { //File header bw.Write('B'); bw.Write('M'); bw.Write(bfSize); bw.Write((Int32)0); //bfReserved 1 and 2 bw.Write((Int32)26); //DIB header (Bitmap core) bw.Write((Int32)12); bw.Write(this.width); bw.Write(this.height); bw.Write((Int16)1); bw.Write((Int16)24); for (ushort i = 0; i < this.width; i++) { for (ushort j = 0; j < this.height; j++) { bw.Write(this.pixels[i, j].b); bw.Write(this.pixels[i, j].g); bw.Write(this.pixels[i, j].r); } for (ushort j = 0; j < padding; j++) //end-of-row padding. { bw.Write((byte)0); } } } } } class Raytracer { static void Main() { var BMP = new BitmapImage(255, 255); for (ushort i = 0; i < 255; i++) { for (ushort j = 0; j < 255; j++) { BMP.setPixel(i, j, new Color((byte)i, 0, (byte)j)); } } for (ushort i = 200; i < 255; i++) { for (ushort j = 200; j < 255; j++) { BMP.setPixel(i, j, new Color(0, 255, 0)); } } BMP.writeImage("C:/Users/Lizzy/test2.bmp"); } } };