1 module nes.image; 2 3 import std.algorithm; 4 5 import nes.color; 6 7 struct Point { 8 int x, y; 9 } 10 11 struct Rectangle { 12 Point min, max; 13 14 int dx() { 15 return this.max.x - this.min.x; 16 } 17 18 int dy() { 19 return this.max.y - this.min.y; 20 } 21 } 22 23 // PointIn reports whether p is in r. 24 bool PointIn(Point p, Rectangle r) { 25 return r.min.x <= p.x && p.x < r.max.x && 26 r.min.y <= p.y && p.y < r.max.y; 27 } 28 29 class ImageRGBA { 30 ubyte[] pix; 31 int stride; 32 Rectangle rect; 33 34 this(Rectangle r) { 35 auto w = r.dx(); 36 auto h = r.dy(); 37 38 this.pix = new ubyte[4 * w * h]; 39 this.stride = 4 * w; 40 this.rect = r; 41 } 42 43 // PixOffset returns the index of the first element of Pix that corresponds to 44 // the pixel at (x, y). 45 int pixOffset(int x, int y) { 46 return (y - this.rect.min.y) * this.stride + (x - this.rect.min.x) * 4; 47 } 48 49 void setRGBA(int x, int y, RGBA c) { 50 if (!PointIn(Point(x, y), this.rect)) { 51 return; 52 } 53 54 auto i = this.pixOffset(x, y); 55 this.pix[i + 0] = c.r; 56 this.pix[i + 1] = c.g; 57 this.pix[i + 2] = c.b; 58 this.pix[i + 3] = c.a; 59 } 60 } 61 62 Rectangle Rect(int x0, int y0, int x1, int y1) { 63 if (x0 > x1) { 64 swap(x0, x1); 65 } 66 67 if (y0 > y1) { 68 swap(y0, y1); 69 } 70 71 return Rectangle(Point(x0, y0), Point(x1, y1)); 72 }