MagickCore  6.9.13-26
Convert, Edit, Or Compose Bitmap Images
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 "magick/pixel-accessor.h"
22 #include "magick/visual-effects.h"
23 
24 #if defined(__cplusplus) || defined(c_plusplus)
25 extern "C" {
26 #endif
27 
28 #define D65X 0.95047
29 #define D65Y 1.0
30 #define D65Z 1.08883
31 #define CIEEpsilon (216.0/24389.0)
32 #define CIEK (24389.0/27.0)
33 
34 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
35  double *X,double *Y,double *Z)
36 {
37  double
38  x,
39  y,
40  z;
41 
42  assert(X != (double *) NULL);
43  assert(Y != (double *) NULL);
44  assert(Z != (double *) NULL);
45  y=(L+16.0)/116.0;
46  x=y+a/500.0;
47  z=y-b/200.0;
48  if ((x*x*x) > CIEEpsilon)
49  x=(x*x*x);
50  else
51  x=(116.0*x-16.0)/CIEK;
52  if (L > (CIEK*CIEEpsilon))
53  y=(y*y*y);
54  else
55  y=L/CIEK;
56  if ((z*z*z) > CIEEpsilon)
57  z=(z*z*z);
58  else
59  z=(116.0*z-16.0)/CIEK;
60  *X=D65X*x;
61  *Y=D65Y*y;
62  *Z=D65Z*z;
63 }
64 
65 static inline void ConvertXYZToLuv(const double X,const double Y,const double Z,
66  double *L,double *u,double *v)
67 {
68  double
69  alpha;
70 
71  assert(L != (double *) NULL);
72  assert(u != (double *) NULL);
73  assert(v != (double *) NULL);
74  if ((Y/D65Y) > CIEEpsilon)
75  *L=(double) (116.0*pow(Y/D65Y,1.0/3.0)-16.0);
76  else
77  *L=CIEK*(Y/D65Y);
78  alpha=MagickSafeReciprocal(X+15.0*Y+3.0*Z);
79  *u=13.0*(*L)*((4.0*alpha*X)-(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z)));
80  *v=13.0*(*L)*((9.0*alpha*Y)-(9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z)));
81  *L/=100.0;
82  *u=(*u+134.0)/354.0;
83  *v=(*v+140.0)/262.0;
84 }
85 
86 static inline void ConvertRGBToXYZ(const Quantum red,const Quantum green,
87  const Quantum blue,double *X,double *Y,double *Z)
88 {
89  double
90  b,
91  g,
92  r;
93 
94  assert(X != (double *) NULL);
95  assert(Y != (double *) NULL);
96  assert(Z != (double *) NULL);
97  r=QuantumScale*DecodePixelGamma((MagickRealType) red);
98  g=QuantumScale*DecodePixelGamma((MagickRealType) green);
99  b=QuantumScale*DecodePixelGamma((MagickRealType) blue);
100  *X=(0.4123955889674142161*r)+(0.3575834307637148171*g)+
101  (0.1804926473817015735*b);
102  *Y=(0.2125862307855955516*r)+(0.7151703037034108499*g)+
103  (0.07220049864333622685*b);
104  *Z=(0.01929721549174694484*r)+(0.1191838645808485318*g)+
105  (0.9504971251315797660*b);
106 }
107 
108 static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
109  double *L,double *a,double *b)
110 {
111  double
112  x,
113  y,
114  z;
115 
116  assert(L != (double *) NULL);
117  assert(a != (double *) NULL);
118  assert(b != (double *) NULL);
119  if ((X/D65X) > CIEEpsilon)
120  x=pow(X/D65X,1.0/3.0);
121  else
122  x=(CIEK*X/D65X+16.0)/116.0;
123  if ((Y/D65Y) > CIEEpsilon)
124  y=pow(Y/D65Y,1.0/3.0);
125  else
126  y=(CIEK*Y/D65Y+16.0)/116.0;
127  if ((Z/D65Z) > CIEEpsilon)
128  z=pow(Z/D65Z,1.0/3.0);
129  else
130  z=(CIEK*Z/D65Z+16.0)/116.0;
131  *L=((116.0*y)-16.0)/100.0;
132  *a=(500.0*(x-y))/255.0+0.5;
133  *b=(200.0*(y-z))/255.0+0.5;
134 }
135 
136 static inline void ConvertLuvToXYZ(const double L,const double u,const double v,
137  double *X,double *Y,double *Z)
138 {
139  double
140  gamma;
141 
142  assert(X != (double *) NULL);
143  assert(Y != (double *) NULL);
144  assert(Z != (double *) NULL);
145  if (L > (CIEK*CIEEpsilon))
146  *Y=(double) pow((L+16.0)/116.0,3.0);
147  else
148  *Y=L/CIEK;
149  gamma=MagickSafeReciprocal((((52.0*L*MagickSafeReciprocal(u+13.0*L*
150  (4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))))-1.0)/3.0)-(-1.0/3.0));
151  *X=gamma*((*Y*((39.0*L*MagickSafeReciprocal(v+13.0*L*(9.0*D65Y/
152  (D65X+15.0*D65Y+3.0*D65Z))))-5.0))+5.0*(*Y));
153  *Z=(*X*(((52.0*L*MagickSafeReciprocal(u+13.0*L*(4.0*D65X/
154  (D65X+15.0*D65Y+3.0*D65Z))))-1.0)/3.0))-5.0*(*Y);
155 }
156 
157 static inline void ConvertXYZToRGB(const double X,const double Y,const double Z,
158  Quantum *red,Quantum *green,Quantum *blue)
159 {
160  double
161  b,
162  g,
163  min,
164  r;
165 
166  assert(red != (Quantum *) NULL);
167  assert(green != (Quantum *) NULL);
168  assert(blue != (Quantum *) NULL);
169  r=(3.240969941904521*X)+(-1.537383177570093*Y)+(-0.498610760293*Z);
170  g=(-0.96924363628087*X)+(1.87596750150772*Y)+(0.041555057407175*Z);
171  b=(0.055630079696993*X)+(-0.20397695888897*Y)+(1.056971514242878*Z);
172  min=MagickMin(r,MagickMin(g,b));
173  if (min < 0.0)
174  {
175  r-=min;
176  g-=min;
177  b-=min;
178  }
179  *red=ClampToQuantum((MagickRealType) EncodePixelGamma((MagickRealType)
180  QuantumRange*r));
181  *green=ClampToQuantum((MagickRealType) EncodePixelGamma((MagickRealType)
182  QuantumRange*g));
183  *blue=ClampToQuantum((MagickRealType) EncodePixelGamma((MagickRealType)
184  QuantumRange*b));
185 }
186 
187 #if defined(__cplusplus) || defined(c_plusplus)
188 }
189 #endif
190 
191 #endif