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