Home | History | Annotate | Download | only in MagickCore
      1 /*
      2   Copyright 1999-2016 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,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+Da*q*(1.0-Sa));
     45 }
     46 
     47 static inline double RoundToUnity(const double value)
     48 {
     49   return(value < 0.0 ? 0.0 : (value > 1.0) ? 1.0 : value);
     50 }
     51 
     52 static inline void CompositePixelOver(const Image *image,const PixelInfo *p,
     53   const double alpha,const Quantum *q,const double beta,Quantum *composite)
     54 {
     55   double
     56     Da,
     57     gamma,
     58     Sa;
     59 
     60   register ssize_t
     61     i;
     62 
     63   /*
     64     Compose pixel p over pixel q with the given alpha.
     65   */
     66   Sa=QuantumScale*alpha;
     67   Da=QuantumScale*beta;
     68   gamma=Sa+Da-Sa*Da;
     69   gamma=PerceptibleReciprocal(gamma);
     70   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
     71   {
     72     PixelChannel
     73       channel;
     74 
     75     PixelTrait
     76       traits;
     77 
     78     channel=GetPixelChannelChannel(image,i);
     79     traits=GetPixelChannelTraits(image,channel);
     80     if (traits == UndefinedPixelTrait)
     81       continue;
     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*RoundToUnity(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   Sa=QuantumScale*alpha;
    134   Da=QuantumScale*beta,
    135   gamma=Sa+Da-Sa*Da;
    136   composite->alpha=(double) QuantumRange*RoundToUnity(gamma);
    137   gamma=PerceptibleReciprocal(gamma);
    138   composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
    139   composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
    140   composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
    141   if (q->colorspace == CMYKColorspace)
    142     composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
    143 }
    144 
    145 static inline void CompositePixelInfoPlus(const PixelInfo *p,
    146   const double alpha,const PixelInfo *q,const double beta,PixelInfo *composite)
    147 {
    148   double
    149     Da,
    150     gamma,
    151     Sa;
    152 
    153   /*
    154     Add two pixels with the given opacities.
    155   */
    156   Sa=QuantumScale*alpha;
    157   Da=QuantumScale*beta;
    158   gamma=RoundToUnity(Sa+Da);  /* 'Plus' blending -- not 'Over' blending */
    159   composite->alpha=(double) QuantumRange*RoundToUnity(gamma);
    160   gamma=PerceptibleReciprocal(gamma);
    161   composite->red=gamma*(Sa*p->red+Da*q->red);
    162   composite->green=gamma*(Sa*p->green+Da*q->green);
    163   composite->blue=gamma*(Sa*p->blue+Da*q->blue);
    164   if (q->colorspace == CMYKColorspace)
    165     composite->black=gamma*(Sa*p->black+Da*q->black);
    166 }
    167 
    168 static inline void CompositePixelInfoAreaBlend(const PixelInfo *p,
    169   const double alpha,const PixelInfo *q,const double beta,const double area,
    170   PixelInfo *composite)
    171 {
    172   /*
    173     Blend pixel colors p and q by the amount given and area.
    174   */
    175   CompositePixelInfoPlus(p,(double) (1.0-area)*alpha,q,(double) (area*beta),
    176     composite);
    177 }
    178 
    179 static inline void CompositePixelInfoBlend(const PixelInfo *p,
    180   const double alpha,const PixelInfo *q,const double beta,PixelInfo *composite)
    181 {
    182   /*
    183     Blend pixel colors p and q by the amount given.
    184   */
    185   CompositePixelInfoPlus(p,(double) (alpha*p->alpha),q,(double) (beta*q->alpha),
    186     composite);
    187 }
    188 
    189 #if defined(__cplusplus) || defined(c_plusplus)
    190 }
    191 #endif
    192 
    193 #endif
    194