]> granicus.if.org Git - imagemagick/blob - MagickCore/composite-private.h
(no commit message)
[imagemagick] / MagickCore / composite-private.h
1 /*
2   Copyright 1999-2014 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
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 */
35 static inline double MagickOver_(const double p,
36   const double alpha,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     PixelChannel
68       channel;
69
70     PixelTrait
71       traits;
72
73     channel=GetPixelChannelChannel(image,i);
74     traits=GetPixelChannelTraits(image,channel);
75     if (traits == UndefinedPixelTrait)
76       continue;
77     if (fabs(alpha-TransparentAlpha) < MagickEpsilon)
78       {
79         composite[i]=q[i];
80         continue;
81       }
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*(Sa*(-Da)+Sa+Da));
111         break;
112       }
113       default:
114       {
115         composite[i]=q[i];
116         break;
117       }
118     }
119   }
120 }
121
122 static inline void CompositePixelInfoOver(const PixelInfo *p,
123   const double alpha,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   if (fabs(alpha-TransparentAlpha) < MagickEpsilon)
134     {
135       *composite=(*p);
136       return;
137     }
138   Sa=QuantumScale*alpha;
139   Da=QuantumScale*beta,
140   gamma=Sa*(-Da)+Sa+Da;
141   composite->alpha=(double) QuantumRange*gamma;
142   gamma=PerceptibleReciprocal(gamma);
143   composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
144   composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
145   composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
146   if (q->colorspace == CMYKColorspace)
147     composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
148 }
149
150 static inline double RoundToUnity(const double value)
151 {
152   return(value < 0.0 ? 0.0 : (value > 1.0) ? 1.0 : value);
153 }
154
155 static inline void CompositePixelInfoPlus(const PixelInfo *p,
156   const double alpha,const PixelInfo *q,const double beta,PixelInfo *composite)
157 {
158   double
159     Da,
160     gamma,
161     Sa;
162
163   /*
164     Add two pixels with the given opacities.
165   */
166   Sa=QuantumScale*alpha;
167   Da=QuantumScale*beta;
168   gamma=RoundToUnity(Sa+Da);  /* 'Plus' blending -- not 'Over' blending */
169   composite->alpha=(double) QuantumRange*gamma;
170   gamma=PerceptibleReciprocal(gamma);
171   composite->red=gamma*(Sa*p->red+Da*q->red);
172   composite->green=gamma*(Sa*p->green+Da*q->green);
173   composite->blue=gamma*(Sa*p->blue+Da*q->blue);
174   if (q->colorspace == CMYKColorspace)
175     composite->black=gamma*(Sa*p->black+Da*q->black);
176 }
177
178 static inline void CompositePixelInfoAreaBlend(const PixelInfo *p,
179   const double alpha,const PixelInfo *q,const double beta,const double area,
180   PixelInfo *composite)
181 {
182   /*
183     Blend pixel colors p and q by the amount given and area.
184   */
185   CompositePixelInfoPlus(p,(double) (1.0-area)*alpha,q,(double) (area*beta),
186     composite);
187 }
188
189 static inline void CompositePixelInfoBlend(const PixelInfo *p,
190   const double alpha,const PixelInfo *q,const double beta,PixelInfo *composite)
191 {
192   /*
193     Blend pixel colors p and q by the amount given.
194   */
195   CompositePixelInfoPlus(p,(double) (alpha*p->alpha),q,(double) (beta*q->alpha),
196     composite);
197 }
198
199 #if defined(__cplusplus) || defined(c_plusplus)
200 }
201 #endif
202
203 #endif