1/*
2  Copyright 1999-2016 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.
6  obtain a copy of the License at
7
8    http://www.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
23#if defined(__cplusplus) || defined(c_plusplus)
24extern "C" {
25#endif
26
27#define D65X  0.950456
28#define D65Y  1.0
29#define D65Z  1.088754
30#define CIEEpsilon  (216.0/24389.0)
31#define CIEK  (24389.0/27.0)
32
33extern MagickPrivate double
34  GenerateDifferentialNoise(RandomInfo *,const Quantum,const NoiseType,
35    const double);
36
37extern MagickPrivate size_t
38  GetOptimalKernelWidth(const double,const double),
39  GetOptimalKernelWidth1D(const double,const double),
40  GetOptimalKernelWidth2D(const double,const double);
41
42extern MagickPrivate void
43  ConvertHCLToRGB(const double,const double,const double,double *,double *,
44    double *),
45  ConvertHCLpToRGB(const double,const double,const double,double *,double *,
46    double *),
47  ConvertHSBToRGB(const double,const double,const double,double *,double *,
48    double *),
49  ConvertHSIToRGB(const double,const double,const double,double *,double *,
50    double *),
51  ConvertHSVToRGB(const double,const double,const double,double *,double *,
52    double *),
53  ConvertHWBToRGB(const double,const double,const double,double *,double *,
54    double *),
55  ConvertLCHabToRGB(const double,const double,const double,double *,double *,
56    double *),
57  ConvertLCHuvToRGB(const double,const double,const double,double *,double *,
58    double *),
59  ConvertRGBToHCL(const double,const double,const double,double *,double *,
60    double *),
61  ConvertRGBToHCLp(const double,const double,const double,double *,double *,
62    double *),
63  ConvertRGBToHSB(const double,const double,const double,double *,double *,
64    double *),
65  ConvertRGBToHSI(const double,const double,const double,double *,double *,
66    double *),
67  ConvertRGBToHSV(const double,const double,const double,double *,double *,
68    double *),
69  ConvertRGBToHWB(const double,const double,const double,double *,double *,
70    double *),
71  ConvertRGBToLCHab(const double,const double,const double,double *,double *,
72    double *),
73  ConvertRGBToLCHuv(const double,const double,const double,double *,double *,
74    double *);
75
76static inline void ConvertLabToXYZ(const double L,const double a,const double b,
77  double *X,double *Y,double *Z)
78{
79  double
80    x,
81    y,
82    z;
83
84  assert(X != (double *) NULL);
85  assert(Y != (double *) NULL);
86  assert(Z != (double *) NULL);
87  y=(L+16.0)/116.0;
88  x=y+a/500.0;
89  z=y-b/200.0;
90  if ((x*x*x) > CIEEpsilon)
91    x=(x*x*x);
92  else
93    x=(116.0*x-16.0)/CIEK;
94  if ((y*y*y) > CIEEpsilon)
95    y=(y*y*y);
96  else
97    y=L/CIEK;
98  if ((z*z*z) > CIEEpsilon)
99    z=(z*z*z);
100  else
101    z=(116.0*z-16.0)/CIEK;
102  *X=D65X*x;
103  *Y=D65Y*y;
104  *Z=D65Z*z;
105}
106
107static inline void ConvertLuvToXYZ(const double L,const double u,const double v,
108  double *X,double *Y,double *Z)
109{
110  assert(X != (double *) NULL);
111  assert(Y != (double *) NULL);
112  assert(Z != (double *) NULL);
113  if (L > (CIEK*CIEEpsilon))
114    *Y=(double) pow((L+16.0)/116.0,3.0);
115  else
116    *Y=L/CIEK;
117  *X=((*Y*((39.0*L/(v+13.0*L*(9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z))))-5.0))+
118    5.0*(*Y))/((((52.0*L/(u+13.0*L*(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))))-1.0)/
119    3.0)-(-1.0/3.0));
120  *Z=(*X*(((52.0*L/(u+13.0*L*(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))))-1.0)/3.0))-
121    5.0*(*Y);
122}
123
124static inline void ConvertRGBToXYZ(const double red,const double green,
125  const double blue,double *X,double *Y,double *Z)
126{
127  double
128    b,
129    g,
130    r;
131
132  /*
133    Convert RGB to XYZ colorspace.
134  */
135  assert(X != (double *) NULL);
136  assert(Y != (double *) NULL);
137  assert(Z != (double *) NULL);
138  r=QuantumScale*DecodePixelGamma(red);
139  g=QuantumScale*DecodePixelGamma(green);
140  b=QuantumScale*DecodePixelGamma(blue);
141  *X=0.4124564*r+0.3575761*g+0.1804375*b;
142  *Y=0.2126729*r+0.7151522*g+0.0721750*b;
143  *Z=0.0193339*r+0.1191920*g+0.9503041*b;
144}
145
146static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
147  double *L,double *a,double *b)
148{
149  double
150    x,
151    y,
152    z;
153
154  assert(L != (double *) NULL);
155  assert(a != (double *) NULL);
156  assert(b != (double *) NULL);
157  if ((X/D65X) > CIEEpsilon)
158    x=pow(X/D65X,1.0/3.0);
159  else
160    x=(CIEK*X/D65X+16.0)/116.0;
161  if ((Y/D65Y) > CIEEpsilon)
162    y=pow(Y/D65Y,1.0/3.0);
163  else
164    y=(CIEK*Y/D65Y+16.0)/116.0;
165  if ((Z/D65Z) > CIEEpsilon)
166    z=pow(Z/D65Z,1.0/3.0);
167  else
168    z=(CIEK*Z/D65Z+16.0)/116.0;
169  *L=((116.0*y)-16.0)/100.0;
170  *a=(500.0*(x-y))/255.0+0.5;
171  *b=(200.0*(y-z))/255.0+0.5;
172}
173
174static inline void ConvertXYZToLuv(const double X,const double Y,const double Z,
175  double *L,double *u,double *v)
176{
177  double
178    alpha;
179
180  assert(L != (double *) NULL);
181  assert(u != (double *) NULL);
182  assert(v != (double *) NULL);
183  if ((Y/D65Y) > CIEEpsilon)
184    *L=(double) (116.0*pow(Y/D65Y,1.0/3.0)-16.0);
185  else
186    *L=CIEK*(Y/D65Y);
187  alpha=PerceptibleReciprocal(X+15.0*Y+3.0*Z);
188  *u=13.0*(*L)*((4.0*alpha*X)-(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z)));
189  *v=13.0*(*L)*((9.0*alpha*Y)-(9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z)));
190  *L/=100.0;
191  *u=(*u+134.0)/354.0;
192  *v=(*v+140.0)/262.0;
193}
194
195static inline void ConvertXYZToRGB(const double X,const double Y,const double Z,
196  double *red,double *green,double *blue)
197{
198  double
199    b,
200    g,
201    r;
202
203  assert(red != (double *) NULL);
204  assert(green != (double *) NULL);
205  assert(blue != (double *) NULL);
206  r=3.2404542*X-1.5371385*Y-0.4985314*Z;
207  g=(-0.9692660)*X+1.8760108*Y+0.0415560*Z;
208  b=0.0556434*X-0.2040259*Y+1.0572252*Z;
209  *red=EncodePixelGamma(QuantumRange*r);
210  *green=EncodePixelGamma(QuantumRange*g);
211  *blue=EncodePixelGamma(QuantumRange*b);
212}
213
214#if defined(__cplusplus) || defined(c_plusplus)
215}
216#endif
217
218#endif
219