1 //Возможно, этому модулю подойдет другое имя 2 module rip.concepts.makers; 3 4 protected { 5 import std.stdio; 6 import std.math; 7 8 import rip.concepts.color; 9 } 10 11 /++ 12 Funcs for translating color formats to RGBColor 13 +/ 14 15 RGBColor makeHSV(in float h, lazy float s, lazy float v) 16 in { 17 if(!isNaN(h)) { 18 assert(h >= 0 && h <= 360, 19 "H must belong to the segment [0, 360] or be NAN"); 20 assert(s >= 0 && s <= 1, 21 "S must belong to the segment [0, 1]"); 22 assert(v >= 0 && v <= 1, 23 "V must belong to the segment [0, 1]"); 24 } 25 } 26 body { 27 if(isNaN(h)) 28 return new RGBColor(0, 0, 0); 29 else { 30 31 float c = v * s; 32 float _h = h / 60; 33 float x = c * (1 - abs(_h % 2 - 1)); 34 float m = v - c; 35 36 float _r = 0, _g = 0, _b = 0; 37 38 if(_h >= 0 && _h < 1) { 39 _r = c; 40 _g = x; 41 } 42 else if(_h < 2) { 43 _r = x; 44 _g = c; 45 } 46 else if(_h < 3) { 47 _g = c; 48 _b = x; 49 } 50 else if(_h < 4) { 51 _g = x; 52 _b = c; 53 } 54 else if(_h < 5) { 55 _r = x; 56 _b = c; 57 } 58 else { 59 _r = c; 60 _b = x; 61 } 62 63 return new RGBColor( 64 round((_r + m) * 255), 65 round((_g + m) * 255), 66 round((_b + m) * 255)); 67 } 68 69 assert(0); 70 } 71 72 /++ ditto +/ 73 //Две практически одинаковые ф-ции в модуле. Надо 74 //подумать об их объединении 75 RGBColor makeHSL(in float h, lazy float s, lazy float l) 76 in { 77 if(!isNaN(h)) { 78 assert(h >= 0 && h < 360, 79 "H must belong to the segment [0, 360) or be NAN"); 80 assert(s >= 0 && s <= 1, 81 "S must belong to the segment [0, 1]"); 82 assert(l >= 0 && l <= 1, 83 "L must belong to the segment [0, 1]"); 84 } 85 } 86 body { 87 if(isNaN(h)) 88 return new RGBColor(0, 0, 0); 89 else { 90 91 float c = (1 - abs(2 * l - 1)) * s; 92 float _h = h / 60; 93 float x = c * (1 - abs(_h % 2 - 1)); 94 float m = l - c / 2; 95 96 float _r = 0, _g = 0, _b = 0; 97 98 if(_h >= 0 && _h < 1) { 99 _r = c; 100 _g = x; 101 } 102 else if(_h < 2) { 103 _r = x; 104 _g = c; 105 } 106 else if(_h < 3) { 107 _g = c; 108 _b = x; 109 } 110 else if(_h < 4) { 111 _g = x; 112 _b = c; 113 } 114 else if(_h < 5) { 115 _r = x; 116 _b = c; 117 } 118 else { 119 _r = c; 120 _b = x; 121 } 122 123 return new RGBColor( 124 round((_r + m) * 255), 125 round((_g + m) * 255), 126 round((_b + m) * 255)); 127 } 128 129 assert(0); 130 } 131 132 /++ ditto +/ 133 RGBColor makeCMYK(in float c, in float m, in float y, in float k) 134 in { 135 assert(c >= 0 && c <= 1, 136 "C must belong to the segment [0, 1]"); 137 assert(m >= 0 && m <= 1, 138 "M must belong to the segment [0, 1]"); 139 assert(y >= 0 && y <= 1, 140 "Y must belong to the segment [0, 1]"); 141 assert(k >= 0 && k <= 1, 142 "K must belong to the segment [0, 1]"); 143 } 144 body { 145 return new RGBColor( 146 round(255 * (1 - c) * (1 - k)), 147 round(255 * (1 - m) * (1 - k)), 148 round(255 * (1 - y) * (1 - k))); 149 } 150 151 /++ ditto +/ 152 RGBColor makeXYZ(float x, float y, float z) 153 in { 154 assert(x >= 0 && x <= 95.047f, 155 "x must belong to the segment [0, 95.047]"); 156 assert(y >= 0 && y <= 100, 157 "y must belong to the segment [0, 100]"); 158 assert(z >= 0 && z <= 108.883f, 159 "z must belong to the segment [0, 108.883]"); 160 } 161 body { 162 x /= 100.0f; 163 y /= 100.0f; 164 z /= 100.0f; 165 166 auto r = x * 3.2406 + y * -1.5372 + z * -0.4986; 167 auto g = x * -0.9689 + y * 1.8758 + z * 0.0415; 168 auto b = x * 0.0557 + y * -0.2040 + z * 1.0570; 169 170 r = r > 0.0031308 ? 1.055 * pow(r, 1 / 2.4) - 0.055 : 12.92 * r; 171 g = g > 0.0031308 ? 1.055 * pow(g, 1 / 2.4) - 0.055 : 12.92 * g; 172 b = b > 0.0031308 ? 1.055 * pow(b, 1 / 2.4) - 0.055 : 12.92 * b; 173 174 return new RGBColor(r * 255.0f, g * 255.0f, b * 255.0f); 175 } 176 177 /++ ditto +/ 178 RGBColor makeLAB(float l, float a, float b) 179 in {} 180 body { 181 const float E = 0.008856f; 182 const float K = 903.3f; 183 184 auto wX = 95.047f; 185 auto wY = 100.0f; 186 auto wZ = 108.883f; 187 188 float _y = (l + 16) / 116; 189 float _x = a / 500 + _y; 190 float _z = _y - b / 200; 191 192 auto y3 = pow(_y, 3); 193 auto x3 = pow(_x, 3); 194 auto z3 = pow(_z, 3); 195 196 if(y3 > E) 197 _y = y3; 198 else 199 _y = (_y - 16 / 116 ) / 7.787; 200 201 if(x3 > E) 202 _x = x3; 203 else 204 _x = (_x - 16 / 116 ) / 7.787; 205 206 if(z3 > E) 207 _z = z3; 208 else 209 _z = (_z - 16 / 116 ) / 7.787; 210 211 _x *= wX; 212 _y *= wY; 213 _z *= wZ; 214 215 return makeXYZ(_x, _y, _z); 216 } 217 218 unittest { 219 auto color = makeHSV(72, 0.83, 0.73); 220 221 assert(color.red!ubyte == 155); 222 assert(color.green!ubyte == 186); 223 assert(color.blue!ubyte == 32); 224 225 float emptyFloat; 226 color = makeHSV(emptyFloat, 0.45, 0.6); 227 228 assert(color.red!ubyte == 0); 229 assert(color.green!ubyte == 0); 230 assert(color.blue!ubyte == 0); 231 }