MagickCore 7.1.1
Convert, Edit, Or Compose Bitmap Images
Loading...
Searching...
No Matches
gem-private.h
1/*
2 Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization
3 dedicated to making software imaging solutions freely available.
4
5 You may not use this file except in compliance with the License. You may
6 obtain a copy of the License at
7
8 https://imagemagick.org/script/license.php
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15
16 MagickCore private graphic gems methods.
17*/
18#ifndef MAGICKCORE_GEM_PRIVATE_H
19#define MAGICKCORE_GEM_PRIVATE_H
20
21#include "MagickCore/pixel-accessor.h"
22#include "MagickCore/visual-effects.h"
23
24#if defined(__cplusplus) || defined(c_plusplus)
25extern "C" {
26#endif
27
28#define IlluminantX 0.95047
29#define IlluminantY 1.0
30#define IlluminantZ 1.08883
31#define CIEEpsilon (216.0/24389.0)
32#define CIEK (24389.0/27.0)
33
34static const PrimaryInfo
35 illuminant_tristimulus[] =
36 {
37 { 1.09850, 1.00000, 0.35585 }, /* A */
38 { 0.99072, 1.00000, 0.85223 }, /* B */
39 { 0.98074, 1.00000, 1.18232 }, /* C */
40 { 0.96422, 1.00000, 0.82521 }, /* D50 */
41 { 0.95682, 1.00000, 0.92149 }, /* D55 */
42 { 0.95047, 1.00000, 1.08883 }, /* D65 */
43 { 0.94972, 1.00000, 1.22638 }, /* D75 */
44 { 1.00000, 1.00000, 1.00000 }, /* E */
45 { 0.99186, 1.00000, 0.67393 }, /* F2 */
46 { 0.95041, 1.00000, 1.08747 }, /* F7 */
47 { 1.00962, 1.00000, 0.64350 } /* F11 */
48 };
49
50extern MagickPrivate double
51 GenerateDifferentialNoise(RandomInfo *,const Quantum,const NoiseType,
52 const double);
53
54extern MagickPrivate size_t
55 GetOptimalKernelWidth(const double,const double),
56 GetOptimalKernelWidth1D(const double,const double),
57 GetOptimalKernelWidth2D(const double,const double);
58
59extern MagickPrivate void
60 ConvertHCLToRGB(const double,const double,const double,double *,double *,
61 double *),
62 ConvertHCLpToRGB(const double,const double,const double,double *,double *,
63 double *),
64 ConvertHSBToRGB(const double,const double,const double,double *,double *,
65 double *),
66 ConvertHSIToRGB(const double,const double,const double,double *,double *,
67 double *),
68 ConvertHSVToRGB(const double,const double,const double,double *,double *,
69 double *),
70 ConvertHWBToRGB(const double,const double,const double,double *,double *,
71 double *),
72 ConvertLCHabToRGB(const double,const double,const double,const IlluminantType,
73 double *,double *,double *),
74 ConvertLCHuvToRGB(const double,const double,const double,const IlluminantType,
75 double *,double *,double *),
76 ConvertRGBToHCL(const double,const double,const double,double *,double *,
77 double *),
78 ConvertRGBToHCLp(const double,const double,const double,double *,double *,
79 double *),
80 ConvertRGBToHSB(const double,const double,const double,double *,double *,
81 double *),
82 ConvertRGBToHSI(const double,const double,const double,double *,double *,
83 double *),
84 ConvertRGBToHSV(const double,const double,const double,double *,double *,
85 double *),
86 ConvertRGBToHWB(const double,const double,const double,double *,double *,
87 double *),
88 ConvertRGBToLab(const double,const double,const double,const IlluminantType,
89 double *,double *,double *),
90 ConvertRGBToLCHab(const double,const double,const double,const IlluminantType,
91 double *,double *,double *),
92 ConvertRGBToLCHuv(const double,const double,const double,const IlluminantType,
93 double *,double *,double *);
94
95static inline void ConvertAdobe98ToXYZ(const double red,const double green,
96 const double blue,double *X,double *Y,double *Z)
97{
98 double
99 b,
100 g,
101 r;
102
103 /*
104 Convert Adobe '98 to XYZ colorspace.
105 */
106 r=QuantumScale*DecodePixelGamma((double) QuantumRange*red);
107 g=QuantumScale*DecodePixelGamma((double) QuantumRange*green);
108 b=QuantumScale*DecodePixelGamma((double) QuantumRange*blue);
109 *X=0.57666904291013050*r+0.18555823790654630*g+0.18822864623499470*b;
110 *Y=0.29734497525053605*r+0.62736356625546610*g+0.07529145849399788*b;
111 *Z=0.02703136138641234*r+0.07068885253582723*g+0.99133753683763880*b;
112}
113
114static inline void ConvertDisplayP3ToXYZ(const double red,const double green,
115 const double blue,double *X,double *Y,double *Z)
116{
117 double
118 b,
119 g,
120 r;
121
122 /*
123 Convert Display P3 to XYZ colorspace.
124 */
125 r=QuantumScale*DecodePixelGamma((double) QuantumRange*red);
126 g=QuantumScale*DecodePixelGamma((double) QuantumRange*green);
127 b=QuantumScale*DecodePixelGamma((double) QuantumRange*blue);
128 *X=0.4865709486482162*r+0.26566769316909306*g+0.1982172852343625*b;
129 *Y=0.2289745640697488*r+0.69173852183650640*g+0.0792869140937450*b;
130 *Z=0.0000000000000000*r+0.04511338185890264*g+1.0439443689009760*b;
131}
132
133static inline void ConvertLabToXYZ(const double L,const double a,const double b,
134 const IlluminantType illuminant,double *X,double *Y,double *Z)
135{
136 double
137 x,
138 y,
139 z;
140
141 y=(L+16.0)/116.0;
142 x=y+a/500.0;
143 z=y-b/200.0;
144 if ((x*x*x) > CIEEpsilon)
145 x=(x*x*x);
146 else
147 x=(116.0*x-16.0)/CIEK;
148 if (L > (CIEK*CIEEpsilon))
149 y=(y*y*y);
150 else
151 y=L/CIEK;
152 if ((z*z*z) > CIEEpsilon)
153 z=(z*z*z);
154 else
155 z=(116.0*z-16.0)/CIEK;
156 *X=illuminant_tristimulus[illuminant].x*x;
157 *Y=illuminant_tristimulus[illuminant].y*y;
158 *Z=illuminant_tristimulus[illuminant].z*z;
159}
160
161static inline void ConvertLuvToXYZ(const double L,const double u,const double v,
162 const IlluminantType illuminant,double *X,double *Y,double *Z)
163{
164 double
165 gamma;
166
167 if (L > (CIEK*CIEEpsilon))
168 *Y=(double) pow((L+16.0)/116.0,3.0);
169 else
170 *Y=L/CIEK;
171 gamma=PerceptibleReciprocal((((52.0*L*PerceptibleReciprocal(u+13.0*L*
172 (4.0*illuminant_tristimulus[illuminant].x/
173 (illuminant_tristimulus[illuminant].x+15.0*
174 illuminant_tristimulus[illuminant].y+3.0*
175 illuminant_tristimulus[illuminant].z))))-1.0)/3.0)-(-1.0/3.0));
176 *X=gamma*((*Y*((39.0*L*PerceptibleReciprocal(v+13.0*L*(9.0*
177 illuminant_tristimulus[illuminant].y/
178 (illuminant_tristimulus[illuminant].x+15.0*
179 illuminant_tristimulus[illuminant].y+3.0*
180 illuminant_tristimulus[illuminant].z))))-5.0))+5.0*(*Y));
181 *Z=(*X*(((52.0*L*PerceptibleReciprocal(u+13.0*L*(4.0*
182 illuminant_tristimulus[illuminant].x/
183 (illuminant_tristimulus[illuminant].x+15.0*
184 illuminant_tristimulus[illuminant].y+3.0*
185 illuminant_tristimulus[illuminant].z))))-1.0)/3.0))-5.0*(*Y);
186}
187
188static inline void ConvertProPhotoToXYZ(const double red,const double green,
189 const double blue,double *X,double *Y,double *Z)
190{
191 double
192 b,
193 g,
194 r;
195
196 /*
197 Convert ProPhoto to XYZ colorspace.
198 */
199 r=QuantumScale*DecodePixelGamma((double) QuantumRange*red);
200 g=QuantumScale*DecodePixelGamma((double) QuantumRange*green);
201 b=QuantumScale*DecodePixelGamma((double) QuantumRange*blue);
202 *X=0.4865709486482162*r+0.26566769316909306*g+0.1982172852343625*b;
203 *X=0.7977604896723027*r+0.13518583717574031*g+0.03134934958152480000*b;
204 *Y=0.2880711282292934*r+0.71184321781010140*g+0.00008565396060525902*b;
205 *Z=0.0000000000000000*r+0.00000000000000000*g+0.82510460251046010000*b;
206}
207
208static inline void ConvertRGBToXYZ(const double red,const double green,
209 const double blue,double *X,double *Y,double *Z)
210{
211 double
212 b,
213 g,
214 r;
215
216 /*
217 Convert RGB to XYZ colorspace.
218 */
219 r=QuantumScale*DecodePixelGamma(red);
220 g=QuantumScale*DecodePixelGamma(green);
221 b=QuantumScale*DecodePixelGamma(blue);
222 *X=0.4124564*r+0.3575761*g+0.1804375*b;
223 *Y=0.2126729*r+0.7151522*g+0.0721750*b;
224 *Z=0.0193339*r+0.1191920*g+0.9503041*b;
225}
226
227static inline void ConvertXYZToAdobe98(const double X,const double Y,
228 const double Z,double *red,double *green,double *blue)
229{
230 double
231 b,
232 g,
233 r;
234
235 r=2.041587903810746500*X-0.56500697427885960*Y-0.34473135077832956*Z;
236 g=(-0.969243636280879500)*X+1.87596750150772020*Y+0.04155505740717557*Z;
237 b=0.013444280632031142*X-0.11836239223101838*Y+1.01517499439120540*Z;
238 *red=QuantumScale*EncodePixelGamma((double) QuantumRange*r);
239 *green=QuantumScale*EncodePixelGamma((double) QuantumRange*g);
240 *blue=QuantumScale*EncodePixelGamma((double) QuantumRange*b);
241}
242
243static inline void ConvertXYZToDisplayP3(const double X,const double Y,
244 const double Z,double *red,double *green,double *blue)
245{
246 double
247 b,
248 g,
249 r;
250
251 r=2.49349691194142500*X-0.93138361791912390*Y-0.402710784450716840*Z;
252 g=(-0.82948896956157470)*X+1.76266406031834630*Y+0.023624685841943577*Z;
253 b=0.03584583024378447*X-0.07617238926804182*Y+0.956884524007687200*Z;
254 *red=QuantumScale*EncodePixelGamma((double) QuantumRange*r);
255 *green=QuantumScale*EncodePixelGamma((double) QuantumRange*g);
256 *blue=QuantumScale*EncodePixelGamma((double) QuantumRange*b);
257}
258
259static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
260 const IlluminantType illuminant,double *L,double *a,double *b)
261{
262 double
263 x,
264 y,
265 z;
266
267 if ((X/illuminant_tristimulus[illuminant].x) > CIEEpsilon)
268 x=pow(X/illuminant_tristimulus[illuminant].x,1.0/3.0);
269 else
270 x=(CIEK*X/illuminant_tristimulus[illuminant].x+16.0)/116.0;
271 if ((Y/illuminant_tristimulus[illuminant].y) > CIEEpsilon)
272 y=pow(Y/illuminant_tristimulus[illuminant].y,1.0/3.0);
273 else
274 y=(CIEK*Y/illuminant_tristimulus[illuminant].y+16.0)/116.0;
275 if ((Z/illuminant_tristimulus[illuminant].z) > CIEEpsilon)
276 z=pow(Z/illuminant_tristimulus[illuminant].z,1.0/3.0);
277 else
278 z=(CIEK*Z/illuminant_tristimulus[illuminant].z+16.0)/116.0;
279 *L=((116.0*y)-16.0)/100.0;
280 *a=(500.0*(x-y))/255.0+0.5;
281 *b=(200.0*(y-z))/255.0+0.5;
282}
283
284static inline void ConvertXYZToLuv(const double X,const double Y,const double Z,
285 const IlluminantType illuminant,double *L,double *u,double *v)
286{
287 double
288 alpha;
289
290 if ((Y/illuminant_tristimulus[illuminant].y) > CIEEpsilon)
291 *L=(double) (116.0*pow(Y/illuminant_tristimulus[illuminant].y,
292 1.0/3.0)-16.0);
293 else
294 *L=CIEK*(Y/illuminant_tristimulus[illuminant].y);
295 alpha=PerceptibleReciprocal(X+15.0*Y+3.0*Z);
296 *u=13.0*(*L)*((4.0*alpha*X)-(4.0*illuminant_tristimulus[illuminant].x/
297 (illuminant_tristimulus[illuminant].x+15.0*
298 illuminant_tristimulus[illuminant].y+3.0*
299 illuminant_tristimulus[illuminant].z)));
300 *v=13.0*(*L)*((9.0*alpha*Y)-(9.0*illuminant_tristimulus[illuminant].y/
301 (illuminant_tristimulus[illuminant].x+15.0*
302 illuminant_tristimulus[illuminant].y+3.0*
303 illuminant_tristimulus[illuminant].z)));
304 *L/=100.0;
305 *u=(*u+134.0)/354.0;
306 *v=(*v+140.0)/262.0;
307}
308
309static inline void ConvertXYZToProPhoto(const double X,const double Y,
310 const double Z,double *red,double *green,double *blue)
311{
312 double
313 b,
314 g,
315 r;
316
317 r=1.3457989731028281*X-0.25558010007997534*Y-0.05110628506753401*Z;
318 g=(-0.5446224939028347)*X+1.50823274131327810*Y+0.02053603239147973*Z;
319 b=0.0000000000000000*X+0.0000000000000000*Y+1.21196754563894540*Z;
320 *red=QuantumScale*EncodePixelGamma((double) QuantumRange*r);
321 *green=QuantumScale*EncodePixelGamma((double) QuantumRange*g);
322 *blue=QuantumScale*EncodePixelGamma((double) QuantumRange*b);
323}
324
325static inline void ConvertXYZToRGB(const double X,const double Y,const double Z,
326 double *red,double *green,double *blue)
327{
328 double
329 b,
330 g,
331 r;
332
333 r=3.2404542*X-1.5371385*Y-0.4985314*Z;
334 g=(-0.9692660)*X+1.8760108*Y+0.0415560*Z;
335 b=0.0556434*X-0.2040259*Y+1.0572252*Z;
336 *red=EncodePixelGamma((double) QuantumRange*r);
337 *green=EncodePixelGamma((double) QuantumRange*g);
338 *blue=EncodePixelGamma((double) QuantumRange*b);
339}
340
341#if defined(__cplusplus) || defined(c_plusplus)
342}
343#endif
344
345#endif