1 /** 2 * Copyright: Mike Wey 2011 3 * License: zlib (See accompanying LICENSE file) 4 * Authors: Mike Wey 5 */ 6 7 module dmagick.ColorCMYK; 8 9 import std.algorithm; 10 11 import dmagick.Color; 12 13 import dmagick.c.magickType; 14 import dmagick.c.quantum; 15 16 /** 17 * The CMY(K) color model describes a color space with subtractive color 18 * composition as it is used for the color printing process, e.g. used by 19 * ink or laser printers. Each color is described by the color components 20 * cyan (C), magenta (M) and yellow (Y). The additional component black (K) 21 * is used for better gray and black reproduction. 22 * 23 * Note: This class doesn't use ICC or ICM profiles for the converson of 24 * CMYK to RGB. 25 */ 26 class ColorCMYK : Color 27 { 28 /** */ 29 this() 30 { 31 super(); 32 } 33 34 /** 35 * Create a CMYK Color from the specified doubles. 36 */ 37 this(double cyan, double magenta, double yellow, double black) 38 { 39 Quantum red, green, blue; 40 41 convertCMYKToRGB(cyan, magenta, yellow, black, red, green, blue); 42 43 super(red, green, blue); 44 } 45 46 /** 47 * The value for cyan. 48 */ 49 void cyan(double cyan) 50 { 51 double oldCyan, magenta, yellow, black; 52 53 convertRGBToCMYK(packet.red, packet.green, packet.blue, oldCyan, magenta, yellow, black); 54 convertCMYKToRGB(cyan, magenta, yellow, black, packet.red, packet.green, packet.blue); 55 } 56 ///ditto 57 double cyan() 58 { 59 double cyan, magenta, yellow, black; 60 61 convertRGBToCMYK(packet.red, packet.green, packet.blue, cyan, magenta, yellow, black); 62 63 return cyan; 64 } 65 66 /** 67 * The value for magenta. 68 */ 69 void magenta(double magenta) 70 { 71 double cyan, oldMagenta, yellow, black; 72 73 convertRGBToCMYK(packet.red, packet.green, packet.blue, cyan, oldMagenta, yellow, black); 74 convertCMYKToRGB(cyan, magenta, yellow, black, packet.red, packet.green, packet.blue); 75 } 76 ///ditto 77 double magenta() 78 { 79 double cyan, magenta, yellow, black; 80 81 convertRGBToCMYK(packet.red, packet.green, packet.blue, cyan, magenta, yellow, black); 82 83 return magenta; 84 } 85 86 /** 87 * The value for yellow. 88 */ 89 void yellow(double yellow) 90 { 91 double cyan, magenta, oldYellow, black; 92 93 convertRGBToCMYK(packet.red, packet.green, packet.blue, cyan, magenta, oldYellow, black); 94 convertCMYKToRGB(cyan, magenta, yellow, black, packet.red, packet.green, packet.blue); 95 } 96 ///ditto 97 double yellow() 98 { 99 double cyan, magenta, yellow, black; 100 101 convertRGBToCMYK(packet.red, packet.green, packet.blue, cyan, magenta, yellow, black); 102 103 return yellow; 104 } 105 106 /** 107 * The value for black. 108 */ 109 void black(double black) 110 { 111 double cyan, magenta, yellow, oldBlack; 112 113 convertRGBToCMYK(packet.red, packet.green, packet.blue, cyan, magenta, yellow, oldBlack); 114 convertCMYKToRGB(cyan, magenta, yellow, black, packet.red, packet.green, packet.blue); 115 } 116 ///ditto 117 double black() 118 { 119 double cyan, magenta, yellow, black; 120 121 convertRGBToCMYK(packet.red, packet.green, packet.blue, cyan, magenta, yellow, black); 122 123 return black; 124 } 125 126 /** 127 * Convert an RGB value to a CMYK value. 128 */ 129 private void convertRGBToCMYK(Quantum red, Quantum green, Quantum blue, ref double cyan, ref double magenta, ref double yellow, ref double black) 130 { 131 double r = scaleQuantumToDouble(red); 132 double g = scaleQuantumToDouble(green); 133 double b = scaleQuantumToDouble(blue); 134 135 black = min(1 - r, 1 - g, 1 - b); 136 137 cyan = (1 - r - black) / (1 - black); 138 magenta = (1 - g - black) / (1 - black); 139 yellow = (1 - b - black) / (1 - black); 140 } 141 142 /** 143 * Convert an CMYK value to a RGB value. 144 */ 145 private void convertCMYKToRGB(double cyan, double magenta, double yellow, double black, ref Quantum red, ref Quantum green, ref Quantum blue) 146 in 147 { 148 assert(cyan <= 1 && cyan >= 0); 149 assert(magenta <= 1 && magenta >= 0); 150 assert(yellow <= 1 && yellow >= 0); 151 assert(black <= 1 && black >= 0); 152 } 153 body 154 { 155 double r = 1 - min(1, cyan * (1 - black) + black); 156 double g = 1 - min(1, magenta * (1 - black) + black); 157 double b = 1 - min(1, yellow * (1 - black) + black); 158 159 red = scaleDoubleToQuantum(r); 160 green = scaleDoubleToQuantum(g); 161 blue = scaleDoubleToQuantum(b); 162 } 163 } 164 165 unittest 166 { 167 assert(new ColorCMYK(0, 1, 1, 0 ) == new Color("red")); 168 169 auto color1 = new ColorCMYK(0.5, 0.5, 0.5, 0.5); 170 auto color2 = new Color("gray25"); 171 172 //Compare the colors a bytes, to compensate for rounding errors. 173 assert(ScaleQuantumToChar(color1.redQuantum) == ScaleQuantumToChar(color2.redQuantum)); 174 assert(ScaleQuantumToChar(color1.greenQuantum) == ScaleQuantumToChar(color2.greenQuantum)); 175 assert(ScaleQuantumToChar(color1.blueQuantum) == ScaleQuantumToChar(color2.blueQuantum)); 176 }