composite-private.h

Go to the documentation of this file.
00001 /*
00002   Copyright 1999-2020 ImageMagick Studio LLC, a non-profit organization
00003   dedicated to making software imaging solutions freely available.
00004 
00005   You may not use this file except in compliance with the License.  You may
00006   obtain a copy of the License at
00007 
00008     https://imagemagick.org/script/license.php
00009 
00010   Unless required by applicable law or agreed to in writing, software
00011   distributed under the License is distributed on an "AS IS" BASIS,
00012   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013   See the License for the specific language governing permissions and
00014   limitations under the License.
00015 
00016   MagickCore image composite private methods.
00017 */
00018 #ifndef MAGICKCORE_COMPOSITE_PRIVATE_H
00019 #define MAGICKCORE_COMPOSITE_PRIVATE_H
00020 
00021 
00022 #include "MagickCore/color.h"
00023 #include "MagickCore/image.h"
00024 #include "MagickCore/image-private.h"
00025 #include "MagickCore/pixel-accessor.h"
00026 #include "MagickCore/pixel-private.h"
00027 
00028 #if defined(__cplusplus) || defined(c_plusplus)
00029 extern "C" {
00030 #endif
00031 
00032 /*
00033   ImageMagick Alpha Composite Inline Methods (special export)
00034 */
00035 static inline double MagickOver_(const double p,const double alpha,
00036   const double q,const double beta)
00037 {
00038   double
00039     Da,
00040     Sa;
00041 
00042   Sa=QuantumScale*alpha;
00043   Da=QuantumScale*beta;
00044   return(Sa*p+Da*q*(1.0-Sa));
00045 }
00046 
00047 static inline double RoundToUnity(const double value)
00048 {
00049   return(value < 0.0 ? 0.0 : (value > 1.0) ? 1.0 : value);
00050 }
00051 
00052 static inline void CompositePixelOver(const Image *image,const PixelInfo *p,
00053   const double alpha,const Quantum *q,const double beta,Quantum *composite)
00054 {
00055   double
00056     Da,
00057     gamma,
00058     Sa;
00059 
00060   register ssize_t
00061     i;
00062 
00063   /*
00064     Compose pixel p over pixel q with the given alpha.
00065   */
00066   Sa=QuantumScale*alpha;
00067   Da=QuantumScale*beta;
00068   gamma=Sa+Da-Sa*Da;
00069   gamma=PerceptibleReciprocal(gamma);
00070   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
00071   {
00072     PixelChannel
00073       channel;
00074 
00075     PixelTrait
00076       traits;
00077 
00078     channel=GetPixelChannelChannel(image,i);
00079     traits=GetPixelChannelTraits(image,channel);
00080     if (traits == UndefinedPixelTrait)
00081       continue;
00082     switch (channel)
00083     {
00084       case RedPixelChannel:
00085       {
00086         composite[i]=ClampToQuantum(gamma*MagickOver_((double) p->red,alpha,
00087           (double) q[i],beta));
00088         break;
00089       }
00090       case GreenPixelChannel:
00091       {
00092         composite[i]=ClampToQuantum(gamma*MagickOver_((double) p->green,alpha,
00093           (double) q[i],beta));
00094         break;
00095       }
00096       case BluePixelChannel:
00097       {
00098         composite[i]=ClampToQuantum(gamma*MagickOver_((double) p->blue,alpha,
00099           (double) q[i],beta));
00100         break;
00101       }
00102       case BlackPixelChannel:
00103       {
00104         composite[i]=ClampToQuantum(gamma*MagickOver_((double) p->black,alpha,
00105           (double) q[i],beta));
00106         break;
00107       }
00108       case AlphaPixelChannel:
00109       {
00110         composite[i]=ClampToQuantum(QuantumRange*RoundToUnity(Sa+Da-Sa*Da));
00111         break;
00112       }
00113       default:
00114       {
00115         composite[i]=q[i];
00116         break;
00117       }
00118     }
00119   }
00120 }
00121 
00122 static inline void CompositePixelInfoOver(const PixelInfo *p,const double alpha,
00123   const PixelInfo *q,const double beta,PixelInfo *composite)
00124 {
00125   double
00126     Da,
00127     gamma,
00128     Sa;
00129 
00130   /*
00131     Compose pixel p over pixel q with the given opacities.
00132   */
00133   Sa=QuantumScale*alpha;
00134   Da=QuantumScale*beta,
00135   gamma=Sa+Da-Sa*Da;
00136   composite->alpha=(double) QuantumRange*RoundToUnity(gamma);
00137   gamma=PerceptibleReciprocal(gamma);
00138   composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
00139   composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
00140   composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
00141   if (q->colorspace == CMYKColorspace)
00142     composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
00143 }
00144 
00145 static inline void CompositePixelInfoPlus(const PixelInfo *p,
00146   const double alpha,const PixelInfo *q,const double beta,PixelInfo *composite)
00147 {
00148   double
00149     Da,
00150     gamma,
00151     Sa;
00152 
00153   /*
00154     Add two pixels with the given opacities.
00155   */
00156   Sa=QuantumScale*alpha;
00157   Da=QuantumScale*beta;
00158   gamma=RoundToUnity(Sa+Da);  /* 'Plus' blending -- not 'Over' blending */
00159   composite->alpha=(double) QuantumRange*RoundToUnity(gamma);
00160   gamma=PerceptibleReciprocal(gamma);
00161   composite->red=gamma*(Sa*p->red+Da*q->red);
00162   composite->green=gamma*(Sa*p->green+Da*q->green);
00163   composite->blue=gamma*(Sa*p->blue+Da*q->blue);
00164   if (q->colorspace == CMYKColorspace)
00165     composite->black=gamma*(Sa*p->black+Da*q->black);
00166 }
00167 
00168 static inline void CompositePixelInfoAreaBlend(const PixelInfo *p,
00169   const double alpha,const PixelInfo *q,const double beta,const double area,
00170   PixelInfo *composite)
00171 {
00172   /*
00173     Blend pixel colors p and q by the amount given and area.
00174   */
00175   CompositePixelInfoPlus(p,(double) (1.0-area)*alpha,q,(double) (area*beta),
00176     composite);
00177 }
00178 
00179 static inline void CompositePixelInfoBlend(const PixelInfo *p,
00180   const double alpha,const PixelInfo *q,const double beta,PixelInfo *composite)
00181 {
00182   /*
00183     Blend pixel colors p and q by the amount given.
00184   */
00185   CompositePixelInfoPlus(p,(double) (alpha*p->alpha),q,(double) (beta*q->alpha),
00186     composite);
00187 }
00188 
00189 static inline MagickBooleanType GetCompositeClipToSelf(
00190   const CompositeOperator compose)
00191 {
00192   switch (compose)
00193   {
00194     case ClearCompositeOp:
00195     case SrcCompositeOp:
00196     case InCompositeOp:
00197     case SrcInCompositeOp:
00198     case OutCompositeOp:
00199     case SrcOutCompositeOp:
00200     case DstInCompositeOp:
00201     case DstAtopCompositeOp:
00202     case CopyAlphaCompositeOp:
00203     case ChangeMaskCompositeOp:
00204     {
00205       return(MagickFalse);
00206       break;
00207     }
00208     default:
00209       break;
00210   }
00211   return(MagickTrue);
00212 }
00213 
00214 #if defined(__cplusplus) || defined(c_plusplus)
00215 }
00216 #endif
00217 
00218 #endif

Generated on 2 Mar 2020 for MagickCore by  doxygen 1.6.1