1 // Written in the D programming language. 2 3 /** 4 This package contains implementations of various common _color types. 5 Types are supplied for various _color spaces, along with comprehensive 6 _color space conversion functionality. 7 8 Authors: Manu Evans 9 Copyright: Copyright (c) 2015, Manu Evans. 10 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0) 11 Source: $(PHOBOSSRC ggplotd/color/package.d) 12 */ 13 module ggplotd.color; 14 15 public import ggplotd.color.rgb; 16 import ggplotd.color.xyz : isXYZ, isxyY; 17 import ggplotd.color.hsx : isHSx; 18 19 @safe pure nothrow @nogc: 20 21 22 /** 23 Detect whether $(D T) is a color type defined under std.color. 24 */ 25 enum isColor(T) = isRGB!T || isHSx!T || isXYZ!T || isxyY!T; 26 27 /// 28 unittest 29 { 30 static assert(isColor!RGB8 == true); 31 static assert(isColor!(XYZ!float) == true); 32 static assert(isColor!float == false); 33 } 34 35 36 // declare some common color types 37 /** 24 bit RGB color type with 8 bits per channel. */ 38 alias RGB8 = RGB!("rgb", ubyte); 39 /** 32 bit RGB color type with 8 bits per channel. */ 40 alias RGBX8 = RGB!("rgbx", ubyte); 41 /** 32 bit RGB + alpha color type with 8 bits per channel. */ 42 alias RGBA8 = RGB!("rgba", ubyte); 43 44 /** Floating point RGB color type. */ 45 alias RGBf32 = RGB!("rgb", float); 46 /** Floating point RGB + alpha color type. */ 47 alias RGBAf32 = RGB!("rgba", float); 48 49 /** 24 bit BGR color type with 8 bits per channel. */ 50 alias BGR8 = RGB!("bgr", ubyte); 51 /** 32 bit BGR color type with 8 bits per channel. */ 52 alias BGRX8 = RGB!("bgrx", ubyte); 53 /** 32 bit BGR + alpha color type with 8 bits per channel. */ 54 alias BGRA8 = RGB!("bgra", ubyte); 55 56 /** 8 bit luminance-only color type. */ 57 alias L8 = RGB!("l", ubyte); 58 /** 8 bit alpha-only color type. */ 59 alias A8 = RGB!("a", ubyte); 60 /** 16 bit luminance + alpha color type with 8 bits per channel. */ 61 alias LA8 = RGB!("la", ubyte); 62 63 /** 16 bit signed UV color type with 8 bits per channel. */ 64 alias UV8 = RGB!("rg", byte); 65 /** Floating point UV color type. */ 66 alias UVf32 = RGB!("rg", float); 67 68 69 /** Set of colors defined by X11, adopted by the W3C, SVG, and other popular libraries. */ 70 enum Colors 71 { 72 aliceBlue = RGB8(240,248,255), 73 antiqueWhite = RGB8(250,235,215), 74 aqua = RGB8(0,255,255), 75 aquamarine = RGB8(127,255,212), 76 azure = RGB8(240,255,255), 77 beige = RGB8(245,245,220), 78 bisque = RGB8(255,228,196), 79 black = RGB8(0,0,0), 80 blanchedAlmond = RGB8(255,235,205), 81 blue = RGB8(0,0,255), 82 blueViolet = RGB8(138,43,226), 83 brown = RGB8(165,42,42), 84 burlyWood = RGB8(222,184,135), 85 cadetBlue = RGB8(95,158,160), 86 chartreuse = RGB8(127,255,0), 87 chocolate = RGB8(210,105,30), 88 coral = RGB8(255,127,80), 89 cornflowerBlue = RGB8(100,149,237), 90 cornsilk = RGB8(255,248,220), 91 crimson = RGB8(220,20,60), 92 cyan = RGB8(0,255,255), 93 darkBlue = RGB8(0,0,139), 94 darkCyan = RGB8(0,139,139), 95 darkGoldenrod = RGB8(184,134,11), 96 darkGray = RGB8(169,169,169), 97 darkGrey = RGB8(169,169,169), 98 darkGreen = RGB8(0,100,0), 99 darkKhaki = RGB8(189,183,107), 100 darkMagenta = RGB8(139,0,139), 101 darkOliveGreen = RGB8(85,107,47), 102 darkOrange = RGB8(255,140,0), 103 darkOrchid = RGB8(153,50,204), 104 darkRed = RGB8(139,0,0), 105 darkSalmon = RGB8(233,150,122), 106 darkSeaGreen = RGB8(143,188,143), 107 darkSlateBlue = RGB8(72,61,139), 108 darkSlateGray = RGB8(47,79,79), 109 darkSlateGrey = RGB8(47,79,79), 110 darkTurquoise = RGB8(0,206,209), 111 darkViolet = RGB8(148,0,211), 112 deepPink = RGB8(255,20,147), 113 deepSkyBlue = RGB8(0,191,255), 114 dimGray = RGB8(105,105,105), 115 dimGrey = RGB8(105,105,105), 116 dodgerBlue = RGB8(30,144,255), 117 fireBrick = RGB8(178,34,34), 118 floralWhite = RGB8(255,250,240), 119 forestGreen = RGB8(34,139,34), 120 fuchsia = RGB8(255,0,255), 121 gainsboro = RGB8(220,220,220), 122 ghostWhite = RGB8(248,248,255), 123 gold = RGB8(255,215,0), 124 goldenrod = RGB8(218,165,32), 125 gray = RGB8(128,128,128), 126 grey = RGB8(128,128,128), 127 green = RGB8(0,128,0), 128 greenYellow = RGB8(173,255,47), 129 honeydew = RGB8(240,255,240), 130 hotPink = RGB8(255,105,180), 131 indianRed = RGB8(205,92,92), 132 indigo = RGB8(75,0,130), 133 ivory = RGB8(255,255,240), 134 khaki = RGB8(240,230,140), 135 lavender = RGB8(230,230,250), 136 lavenderBlush = RGB8(255,240,245), 137 lawnGreen = RGB8(124,252,0), 138 lemonChiffon = RGB8(255,250,205), 139 lightBlue = RGB8(173,216,230), 140 lightCoral = RGB8(240,128,128), 141 lightCyan = RGB8(224,255,255), 142 lightGoldenrodYellow = RGB8(250,250,210), 143 lightGray = RGB8(211,211,211), 144 lightGrey = RGB8(211,211,211), 145 lightGreen = RGB8(144,238,144), 146 lightPink = RGB8(255,182,193), 147 lightSalmon = RGB8(255,160,122), 148 lightSeaGreen = RGB8(32,178,170), 149 lightSkyBlue = RGB8(135,206,250), 150 lightSlateGray = RGB8(119,136,153), 151 lightSlateGrey = RGB8(119,136,153), 152 lightSteelBlue = RGB8(176,196,222), 153 lightYellow = RGB8(255,255,224), 154 lime = RGB8(0,255,0), 155 limeGreen = RGB8(50,205,50), 156 linen = RGB8(250,240,230), 157 magenta = RGB8(255,0,255), 158 maroon = RGB8(128,0,0), 159 mediumAquamarine = RGB8(102,205,170), 160 mediumBlue = RGB8(0,0,205), 161 mediumOrchid = RGB8(186,85,211), 162 mediumPurple = RGB8(147,112,219), 163 mediumSeaGreen = RGB8(60,179,113), 164 mediumSlateBlue = RGB8(123,104,238), 165 mediumSpringGreen = RGB8(0,250,154), 166 mediumTurquoise = RGB8(72,209,204), 167 mediumVioletRed = RGB8(199,21,133), 168 midnightBlue = RGB8(25,25,112), 169 mintCream = RGB8(245,255,250), 170 mistyRose = RGB8(255,228,225), 171 moccasin = RGB8(255,228,181), 172 navajoWhite = RGB8(255,222,173), 173 navy = RGB8(0,0,128), 174 oldLace = RGB8(253,245,230), 175 olive = RGB8(128,128,0), 176 oliveDrab = RGB8(107,142,35), 177 orange = RGB8(255,165,0), 178 orangeRed = RGB8(255,69,0), 179 orchid = RGB8(218,112,214), 180 paleGoldenrod = RGB8(238,232,170), 181 paleGreen = RGB8(152,251,152), 182 paleTurquoise = RGB8(175,238,238), 183 paleVioletRed = RGB8(219,112,147), 184 papayaWhip = RGB8(255,239,213), 185 peachPuff = RGB8(255,218,185), 186 peru = RGB8(205,133,63), 187 pink = RGB8(255,192,203), 188 plum = RGB8(221,160,221), 189 powderBlue = RGB8(176,224,230), 190 purple = RGB8(128,0,128), 191 red = RGB8(255,0,0), 192 rosyBrown = RGB8(188,143,143), 193 royalBlue = RGB8(65,105,225), 194 saddleBrown = RGB8(139,69,19), 195 salmon = RGB8(250,128,114), 196 sandyBrown = RGB8(244,164,96), 197 seaGreen = RGB8(46,139,87), 198 seashell = RGB8(255,245,238), 199 sienna = RGB8(160,82,45), 200 silver = RGB8(192,192,192), 201 skyBlue = RGB8(135,206,235), 202 slateBlue = RGB8(106,90,205), 203 slateGray = RGB8(112,128,144), 204 slateGrey = RGB8(112,128,144), 205 snow = RGB8(255,250,250), 206 springGreen = RGB8(0,255,127), 207 steelBlue = RGB8(70,130,180), 208 tan = RGB8(210,180,140), 209 teal = RGB8(0,128,128), 210 thistle = RGB8(216,191,216), 211 tomato = RGB8(255,99,71), 212 turquoise = RGB8(64,224,208), 213 violet = RGB8(238,130,238), 214 wheat = RGB8(245,222,179), 215 white = RGB8(255,255,255), 216 whiteSmoke = RGB8(245,245,245), 217 yellow = RGB8(255,255,0), 218 yellowGreen = RGB8(154,205,50) 219 } 220 221 222 // some common color operations 223 C lerp(C, F)(C a, C b, F t) 224 { 225 return blend(a, b, 1-t, t, 1-t, t); 226 } 227 228 C blend(C, F)(C src, C dest, F srcFactor, F destFactor) 229 { 230 return blend(src, dest, srcFactor, destFactor, srcFactor, destFactor); 231 } 232 233 C blend(C, F)(C src, C dest, F srcFactor, F destFactor, F srcAlphaFactor, F destAlphaFactor) if(isRGB!C && isFloatingPoint!F) 234 { 235 C r; 236 static if(C.CanFind!(components, 'r')) 237 r.r = cast(typeof(r.r))(src.r*srcFactor + dest.r*destFactor); 238 static if(C.CanFind!(components, 'g')) 239 r.g = cast(typeof(r.g))(src.g*srcFactor + dest.g*destFactor); 240 static if(C.CanFind!(components, 'b')) 241 r.b = cast(typeof(r.b))(src.b*srcFactor + dest.b*destFactor); 242 static if(C.CanFind!(components, 'l')) 243 r.l = cast(typeof(r.l))(src.l*srcFactor + dest.l*destFactor); 244 static if(C.CanFind!(components, 'a')) 245 r.a = cast(typeof(r.a))(src.a*srcAlphaFactor + dest.a*destAlphaFactor); 246 return r; 247 } 248 249 250 package: 251 252 // build mixin code to perform expresions per-element 253 template ComponentExpression(string expression, string component, string op) 254 { 255 template BuildExpression(string e, string c, string op) 256 { 257 static if(e.length == 0) 258 enum BuildExpression = ""; 259 else static if(e[0] == '_') 260 enum BuildExpression = c ~ BuildExpression!(e[1..$], c, op); 261 else static if(e[0] == '#') 262 enum BuildExpression = op ~ BuildExpression!(e[1..$], c, op); 263 else 264 enum BuildExpression = e[0] ~ BuildExpression!(e[1..$], c, op); 265 } 266 enum ComponentExpression = 267 "static if(is(typeof(this." ~ component ~ ")))" ~ "\n\t" ~ 268 BuildExpression!(expression, component, op); 269 } 270 271 mixin template ColorOperators(Components...) 272 { 273 typeof(this) opUnary(string op)() const if(op == "+" || op == "-" || (op == "~" && isIntegral!ComponentType)) 274 { 275 Unqual!(typeof(this)) res = this; 276 foreach(c; Components) 277 mixin(ComponentExpression!("res._ = #_;", c, op)); 278 return res; 279 } 280 typeof(this) opBinary(string op)(typeof(this) rh) const if(op == "+" || op == "-" || op == "*" || op == "/") 281 { 282 Unqual!(typeof(this)) res = this; 283 foreach(c; Components) 284 mixin(ComponentExpression!("res._ #= rh._;", c, op)); 285 return res; 286 } 287 typeof(this) opBinary(string op, S)(S rh) const if(isNumeric!S && (op == "*" || op == "/" || op == "^^")) 288 { 289 Unqual!(typeof(this)) res = this; 290 foreach(c; Components) 291 mixin(ComponentExpression!("res._ #= rh;", c, op)); 292 return res; 293 } 294 ref typeof(this) opOpAssign(string op)(typeof(this) rh) if(op == "+" || op == "-" || op == "*" || op == "/") 295 { 296 foreach(c; Components) 297 mixin(ComponentExpression!("_ #= rh._;", c, op)); 298 return this; 299 } 300 ref typeof(this) opOpAssign(string op, S)(S rh) if(isNumeric!S && (op == "*" || op == "/" || op == "^^")) 301 { 302 foreach(c; Components) 303 mixin(ComponentExpression!("_ #= rh;", c, op)); 304 return this; 305 } 306 }