• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 #include "MagickCore/pixel-accessor.h"
22 #include "MagickCore/visual-effects.h"
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
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 
50 extern MagickPrivate double
51   GenerateDifferentialNoise(RandomInfo *,const Quantum,const NoiseType,
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 
ConvertAdobe98ToXYZ(const double red,const double green,const double blue,double * X,double * Y,double * Z)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);
109   r=QuantumScale*DecodePixelGamma(red);
110   g=QuantumScale*DecodePixelGamma(green);
111   b=QuantumScale*DecodePixelGamma(blue);
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 
ConvertDisplayP3ToXYZ(const double red,const double green,const double blue,double * X,double * Y,double * Z)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);
131   r=QuantumScale*DecodePixelGamma(red);
132   g=QuantumScale*DecodePixelGamma(green);
133   b=QuantumScale*DecodePixelGamma(blue);
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 
ConvertLabToXYZ(const double L,const double a,const double b,const IlluminantType illuminant,double * X,double * Y,double * Z)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 
ConvertLuvToXYZ(const double L,const double u,const double v,const IlluminantType illuminant,double * X,double * Y,double * Z)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 
ConvertProPhotoToXYZ(const double red,const double green,const double blue,double * X,double * Y,double * Z)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);
214   r=QuantumScale*DecodePixelGamma(red);
215   g=QuantumScale*DecodePixelGamma(green);
216   b=QuantumScale*DecodePixelGamma(blue);
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 
ConvertRGBToXYZ(const double red,const double green,const double blue,double * X,double * Y,double * Z)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);
236   r=QuantumScale*DecodePixelGamma(red);
237   g=QuantumScale*DecodePixelGamma(green);
238   b=QuantumScale*DecodePixelGamma(blue);
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 
ConvertXYZToAdobe98(const double X,const double Y,const double Z,double * red,double * green,double * blue)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;
258   *red=EncodePixelGamma(QuantumRange*r);
259   *green=EncodePixelGamma(QuantumRange*g);
260   *blue=EncodePixelGamma(QuantumRange*b);
261 }
262 
ConvertXYZToDisplayP3(const double X,const double Y,const double Z,double * red,double * green,double * blue)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;
277   *red=EncodePixelGamma(QuantumRange*r);
278   *green=EncodePixelGamma(QuantumRange*g);
279   *blue=EncodePixelGamma(QuantumRange*b);
280 }
281 
ConvertXYZToLab(const double X,const double Y,const double Z,const IlluminantType illuminant,double * L,double * a,double * b)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 
ConvertXYZToLuv(const double X,const double Y,const double Z,const IlluminantType illuminant,double * L,double * u,double * v)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 
ConvertXYZToProPhoto(const double X,const double Y,const double Z,double * red,double * green,double * blue)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;
352   *red=EncodePixelGamma(QuantumRange*r);
353   *green=EncodePixelGamma(QuantumRange*g);
354   *blue=EncodePixelGamma(QuantumRange*b);
355 }
356 
ConvertXYZToRGB(const double X,const double Y,const double Z,double * red,double * green,double * blue)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;
371   *red=EncodePixelGamma(QuantumRange*r);
372   *green=EncodePixelGamma(QuantumRange*g);
373   *blue=EncodePixelGamma(QuantumRange*b);
374 }
375 
376 #if defined(__cplusplus) || defined(c_plusplus)
377 }
378 #endif
379 
380 #endif
381