1 /** 2 This module defines the notion of an Image. 3 An Image is simply defined as a 2D array of elements, with 4 methods to set/get those elements. 5 6 The Image concept might be the basis of a generic software renderer. 7 */ 8 module gfm.image.image; 9 10 import gfm.math.vector; 11 12 // An image is a concept 13 14 15 /** 16 * Test if I is an Image. 17 * 18 * An image has the following features: 19 * $(UL 20 * $(LI defines element_t as the type of elements (eg. pixels).) 21 * $(LI has a dimension of type vec2i.) 22 * $(LI has getter/setter for individual elements.) 23 * ) 24 */ 25 template isImage(I) 26 { 27 enum bool isImage = is(typeof( 28 { 29 I i; // can be defined 30 const I ci; 31 I.element_t e; // defined the type element_t 32 vec2i dim = ci.dimension; // has dimension 33 I.element_t f = ci.get(0, 0); // can get element 34 i.set(0, 0, f); // can set element 35 }())); 36 } 37 38 /// Returns: true if an image contains the given point. 39 deprecated("Use ae.utils.graphics instead") 40 bool contains(I)(I img, int x, int y) if (isImage!I) 41 { 42 return cast(uint)x < img.dimension.x && cast(uint)y < img.dimension.y; 43 } 44 45 /// EdgeMode defines how images are sampled beyond their boundaries. 46 deprecated("Use ae.utils.graphics instead") 47 enum EdgeMode 48 { 49 BLACK, /// Return black. 50 CLAMP, /// Clamp to edge. 51 REPEAT, /// Repeat from the other side of the image. 52 CRASH /// Crash. 53 } 54 55 56 /// Draws a single pixel. 57 deprecated("Use ae.utils.graphics instead") 58 void drawPixel(I, P)(I img, int x, int y, P p) if (isImage!I && is(P : I.element_t)) 59 { 60 if (!img.contains(x, y)) 61 return; 62 img.set(x, y, p); 63 } 64 65 /// Returns: pixel of an Image at position (x, y). 66 /// At boundaries, what happens depends on em. 67 deprecated("Use ae.utils.graphics instead") 68 I.element_t getPixel(I)(I img, int x, int y, EdgeMode em) 69 { 70 if (!img.contains(x, y)) 71 { 72 final switch(em) 73 { 74 case EdgeMode.BLACK: 75 return I.element_t.init; 76 77 case EdgeMode.CLAMP: 78 { 79 if (x < 0) x = 0; 80 if (y < 0) y = 0; 81 if (x >= img.dimension.x) x = img.dimension.x - 1; 82 if (y >= img.dimension.y) y = img.dimension.y - 1; 83 break; 84 } 85 86 case EdgeMode.REPEAT: 87 { 88 x = moduloWrap!int(x, img.dimension.x); 89 y = moduloWrap!int(y, img.dimension.y); 90 break; 91 } 92 93 case EdgeMode.CRASH: 94 assert(false); 95 } 96 } 97 98 return img.get(x, y); 99 } 100 101 /// Draws a rectangle outline in an Image. 102 deprecated("Use ae.utils.graphics instead") 103 void drawRect(I, P)(I img, int x, int y, int width, int height, P e) if (isImage!I && is(P : I.element_t)) 104 { 105 drawHorizontalLine(img, x, x + width, y, e); 106 drawHorizontalLine(img, x, x + width, y + height - 1, e); 107 drawVerticalLine(img, x, y, y + height, e); 108 drawVerticalLine(img, x + width - 1, y, y + height, e); 109 } 110 111 /// Fills an uniform rectangle area in an Image. 112 deprecated("Use ae.utils.graphics instead") 113 void fillRect(I, P)(I img, int x, int y, int width, int height, P e) if (isImage!I && is(P : I.element_t)) 114 { 115 for (int j = 0; j < height; ++j) 116 for (int i = 0; i < width; ++i) 117 img.set(x + i, y + j, e); 118 } 119 120 /// Fills a whole image with a single element value. 121 deprecated("Use ae.utils.graphics instead") 122 void fillImage(I, P)(I img, P e) if (isImage!I && is(P : I.element_t)) 123 { 124 immutable int width = img.dimension.x; 125 immutable int height = img.dimension.y; 126 for (int j = 0; j < height; ++j) 127 for (int i = 0; i < width; ++i) 128 img.set(i, j, e); 129 } 130 131 /// Performs an image blit from src to dest. 132 deprecated("Use ae.utils.graphics instead") 133 void copyRect(I)(I dest, I src) if (isImage!I) 134 { 135 // check same size 136 assert(dest.dimension == src.dimension); 137 138 immutable int width = dest.dimension.x; 139 immutable int height = dest.dimension.y; 140 for (int j = 0; j < height; ++j) 141 for (int i = 0; i < width; ++i) 142 { 143 auto p = src.get(i, j); 144 dest.set(i, j, p); 145 } 146 } 147 148 /// Draws an horizontal line on an Image. 149 deprecated("Use ae.utils.graphics instead") 150 void drawHorizontalLine(I, P)(I img, int x1, int x2, int y, P p) if (isImage!I && is(P : I.element_t)) 151 { 152 for (int x = x1; x < x2; ++x) 153 img.drawPixel(x, y, p); 154 } 155 156 /// Draws a vertical line on an Image. 157 deprecated("Use ae.utils.graphics instead") 158 void drawVerticalLine(I, P)(I img, int x, int y1, int y2, P p) if (isImage!I && is(P : I.element_t)) 159 { 160 for (int y = y1; y < y2; ++y) 161 img.drawPixel(x, y, p); 162 }