MagickCore 7.1.1
Convert, Edit, Or Compose Bitmap Images
Loading...
Searching...
No Matches
composite-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 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/artifact.h"
25#include "MagickCore/image-private.h"
26#include "MagickCore/pixel-accessor.h"
27
28#if defined(__cplusplus) || defined(c_plusplus)
29extern "C" {
30#endif
31
32/*
33 ImageMagick Alpha Composite Inline Methods (special export)
34*/
35static 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
47static inline double RoundToUnity(const double value)
48{
49 return(value < 0.0 ? 0.0 : (value > 1.0) ? 1.0 : value);
50}
51
52static 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((double) QuantumRange*
111 RoundToUnity(Sa+Da-Sa*Da));
112 break;
113 }
114 default:
115 {
116 composite[i]=q[i];
117 break;
118 }
119 }
120 }
121}
122
123static inline void CompositePixelInfoOver(const PixelInfo *p,const double alpha,
124 const PixelInfo *q,const double beta,PixelInfo *composite)
125{
126 double
127 Da,
128 gamma,
129 Sa;
130
131 /*
132 Compose pixel p over pixel q with the given opacities.
133 */
134 Sa=QuantumScale*alpha;
135 Da=QuantumScale*beta,
136 gamma=Sa+Da-Sa*Da;
137 composite->alpha=(double) QuantumRange*RoundToUnity(gamma);
138 gamma=PerceptibleReciprocal(gamma);
139 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
140 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
141 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
142 if (q->colorspace == CMYKColorspace)
143 composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
144}
145
146static inline void CompositePixelInfoPlus(const PixelInfo *p,
147 const double alpha,const PixelInfo *q,const double beta,PixelInfo *composite)
148{
149 double
150 Da,
151 gamma,
152 Sa;
153
154 /*
155 Add two pixels with the given opacities.
156 */
157 Sa=QuantumScale*alpha;
158 Da=QuantumScale*beta;
159 gamma=RoundToUnity(Sa+Da); /* 'Plus' blending -- not 'Over' blending */
160 composite->alpha=(double) QuantumRange*RoundToUnity(gamma);
161 gamma=PerceptibleReciprocal(gamma);
162 composite->red=gamma*(Sa*p->red+Da*q->red);
163 composite->green=gamma*(Sa*p->green+Da*q->green);
164 composite->blue=gamma*(Sa*p->blue+Da*q->blue);
165 if (q->colorspace == CMYKColorspace)
166 composite->black=gamma*(Sa*p->black+Da*q->black);
167}
168
169static inline void CompositePixelInfoAreaBlend(const PixelInfo *p,
170 const double alpha,const PixelInfo *q,const double beta,const double area,
171 PixelInfo *composite)
172{
173 /*
174 Blend pixel colors p and q by the amount given and area.
175 */
176 CompositePixelInfoPlus(p,(double) (1.0-area)*alpha,q,(double) (area*beta),
177 composite);
178}
179
180static inline void CompositePixelInfoBlend(const PixelInfo *p,
181 const double alpha,const PixelInfo *q,const double beta,PixelInfo *composite)
182{
183 /*
184 Blend pixel colors p and q by the amount given.
185 */
186 CompositePixelInfoPlus(p,(double) (alpha*p->alpha),q,(double) (beta*q->alpha),
187 composite);
188}
189
190static inline void DisableCompositeClampUnlessSpecified(Image *image)
191{
192 if (GetImageArtifact(image,"compose:clamp") == (const char *) NULL)
193 (void) SetImageArtifact(image,"compose:clamp","off");
194}
195
196static inline MagickBooleanType GetCompositeClipToSelf(
197 const CompositeOperator compose)
198{
199 switch (compose)
200 {
201 case ClearCompositeOp:
202 case SrcCompositeOp:
203 case InCompositeOp:
204 case SrcInCompositeOp:
205 case OutCompositeOp:
206 case SrcOutCompositeOp:
207 case DstInCompositeOp:
208 case DstAtopCompositeOp:
209 case CopyAlphaCompositeOp:
210 case ChangeMaskCompositeOp:
211 {
212 return(MagickFalse);
213 break;
214 }
215 default:
216 break;
217 }
218 return(MagickTrue);
219}
220
221#if defined(__cplusplus) || defined(c_plusplus)
222}
223#endif
224
225#endif