]> granicus.if.org Git - imagemagick/blob - MagickCore/composite-private.h
(no commit message)
[imagemagick] / MagickCore / composite-private.h
1 /*
2   Copyright 1999-2012 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
34 static inline MagickRealType MagickOver_(const MagickRealType p,
35   const MagickRealType alpha,const MagickRealType q,const MagickRealType beta)
36 {
37   MagickRealType
38     Da,
39     Sa;
40
41   Sa=QuantumScale*alpha;
42   Da=QuantumScale*beta;
43   return(Sa*p-Sa*Da*q+Da*q);
44 }
45
46 static inline void CompositePixelOver(const Image *image,const PixelInfo *p,
47   const MagickRealType alpha,const Quantum *q,const MagickRealType beta,
48   Quantum *composite)
49 {
50   MagickRealType
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=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
65   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
66   {
67     PixelChannel
68       channel;
69
70     PixelTrait
71       traits;
72
73     channel=GetPixelChannelMapChannel(image,i);
74     traits=GetPixelChannelMapTraits(image,channel);
75     if (traits == UndefinedPixelTrait)
76       continue;
77     switch (channel)
78     {
79       case RedPixelChannel:
80       {
81         composite[i]=ClampToQuantum(gamma*MagickOver_((MagickRealType) p->red,
82           alpha,(MagickRealType) q[i],beta));
83         break;
84       }
85       case GreenPixelChannel:
86       {
87         composite[i]=ClampToQuantum(gamma*MagickOver_((MagickRealType) p->green,
88           alpha,(MagickRealType) q[i],beta));
89         break;
90       }
91       case BluePixelChannel:
92       {
93         composite[i]=ClampToQuantum(gamma*MagickOver_((MagickRealType) p->blue,
94           alpha,(MagickRealType) q[i],beta));
95         break;
96       }
97       case BlackPixelChannel:
98       {
99         composite[i]=ClampToQuantum(gamma*MagickOver_((MagickRealType) p->black,
100           alpha,(MagickRealType) q[i],beta));
101         break;
102       }
103       case AlphaPixelChannel:
104       {
105         composite[i]=ClampToQuantum(QuantumRange*(Sa*(-Da)+Sa+Da));
106         break;
107       }
108       default:
109         break;
110     }
111   }
112 }
113
114 static inline void CompositePixelInfoOver(const PixelInfo *p,
115   const MagickRealType alpha,const PixelInfo *q,const MagickRealType beta,
116   PixelInfo *composite)
117 {
118   MagickRealType
119     Da,
120     gamma,
121     Sa;
122
123   /*
124     Compose pixel p over pixel q with the given opacities.
125   */
126   if (fabs(alpha-OpaqueAlpha) < MagickEpsilon)
127     {
128       *composite=(*p);
129       return;
130     }
131   Sa=QuantumScale*alpha;
132   Da=QuantumScale*beta,
133   gamma=Sa*(-Da)+Sa+Da;
134   composite->alpha=(MagickRealType) QuantumRange*gamma;
135   gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
136   composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
137   composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
138   composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
139   if (q->colorspace == CMYKColorspace)
140     composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
141 }
142
143 static inline MagickRealType RoundToUnity(const MagickRealType value)
144 {
145   return(value < 0.0 ? 0.0 : (value > 1.0) ? 1.0 : value);
146 }
147
148 static inline void CompositePixelInfoPlus(const PixelInfo *p,
149   const MagickRealType alpha,const PixelInfo *q,const MagickRealType beta,
150   PixelInfo *composite)
151 {
152   MagickRealType
153     Da,
154     gamma,
155     Sa;
156
157   /*
158     Add two pixels with the given opacities.
159   */
160   Sa=QuantumScale*alpha;
161   Da=QuantumScale*beta;
162   gamma=RoundToUnity(Sa+Da);  /* 'Plus' blending -- not 'Over' blending */
163   composite->alpha=(MagickRealType) QuantumRange*gamma;
164   gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
165   composite->red=gamma*(Sa*p->red+Da*q->red);
166   composite->green=gamma*(Sa*p->green+Da*q->green);
167   composite->blue=gamma*(Sa*p->blue+Da*q->blue);
168   if (q->colorspace == CMYKColorspace)
169     composite->black=gamma*(Sa*p->black+Da*q->black);
170 }
171
172 static inline void CompositePixelInfoAreaBlend(const PixelInfo *p,
173   const MagickRealType alpha,const PixelInfo *q,const MagickRealType beta,
174   const MagickRealType area,PixelInfo *composite)
175 {
176   /*
177     Blend pixel colors p and q by the amount given and area.
178   */
179   CompositePixelInfoPlus(p,(MagickRealType) (1.0-area)*alpha,q,(MagickRealType)
180     (area*beta),composite);
181 }
182
183 static inline void CompositePixelInfoBlend(const PixelInfo *p,
184   const MagickRealType alpha,const PixelInfo *q,const MagickRealType beta,
185   PixelInfo *composite)
186 {
187   /*
188     Blend pixel colors p and q by the amount given.
189   */
190   CompositePixelInfoPlus(p,(MagickRealType) (alpha*p->alpha),q,(MagickRealType)
191     (beta*q->alpha),composite);
192 }
193
194 #if defined(__cplusplus) || defined(c_plusplus)
195 }
196 #endif
197
198 #endif