blob: 5a07c22d13845193abed48e161de2cbc7dfae24b [file] [log] [blame]
cristyd1dd6e42011-09-04 01:46:08 +00001/*
Cristy7ce65e72015-12-12 18:03:16 -05002 Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization
cristyd1dd6e42011-09-04 01:46:08 +00003 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*/
Cristy83bceaa2016-06-03 20:39:35 -040018#ifndef MAGICKCORE_GEM_PRIVATE_H
19#define MAGICKCORE_GEM_PRIVATE_H
cristyd1dd6e42011-09-04 01:46:08 +000020
cristy0b9c0d82015-05-24 22:27:57 +000021#include "MagickCore/pixel-accessor.h"
cristy6398ec72013-11-28 02:00:27 +000022
cristyd1dd6e42011-09-04 01:46:08 +000023#if defined(__cplusplus) || defined(c_plusplus)
24extern "C" {
25#endif
26
cristy15ec6a62013-04-20 01:11:51 +000027#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)
cristyd803bd02013-04-03 19:10:51 +000032
cristy8ea81222011-09-04 10:33:32 +000033extern MagickPrivate double
34 GenerateDifferentialNoise(RandomInfo *,const Quantum,const NoiseType,
cristy9ed1f812011-10-08 02:00:08 +000035 const double);
cristy8ea81222011-09-04 10:33:32 +000036
37extern MagickPrivate size_t
38 GetOptimalKernelWidth(const double,const double),
39 GetOptimalKernelWidth1D(const double,const double),
40 GetOptimalKernelWidth2D(const double,const double);
41
cristyd1dd6e42011-09-04 01:46:08 +000042extern MagickPrivate void
cristy722fc0c2012-08-04 23:15:43 +000043 ConvertHCLToRGB(const double,const double,const double,double *,double *,
44 double *),
cristy9e2436a2013-05-02 20:35:59 +000045 ConvertHCLpToRGB(const double,const double,const double,double *,double *,
46 double *),
cristy0a39a5c2012-06-27 12:51:45 +000047 ConvertHSBToRGB(const double,const double,const double,double *,double *,
cristyd1dd6e42011-09-04 01:46:08 +000048 double *),
cristyaf64eb22013-05-02 14:07:10 +000049 ConvertHSIToRGB(const double,const double,const double,double *,double *,
50 double *),
cristy246c3132013-05-02 16:35:53 +000051 ConvertHSVToRGB(const double,const double,const double,double *,double *,
52 double *),
cristy0a39a5c2012-06-27 12:51:45 +000053 ConvertHWBToRGB(const double,const double,const double,double *,double *,
cristy3094b7f2011-10-01 23:18:02 +000054 double *),
cristydf42b172013-04-05 13:35:37 +000055 ConvertLCHabToRGB(const double,const double,const double,double *,double *,
56 double *),
57 ConvertLCHuvToRGB(const double,const double,const double,double *,double *,
cristyb2850952013-04-04 19:00:52 +000058 double *),
cristy722fc0c2012-08-04 23:15:43 +000059 ConvertRGBToHCL(const double,const double,const double,double *,double *,
60 double *),
cristy9e2436a2013-05-02 20:35:59 +000061 ConvertRGBToHCLp(const double,const double,const double,double *,double *,
62 double *),
cristy0a39a5c2012-06-27 12:51:45 +000063 ConvertRGBToHSB(const double,const double,const double,double *,double *,
cristy3094b7f2011-10-01 23:18:02 +000064 double *),
cristyaf64eb22013-05-02 14:07:10 +000065 ConvertRGBToHSI(const double,const double,const double,double *,double *,
66 double *),
cristy246c3132013-05-02 16:35:53 +000067 ConvertRGBToHSV(const double,const double,const double,double *,double *,
68 double *),
cristy0a39a5c2012-06-27 12:51:45 +000069 ConvertRGBToHWB(const double,const double,const double,double *,double *,
cristyb2850952013-04-04 19:00:52 +000070 double *),
cristydf42b172013-04-05 13:35:37 +000071 ConvertRGBToLCHab(const double,const double,const double,double *,double *,
72 double *),
73 ConvertRGBToLCHuv(const double,const double,const double,double *,double *,
cristyd1dd6e42011-09-04 01:46:08 +000074 double *);
75
cristyd803bd02013-04-03 19:10:51 +000076static 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);
cristy35605e92013-05-06 11:33:57 +000087 y=(L+16.0)/116.0;
88 x=y+a/500.0;
89 z=y-b/200.0;
cristyd803bd02013-04-03 19:10:51 +000090 if ((x*x*x) > CIEEpsilon)
91 x=(x*x*x);
92 else
cristy15ec6a62013-04-20 01:11:51 +000093 x=(116.0*x-16.0)/CIEK;
cristyd803bd02013-04-03 19:10:51 +000094 if ((y*y*y) > CIEEpsilon)
95 y=(y*y*y);
96 else
cristy35605e92013-05-06 11:33:57 +000097 y=L/CIEK;
cristyd803bd02013-04-03 19:10:51 +000098 if ((z*z*z) > CIEEpsilon)
99 z=(z*z*z);
100 else
cristy15ec6a62013-04-20 01:11:51 +0000101 z=(116.0*z-16.0)/CIEK;
102 *X=D65X*x;
103 *Y=D65Y*y;
104 *Z=D65Z*z;
cristyd803bd02013-04-03 19:10:51 +0000105}
106
cristydf42b172013-04-05 13:35:37 +0000107static 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);
cristya8716912013-05-06 12:04:10 +0000113 if (L > (CIEK*CIEEpsilon))
114 *Y=(double) pow((L+16.0)/116.0,3.0);
cristydf42b172013-04-05 13:35:37 +0000115 else
cristya8716912013-05-06 12:04:10 +0000116 *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))+
cristy887d5132013-05-06 20:05:35 +0000118 5.0*(*Y))/((((52.0*L/(u+13.0*L*(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))))-1.0)/
cristya8716912013-05-06 12:04:10 +0000119 3.0)-(-1.0/3.0));
cristy887d5132013-05-06 20:05:35 +0000120 *Z=(*X*(((52.0*L/(u+13.0*L*(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))))-1.0)/3.0))-
cristya8716912013-05-06 12:04:10 +0000121 5.0*(*Y);
cristydf42b172013-04-05 13:35:37 +0000122}
123
cristyd803bd02013-04-03 19:10:51 +0000124static 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
cristy8eccf572013-05-03 17:30:54 +0000132 /*
133 Convert RGB to XYZ colorspace.
134 */
cristyd803bd02013-04-03 19:10:51 +0000135 assert(X != (double *) NULL);
136 assert(Y != (double *) NULL);
137 assert(Z != (double *) NULL);
cristy58f75372013-05-05 17:34:43 +0000138 r=QuantumScale*DecodePixelGamma(red);
139 g=QuantumScale*DecodePixelGamma(green);
140 b=QuantumScale*DecodePixelGamma(blue);
cristyd65a94d2015-01-28 22:20:48 +0000141 *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;
cristyd803bd02013-04-03 19:10:51 +0000144}
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;
cristyc32cb022013-05-06 13:32:31 +0000153
cristyd803bd02013-04-03 19:10:51 +0000154 assert(L != (double *) NULL);
155 assert(a != (double *) NULL);
156 assert(b != (double *) NULL);
cristy15ec6a62013-04-20 01:11:51 +0000157 if ((X/D65X) > CIEEpsilon)
158 x=pow(X/D65X,1.0/3.0);
cristyd803bd02013-04-03 19:10:51 +0000159 else
cristy15ec6a62013-04-20 01:11:51 +0000160 x=(CIEK*X/D65X+16.0)/116.0;
161 if ((Y/D65Y) > CIEEpsilon)
162 y=pow(Y/D65Y,1.0/3.0);
cristyd803bd02013-04-03 19:10:51 +0000163 else
cristy15ec6a62013-04-20 01:11:51 +0000164 y=(CIEK*Y/D65Y+16.0)/116.0;
165 if ((Z/D65Z) > CIEEpsilon)
166 z=pow(Z/D65Z,1.0/3.0);
cristyd803bd02013-04-03 19:10:51 +0000167 else
cristy15ec6a62013-04-20 01:11:51 +0000168 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;
cristyd803bd02013-04-03 19:10:51 +0000172}
173
cristydf42b172013-04-05 13:35:37 +0000174static 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);
cristy15ec6a62013-04-20 01:11:51 +0000183 if ((Y/D65Y) > CIEEpsilon)
184 *L=(double) (116.0*pow(Y/D65Y,1.0/3.0)-16.0);
cristydf42b172013-04-05 13:35:37 +0000185 else
cristy15ec6a62013-04-20 01:11:51 +0000186 *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;
cristydf42b172013-04-05 13:35:37 +0000193}
194
cristy48348e72013-05-07 01:21:28 +0000195static inline void ConvertXYZToRGB(const double X,const double Y,const double Z,
cristyd803bd02013-04-03 19:10:51 +0000196 double *red,double *green,double *blue)
197{
198 double
199 b,
200 g,
201 r;
202
cristyd803bd02013-04-03 19:10:51 +0000203 assert(red != (double *) NULL);
204 assert(green != (double *) NULL);
205 assert(blue != (double *) NULL);
cristyd65a94d2015-01-28 22:20:48 +0000206 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;
cristy58f75372013-05-05 17:34:43 +0000209 *red=EncodePixelGamma(QuantumRange*r);
210 *green=EncodePixelGamma(QuantumRange*g);
211 *blue=EncodePixelGamma(QuantumRange*b);
cristyd803bd02013-04-03 19:10:51 +0000212}
213
cristyd1dd6e42011-09-04 01:46:08 +0000214#if defined(__cplusplus) || defined(c_plusplus)
215}
216#endif
217
218#endif