blob: e15f74106fa89558c0e5734af8a269cd8969a002 [file] [log] [blame]
cristyd1dd6e42011-09-04 01:46:08 +00001/*
Cristyf775a5c2019-11-26 14:27:47 -05002 Copyright 1999-2020 ImageMagick Studio LLC, a non-profit organization
cristyd1dd6e42011-09-04 01:46:08 +00003 dedicated to making software imaging solutions freely available.
4
Cristy57b308b2019-01-19 17:53:40 -05005 You may not use this file except in compliance with the License. You may
cristyd1dd6e42011-09-04 01:46:08 +00006 obtain a copy of the License at
7
Cristy9ddfcca2018-09-09 19:46:34 -04008 https://imagemagick.org/script/license.php
cristyd1dd6e42011-09-04 01:46:08 +00009
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"
Cristyd2f22342020-01-05 11:46:47 -050022#include "MagickCore/visual-effects.h"
cristy6398ec72013-11-28 02:00:27 +000023
cristyd1dd6e42011-09-04 01:46:08 +000024#if defined(__cplusplus) || defined(c_plusplus)
25extern "C" {
26#endif
27
cristy15ec6a62013-04-20 01:11:51 +000028#define D65X 0.950456
29#define D65Y 1.0
30#define D65Z 1.088754
31#define CIEEpsilon (216.0/24389.0)
32#define CIEK (24389.0/27.0)
cristyd803bd02013-04-03 19:10:51 +000033
cristy8ea81222011-09-04 10:33:32 +000034extern MagickPrivate double
35 GenerateDifferentialNoise(RandomInfo *,const Quantum,const NoiseType,
cristy9ed1f812011-10-08 02:00:08 +000036 const double);
cristy8ea81222011-09-04 10:33:32 +000037
38extern MagickPrivate size_t
39 GetOptimalKernelWidth(const double,const double),
40 GetOptimalKernelWidth1D(const double,const double),
41 GetOptimalKernelWidth2D(const double,const double);
42
cristyd1dd6e42011-09-04 01:46:08 +000043extern MagickPrivate void
cristy722fc0c2012-08-04 23:15:43 +000044 ConvertHCLToRGB(const double,const double,const double,double *,double *,
45 double *),
cristy9e2436a2013-05-02 20:35:59 +000046 ConvertHCLpToRGB(const double,const double,const double,double *,double *,
47 double *),
cristy0a39a5c2012-06-27 12:51:45 +000048 ConvertHSBToRGB(const double,const double,const double,double *,double *,
cristyd1dd6e42011-09-04 01:46:08 +000049 double *),
cristyaf64eb22013-05-02 14:07:10 +000050 ConvertHSIToRGB(const double,const double,const double,double *,double *,
51 double *),
cristy246c3132013-05-02 16:35:53 +000052 ConvertHSVToRGB(const double,const double,const double,double *,double *,
53 double *),
cristy0a39a5c2012-06-27 12:51:45 +000054 ConvertHWBToRGB(const double,const double,const double,double *,double *,
cristy3094b7f2011-10-01 23:18:02 +000055 double *),
cristydf42b172013-04-05 13:35:37 +000056 ConvertLCHabToRGB(const double,const double,const double,double *,double *,
57 double *),
58 ConvertLCHuvToRGB(const double,const double,const double,double *,double *,
cristyb2850952013-04-04 19:00:52 +000059 double *),
cristy722fc0c2012-08-04 23:15:43 +000060 ConvertRGBToHCL(const double,const double,const double,double *,double *,
61 double *),
cristy9e2436a2013-05-02 20:35:59 +000062 ConvertRGBToHCLp(const double,const double,const double,double *,double *,
63 double *),
cristy0a39a5c2012-06-27 12:51:45 +000064 ConvertRGBToHSB(const double,const double,const double,double *,double *,
cristy3094b7f2011-10-01 23:18:02 +000065 double *),
cristyaf64eb22013-05-02 14:07:10 +000066 ConvertRGBToHSI(const double,const double,const double,double *,double *,
67 double *),
cristy246c3132013-05-02 16:35:53 +000068 ConvertRGBToHSV(const double,const double,const double,double *,double *,
69 double *),
cristy0a39a5c2012-06-27 12:51:45 +000070 ConvertRGBToHWB(const double,const double,const double,double *,double *,
cristyb2850952013-04-04 19:00:52 +000071 double *),
cristydf42b172013-04-05 13:35:37 +000072 ConvertRGBToLCHab(const double,const double,const double,double *,double *,
73 double *),
74 ConvertRGBToLCHuv(const double,const double,const double,double *,double *,
cristyd1dd6e42011-09-04 01:46:08 +000075 double *);
76
cristyd803bd02013-04-03 19:10:51 +000077static inline void ConvertLabToXYZ(const double L,const double a,const double b,
78 double *X,double *Y,double *Z)
79{
80 double
81 x,
82 y,
83 z;
84
85 assert(X != (double *) NULL);
86 assert(Y != (double *) NULL);
87 assert(Z != (double *) NULL);
cristy35605e92013-05-06 11:33:57 +000088 y=(L+16.0)/116.0;
89 x=y+a/500.0;
90 z=y-b/200.0;
cristyd803bd02013-04-03 19:10:51 +000091 if ((x*x*x) > CIEEpsilon)
92 x=(x*x*x);
93 else
cristy15ec6a62013-04-20 01:11:51 +000094 x=(116.0*x-16.0)/CIEK;
cristyd803bd02013-04-03 19:10:51 +000095 if ((y*y*y) > CIEEpsilon)
96 y=(y*y*y);
97 else
cristy35605e92013-05-06 11:33:57 +000098 y=L/CIEK;
cristyd803bd02013-04-03 19:10:51 +000099 if ((z*z*z) > CIEEpsilon)
100 z=(z*z*z);
101 else
cristy15ec6a62013-04-20 01:11:51 +0000102 z=(116.0*z-16.0)/CIEK;
103 *X=D65X*x;
104 *Y=D65Y*y;
105 *Z=D65Z*z;
cristyd803bd02013-04-03 19:10:51 +0000106}
107
cristydf42b172013-04-05 13:35:37 +0000108static inline void ConvertLuvToXYZ(const double L,const double u,const double v,
109 double *X,double *Y,double *Z)
110{
Cristy3d71aa82019-10-11 19:47:56 -0400111 double
112 gamma;
113
cristydf42b172013-04-05 13:35:37 +0000114 assert(X != (double *) NULL);
115 assert(Y != (double *) NULL);
116 assert(Z != (double *) NULL);
cristya8716912013-05-06 12:04:10 +0000117 if (L > (CIEK*CIEEpsilon))
118 *Y=(double) pow((L+16.0)/116.0,3.0);
cristydf42b172013-04-05 13:35:37 +0000119 else
cristya8716912013-05-06 12:04:10 +0000120 *Y=L/CIEK;
Cristy3d71aa82019-10-11 19:47:56 -0400121 gamma=PerceptibleReciprocal((((52.0*L/(u+13.0*L*(4.0*D65X/(D65X+15.0*D65Y+
122 3.0*D65Z))))-1.0)/3.0)-(-1.0/3.0));
123 *X=gamma*((*Y*((39.0*L/(v+13.0*L*(9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z))))-5.0))+
124 5.0*(*Y));
cristy887d5132013-05-06 20:05:35 +0000125 *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 +0000126 5.0*(*Y);
cristydf42b172013-04-05 13:35:37 +0000127}
128
cristyd803bd02013-04-03 19:10:51 +0000129static inline void ConvertRGBToXYZ(const double red,const double green,
130 const double blue,double *X,double *Y,double *Z)
131{
132 double
133 b,
134 g,
135 r;
136
cristy8eccf572013-05-03 17:30:54 +0000137 /*
138 Convert RGB to XYZ colorspace.
139 */
cristyd803bd02013-04-03 19:10:51 +0000140 assert(X != (double *) NULL);
141 assert(Y != (double *) NULL);
142 assert(Z != (double *) NULL);
cristy58f75372013-05-05 17:34:43 +0000143 r=QuantumScale*DecodePixelGamma(red);
144 g=QuantumScale*DecodePixelGamma(green);
145 b=QuantumScale*DecodePixelGamma(blue);
cristyd65a94d2015-01-28 22:20:48 +0000146 *X=0.4124564*r+0.3575761*g+0.1804375*b;
147 *Y=0.2126729*r+0.7151522*g+0.0721750*b;
148 *Z=0.0193339*r+0.1191920*g+0.9503041*b;
cristyd803bd02013-04-03 19:10:51 +0000149}
150
151static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
152 double *L,double *a,double *b)
153{
154 double
155 x,
156 y,
157 z;
cristyc32cb022013-05-06 13:32:31 +0000158
cristyd803bd02013-04-03 19:10:51 +0000159 assert(L != (double *) NULL);
160 assert(a != (double *) NULL);
161 assert(b != (double *) NULL);
cristy15ec6a62013-04-20 01:11:51 +0000162 if ((X/D65X) > CIEEpsilon)
163 x=pow(X/D65X,1.0/3.0);
cristyd803bd02013-04-03 19:10:51 +0000164 else
cristy15ec6a62013-04-20 01:11:51 +0000165 x=(CIEK*X/D65X+16.0)/116.0;
166 if ((Y/D65Y) > CIEEpsilon)
167 y=pow(Y/D65Y,1.0/3.0);
cristyd803bd02013-04-03 19:10:51 +0000168 else
cristy15ec6a62013-04-20 01:11:51 +0000169 y=(CIEK*Y/D65Y+16.0)/116.0;
170 if ((Z/D65Z) > CIEEpsilon)
171 z=pow(Z/D65Z,1.0/3.0);
cristyd803bd02013-04-03 19:10:51 +0000172 else
cristy15ec6a62013-04-20 01:11:51 +0000173 z=(CIEK*Z/D65Z+16.0)/116.0;
174 *L=((116.0*y)-16.0)/100.0;
175 *a=(500.0*(x-y))/255.0+0.5;
176 *b=(200.0*(y-z))/255.0+0.5;
cristyd803bd02013-04-03 19:10:51 +0000177}
178
cristydf42b172013-04-05 13:35:37 +0000179static inline void ConvertXYZToLuv(const double X,const double Y,const double Z,
180 double *L,double *u,double *v)
181{
182 double
183 alpha;
184
185 assert(L != (double *) NULL);
186 assert(u != (double *) NULL);
187 assert(v != (double *) NULL);
cristy15ec6a62013-04-20 01:11:51 +0000188 if ((Y/D65Y) > CIEEpsilon)
189 *L=(double) (116.0*pow(Y/D65Y,1.0/3.0)-16.0);
cristydf42b172013-04-05 13:35:37 +0000190 else
cristy15ec6a62013-04-20 01:11:51 +0000191 *L=CIEK*(Y/D65Y);
192 alpha=PerceptibleReciprocal(X+15.0*Y+3.0*Z);
193 *u=13.0*(*L)*((4.0*alpha*X)-(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z)));
194 *v=13.0*(*L)*((9.0*alpha*Y)-(9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z)));
195 *L/=100.0;
196 *u=(*u+134.0)/354.0;
197 *v=(*v+140.0)/262.0;
cristydf42b172013-04-05 13:35:37 +0000198}
199
cristy48348e72013-05-07 01:21:28 +0000200static inline void ConvertXYZToRGB(const double X,const double Y,const double Z,
cristyd803bd02013-04-03 19:10:51 +0000201 double *red,double *green,double *blue)
202{
203 double
204 b,
205 g,
206 r;
207
cristyd803bd02013-04-03 19:10:51 +0000208 assert(red != (double *) NULL);
209 assert(green != (double *) NULL);
210 assert(blue != (double *) NULL);
cristyd65a94d2015-01-28 22:20:48 +0000211 r=3.2404542*X-1.5371385*Y-0.4985314*Z;
212 g=(-0.9692660)*X+1.8760108*Y+0.0415560*Z;
213 b=0.0556434*X-0.2040259*Y+1.0572252*Z;
cristy58f75372013-05-05 17:34:43 +0000214 *red=EncodePixelGamma(QuantumRange*r);
215 *green=EncodePixelGamma(QuantumRange*g);
216 *blue=EncodePixelGamma(QuantumRange*b);
cristyd803bd02013-04-03 19:10:51 +0000217}
218
cristyd1dd6e42011-09-04 01:46:08 +0000219#if defined(__cplusplus) || defined(c_plusplus)
220}
221#endif
222
223#endif