| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
pp_add_exported( |
|
2
|
|
|
|
|
|
|
'rgb_to_xyz', 'xyz_to_rgb', |
|
3
|
|
|
|
|
|
|
'xyz_to_lab', 'lab_to_xyz', |
|
4
|
|
|
|
|
|
|
'rgb_to_lch', 'lch_to_rgb', |
|
5
|
|
|
|
|
|
|
'rgb_to_lab', 'lab_to_rgb', |
|
6
|
|
|
|
|
|
|
'add_rgb_space', |
|
7
|
|
|
|
|
|
|
); |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
$PDL::Graphics::ColorSpace::VERSION = '0.206'; |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
pp_setversion("'$PDL::Graphics::ColorSpace::VERSION'"); |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
pp_addpm({At=>'Top'}, <<'EOD'); |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=encoding utf8 |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 NAME |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
PDL::Graphics::ColorSpace - colour-space conversions for PDL |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
use PDL::LiteF; |
|
24
|
|
|
|
|
|
|
use PDL::IO::Pic; |
|
25
|
|
|
|
|
|
|
use PDL::Graphics::ColorSpace; |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
my $image_rgb = PDL->rpic('photo.jpg') if PDL->rpiccan('JPEG'); |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# convert RGB value from [0,255] to [0,1] |
|
30
|
|
|
|
|
|
|
$image_rgb = $image_rgb->double / 255; |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
my $image_xyz = $image_rgb->rgb_to_xyz( 'sRGB' ); |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
Or |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
my $image_xyz = rgb_to_xyz( $image_rgb, 'sRGB' ); |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
Does image color space conversions such as RGB to XYZ and Lab to LCH. Derived from Graphics::ColorObject (Izvorski & Reibenschuh, 2005) but since it's implemented in C and PDL, it runs *much* faster. |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
Often the conversion will return out-of-gamut values. Retaining out-of-gamut values allows chained conversions to be lossless and reverse conversions to produce the original values. You can clip the values to be within-gamut if necessary. Please check the specific color space for the gamut range. |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=head1 COLOR SPACES |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=head2 RGB |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
An RGB color space is any additive color space based on the RGB color model. A particular RGB color space is defined by the three chromaticities of the red, green, and blue additive primaries, and can produce any chromaticity that is the triangle defined by those primary colors. The complete specification of an RGB color space also requires a white point chromaticity and a gamma correction curve. |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
For more info on the RGB color space, see L. |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
This module expects and produces RGB values normalized to be in the range of [0,1]. If you have / need integer value between [0,255], divide or multiply the values by 255. |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=head2 CMYK |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
CMYK refers to the four inks used in some color printing: cyan, magenta, yellow, and key (black). The CMYK model works by partially or entirely masking colors on a lighter, usually white, background. The ink reduces the light that would otherwise be reflected. Such a model is called subtractive because inks "subtract" brightness from white. |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
In additive color models such as RGB, white is the "additive" combination of all primary colored lights, while black is the absence of light. In the CMYK model, it is the opposite: white is the natural color of the paper or other background, while black results from a full combination of colored inks. To save money on ink, and to produce deeper black tones, unsaturated and dark colors are produced by using black ink instead of the combination of cyan, magenta and yellow. |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
For more info, see L. |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head2 HSL |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Hue, Saturation and Luminance (or brightness). |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
The HSL color space defines colors more naturally: Hue specifies the base color, the other two values then let you specify the saturation of that color and how bright the color should be. |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
Hue is specified here as degrees ranging from 0 to 360. There are 6 base colors: |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
0 red |
|
71
|
|
|
|
|
|
|
60 yellow |
|
72
|
|
|
|
|
|
|
120 green |
|
73
|
|
|
|
|
|
|
180 cyan |
|
74
|
|
|
|
|
|
|
240 blue |
|
75
|
|
|
|
|
|
|
300 magenta |
|
76
|
|
|
|
|
|
|
360 red |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
Saturation specifies the distance from the middle of the color wheel. So a saturation value of 0 (0%) means "center of the wheel", i.e. a grey value, whereas a saturation value of 1 (100%) means "at the border of the wheel", where the color is fully saturated. |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
Luminance describes how "bright" the color is. 0 (0%) means 0 brightness and the color is black. 1 (100%) means maximum brightness and the color is white. |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
For more info, see L. |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
=head2 XYZ and xyY |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
The CIE XYZ color space was derived the CIE RGB color space. XYZ are three hypothetical primaries. Y means brightness, Z is quasi-equal to blue stimulation, and X is a mix which looks like red sensitivity curve of cones. All visible colors can be represented by using only positive values of X, Y, and Z. The main advantage of the CIE XYZ space (and any color space based on it) is that this space is completely device-independent. |
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
For more info, see L. |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
=head2 Lab |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
A Lab color space is a color-opponent space with dimension L for lightness and a and b for the color-opponent dimensions, based on nonlinearly compressed CIE XYZ color space coordinates. It's derived from the "master" space CIE 1931 XYZ color space but is more perceptually uniform than XYZ. The Lab space is relative to the white point of the XYZ data they were converted from. Lab values do not define absolute colors unless the white point is also specified. |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
For more info, see L. |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=head2 LCH |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
This is possibly a little easier to comprehend than the Lab colour space, with which it shares several features. It is more correctly known as L*C*H*. Essentially it is in the form of a sphere. There are three axes; L* and C* and H°. |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
The L* axis represents Lightness. This is vertical; from 0, which has no lightness (i.e. absolute black), at the bottom; through 50 in the middle, to 100 which is maximum lightness (i.e. absolute white) at the top. |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
The C* axis represents Chroma or "saturation". This ranges from 0 at the centre of the circle, which is completely unsaturated (i.e. a neutral grey, black or white) to 100 or more at the edge of the circle for very high Chroma (saturation) or "colour purity". |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
If we take a horizontal slice through the centre, we see a coloured circle. Around the edge of the circle we see every possible saturated colour, or Hue. This circular axis is known as H° for Hue. The units are in the form of degrees° (or angles), ranging from 0 (red) through 90 (yellow), 180 (green), 270 (blue) and back to 0. |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
For more info, see L. |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=head1 OPTIONS |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
Some conversions require specifying the RGB space which includes gamma curve and white point definitions. Supported RGB spaces include (aliases in square brackets): |
|
111
|
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
Adobe RGB (1998) [Adobe] |
|
113
|
|
|
|
|
|
|
Apple RGB [Apple] |
|
114
|
|
|
|
|
|
|
BestRGB |
|
115
|
|
|
|
|
|
|
Beta RGB |
|
116
|
|
|
|
|
|
|
BruceRGB |
|
117
|
|
|
|
|
|
|
CIE |
|
118
|
|
|
|
|
|
|
ColorMatch |
|
119
|
|
|
|
|
|
|
DonRGB4 |
|
120
|
|
|
|
|
|
|
ECI |
|
121
|
|
|
|
|
|
|
Ekta Space PS5 |
|
122
|
|
|
|
|
|
|
NTSC [601] [CIE Rec 601] |
|
123
|
|
|
|
|
|
|
PAL/SECAM [PAL] [CIE ITU] |
|
124
|
|
|
|
|
|
|
ProPhoto |
|
125
|
|
|
|
|
|
|
SMPTE-C [SMPTE] |
|
126
|
|
|
|
|
|
|
WideGamut |
|
127
|
|
|
|
|
|
|
sRGB [709] [CIE Rec 709] |
|
128
|
|
|
|
|
|
|
lsRGB |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
You can also add custom RGB space definitions via the function add_rgb_space. |
|
131
|
|
|
|
|
|
|
Alternatively, as of 0.202 you can directly supply the function with a |
|
132
|
|
|
|
|
|
|
hash-ref in the same format. |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=head1 CONVERSIONS |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
Some conversions, if not already included as functions, can be achieved |
|
137
|
|
|
|
|
|
|
by chaining existing functions. For example, LCH to HSV conversion can |
|
138
|
|
|
|
|
|
|
be achieved by chaining lch_to_rgb and rgb_to_hsv: |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
my $hsv = rgb_to_hsv( lch_to_rgb( $lch, 'sRGB' ), 'sRGB' ); |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
To generate a local diagram of what conversions are available between |
|
143
|
|
|
|
|
|
|
formats, using GraphViz, you can use this script: |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
use blib; |
|
146
|
|
|
|
|
|
|
use PDL::Graphics::ColorSpace; |
|
147
|
|
|
|
|
|
|
print "digraph {\n"; |
|
148
|
|
|
|
|
|
|
print join(' -> ', split /_to_/), "\n" |
|
149
|
|
|
|
|
|
|
for grep !/^_/ && /_to_/, @PDL::Graphics::ColorSpace::EXPORT_OK; |
|
150
|
|
|
|
|
|
|
print "}\n"; |
|
151
|
|
|
|
|
|
|
# then: |
|
152
|
|
|
|
|
|
|
perl scriptname >d.dot; dot -Tsvg d.dot >d.svg; display d.svg |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
(As of 0.202, this is everything to and from C, plus C <-> |
|
155
|
|
|
|
|
|
|
C <-> C) |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=cut |
|
158
|
1
|
|
|
1
|
|
10
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
47
|
|
|
159
|
1
|
|
|
1
|
|
6
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
92
|
|
|
160
|
|
|
|
|
|
|
use warnings; |
|
161
|
1
|
|
|
1
|
|
6
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
80
|
|
|
162
|
1
|
|
|
1
|
|
8
|
use Carp; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
8
|
|
|
163
|
1
|
|
|
1
|
|
3489
|
use PDL::LiteF; |
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
1315
|
|
|
164
|
|
|
|
|
|
|
use PDL::Graphics::ColorSpace::RGBSpace; |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
my $RGB_SPACE = $PDL::Graphics::ColorSpace::RGBSpace::RGB_SPACE; |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
EOD |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
pp_addhdr(' |
|
171
|
|
|
|
|
|
|
#include |
|
172
|
|
|
|
|
|
|
#include "color_space.h" /* Local decs */ |
|
173
|
|
|
|
|
|
|
' |
|
174
|
|
|
|
|
|
|
); |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
pp_def('rgb_to_cmyk', |
|
177
|
|
|
|
|
|
|
Pars => 'rgb(c=3); [o]cmyk(d=4)', |
|
178
|
|
|
|
|
|
|
HandleBad => 1, |
|
179
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
180
|
|
|
|
|
|
|
Code => ' |
|
181
|
|
|
|
|
|
|
/* First check for bad values */ |
|
182
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(rgb(c=>0)) || $ISBAD(rgb(c=>1)) || $ISBAD(rgb(c=>2))) { |
|
183
|
|
|
|
|
|
|
loop (d) %{ |
|
184
|
|
|
|
|
|
|
$SETBAD(cmyk()); |
|
185
|
|
|
|
|
|
|
%} |
|
186
|
|
|
|
|
|
|
/* skip to the next cmyk triple */ |
|
187
|
|
|
|
|
|
|
} |
|
188
|
|
|
|
|
|
|
else,) { |
|
189
|
|
|
|
|
|
|
rgb2cmyk($P(rgb), $P(cmyk)); |
|
190
|
|
|
|
|
|
|
} |
|
191
|
|
|
|
|
|
|
', |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
Doc => <<'DOCUMENTATION', |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=pod |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=for ref |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
Converts an RGB color triple to an CMYK color quadruple. |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the rgb values must be size 3, i.e. the dimensions must look like (3, m, n, ...). The first dimension of the ndarrays holding the cmyk values must be size 4. |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=for usage |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
Usage: |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
my $cmyk = rgb_to_cmyk( $rgb ); |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=cut |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
DOCUMENTATION |
|
212
|
|
|
|
|
|
|
BadDoc => <
|
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=for bad |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
If C encounters a bad value in any of the R, G, or B values the output ndarray will be marked as bad and the associated C, M, Y, and K values will all be marked as bad. |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=cut |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
BADDOC |
|
221
|
|
|
|
|
|
|
); |
|
222
|
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
pp_def('cmyk_to_rgb', |
|
225
|
|
|
|
|
|
|
Pars => 'cmyk(d=4); [o]rgb(c=3)', |
|
226
|
|
|
|
|
|
|
HandleBad => 1, |
|
227
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
228
|
|
|
|
|
|
|
Code => ' |
|
229
|
|
|
|
|
|
|
/* First check for bad values */ |
|
230
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(cmyk(d=>0)) || $ISBAD(cmyk(d=>1)) || $ISBAD(cmyk(d=>2)) || $ISBAD(cmyk(d=>3))) { |
|
231
|
|
|
|
|
|
|
loop (c) %{ |
|
232
|
|
|
|
|
|
|
$SETBAD(rgb()); |
|
233
|
|
|
|
|
|
|
%} |
|
234
|
|
|
|
|
|
|
/* skip to the next cmyk triple */ |
|
235
|
|
|
|
|
|
|
} |
|
236
|
|
|
|
|
|
|
else,) { |
|
237
|
|
|
|
|
|
|
cmyk2rgb($P(cmyk), $P(rgb)); |
|
238
|
|
|
|
|
|
|
} |
|
239
|
|
|
|
|
|
|
', |
|
240
|
|
|
|
|
|
|
Doc => <<'DOCUMENTATION', |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=pod |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=for ref |
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
Converts an CMYK color quadruple to an RGB color triple |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the cmyk values must be size 4, i.e. the dimensions must look like (4, m, n, ...). The first dimension of the ndarray holding the rgb values must be 3. |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=for usage |
|
251
|
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
Usage: |
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
my $rgb = cmyk_to_rgb( $cmyk ); |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=cut |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
DOCUMENTATION |
|
259
|
|
|
|
|
|
|
BadDoc => <
|
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=for bad |
|
262
|
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
If C encounters a bad value in any of the C, M, Y, or K quantities, the output ndarray will be marked as bad and the associated R, G, and B color values will all be marked as bad. |
|
264
|
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
=cut |
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
BADDOC |
|
268
|
|
|
|
|
|
|
); |
|
269
|
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
pp_def('rgb_to_hsl', |
|
272
|
|
|
|
|
|
|
Pars => 'rgb(c=3); [o]hsl(c=3)', |
|
273
|
|
|
|
|
|
|
HandleBad => 1, |
|
274
|
|
|
|
|
|
|
Inplace => 1, |
|
275
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
276
|
|
|
|
|
|
|
Code => ' |
|
277
|
|
|
|
|
|
|
/* First check for bad values */ |
|
278
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(rgb(c=>0)) || $ISBAD(rgb(c=>1)) || $ISBAD(rgb(c=>2))) { |
|
279
|
|
|
|
|
|
|
loop (c) %{ |
|
280
|
|
|
|
|
|
|
$SETBAD(hsl()); |
|
281
|
|
|
|
|
|
|
%} |
|
282
|
|
|
|
|
|
|
/* skip to the next hsl triple */ |
|
283
|
|
|
|
|
|
|
} |
|
284
|
|
|
|
|
|
|
else,) { |
|
285
|
|
|
|
|
|
|
rgb2hsl($P(rgb), $P(hsl)); |
|
286
|
|
|
|
|
|
|
} |
|
287
|
|
|
|
|
|
|
', |
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
Doc => <<'DOCUMENTATION', |
|
290
|
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=pod |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=for ref |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
Converts an RGB color triple to an HSL color triple. |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the hsl and rgb values must be size 3, i.e. the dimensions must look like (3, m, n, ...). |
|
298
|
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
=for usage |
|
300
|
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
Usage: |
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
my $hsl = rgb_to_hsl( $rgb ); |
|
304
|
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=cut |
|
306
|
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
DOCUMENTATION |
|
308
|
|
|
|
|
|
|
BadDoc => <
|
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
=for bad |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
If C encounters a bad value in any of the R, G, or B values the output ndarray will be marked as bad and the associated H, S, and L values will all be marked as bad. |
|
313
|
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
=cut |
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
BADDOC |
|
317
|
|
|
|
|
|
|
); |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
pp_def('hsl_to_rgb', |
|
321
|
|
|
|
|
|
|
Pars => 'hsl(c=3); [o]rgb(c=3)', |
|
322
|
|
|
|
|
|
|
HandleBad => 1, |
|
323
|
|
|
|
|
|
|
Inplace => 1, |
|
324
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
325
|
|
|
|
|
|
|
Code => ' |
|
326
|
|
|
|
|
|
|
/* First check for bad values */ |
|
327
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(hsl(c=>0)) || $ISBAD(hsl(c=>1)) || $ISBAD(hsl(c=>2))) { |
|
328
|
|
|
|
|
|
|
loop (c) %{ |
|
329
|
|
|
|
|
|
|
$SETBAD(rgb()); |
|
330
|
|
|
|
|
|
|
%} |
|
331
|
|
|
|
|
|
|
/* skip to the next hsl triple */ |
|
332
|
|
|
|
|
|
|
} |
|
333
|
|
|
|
|
|
|
else,) { |
|
334
|
|
|
|
|
|
|
hsl2rgb($P(hsl), $P(rgb)); |
|
335
|
|
|
|
|
|
|
} |
|
336
|
|
|
|
|
|
|
', |
|
337
|
|
|
|
|
|
|
Doc => <<'DOCUMENTATION', |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=pod |
|
340
|
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
=for ref |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
Converts an HSL color triple to an RGB color triple |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the hsl and rgb values must be size 3, i.e. the dimensions must look like (3, m, n, ...). |
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
=for usage |
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
Usage: |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
my $rgb = hsl_to_rgb( $hsl ); |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
=cut |
|
354
|
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
DOCUMENTATION |
|
356
|
|
|
|
|
|
|
BadDoc => <
|
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
=for bad |
|
359
|
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
If C encounters a bad value in any of the H, S, or V quantities, the output ndarray will be marked as bad and the associated R, G, and B color values will all be marked as bad. |
|
361
|
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=cut |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
BADDOC |
|
365
|
|
|
|
|
|
|
); |
|
366
|
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
pp_def('rgb_to_hsv', |
|
369
|
|
|
|
|
|
|
Pars => 'rgb(c=3); [o]hsv(c=3)', |
|
370
|
|
|
|
|
|
|
HandleBad => 1, |
|
371
|
|
|
|
|
|
|
Inplace => 1, |
|
372
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
373
|
|
|
|
|
|
|
Code => ' |
|
374
|
|
|
|
|
|
|
/* First check for bad values */ |
|
375
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(rgb(c=>0)) || $ISBAD(rgb(c=>1)) || $ISBAD(rgb(c=>2))) { |
|
376
|
|
|
|
|
|
|
loop (c) %{ |
|
377
|
|
|
|
|
|
|
$SETBAD(hsv()); |
|
378
|
|
|
|
|
|
|
%} |
|
379
|
|
|
|
|
|
|
/* skip to the next hsv triple */ |
|
380
|
|
|
|
|
|
|
} |
|
381
|
|
|
|
|
|
|
else,) { |
|
382
|
|
|
|
|
|
|
rgb2hsv($P(rgb), $P(hsv)); |
|
383
|
|
|
|
|
|
|
} |
|
384
|
|
|
|
|
|
|
', |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
Doc => <<'DOCUMENTATION', |
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
=pod |
|
389
|
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=for ref |
|
391
|
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
Converts an RGB color triple to an HSV color triple. |
|
393
|
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the hsv and rgb values must be size 3, i.e. the dimensions must look like (3, m, n, ...). |
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
=for usage |
|
397
|
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
Usage: |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
my $hsv = rgb_to_hsv( $rgb ); |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=cut |
|
403
|
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
DOCUMENTATION |
|
405
|
|
|
|
|
|
|
BadDoc => <
|
|
406
|
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
=for bad |
|
408
|
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
If C encounters a bad value in any of the R, G, or B values the output ndarray will be marked as bad and the associated H, S, and V values will all be marked as bad. |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
=cut |
|
412
|
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
BADDOC |
|
414
|
|
|
|
|
|
|
); |
|
415
|
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
pp_def('hsv_to_rgb', |
|
418
|
|
|
|
|
|
|
Pars => 'hsv(c=3); [o]rgb(c=3)', |
|
419
|
|
|
|
|
|
|
HandleBad => 1, |
|
420
|
|
|
|
|
|
|
Inplace => 1, |
|
421
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
422
|
|
|
|
|
|
|
Code => ' |
|
423
|
|
|
|
|
|
|
/* First check for bad values */ |
|
424
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(hsv(c=>0)) || $ISBAD(hsv(c=>1)) || $ISBAD(hsv(c=>2))) { |
|
425
|
|
|
|
|
|
|
loop (c) %{ |
|
426
|
|
|
|
|
|
|
$SETBAD(rgb()); |
|
427
|
|
|
|
|
|
|
%} |
|
428
|
|
|
|
|
|
|
/* skip to the next rgb triple */ |
|
429
|
|
|
|
|
|
|
} |
|
430
|
|
|
|
|
|
|
else,) { |
|
431
|
|
|
|
|
|
|
hsv2rgb($P(hsv), $P(rgb)); |
|
432
|
|
|
|
|
|
|
} |
|
433
|
|
|
|
|
|
|
', |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
Doc => <<'DOCUMENTATION', |
|
436
|
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
=pod |
|
438
|
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
=for ref |
|
440
|
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
Converts an HSV color triple to an RGB color triple |
|
442
|
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the hsv and rgb values must be size 3, i.e. the dimensions must look like (3, m, n, ...). |
|
444
|
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
=for usage |
|
446
|
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
Usage: |
|
448
|
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
my $rgb = hsv_to_rgb( $hsv ); |
|
450
|
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
=cut |
|
452
|
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
DOCUMENTATION |
|
454
|
|
|
|
|
|
|
BadDoc => <
|
|
455
|
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
=for bad |
|
457
|
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
If C encounters a bad value in any of the H, S, or V quantities, the output ndarray will be marked as bad and the associated R, G, and B color values will all be marked as bad. |
|
459
|
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
=cut |
|
461
|
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
BADDOC |
|
463
|
|
|
|
|
|
|
); |
|
464
|
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
pp_def('xyY_to_xyz', |
|
467
|
|
|
|
|
|
|
Pars => 'xyY(c=3); [o]xyz(c=3)', |
|
468
|
|
|
|
|
|
|
Doc => 'Internal function for white point calculation. Use it if you must.', |
|
469
|
|
|
|
|
|
|
HandleBad => 1, |
|
470
|
|
|
|
|
|
|
Inplace => 1, |
|
471
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
472
|
|
|
|
|
|
|
Code => ' |
|
473
|
|
|
|
|
|
|
/* First check for bad values */ |
|
474
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(xyY(c=>0)) || $ISBAD(xyY(c=>1)) || $ISBAD(xyY(c=>2))) { |
|
475
|
|
|
|
|
|
|
loop (c) %{ |
|
476
|
|
|
|
|
|
|
$SETBAD(xyz()); |
|
477
|
|
|
|
|
|
|
%} |
|
478
|
|
|
|
|
|
|
/* skip to the next hsl triple */ |
|
479
|
|
|
|
|
|
|
} |
|
480
|
|
|
|
|
|
|
else,) { |
|
481
|
|
|
|
|
|
|
xyY2xyz($P(xyY), $P(xyz)); |
|
482
|
|
|
|
|
|
|
} |
|
483
|
|
|
|
|
|
|
', |
|
484
|
|
|
|
|
|
|
); |
|
485
|
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
pp_def('_rgb_to_xyz', |
|
488
|
|
|
|
|
|
|
Pars => 'rgb(c=3); gamma(); m(i=3,rows=3); [o]xyz(c=3)', |
|
489
|
|
|
|
|
|
|
HandleBad => 1, |
|
490
|
|
|
|
|
|
|
Inplace => ['rgb'], |
|
491
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
492
|
|
|
|
|
|
|
Code => ' |
|
493
|
|
|
|
|
|
|
/* First check for bad values */ |
|
494
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(rgb(c=>0)) || $ISBAD(rgb(c=>1)) || $ISBAD(rgb(c=>2))) { |
|
495
|
|
|
|
|
|
|
loop (c) %{ |
|
496
|
|
|
|
|
|
|
$SETBAD(xyz()); |
|
497
|
|
|
|
|
|
|
%} |
|
498
|
|
|
|
|
|
|
/* skip to the next xyz triple */ |
|
499
|
|
|
|
|
|
|
} |
|
500
|
|
|
|
|
|
|
else,) { |
|
501
|
|
|
|
|
|
|
rgb2xyz($P(rgb), $gamma(), &$m(i=>0,rows=>0), &$m(i=>0,rows=>1), &$m(i=>0,rows=>2), $P(xyz)); |
|
502
|
|
|
|
|
|
|
} |
|
503
|
|
|
|
|
|
|
', |
|
504
|
|
|
|
|
|
|
Doc => undef, |
|
505
|
|
|
|
|
|
|
); |
|
506
|
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
pp_def('_xyz_to_rgb', |
|
509
|
|
|
|
|
|
|
Pars => 'xyz(c=3); gamma(); mstar(i=3,rows=3); [o]rgb(c=3)', |
|
510
|
|
|
|
|
|
|
HandleBad => 1, |
|
511
|
|
|
|
|
|
|
Inplace => ['xyz'], |
|
512
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
513
|
|
|
|
|
|
|
Code => ' |
|
514
|
|
|
|
|
|
|
/* First check for bad values */ |
|
515
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(xyz(c=>0)) || $ISBAD(xyz(c=>1)) || $ISBAD(xyz(c=>2))) { |
|
516
|
|
|
|
|
|
|
loop (c) %{ |
|
517
|
|
|
|
|
|
|
$SETBAD(rgb()); |
|
518
|
|
|
|
|
|
|
%} |
|
519
|
|
|
|
|
|
|
/* skip to the next rgb triple */ |
|
520
|
|
|
|
|
|
|
} |
|
521
|
|
|
|
|
|
|
else,) { |
|
522
|
|
|
|
|
|
|
xyz2rgb($P(xyz), $gamma(), &$mstar(i=>0,rows=>0), &$mstar(i=>0,rows=>1), &$mstar(i=>0,rows=>2), $P(rgb)); |
|
523
|
|
|
|
|
|
|
} |
|
524
|
|
|
|
|
|
|
', |
|
525
|
|
|
|
|
|
|
Doc => undef, |
|
526
|
|
|
|
|
|
|
); |
|
527
|
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
pp_def('_xyz_to_lab', |
|
530
|
|
|
|
|
|
|
Pars => 'xyz(c=3); w(d=2); [o]lab(c=3)', |
|
531
|
|
|
|
|
|
|
Doc => undef, |
|
532
|
|
|
|
|
|
|
HandleBad => 1, |
|
533
|
|
|
|
|
|
|
Inplace => ['xyz'], |
|
534
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
535
|
|
|
|
|
|
|
Code => ' |
|
536
|
|
|
|
|
|
|
/* construct white point */ |
|
537
|
|
|
|
|
|
|
double xyY[3] = { $w(d=>0), $w(d=>1), 1.0 }; |
|
538
|
|
|
|
|
|
|
double xyz_white[3]; |
|
539
|
|
|
|
|
|
|
xyY2xyz( &xyY[0], &xyz_white[0] ); |
|
540
|
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
threadloop %{ |
|
542
|
|
|
|
|
|
|
/* First check for bad values */ |
|
543
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(xyz(c=>0)) || $ISBAD(xyz(c=>1)) || $ISBAD(xyz(c=>2))) { |
|
544
|
|
|
|
|
|
|
loop (c) %{ |
|
545
|
|
|
|
|
|
|
$SETBAD(lab()); |
|
546
|
|
|
|
|
|
|
%} |
|
547
|
|
|
|
|
|
|
/* skip to the next xyz triple */ |
|
548
|
|
|
|
|
|
|
} |
|
549
|
|
|
|
|
|
|
else,) { |
|
550
|
|
|
|
|
|
|
xyz2lab( $P(xyz), &xyz_white[0], $P(lab) ); |
|
551
|
|
|
|
|
|
|
} |
|
552
|
|
|
|
|
|
|
%} |
|
553
|
|
|
|
|
|
|
', |
|
554
|
|
|
|
|
|
|
); |
|
555
|
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
pp_def('_lab_to_xyz', |
|
558
|
|
|
|
|
|
|
Pars => 'lab(c=3); w(d=2); [o]xyz(c=3)', |
|
559
|
|
|
|
|
|
|
Doc => undef, |
|
560
|
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
HandleBad => 1, |
|
562
|
|
|
|
|
|
|
Inplace => ['lab'], |
|
563
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
564
|
|
|
|
|
|
|
Code => ' |
|
565
|
|
|
|
|
|
|
/* construct white point */ |
|
566
|
|
|
|
|
|
|
double xyY[3] = { $w(d=>0), $w(d=>1), 1.0 }; |
|
567
|
|
|
|
|
|
|
double xyz_white[3]; |
|
568
|
|
|
|
|
|
|
xyY2xyz( &xyY[0], &xyz_white[0] ); |
|
569
|
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
threadloop %{ |
|
571
|
|
|
|
|
|
|
/* First check for bad values */ |
|
572
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(lab(c=>0)) || $ISBAD(lab(c=>1)) || $ISBAD(lab(c=>2))) { |
|
573
|
|
|
|
|
|
|
loop (c) %{ |
|
574
|
|
|
|
|
|
|
$SETBAD(xyz()); |
|
575
|
|
|
|
|
|
|
%} |
|
576
|
|
|
|
|
|
|
/* skip to the next lab triple */ |
|
577
|
|
|
|
|
|
|
} |
|
578
|
|
|
|
|
|
|
else,) { |
|
579
|
|
|
|
|
|
|
lab2xyz( $P(lab), &xyz_white[0], $P(xyz) ); |
|
580
|
|
|
|
|
|
|
} |
|
581
|
|
|
|
|
|
|
%} |
|
582
|
|
|
|
|
|
|
', |
|
583
|
|
|
|
|
|
|
); |
|
584
|
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
pp_def('lab_to_lch', |
|
587
|
|
|
|
|
|
|
Pars => 'lab(c=3); [o]lch(c=3)', |
|
588
|
|
|
|
|
|
|
HandleBad => 1, |
|
589
|
|
|
|
|
|
|
Inplace => 1, |
|
590
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
591
|
|
|
|
|
|
|
Code => ' |
|
592
|
|
|
|
|
|
|
/* First check for bad values */ |
|
593
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(lab(c=>0)) || $ISBAD(lab(c=>1)) || $ISBAD(lab(c=>2))) { |
|
594
|
|
|
|
|
|
|
loop (c) %{ |
|
595
|
|
|
|
|
|
|
$SETBAD(lch()); |
|
596
|
|
|
|
|
|
|
%} |
|
597
|
|
|
|
|
|
|
/* skip to the next lch triple */ |
|
598
|
|
|
|
|
|
|
} |
|
599
|
|
|
|
|
|
|
else,) { |
|
600
|
|
|
|
|
|
|
lab2lch( $P(lab), $P(lch) ); |
|
601
|
|
|
|
|
|
|
} |
|
602
|
|
|
|
|
|
|
', |
|
603
|
|
|
|
|
|
|
Doc => <<'DOCUMENTATION', |
|
604
|
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
=pod |
|
606
|
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
=for ref |
|
608
|
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
Converts an Lab color triple to an LCH color triple. |
|
610
|
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the lab values must be size 3, i.e. the dimensions must look like (3, m, n, ...). |
|
612
|
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
=for usage |
|
614
|
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
Usage: |
|
616
|
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
my $lch = lab_to_lch( $lab ); |
|
618
|
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
=cut |
|
620
|
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
DOCUMENTATION |
|
622
|
|
|
|
|
|
|
BadDoc => <
|
|
623
|
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
=for bad |
|
625
|
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
If C encounters a bad value in any of the L, a, or b values the output ndarray will be marked as bad and the associated L, C, and H values will all be marked as bad. |
|
627
|
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
=cut |
|
629
|
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
BADDOC |
|
631
|
|
|
|
|
|
|
); |
|
632
|
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
pp_def('lch_to_lab', |
|
635
|
|
|
|
|
|
|
Pars => 'lch(c=3); [o]lab(c=3)', |
|
636
|
|
|
|
|
|
|
HandleBad => 1, |
|
637
|
|
|
|
|
|
|
Inplace => 1, |
|
638
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
639
|
|
|
|
|
|
|
Code => ' |
|
640
|
|
|
|
|
|
|
/* First check for bad values */ |
|
641
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(lch(c=>0)) || $ISBAD(lch(c=>1)) || $ISBAD(lch(c=>2))) { |
|
642
|
|
|
|
|
|
|
loop (c) %{ |
|
643
|
|
|
|
|
|
|
$SETBAD(lab()); |
|
644
|
|
|
|
|
|
|
%} |
|
645
|
|
|
|
|
|
|
/* skip to the next lab triple */ |
|
646
|
|
|
|
|
|
|
} |
|
647
|
|
|
|
|
|
|
else,) { |
|
648
|
|
|
|
|
|
|
lch2lab( $P(lch), $P(lab) ); |
|
649
|
|
|
|
|
|
|
} |
|
650
|
|
|
|
|
|
|
', |
|
651
|
|
|
|
|
|
|
Doc => <<'DOCUMENTATION', |
|
652
|
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
=pod |
|
654
|
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
=for ref |
|
656
|
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
Converts an LCH color triple to an Lab color triple. |
|
658
|
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the lch values must be size 3, i.e. the dimensions must look like (3, m, n, ...). |
|
660
|
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
=for usage |
|
662
|
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
Usage: |
|
664
|
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
my $lab = lch_to_lab( $lch ); |
|
666
|
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
=cut |
|
668
|
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
DOCUMENTATION |
|
670
|
|
|
|
|
|
|
BadDoc => <
|
|
671
|
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
=for bad |
|
673
|
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
If C encounters a bad value in any of the L, C, or H values the output ndarray will be marked as bad and the associated L, a, and b values will all be marked as bad. |
|
675
|
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
=cut |
|
677
|
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
BADDOC |
|
679
|
|
|
|
|
|
|
); |
|
680
|
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
pp_def('rgb_to_linear', |
|
683
|
|
|
|
|
|
|
Pars => 'rgb(c=3); gamma(); [o]out(c=3)', |
|
684
|
|
|
|
|
|
|
HandleBad => 1, |
|
685
|
|
|
|
|
|
|
Inplace => ['rgb'], |
|
686
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
687
|
|
|
|
|
|
|
Code => ' |
|
688
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(rgb(c=>0)) || $ISBAD(rgb(c=>1)) || $ISBAD(rgb(c=>2))) { |
|
689
|
|
|
|
|
|
|
loop (c) %{ $SETBAD(out()); %} |
|
690
|
|
|
|
|
|
|
} |
|
691
|
|
|
|
|
|
|
else,) { |
|
692
|
|
|
|
|
|
|
rgb2linear( $P(rgb), $gamma(), $P(out) ); |
|
693
|
|
|
|
|
|
|
} |
|
694
|
|
|
|
|
|
|
', |
|
695
|
|
|
|
|
|
|
Doc => <<'DOCUMENTATION', |
|
696
|
|
|
|
|
|
|
=for ref |
|
697
|
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
Converts an RGB color triple (presumably with gamma) to an RGB color triple |
|
699
|
|
|
|
|
|
|
with linear values. |
|
700
|
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
=for usage |
|
702
|
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
Usage: |
|
704
|
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
my $rgb_linear = rgb_to_linear( $gammaed, 2.2 ); |
|
706
|
|
|
|
|
|
|
DOCUMENTATION |
|
707
|
|
|
|
|
|
|
BadDoc => <
|
|
708
|
|
|
|
|
|
|
=for bad |
|
709
|
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
If C encounters a bad value in any of the R, G, or B |
|
711
|
|
|
|
|
|
|
values the output ndarray will be marked as bad and the associated R, |
|
712
|
|
|
|
|
|
|
G, and B values will all be marked as bad. |
|
713
|
|
|
|
|
|
|
BADDOC |
|
714
|
|
|
|
|
|
|
); |
|
715
|
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
pp_def('rgb_from_linear', |
|
718
|
|
|
|
|
|
|
Pars => 'rgb(c=3); gamma(); [o]out(c=3)', |
|
719
|
|
|
|
|
|
|
HandleBad => 1, |
|
720
|
|
|
|
|
|
|
Inplace => ['rgb'], |
|
721
|
|
|
|
|
|
|
GenericTypes=>['D'], |
|
722
|
|
|
|
|
|
|
Code => ' |
|
723
|
|
|
|
|
|
|
PDL_IF_BAD(if ($ISBAD(rgb(c=>0)) || $ISBAD(rgb(c=>1)) || $ISBAD(rgb(c=>2))) { |
|
724
|
|
|
|
|
|
|
loop (c) %{ $SETBAD(out()); %} |
|
725
|
|
|
|
|
|
|
} |
|
726
|
|
|
|
|
|
|
else,) { |
|
727
|
|
|
|
|
|
|
rgb2gamma( $P(rgb), $gamma(), $P(out) ); |
|
728
|
|
|
|
|
|
|
} |
|
729
|
|
|
|
|
|
|
', |
|
730
|
|
|
|
|
|
|
Doc => <<'DOCUMENTATION', |
|
731
|
|
|
|
|
|
|
=for ref |
|
732
|
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
Converts an RGB color triple (presumably linear) to an RGB color triple |
|
734
|
|
|
|
|
|
|
with the specified gamma. |
|
735
|
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
=for usage |
|
737
|
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
Usage: |
|
739
|
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
my $gammaed = rgb_from_linear( $rgb_linear, 2.2 ); |
|
741
|
|
|
|
|
|
|
DOCUMENTATION |
|
742
|
|
|
|
|
|
|
BadDoc => <
|
|
743
|
|
|
|
|
|
|
=for bad |
|
744
|
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
If C encounters a bad value in any of the R, G, or B |
|
746
|
|
|
|
|
|
|
values the output ndarray will be marked as bad and the associated R, |
|
747
|
|
|
|
|
|
|
G, and B values will all be marked as bad. |
|
748
|
|
|
|
|
|
|
BADDOC |
|
749
|
|
|
|
|
|
|
); |
|
750
|
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
pp_addpm(<<'EOD'); |
|
753
|
|
|
|
|
|
|
|
|
754
|
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
=head2 rgb_to_xyz |
|
756
|
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
=for ref |
|
758
|
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
Converts an RGB color triple to an XYZ color triple. |
|
760
|
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the rgb values must be size 3, i.e. the dimensions must look like (3, m, n, ...). |
|
762
|
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
=for bad |
|
764
|
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
If C encounters a bad value in any of the R, G, or B values the output ndarray will be marked as bad and the associated X, Y, and Z values will all be marked as bad. |
|
766
|
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
=for usage |
|
768
|
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
Usage: |
|
770
|
|
|
|
|
|
|
|
|
771
|
|
|
|
|
|
|
my $xyz = rgb_to_xyz( $rgb, 'sRGB' ); |
|
772
|
|
|
|
|
|
|
my $xyz = rgb_to_xyz( $rgb, \%rgb_spec ); |
|
773
|
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
=cut |
|
775
|
|
|
|
|
|
|
|
|
776
|
10
|
|
|
10
|
0
|
276006
|
*rgb_to_xyz = \&PDL::rgb_to_xyz; |
|
777
|
10
|
|
|
|
|
30
|
sub PDL::rgb_to_xyz { |
|
778
|
10
|
|
|
|
|
26
|
my ($rgb, $space) = @_; |
|
779
|
10
|
|
|
|
|
166
|
my $spec = get_space($space); |
|
780
|
|
|
|
|
|
|
my $m = PDL->topdl( $spec->{m} ); |
|
781
|
|
|
|
|
|
|
return _rgb_to_xyz( $rgb, $spec->{gamma}, $m ); |
|
782
|
|
|
|
|
|
|
} |
|
783
|
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
=head2 xyz_to_rgb |
|
786
|
|
|
|
|
|
|
|
|
787
|
|
|
|
|
|
|
=for ref |
|
788
|
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
Converts an XYZ color triple to an RGB color triple. |
|
790
|
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the xyz and rgb values must be size 3, i.e. the dimensions must look like (3, m, n, ...). |
|
792
|
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
=for bad |
|
794
|
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
If C encounters a bad value in any of the X, Y, or Z values the output ndarray will be marked as bad and the associated R, G, and B values will all be marked as bad. |
|
796
|
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
=for usage |
|
798
|
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
Usage: |
|
800
|
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
my $rgb = xyz_to_rgb( $xyz, 'sRGB' ); |
|
802
|
|
|
|
|
|
|
my $rgb = xyz_to_rgb( $xyz, \%rgb_spec ); |
|
803
|
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
=cut |
|
805
|
5
|
|
|
5
|
0
|
8
|
|
|
806
|
5
|
|
|
|
|
8
|
*xyz_to_rgb = \&PDL::xyz_to_rgb; |
|
807
|
5
|
50
|
|
|
|
15
|
sub PDL::xyz_to_rgb { |
|
808
|
5
|
|
|
|
|
78
|
my ($xyz, $space) = @_; |
|
809
|
|
|
|
|
|
|
my $spec = get_space($space); |
|
810
|
|
|
|
|
|
|
my $mstar = exists $spec->{mstar} ? PDL->topdl( $spec->{mstar} ) : PDL->topdl( $spec->{m} )->inv; |
|
811
|
|
|
|
|
|
|
return _xyz_to_rgb( $xyz, $spec->{gamma}, $mstar ); |
|
812
|
|
|
|
|
|
|
} |
|
813
|
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
=head2 xyz_to_lab |
|
816
|
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
=for ref |
|
818
|
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
Converts an XYZ color triple to an Lab color triple. |
|
820
|
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the xyz values must be size 3, i.e. the dimensions must look like (3, m, n, ...). |
|
822
|
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
=for bad |
|
824
|
|
|
|
|
|
|
|
|
825
|
|
|
|
|
|
|
If C encounters a bad value in any of the X, Y, or Z values the output ndarray will be marked as bad and the associated L, a, and b values will all be marked as bad. |
|
826
|
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
=for usage |
|
828
|
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
Usage: |
|
830
|
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
my $lab = xyz_to_lab( $xyz, 'sRGB' ); |
|
832
|
|
|
|
|
|
|
my $lab = xyz_to_lab( $xyz, \%rgb_spec ); |
|
833
|
|
|
|
|
|
|
|
|
834
|
8
|
|
|
8
|
0
|
889
|
=cut |
|
835
|
8
|
|
|
|
|
11
|
|
|
836
|
8
|
|
|
|
|
13
|
*xyz_to_lab = \&PDL::xyz_to_lab; |
|
837
|
8
|
|
|
|
|
72
|
sub PDL::xyz_to_lab { |
|
838
|
|
|
|
|
|
|
my ($xyz, $space) = @_; |
|
839
|
|
|
|
|
|
|
my $spec = get_space($space); |
|
840
|
|
|
|
|
|
|
my $w = PDL->topdl($spec->{white_point}); |
|
841
|
|
|
|
|
|
|
return _xyz_to_lab( $xyz, $w ); |
|
842
|
|
|
|
|
|
|
} |
|
843
|
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
|
|
845
|
|
|
|
|
|
|
=head2 lab_to_xyz |
|
846
|
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
=for ref |
|
848
|
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
Converts an Lab color triple to an XYZ color triple. |
|
850
|
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the lab values must be size 3, i.e. the dimensions must look like (3, m, n, ...). |
|
852
|
|
|
|
|
|
|
|
|
853
|
|
|
|
|
|
|
=for bad |
|
854
|
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
If C encounters a bad value in any of the L, a, or b values the output ndarray will be marked as bad and the associated X, Y, and Z values will all be marked as bad. |
|
856
|
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
=for usage |
|
858
|
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
Usage: |
|
860
|
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
my $xyz = lab_to_xyz( $lab, 'sRGB' ); |
|
862
|
|
|
|
|
|
|
my $xyz = lab_to_xyz( $lab, \%rgb_spec ); |
|
863
|
7
|
|
|
7
|
0
|
783
|
|
|
864
|
7
|
|
|
|
|
12
|
=cut |
|
865
|
7
|
|
|
|
|
17
|
|
|
866
|
7
|
|
|
|
|
103
|
*lab_to_xyz = \&PDL::lab_to_xyz; |
|
867
|
|
|
|
|
|
|
sub PDL::lab_to_xyz { |
|
868
|
|
|
|
|
|
|
my ($lab, $space) = @_; |
|
869
|
|
|
|
|
|
|
my $spec = get_space($space); |
|
870
|
|
|
|
|
|
|
my $w = PDL->topdl($spec->{white_point}); |
|
871
|
|
|
|
|
|
|
return _lab_to_xyz( $lab, $w ); |
|
872
|
|
|
|
|
|
|
} |
|
873
|
|
|
|
|
|
|
|
|
874
|
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
=head2 rgb_to_lch |
|
876
|
|
|
|
|
|
|
|
|
877
|
|
|
|
|
|
|
=for ref |
|
878
|
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
Converts an RGB color triple to an LCH color triple. |
|
880
|
|
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the rgb values must be size 3, i.e. the dimensions must look like (3, m, n, ...). |
|
882
|
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
=for bad |
|
884
|
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
If C encounters a bad value in any of the R, G, or B values the output ndarray will be marked as bad and the associated L, C, and H values will all be marked as bad. |
|
886
|
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
=for usage |
|
888
|
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
Usage: |
|
890
|
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
my $lch = rgb_to_lch( $rgb, 'sRGB' ); |
|
892
|
4
|
|
|
4
|
0
|
2826
|
my $lch = rgb_to_lch( $rgb, \%rgb_spec ); |
|
893
|
4
|
|
|
|
|
9
|
|
|
894
|
4
|
|
|
|
|
7
|
=cut |
|
895
|
4
|
|
|
|
|
37
|
|
|
896
|
|
|
|
|
|
|
*rgb_to_lch = \&PDL::rgb_to_lch; |
|
897
|
|
|
|
|
|
|
sub PDL::rgb_to_lch { |
|
898
|
|
|
|
|
|
|
my ($rgb, $space) = @_; |
|
899
|
|
|
|
|
|
|
my $spec = get_space($space); |
|
900
|
|
|
|
|
|
|
my $lab = xyz_to_lab( rgb_to_xyz( $rgb, $spec ), $spec ); |
|
901
|
|
|
|
|
|
|
return lab_to_lch( $lab ); |
|
902
|
|
|
|
|
|
|
} |
|
903
|
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
|
|
905
|
|
|
|
|
|
|
=head2 lch_to_rgb |
|
906
|
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
=for ref |
|
908
|
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
Converts an LCH color triple to an RGB color triple. |
|
910
|
|
|
|
|
|
|
|
|
911
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the lch values must be size 3, i.e. the dimensions must look like (3, m, n, ...). |
|
912
|
|
|
|
|
|
|
|
|
913
|
|
|
|
|
|
|
=for bad |
|
914
|
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
If C encounters a bad value in any of the L, C, or H values the output ndarray will be marked as bad and the associated R, G, and B values will all be marked as bad. |
|
916
|
|
|
|
|
|
|
|
|
917
|
|
|
|
|
|
|
=for usage |
|
918
|
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
Usage: |
|
920
|
|
|
|
|
|
|
|
|
921
|
2
|
|
|
2
|
0
|
804
|
my $rgb = lch_to_rgb( $lch, 'sRGB' ); |
|
922
|
2
|
|
|
|
|
5
|
my $rgb = lch_to_rgb( $lch, \%rgb_spec ); |
|
923
|
2
|
|
|
|
|
40
|
|
|
924
|
2
|
|
|
|
|
7
|
=cut |
|
925
|
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
*lch_to_rgb = \&PDL::lch_to_rgb; |
|
927
|
|
|
|
|
|
|
sub PDL::lch_to_rgb { |
|
928
|
|
|
|
|
|
|
my ($lch, $space) = @_; |
|
929
|
|
|
|
|
|
|
my $spec = get_space($space); |
|
930
|
|
|
|
|
|
|
my $xyz = lab_to_xyz( lch_to_lab( $lch ), $spec ); |
|
931
|
|
|
|
|
|
|
return xyz_to_rgb( $xyz, $spec ); |
|
932
|
|
|
|
|
|
|
} |
|
933
|
|
|
|
|
|
|
|
|
934
|
|
|
|
|
|
|
|
|
935
|
|
|
|
|
|
|
=head2 rgb_to_lab |
|
936
|
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
=for ref |
|
938
|
|
|
|
|
|
|
|
|
939
|
|
|
|
|
|
|
Converts an RGB color triple to an LAB color triple. |
|
940
|
|
|
|
|
|
|
|
|
941
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the rgb values must be size 3, i.e. the dimensions must look like (3, m, n, ...). |
|
942
|
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
=for bad |
|
944
|
|
|
|
|
|
|
|
|
945
|
|
|
|
|
|
|
If C encounters a bad value in any of the R, G, or B values the output ndarray will be marked as bad and the associated L, A, and B values will all be marked as bad. |
|
946
|
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
=for usage |
|
948
|
|
|
|
|
|
|
|
|
949
|
|
|
|
|
|
|
Usage: |
|
950
|
2
|
|
|
2
|
0
|
932
|
|
|
951
|
2
|
|
|
|
|
6
|
my $lab = rgb_to_lab( $rgb, 'sRGB' ); |
|
952
|
2
|
|
|
|
|
4
|
my $lab = rgb_to_lab( $rgb, \%rgb_spec ); |
|
953
|
|
|
|
|
|
|
|
|
954
|
|
|
|
|
|
|
=cut |
|
955
|
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
*rgb_to_lab = \&PDL::rgb_to_lab; |
|
957
|
|
|
|
|
|
|
sub PDL::rgb_to_lab { |
|
958
|
|
|
|
|
|
|
my ($rgb, $space) = @_; |
|
959
|
|
|
|
|
|
|
my $spec = get_space($space); |
|
960
|
|
|
|
|
|
|
return xyz_to_lab( rgb_to_xyz( $rgb, $spec ), $spec ); |
|
961
|
|
|
|
|
|
|
} |
|
962
|
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
|
|
964
|
|
|
|
|
|
|
=head2 lab_to_rgb |
|
965
|
|
|
|
|
|
|
|
|
966
|
|
|
|
|
|
|
=for ref |
|
967
|
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
Converts an LAB color triple to an RGB color triple. |
|
969
|
|
|
|
|
|
|
|
|
970
|
|
|
|
|
|
|
The first dimension of the ndarrays holding the lab values must be size 3, i.e. the dimensions must look like (3, m, n, ...). |
|
971
|
|
|
|
|
|
|
|
|
972
|
|
|
|
|
|
|
=for bad |
|
973
|
|
|
|
|
|
|
|
|
974
|
|
|
|
|
|
|
If C encounters a bad value in any of the L, A, or B values the output ndarray will be marked as bad and the associated R, G, and B values will all be marked as bad. |
|
975
|
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
=for usage |
|
977
|
|
|
|
|
|
|
|
|
978
|
2
|
|
|
2
|
0
|
797
|
Usage: |
|
979
|
2
|
|
|
|
|
6
|
|
|
980
|
2
|
|
|
|
|
4
|
my $rgb = lab_to_rgb( $lab, 'sRGB' ); |
|
981
|
|
|
|
|
|
|
my $rgb = lab_to_rgb( $lab, \%rgb_spec ); |
|
982
|
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
=cut |
|
984
|
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
*lab_to_rgb = \&PDL::lab_to_rgb; |
|
986
|
|
|
|
|
|
|
sub PDL::lab_to_rgb { |
|
987
|
|
|
|
|
|
|
my ($lab, $space) = @_; |
|
988
|
|
|
|
|
|
|
my $spec = get_space($space); |
|
989
|
|
|
|
|
|
|
return xyz_to_rgb( lab_to_xyz( $lab, $spec ), $spec ); |
|
990
|
|
|
|
|
|
|
} |
|
991
|
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
|
|
993
|
|
|
|
|
|
|
=head2 add_rgb_space |
|
994
|
|
|
|
|
|
|
|
|
995
|
|
|
|
|
|
|
Supports adding custom RGB space definitions. The C and C |
|
996
|
|
|
|
|
|
|
can be supplied as PDL ndarrays if desired. As of 0.202, you don't need |
|
997
|
|
|
|
|
|
|
to provide an C since the inverse of the C will be calculated |
|
998
|
|
|
|
|
|
|
(once) as a default. |
|
999
|
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
Usage: |
|
1001
|
|
|
|
|
|
|
|
|
1002
|
|
|
|
|
|
|
my %custom_space = ( |
|
1003
|
|
|
|
|
|
|
custom_1 => { |
|
1004
|
|
|
|
|
|
|
'gamma' => '2.2', |
|
1005
|
|
|
|
|
|
|
'm' => [ |
|
1006
|
|
|
|
|
|
|
[ |
|
1007
|
|
|
|
|
|
|
'0.467384242424242', |
|
1008
|
|
|
|
|
|
|
'0.240995', |
|
1009
|
|
|
|
|
|
|
'0.0219086363636363' |
|
1010
|
|
|
|
|
|
|
], |
|
1011
|
|
|
|
|
|
|
[ |
|
1012
|
|
|
|
|
|
|
'0.294454030769231', |
|
1013
|
|
|
|
|
|
|
'0.683554', |
|
1014
|
|
|
|
|
|
|
'0.0736135076923076' |
|
1015
|
|
|
|
|
|
|
], |
|
1016
|
|
|
|
|
|
|
[ |
|
1017
|
|
|
|
|
|
|
'0.18863', |
|
1018
|
|
|
|
|
|
|
'0.075452', |
|
1019
|
|
|
|
|
|
|
'0.993451333333334' |
|
1020
|
|
|
|
|
|
|
] |
|
1021
|
|
|
|
|
|
|
], |
|
1022
|
|
|
|
|
|
|
'white_point' => [ |
|
1023
|
|
|
|
|
|
|
'0.312713', |
|
1024
|
|
|
|
|
|
|
'0.329016' |
|
1025
|
|
|
|
|
|
|
], |
|
1026
|
|
|
|
|
|
|
}, |
|
1027
|
|
|
|
|
|
|
custom_2 => { ... }, |
|
1028
|
|
|
|
|
|
|
); |
|
1029
|
|
|
|
|
|
|
|
|
1030
|
|
|
|
|
|
|
add_rgb_space( \%custom_space ); |
|
1031
|
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
my $rgb = lch_to_rgb( $lch, 'custom_1' ); |
|
1033
|
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
=cut |
|
1035
|
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
*add_rgb_space = \&PDL::Graphics::ColorSpace::RGBSpace::add_rgb_space; |
|
1037
|
|
|
|
|
|
|
*get_space = \&PDL::Graphics::ColorSpace::RGBSpace::get_space; |
|
1038
|
|
|
|
|
|
|
|
|
1039
|
|
|
|
|
|
|
|
|
1040
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
1041
|
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
Graphics::ColorObject |
|
1043
|
|
|
|
|
|
|
|
|
1044
|
|
|
|
|
|
|
=head1 AUTHOR |
|
1045
|
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
~~~~~~~~~~~~ ~~~~~ ~~~~~~~~ ~~~~~ ~~~ `` ><((("> |
|
1047
|
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
Copyright (C) 2012 Maggie J. Xiong |
|
1049
|
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
Original work sponsored by Shutterstock, LLC L |
|
1051
|
|
|
|
|
|
|
|
|
1052
|
|
|
|
|
|
|
All rights reserved. There is no warranty. You are allowed to redistribute this software / documentation as described in the file COPYING in the PDL distribution. |
|
1053
|
|
|
|
|
|
|
|
|
1054
|
|
|
|
|
|
|
=cut |
|
1055
|
|
|
|
|
|
|
|
|
1056
|
|
|
|
|
|
|
EOD |
|
1057
|
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
pp_done(); |