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 }