MagickCore 6.9.13
Loading...
Searching...
No Matches
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)
25extern "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
34static 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
65static 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=PerceptibleReciprocal(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
86static 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
108static 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
136static 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=PerceptibleReciprocal((((52.0*L*PerceptibleReciprocal(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*PerceptibleReciprocal(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*PerceptibleReciprocal(u+13.0*L*(4.0*D65X/
154 (D65X+15.0*D65Y+3.0*D65Z))))-1.0)/3.0))-5.0*(*Y);
155}
156
157static 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