MagickCore  7.1.0
composite-private.h
Go to the documentation of this file.
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"
26 
27 #if defined(__cplusplus) || defined(c_plusplus)
28 extern "C" {
29 #endif
30 
31 /*
32  ImageMagick Alpha Composite Inline Methods (special export)
33 */
34 static inline double MagickOver_(const double p,const double alpha,
35  const double q,const double beta)
36 {
37  double
38  Da,
39  Sa;
40 
41  Sa=QuantumScale*alpha;
42  Da=QuantumScale*beta;
43  return(Sa*p+Da*q*(1.0-Sa));
44 }
45 
46 static inline double RoundToUnity(const double value)
47 {
48  return(value < 0.0 ? 0.0 : (value > 1.0) ? 1.0 : value);
49 }
50 
51 static inline void CompositePixelOver(const Image *image,const PixelInfo *p,
52  const double alpha,const Quantum *q,const double beta,Quantum *composite)
53 {
54  double
55  Da,
56  gamma,
57  Sa;
58 
59  ssize_t
60  i;
61 
62  /*
63  Compose pixel p over pixel q with the given alpha.
64  */
65  Sa=QuantumScale*alpha;
66  Da=QuantumScale*beta;
67  gamma=Sa+Da-Sa*Da;
68  gamma=PerceptibleReciprocal(gamma);
69  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
70  {
72  channel;
73 
75  traits;
76 
77  channel=GetPixelChannelChannel(image,i);
78  traits=GetPixelChannelTraits(image,channel);
79  if (traits == UndefinedPixelTrait)
80  continue;
81  switch (channel)
82  {
83  case RedPixelChannel:
84  {
85  composite[i]=ClampToQuantum(gamma*MagickOver_((double) p->red,alpha,
86  (double) q[i],beta));
87  break;
88  }
89  case GreenPixelChannel:
90  {
91  composite[i]=ClampToQuantum(gamma*MagickOver_((double) p->green,alpha,
92  (double) q[i],beta));
93  break;
94  }
95  case BluePixelChannel:
96  {
97  composite[i]=ClampToQuantum(gamma*MagickOver_((double) p->blue,alpha,
98  (double) q[i],beta));
99  break;
100  }
101  case BlackPixelChannel:
102  {
103  composite[i]=ClampToQuantum(gamma*MagickOver_((double) p->black,alpha,
104  (double) q[i],beta));
105  break;
106  }
107  case AlphaPixelChannel:
108  {
109  composite[i]=ClampToQuantum(QuantumRange*RoundToUnity(Sa+Da-Sa*Da));
110  break;
111  }
112  default:
113  {
114  composite[i]=q[i];
115  break;
116  }
117  }
118  }
119 }
120 
121 static inline void CompositePixelInfoOver(const PixelInfo *p,const double alpha,
122  const PixelInfo *q,const double beta,PixelInfo *composite)
123 {
124  double
125  Da,
126  gamma,
127  Sa;
128 
129  /*
130  Compose pixel p over pixel q with the given opacities.
131  */
132  Sa=QuantumScale*alpha;
133  Da=QuantumScale*beta,
134  gamma=Sa+Da-Sa*Da;
135  composite->alpha=(double) QuantumRange*RoundToUnity(gamma);
136  gamma=PerceptibleReciprocal(gamma);
137  composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
138  composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
139  composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
140  if (q->colorspace == CMYKColorspace)
141  composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
142 }
143 
144 static inline void CompositePixelInfoPlus(const PixelInfo *p,
145  const double alpha,const PixelInfo *q,const double beta,PixelInfo *composite)
146 {
147  double
148  Da,
149  gamma,
150  Sa;
151 
152  /*
153  Add two pixels with the given opacities.
154  */
155  Sa=QuantumScale*alpha;
156  Da=QuantumScale*beta;
157  gamma=RoundToUnity(Sa+Da); /* 'Plus' blending -- not 'Over' blending */
158  composite->alpha=(double) QuantumRange*RoundToUnity(gamma);
159  gamma=PerceptibleReciprocal(gamma);
160  composite->red=gamma*(Sa*p->red+Da*q->red);
161  composite->green=gamma*(Sa*p->green+Da*q->green);
162  composite->blue=gamma*(Sa*p->blue+Da*q->blue);
163  if (q->colorspace == CMYKColorspace)
164  composite->black=gamma*(Sa*p->black+Da*q->black);
165 }
166 
167 static inline void CompositePixelInfoAreaBlend(const PixelInfo *p,
168  const double alpha,const PixelInfo *q,const double beta,const double area,
169  PixelInfo *composite)
170 {
171  /*
172  Blend pixel colors p and q by the amount given and area.
173  */
174  CompositePixelInfoPlus(p,(double) (1.0-area)*alpha,q,(double) (area*beta),
175  composite);
176 }
177 
178 static inline void CompositePixelInfoBlend(const PixelInfo *p,
179  const double alpha,const PixelInfo *q,const double beta,PixelInfo *composite)
180 {
181  /*
182  Blend pixel colors p and q by the amount given.
183  */
184  CompositePixelInfoPlus(p,(double) (alpha*p->alpha),q,(double) (beta*q->alpha),
185  composite);
186 }
187 
189  const CompositeOperator compose)
190 {
191  switch (compose)
192  {
193  case ClearCompositeOp:
194  case SrcCompositeOp:
195  case InCompositeOp:
196  case SrcInCompositeOp:
197  case OutCompositeOp:
198  case SrcOutCompositeOp:
199  case DstInCompositeOp:
200  case DstAtopCompositeOp:
203  {
204  return(MagickFalse);
205  break;
206  }
207  default:
208  break;
209  }
210  return(MagickTrue);
211 }
212 
213 #if defined(__cplusplus) || defined(c_plusplus)
214 }
215 #endif
216 
217 #endif
static double MagickOver_(const double p, const double alpha, const double q, const double beta)
static void CompositePixelInfoPlus(const PixelInfo *p, const double alpha, const PixelInfo *q, const double beta, PixelInfo *composite)
MagickRealType red
Definition: pixel.h:193
static PixelTrait GetPixelChannelTraits(const Image *magick_restrict image, const PixelChannel channel)
MagickRealType alpha
Definition: pixel.h:193
static Quantum ClampToQuantum(const MagickRealType quantum)
Definition: quantum.h:85
Definition: image.h:151
MagickBooleanType
Definition: magick-type.h:161
static double PerceptibleReciprocal(const double x)
static void CompositePixelInfoOver(const PixelInfo *p, const double alpha, const PixelInfo *q, const double beta, PixelInfo *composite)
static void CompositePixelInfoAreaBlend(const PixelInfo *p, const double alpha, const PixelInfo *q, const double beta, const double area, PixelInfo *composite)
MagickRealType blue
Definition: pixel.h:193
#define QuantumScale
Definition: magick-type.h:119
PixelChannel
Definition: pixel.h:70
static double RoundToUnity(const double value)
static size_t GetPixelChannels(const Image *magick_restrict image)
static MagickBooleanType GetCompositeClipToSelf(const CompositeOperator compose)
static PixelChannel GetPixelChannelChannel(const Image *magick_restrict image, const ssize_t offset)
unsigned short Quantum
Definition: magick-type.h:86
MagickRealType black
Definition: pixel.h:193
MagickRealType green
Definition: pixel.h:193
CompositeOperator
Definition: composite.h:25
static void CompositePixelInfoBlend(const PixelInfo *p, const double alpha, const PixelInfo *q, const double beta, PixelInfo *composite)
ColorspaceType colorspace
Definition: pixel.h:178
PixelTrait
Definition: pixel.h:137
#define QuantumRange
Definition: magick-type.h:87
static void CompositePixelOver(const Image *image, const PixelInfo *p, const double alpha, const Quantum *q, const double beta, Quantum *composite)