1 /*
2 Copyright 1999-2021 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 image composite private methods.
17 */
18 #ifndef MAGICKCORE_COMPOSITE_PRIVATE_H
19 #define MAGICKCORE_COMPOSITE_PRIVATE_H
20
21
22 #include "MagickCore/color.h"
23 #include "MagickCore/image.h"
24 #include "MagickCore/image-private.h"
25 #include "MagickCore/pixel-accessor.h"
26 #include "MagickCore/pixel-private.h"
27
28 #if defined(__cplusplus) || defined(c_plusplus)
29 extern "C" {
30 #endif
31
32 /*
33 ImageMagick Alpha Composite Inline Methods (special export)
34 */
MagickOver_(const double p,const double alpha,const double q,const double beta)35 static inline double MagickOver_(const double p,const double alpha,
36 const double q,const double beta)
37 {
38 double
39 Da,
40 Sa;
41
42 Sa=QuantumScale*alpha;
43 Da=QuantumScale*beta;
44 return(Sa*p+Da*q*(1.0-Sa));
45 }
46
RoundToUnity(const double value)47 static inline double RoundToUnity(const double value)
48 {
49 return(value < 0.0 ? 0.0 : (value > 1.0) ? 1.0 : value);
50 }
51
CompositePixelOver(const Image * image,const PixelInfo * p,const double alpha,const Quantum * q,const double beta,Quantum * composite)52 static inline void CompositePixelOver(const Image *image,const PixelInfo *p,
53 const double alpha,const Quantum *q,const double beta,Quantum *composite)
54 {
55 double
56 Da,
57 gamma,
58 Sa;
59
60 ssize_t
61 i;
62
63 /*
64 Compose pixel p over pixel q with the given alpha.
65 */
66 Sa=QuantumScale*alpha;
67 Da=QuantumScale*beta;
68 gamma=Sa+Da-Sa*Da;
69 gamma=PerceptibleReciprocal(gamma);
70 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
71 {
72 PixelChannel
73 channel;
74
75 PixelTrait
76 traits;
77
78 channel=GetPixelChannelChannel(image,i);
79 traits=GetPixelChannelTraits(image,channel);
80 if (traits == UndefinedPixelTrait)
81 continue;
82 switch (channel)
83 {
84 case RedPixelChannel:
85 {
86 composite[i]=ClampToQuantum(gamma*MagickOver_((double) p->red,alpha,
87 (double) q[i],beta));
88 break;
89 }
90 case GreenPixelChannel:
91 {
92 composite[i]=ClampToQuantum(gamma*MagickOver_((double) p->green,alpha,
93 (double) q[i],beta));
94 break;
95 }
96 case BluePixelChannel:
97 {
98 composite[i]=ClampToQuantum(gamma*MagickOver_((double) p->blue,alpha,
99 (double) q[i],beta));
100 break;
101 }
102 case BlackPixelChannel:
103 {
104 composite[i]=ClampToQuantum(gamma*MagickOver_((double) p->black,alpha,
105 (double) q[i],beta));
106 break;
107 }
108 case AlphaPixelChannel:
109 {
110 composite[i]=ClampToQuantum(QuantumRange*RoundToUnity(Sa+Da-Sa*Da));
111 break;
112 }
113 default:
114 {
115 composite[i]=q[i];
116 break;
117 }
118 }
119 }
120 }
121
CompositePixelInfoOver(const PixelInfo * p,const double alpha,const PixelInfo * q,const double beta,PixelInfo * composite)122 static inline void CompositePixelInfoOver(const PixelInfo *p,const double alpha,
123 const PixelInfo *q,const double beta,PixelInfo *composite)
124 {
125 double
126 Da,
127 gamma,
128 Sa;
129
130 /*
131 Compose pixel p over pixel q with the given opacities.
132 */
133 Sa=QuantumScale*alpha;
134 Da=QuantumScale*beta,
135 gamma=Sa+Da-Sa*Da;
136 composite->alpha=(double) QuantumRange*RoundToUnity(gamma);
137 gamma=PerceptibleReciprocal(gamma);
138 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
139 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
140 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
141 if (q->colorspace == CMYKColorspace)
142 composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
143 }
144
CompositePixelInfoPlus(const PixelInfo * p,const double alpha,const PixelInfo * q,const double beta,PixelInfo * composite)145 static inline void CompositePixelInfoPlus(const PixelInfo *p,
146 const double alpha,const PixelInfo *q,const double beta,PixelInfo *composite)
147 {
148 double
149 Da,
150 gamma,
151 Sa;
152
153 /*
154 Add two pixels with the given opacities.
155 */
156 Sa=QuantumScale*alpha;
157 Da=QuantumScale*beta;
158 gamma=RoundToUnity(Sa+Da); /* 'Plus' blending -- not 'Over' blending */
159 composite->alpha=(double) QuantumRange*RoundToUnity(gamma);
160 gamma=PerceptibleReciprocal(gamma);
161 composite->red=gamma*(Sa*p->red+Da*q->red);
162 composite->green=gamma*(Sa*p->green+Da*q->green);
163 composite->blue=gamma*(Sa*p->blue+Da*q->blue);
164 if (q->colorspace == CMYKColorspace)
165 composite->black=gamma*(Sa*p->black+Da*q->black);
166 }
167
CompositePixelInfoAreaBlend(const PixelInfo * p,const double alpha,const PixelInfo * q,const double beta,const double area,PixelInfo * composite)168 static inline void CompositePixelInfoAreaBlend(const PixelInfo *p,
169 const double alpha,const PixelInfo *q,const double beta,const double area,
170 PixelInfo *composite)
171 {
172 /*
173 Blend pixel colors p and q by the amount given and area.
174 */
175 CompositePixelInfoPlus(p,(double) (1.0-area)*alpha,q,(double) (area*beta),
176 composite);
177 }
178
CompositePixelInfoBlend(const PixelInfo * p,const double alpha,const PixelInfo * q,const double beta,PixelInfo * composite)179 static inline void CompositePixelInfoBlend(const PixelInfo *p,
180 const double alpha,const PixelInfo *q,const double beta,PixelInfo *composite)
181 {
182 /*
183 Blend pixel colors p and q by the amount given.
184 */
185 CompositePixelInfoPlus(p,(double) (alpha*p->alpha),q,(double) (beta*q->alpha),
186 composite);
187 }
188
GetCompositeClipToSelf(const CompositeOperator compose)189 static inline MagickBooleanType GetCompositeClipToSelf(
190 const CompositeOperator compose)
191 {
192 switch (compose)
193 {
194 case ClearCompositeOp:
195 case SrcCompositeOp:
196 case InCompositeOp:
197 case SrcInCompositeOp:
198 case OutCompositeOp:
199 case SrcOutCompositeOp:
200 case DstInCompositeOp:
201 case DstAtopCompositeOp:
202 case CopyAlphaCompositeOp:
203 case ChangeMaskCompositeOp:
204 {
205 return(MagickFalse);
206 break;
207 }
208 default:
209 break;
210 }
211 return(MagickTrue);
212 }
213
214 #if defined(__cplusplus) || defined(c_plusplus)
215 }
216 #endif
217
218 #endif
219