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