• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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