18#ifndef MAGICKCORE_GEM_PRIVATE_H
19#define MAGICKCORE_GEM_PRIVATE_H
21#include "MagickCore/pixel-accessor.h"
22#include "MagickCore/visual-effects.h"
24#if defined(__cplusplus) || defined(c_plusplus)
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)
35 illuminant_tristimulus[] =
37 { 1.09850, 1.00000, 0.35585 },
38 { 0.99072, 1.00000, 0.85223 },
39 { 0.98074, 1.00000, 1.18232 },
40 { 0.96422, 1.00000, 0.82521 },
41 { 0.95682, 1.00000, 0.92149 },
42 { 0.95047, 1.00000, 1.08883 },
43 { 0.94972, 1.00000, 1.22638 },
44 { 1.00000, 1.00000, 1.00000 },
45 { 0.99186, 1.00000, 0.67393 },
46 { 0.95041, 1.00000, 1.08747 },
47 { 1.00962, 1.00000, 0.64350 }
50extern MagickPrivate
double
51 GenerateDifferentialNoise(
RandomInfo *,
const Quantum,
const NoiseType,
54extern MagickPrivate
size_t
55 GetOptimalKernelWidth(
const double,
const double),
56 GetOptimalKernelWidth1D(
const double,
const double),
57 GetOptimalKernelWidth2D(
const double,
const double);
59extern MagickPrivate
void
60 ConvertHCLToRGB(
const double,
const double,
const double,
double *,
double *,
62 ConvertHCLpToRGB(
const double,
const double,
const double,
double *,
double *,
64 ConvertHSBToRGB(
const double,
const double,
const double,
double *,
double *,
66 ConvertHSIToRGB(
const double,
const double,
const double,
double *,
double *,
68 ConvertHSVToRGB(
const double,
const double,
const double,
double *,
double *,
70 ConvertHWBToRGB(
const double,
const double,
const double,
double *,
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 *,
78 ConvertRGBToHCLp(
const double,
const double,
const double,
double *,
double *,
80 ConvertRGBToHSB(
const double,
const double,
const double,
double *,
double *,
82 ConvertRGBToHSI(
const double,
const double,
const double,
double *,
double *,
84 ConvertRGBToHSV(
const double,
const double,
const double,
double *,
double *,
86 ConvertRGBToHWB(
const double,
const double,
const double,
double *,
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 *);
95static inline void ConvertAdobe98ToXYZ(
const double red,
const double green,
96 const double blue,
double *X,
double *Y,
double *Z)
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;
114static inline void ConvertDisplayP3ToXYZ(
const double red,
const double green,
115 const double blue,
double *X,
double *Y,
double *Z)
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;
133static inline void ConvertLabToXYZ(
const double L,
const double a,
const double b,
134 const IlluminantType illuminant,
double *X,
double *Y,
double *Z)
144 if ((x*x*x) > CIEEpsilon)
147 x=(116.0*x-16.0)/CIEK;
148 if (L > (CIEK*CIEEpsilon))
152 if ((z*z*z) > CIEEpsilon)
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;
161static inline void ConvertLuvToXYZ(
const double L,
const double u,
const double v,
162 const IlluminantType illuminant,
double *X,
double *Y,
double *Z)
167 if (L > (CIEK*CIEEpsilon))
168 *Y=(double) pow((L+16.0)/116.0,3.0);
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);
188static inline void ConvertProPhotoToXYZ(
const double red,
const double green,
189 const double blue,
double *X,
double *Y,
double *Z)
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;
208static inline void ConvertRGBToXYZ(
const double red,
const double green,
209 const double blue,
double *X,
double *Y,
double *Z)
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;
227static inline void ConvertXYZToAdobe98(
const double X,
const double Y,
228 const double Z,
double *red,
double *green,
double *blue)
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);
243static inline void ConvertXYZToDisplayP3(
const double X,
const double Y,
244 const double Z,
double *red,
double *green,
double *blue)
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);
259static inline void ConvertXYZToLab(
const double X,
const double Y,
const double Z,
260 const IlluminantType illuminant,
double *L,
double *a,
double *b)
267 if ((X/illuminant_tristimulus[illuminant].x) > CIEEpsilon)
268 x=pow(X/illuminant_tristimulus[illuminant].x,1.0/3.0);
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);
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);
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;
284static inline void ConvertXYZToLuv(
const double X,
const double Y,
const double Z,
285 const IlluminantType illuminant,
double *L,
double *u,
double *v)
290 if ((Y/illuminant_tristimulus[illuminant].y) > CIEEpsilon)
291 *L=(double) (116.0*pow(Y/illuminant_tristimulus[illuminant].y,
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)));
309static inline void ConvertXYZToProPhoto(
const double X,
const double Y,
310 const double Z,
double *red,
double *green,
double *blue)
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);
325static inline void ConvertXYZToRGB(
const double X,
const double Y,
const double Z,
326 double *red,
double *green,
double *blue)
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);
341#if defined(__cplusplus) || defined(c_plusplus)