MagickCore  7.1.0
gem-private.h
Go to the documentation of this file.
1 /*
2  Copyright 1999-2021 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 
23 
24 #if defined(__cplusplus) || defined(c_plusplus)
25 extern "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 
34 static const PrimaryInfo
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 
50 extern MagickPrivate double
52  const double);
53 
54 extern MagickPrivate size_t
55  GetOptimalKernelWidth(const double,const double),
56  GetOptimalKernelWidth1D(const double,const double),
57  GetOptimalKernelWidth2D(const double,const double);
58 
59 extern 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 
95 static 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  assert(X != (double *) NULL);
107  assert(Y != (double *) NULL);
108  assert(Z != (double *) NULL);
112  *X=0.57666904291013050*r+0.18555823790654630*g+0.18822864623499470*b;
113  *Y=0.29734497525053605*r+0.62736356625546610*g+0.07529145849399788*b;
114  *Z=0.02703136138641234*r+0.07068885253582723*g+0.99133753683763880*b;
115 }
116 
117 static inline void ConvertDisplayP3ToXYZ(const double red,const double green,
118  const double blue,double *X,double *Y,double *Z)
119 {
120  double
121  b,
122  g,
123  r;
124 
125  /*
126  Convert Display P3 to XYZ colorspace.
127  */
128  assert(X != (double *) NULL);
129  assert(Y != (double *) NULL);
130  assert(Z != (double *) NULL);
134  *X=0.4865709486482162*r+0.26566769316909306*g+0.1982172852343625*b;
135  *Y=0.2289745640697488*r+0.69173852183650640*g+0.0792869140937450*b;
136  *Z=0.0000000000000000*r+0.04511338185890264*g+1.0439443689009760*b;
137 }
138 
139 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
140  const IlluminantType illuminant,double *X,double *Y,double *Z)
141 {
142  double
143  x,
144  y,
145  z;
146 
147  assert(X != (double *) NULL);
148  assert(Y != (double *) NULL);
149  assert(Z != (double *) NULL);
150  y=(L+16.0)/116.0;
151  x=y+a/500.0;
152  z=y-b/200.0;
153  if ((x*x*x) > CIEEpsilon)
154  x=(x*x*x);
155  else
156  x=(116.0*x-16.0)/CIEK;
157  if (L > (CIEK*CIEEpsilon))
158  y=(y*y*y);
159  else
160  y=L/CIEK;
161  if ((z*z*z) > CIEEpsilon)
162  z=(z*z*z);
163  else
164  z=(116.0*z-16.0)/CIEK;
165  *X=illuminant_tristimulus[illuminant].x*x;
166  *Y=illuminant_tristimulus[illuminant].y*y;
167  *Z=illuminant_tristimulus[illuminant].z*z;
168 }
169 
170 static inline void ConvertLuvToXYZ(const double L,const double u,const double v,
171  const IlluminantType illuminant,double *X,double *Y,double *Z)
172 {
173  double
174  gamma;
175 
176  assert(X != (double *) NULL);
177  assert(Y != (double *) NULL);
178  assert(Z != (double *) NULL);
179  if (L > (CIEK*CIEEpsilon))
180  *Y=(double) pow((L+16.0)/116.0,3.0);
181  else
182  *Y=L/CIEK;
183  gamma=PerceptibleReciprocal((((52.0*L*PerceptibleReciprocal(u+13.0*L*
184  (4.0*illuminant_tristimulus[illuminant].x/
185  (illuminant_tristimulus[illuminant].x+15.0*
186  illuminant_tristimulus[illuminant].y+3.0*
187  illuminant_tristimulus[illuminant].z))))-1.0)/3.0)-(-1.0/3.0));
188  *X=gamma*((*Y*((39.0*L*PerceptibleReciprocal(v+13.0*L*(9.0*
189  illuminant_tristimulus[illuminant].y/
190  (illuminant_tristimulus[illuminant].x+15.0*
191  illuminant_tristimulus[illuminant].y+3.0*
192  illuminant_tristimulus[illuminant].z))))-5.0))+5.0*(*Y));
193  *Z=(*X*(((52.0*L*PerceptibleReciprocal(u+13.0*L*(4.0*
194  illuminant_tristimulus[illuminant].x/
195  (illuminant_tristimulus[illuminant].x+15.0*
196  illuminant_tristimulus[illuminant].y+3.0*
197  illuminant_tristimulus[illuminant].z))))-1.0)/3.0))-5.0*(*Y);
198 }
199 
200 static inline void ConvertProPhotoToXYZ(const double red,const double green,
201  const double blue,double *X,double *Y,double *Z)
202 {
203  double
204  b,
205  g,
206  r;
207 
208  /*
209  Convert ProPhoto to XYZ colorspace.
210  */
211  assert(X != (double *) NULL);
212  assert(Y != (double *) NULL);
213  assert(Z != (double *) NULL);
217  *X=0.7977604896723027*r+0.13518583717574031*g+0.03134934958152480000*b;
218  *Y=0.2880711282292934*r+0.71184321781010140*g+0.00008565396060525902*b;
219  *Z=0.0000000000000000*r+0.00000000000000000*g+0.82510460251046010000*b;
220 }
221 
222 static inline void ConvertRGBToXYZ(const double red,const double green,
223  const double blue,double *X,double *Y,double *Z)
224 {
225  double
226  b,
227  g,
228  r;
229 
230  /*
231  Convert RGB to XYZ colorspace.
232  */
233  assert(X != (double *) NULL);
234  assert(Y != (double *) NULL);
235  assert(Z != (double *) NULL);
239  *X=0.4124564*r+0.3575761*g+0.1804375*b;
240  *Y=0.2126729*r+0.7151522*g+0.0721750*b;
241  *Z=0.0193339*r+0.1191920*g+0.9503041*b;
242 }
243 
244 static inline void ConvertXYZToAdobe98(const double X,const double Y,
245  const double Z,double *red,double *green,double *blue)
246 {
247  double
248  b,
249  g,
250  r;
251 
252  assert(red != (double *) NULL);
253  assert(green != (double *) NULL);
254  assert(blue != (double *) NULL);
255  r=2.041587903810746500*X-0.56500697427885960*Y-0.34473135077832956*Z;
256  g=(-0.969243636280879500)*X+1.87596750150772020*Y+0.04155505740717557*Z;
257  b=0.013444280632031142*X-0.11836239223101838*Y+1.01517499439120540*Z;
259  *green=EncodePixelGamma(QuantumRange*g);
261 }
262 
263 static inline void ConvertXYZToDisplayP3(const double X,const double Y,
264  const double Z,double *red,double *green,double *blue)
265 {
266  double
267  b,
268  g,
269  r;
270 
271  assert(red != (double *) NULL);
272  assert(green != (double *) NULL);
273  assert(blue != (double *) NULL);
274  r=2.49349691194142500*X-0.93138361791912390*Y-0.402710784450716840*Z;
275  g=(-0.82948896956157470)*X+1.76266406031834630*Y+0.023624685841943577*Z;
276  b=0.03584583024378447*X-0.07617238926804182*Y+0.956884524007687200*Z;
278  *green=EncodePixelGamma(QuantumRange*g);
280 }
281 
282 static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
283  const IlluminantType illuminant,double *L,double *a,double *b)
284 {
285  double
286  x,
287  y,
288  z;
289 
290  assert(L != (double *) NULL);
291  assert(a != (double *) NULL);
292  assert(b != (double *) NULL);
293  if ((X/illuminant_tristimulus[illuminant].x) > CIEEpsilon)
294  x=pow(X/illuminant_tristimulus[illuminant].x,1.0/3.0);
295  else
296  x=(CIEK*X/illuminant_tristimulus[illuminant].x+16.0)/116.0;
297  if ((Y/illuminant_tristimulus[illuminant].y) > CIEEpsilon)
298  y=pow(Y/illuminant_tristimulus[illuminant].y,1.0/3.0);
299  else
300  y=(CIEK*Y/illuminant_tristimulus[illuminant].y+16.0)/116.0;
301  if ((Z/illuminant_tristimulus[illuminant].z) > CIEEpsilon)
302  z=pow(Z/illuminant_tristimulus[illuminant].z,1.0/3.0);
303  else
304  z=(CIEK*Z/illuminant_tristimulus[illuminant].z+16.0)/116.0;
305  *L=((116.0*y)-16.0)/100.0;
306  *a=(500.0*(x-y))/255.0+0.5;
307  *b=(200.0*(y-z))/255.0+0.5;
308 }
309 
310 static inline void ConvertXYZToLuv(const double X,const double Y,const double Z,
311  const IlluminantType illuminant,double *L,double *u,double *v)
312 {
313  double
314  alpha;
315 
316  assert(L != (double *) NULL);
317  assert(u != (double *) NULL);
318  assert(v != (double *) NULL);
319  if ((Y/illuminant_tristimulus[illuminant].y) > CIEEpsilon)
320  *L=(double) (116.0*pow(Y/illuminant_tristimulus[illuminant].y,
321  1.0/3.0)-16.0);
322  else
323  *L=CIEK*(Y/illuminant_tristimulus[illuminant].y);
324  alpha=PerceptibleReciprocal(X+15.0*Y+3.0*Z);
325  *u=13.0*(*L)*((4.0*alpha*X)-(4.0*illuminant_tristimulus[illuminant].x/
326  (illuminant_tristimulus[illuminant].x+15.0*
327  illuminant_tristimulus[illuminant].y+3.0*
328  illuminant_tristimulus[illuminant].z)));
329  *v=13.0*(*L)*((9.0*alpha*Y)-(9.0*illuminant_tristimulus[illuminant].y/
330  (illuminant_tristimulus[illuminant].x+15.0*
331  illuminant_tristimulus[illuminant].y+3.0*
332  illuminant_tristimulus[illuminant].z)));
333  *L/=100.0;
334  *u=(*u+134.0)/354.0;
335  *v=(*v+140.0)/262.0;
336 }
337 
338 static inline void ConvertXYZToProPhoto(const double X,const double Y,
339  const double Z,double *red,double *green,double *blue)
340 {
341  double
342  b,
343  g,
344  r;
345 
346  assert(red != (double *) NULL);
347  assert(green != (double *) NULL);
348  assert(blue != (double *) NULL);
349  r=1.3457989731028281*X-0.25558010007997534*Y-0.05110628506753401*Z;
350  g=(-0.5446224939028347)*X+1.50823274131327810*Y+0.02053603239147973*Z;
351  b=0.0000000000000000*X+0.0000000000000000*Y+1.21196754563894540*Z;
353  *green=EncodePixelGamma(QuantumRange*g);
355 }
356 
357 static inline void ConvertXYZToRGB(const double X,const double Y,const double Z,
358  double *red,double *green,double *blue)
359 {
360  double
361  b,
362  g,
363  r;
364 
365  assert(red != (double *) NULL);
366  assert(green != (double *) NULL);
367  assert(blue != (double *) NULL);
368  r=3.2404542*X-1.5371385*Y-0.4985314*Z;
369  g=(-0.9692660)*X+1.8760108*Y+0.0415560*Z;
370  b=0.0556434*X-0.2040259*Y+1.0572252*Z;
372  *green=EncodePixelGamma(QuantumRange*g);
374 }
375 
376 #if defined(__cplusplus) || defined(c_plusplus)
377 }
378 #endif
379 
380 #endif
MagickExport MagickRealType EncodePixelGamma(const MagickRealType pixel)
Definition: pixel.c:446
static void ConvertXYZToDisplayP3(const double X, const double Y, const double Z, double *red, double *green, double *blue)
Definition: gem-private.h:263
MagickPrivate void ConvertHSIToRGB(const double, const double, const double, double *, double *, double *)
static void ConvertXYZToLuv(const double X, const double Y, const double Z, const IlluminantType illuminant, double *L, double *u, double *v)
Definition: gem-private.h:310
#define CIEK
Definition: gem-private.h:32
static void ConvertProPhotoToXYZ(const double red, const double green, const double blue, double *X, double *Y, double *Z)
Definition: gem-private.h:200
MagickPrivate void ConvertLCHuvToRGB(const double, const double, const double, const IlluminantType, double *, double *, double *)
double x
Definition: image.h:99
static void ConvertXYZToAdobe98(const double X, const double Y, const double Z, double *red, double *green, double *blue)
Definition: gem-private.h:244
#define CIEEpsilon
Definition: gem-private.h:31
MagickPrivate void ConvertRGBToLCHuv(const double, const double, const double, const IlluminantType, double *, double *, double *)
Definition: gem.c:1424
MagickPrivate double GenerateDifferentialNoise(RandomInfo *, const Quantum, const NoiseType, const double)
Definition: gem.c:1505
static void ConvertAdobe98ToXYZ(const double red, const double green, const double blue, double *X, double *Y, double *Z)
Definition: gem-private.h:95
double z
Definition: image.h:99
MagickPrivate size_t GetOptimalKernelWidth1D(const double, const double)
NoiseType
static const PrimaryInfo illuminant_tristimulus[]
Definition: gem-private.h:35
MagickPrivate void ConvertRGBToHSB(const double, const double, const double, double *, double *, double *)
MagickExport MagickRealType DecodePixelGamma(const MagickRealType pixel)
Definition: pixel.c:319
MagickPrivate void ConvertLCHabToRGB(const double, const double, const double, const IlluminantType, double *, double *, double *)
static double PerceptibleReciprocal(const double x)
MagickPrivate size_t GetOptimalKernelWidth2D(const double, const double)
Definition: gem.c:1685
static void ConvertXYZToProPhoto(const double X, const double Y, const double Z, double *red, double *green, double *blue)
Definition: gem-private.h:338
MagickPrivate void ConvertRGBToHSV(const double, const double, const double, double *, double *, double *)
static void ConvertXYZToLab(const double X, const double Y, const double Z, const IlluminantType illuminant, double *L, double *a, double *b)
Definition: gem-private.h:282
static void ConvertDisplayP3ToXYZ(const double red, const double green, const double blue, double *X, double *Y, double *Z)
Definition: gem-private.h:117
MagickPrivate void ConvertRGBToHSI(const double, const double, const double, double *, double *, double *)
MagickPrivate void ConvertRGBToLab(const double, const double, const double, const IlluminantType, double *, double *, double *)
static void ConvertLabToXYZ(const double L, const double a, const double b, const IlluminantType illuminant, double *X, double *Y, double *Z)
Definition: gem-private.h:139
#define QuantumScale
Definition: magick-type.h:119
IlluminantType
Definition: color.h:40
double y
Definition: image.h:99
static void ConvertLuvToXYZ(const double L, const double u, const double v, const IlluminantType illuminant, double *X, double *Y, double *Z)
Definition: gem-private.h:170
MagickPrivate void ConvertHWBToRGB(const double, const double, const double, double *, double *, double *)
static void ConvertRGBToXYZ(const double red, const double green, const double blue, double *X, double *Y, double *Z)
Definition: gem-private.h:222
unsigned short Quantum
Definition: magick-type.h:86
MagickPrivate void ConvertHSVToRGB(const double, const double, const double, double *, double *, double *)
MagickPrivate size_t GetOptimalKernelWidth(const double, const double)
MagickPrivate void ConvertHCLToRGB(const double, const double, const double, double *, double *, double *)
MagickPrivate void ConvertRGBToHWB(const double, const double, const double, double *, double *, double *)
MagickPrivate void ConvertHCLpToRGB(const double, const double, const double, double *, double *, double *)
static void ConvertXYZToRGB(const double X, const double Y, const double Z, double *red, double *green, double *blue)
Definition: gem-private.h:357
#define MagickPrivate
MagickPrivate void ConvertHSBToRGB(const double, const double, const double, double *, double *, double *)
MagickPrivate void ConvertRGBToHCL(const double, const double, const double, double *, double *, double *)
MagickPrivate void ConvertRGBToLCHab(const double, const double, const double, const IlluminantType, double *, double *, double *)
#define QuantumRange
Definition: magick-type.h:87
MagickPrivate void ConvertRGBToHCLp(const double, const double, const double, double *, double *, double *)