]> granicus.if.org Git - imagemagick/blob - MagickCore/composite-private.h
(no commit message)
[imagemagick] / MagickCore / composite-private.h
1 /*
2   Copyright 1999-2013 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.
6   obtain a copy of the License at
7
8     http://www.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 #if defined(__cplusplus) || defined(c_plusplus)
22 extern "C" {
23 #endif
24
25 /*
26   ImageMagick Alpha Composite Inline Methods (special export)
27 */
28
29 #include "MagickCore/color.h"
30 #include "MagickCore/image.h"
31 #include "MagickCore/image-private.h"
32 #include "MagickCore/pixel-accessor.h"
33 #include "MagickCore/pixel-private.h"
34
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-Sa*Da*q+Da*q);
45 }
46
47 static inline void CompositePixelOver(const Image *image,const PixelInfo *p,
48   const double alpha,const Quantum *q,const double beta,Quantum *composite)
49 {
50   double
51     Da,
52     gamma,
53     Sa;
54
55   register ssize_t
56     i;
57
58   /*
59     Compose pixel p over pixel q with the given alpha.
60   */
61   Sa=QuantumScale*alpha;
62   Da=QuantumScale*beta,
63   gamma=Sa*(-Da)+Sa+Da;
64   gamma=PerceptibleReciprocal(gamma);
65   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
66   {
67     double
68       pixel;
69
70     PixelChannel
71       channel;
72
73     PixelTrait
74       traits;
75
76     channel=GetPixelChannelChannel(image,i);
77     traits=GetPixelChannelTraits(image,channel);
78     if (traits == UndefinedPixelTrait)
79       continue;
80     if (((traits & CopyPixelTrait) != 0) || (GetPixelMask(image,q) != 0) ||
81         (fabs(alpha-TransparentAlpha) < MagickEpsilon))
82       {
83         composite[i]=q[i];
84         continue;
85       }
86     switch (channel)
87     {
88       case RedPixelChannel:
89       {
90         pixel=gamma*MagickOver_((double) p->red,alpha,(double) q[i],beta);
91         break;
92       }
93       case GreenPixelChannel:
94       {
95         pixel=gamma*MagickOver_((double) p->green,alpha,(double) q[i],beta);
96         break;
97       }
98       case BluePixelChannel:
99       {
100         pixel=gamma*MagickOver_((double) p->blue,alpha,(double) q[i],beta);
101         break;
102       }
103       case BlackPixelChannel:
104       {
105         pixel=gamma*MagickOver_((double) p->black,alpha,(double) q[i],beta);
106         break;
107       }
108       case AlphaPixelChannel:
109       {
110         pixel=QuantumRange*(Sa*(-Da)+Sa+Da);
111         break;
112       }
113       default:
114       {
115         pixel=(double) q[i];
116         break;
117       }
118     }
119     composite[i]=ClampToQuantum(pixel);
120   }
121 }
122
123 static 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   if (fabs(alpha-TransparentAlpha) < MagickEpsilon)
135     {
136       *composite=(*p);
137       return;
138     }
139   Sa=QuantumScale*alpha;
140   Da=QuantumScale*beta,
141   gamma=Sa*(-Da)+Sa+Da;
142   composite->alpha=(double) QuantumRange*gamma;
143   gamma=PerceptibleReciprocal(gamma);
144   composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
145   composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
146   composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
147   if (q->colorspace == CMYKColorspace)
148     composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
149 }
150
151 static inline double RoundToUnity(const double value)
152 {
153   return(value < 0.0 ? 0.0 : (value > 1.0) ? 1.0 : value);
154 }
155
156 static inline void CompositePixelInfoPlus(const PixelInfo *p,const double alpha,
157   const PixelInfo *q,const double beta,PixelInfo *composite)
158 {
159   double
160     Da,
161     gamma,
162     Sa;
163
164   /*
165     Add two pixels with the given opacities.
166   */
167   Sa=QuantumScale*alpha;
168   Da=QuantumScale*beta;
169   gamma=RoundToUnity(Sa+Da);  /* 'Plus' blending -- not 'Over' blending */
170   composite->alpha=(double) QuantumRange*gamma;
171   gamma=PerceptibleReciprocal(gamma);
172   composite->red=gamma*(Sa*p->red+Da*q->red);
173   composite->green=gamma*(Sa*p->green+Da*q->green);
174   composite->blue=gamma*(Sa*p->blue+Da*q->blue);
175   if (q->colorspace == CMYKColorspace)
176     composite->black=gamma*(Sa*p->black+Da*q->black);
177 }
178
179 static inline void CompositePixelInfoAreaBlend(const PixelInfo *p,
180   const double alpha,const PixelInfo *q,const double beta,const double area,
181   PixelInfo *composite)
182 {
183   /*
184     Blend pixel colors p and q by the amount given and area.
185   */
186   CompositePixelInfoPlus(p,(double) (1.0-area)*alpha,q,(double) (area*beta),
187     composite);
188 }
189
190 static inline void CompositePixelInfoBlend(const PixelInfo *p,
191   const double alpha,const PixelInfo *q,const double beta,PixelInfo *composite)
192 {
193   /*
194     Blend pixel colors p and q by the amount given.
195   */
196   CompositePixelInfoPlus(p,(double) (alpha*p->alpha),q,(double) (beta*q->alpha),
197     composite);
198 }
199
200 #if defined(__cplusplus) || defined(c_plusplus)
201 }
202 #endif
203
204 #endif