]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/composite.c
(no commit message)
[imagemagick] / MagickCore / composite.c
index 428d827b4d1a394274d573c5adf8ec4690c7210a..7ce26528f87ec21e1237131828d20c1a6e3935b2 100644 (file)
@@ -72,6 +72,7 @@
 #include "MagickCore/string_.h"
 #include "MagickCore/thread-private.h"
 #include "MagickCore/utility.h"
+#include "MagickCore/utility-private.h"
 #include "MagickCore/version.h"
 \f
 /*
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   C o m p o s i t e I m a g e C h a n n e l                                 %
+%   C o m p o s i t e I m a g e                                               %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  CompositeImageChannel() returns the second image composited onto the first
+%  CompositeImage() returns the second image composited onto the first
 %  at the specified offset, using the specified composite method.
 %
-%  The format of the CompositeImageChannel method is:
+%  The format of the CompositeImage method is:
 %
 %      MagickBooleanType CompositeImage(Image *image,
 %        const CompositeOperator compose,Image *composite_image,
-%        const ssize_t x_offset,const ssize_t y_offset)
-%      MagickBooleanType CompositeImageChannel(Image *image,
-%        const ChannelType channel,const CompositeOperator compose,
-%        Image *composite_image,const ssize_t x_offset,const ssize_t y_offset)
+%        const ssize_t x_offset,const ssize_t y_offset,ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
 %    o image: the destination image, modified by he composition
 %
-%    o channel: the channel.
-%
 %    o compose: This operator affects how the composite is applied to
 %      the image.  The operators and how they are utilized are listed here
 %      http://www.w3.org/TR/SVG12/#compositing.
 %
 %        Previous to IM v6.5.3-3  this was called "modify-outside-overlay"
 %
+%    o exception: return any errors or warnings in this structure.
+%
 */
 
 static inline double MagickMin(const double x,const double y)
@@ -333,8 +331,8 @@ static inline MagickRealType Darken(const MagickRealType p,
   return(MagickOver_(q,beta,p,alpha));    /* dst-over */
 }
 
-static inline void CompositeDarken(const PixelInfo *p,const PixelInfo *q,
-  const ChannelType channel,PixelInfo *composite)
+static inline void CompositeDarken(const Image *image,const PixelInfo *p,
+  const PixelInfo *q,PixelInfo *composite)
 {
   MagickRealType
     gamma;
@@ -343,21 +341,21 @@ static inline void CompositeDarken(const PixelInfo *p,const PixelInfo *q,
     Darken is equivalent to a 'Minimum' method OR a greyscale version of a
     binary 'Or' OR the 'Intersection' of pixel sets.
   */
-  if ((channel & SyncChannels) == 0)
+  if (image->sync == MagickFalse)
     {
       /*
         Handle channels as separate grayscale channels.
       */
-      if ((channel & RedChannel) != 0)
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         composite->red=MagickMin(p->red,q->red);
-      if ((channel & GreenChannel) != 0)
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         composite->green=MagickMin(p->green,q->green);
-      if ((channel & BlueChannel) != 0)
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         composite->blue=MagickMin(p->blue,q->blue);
-      if ((channel & BlackChannel) != 0 &&
+      if ((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0 &&
           (q->colorspace == CMYKColorspace))
         composite->black=MagickMin(p->black,q->black);
-      if ((channel & AlphaChannel) != 0)
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         composite->alpha=MagickMax(p->alpha,q->alpha);
       return;
     }
@@ -371,8 +369,8 @@ static inline void CompositeDarken(const PixelInfo *p,const PixelInfo *q,
     composite->black=gamma*Darken(p->black,p->alpha,q->black,q->alpha);
 }
 
-static inline void CompositeDarkenIntensity(const PixelInfo *p,
-  const PixelInfo *q,const ChannelType channel,PixelInfo *composite)
+static inline void CompositeDarkenIntensity(const Image *image,
+  const PixelInfo *p,const PixelInfo *q,PixelInfo *composite)
 {
   MagickRealType
     Da,
@@ -383,23 +381,23 @@ static inline void CompositeDarkenIntensity(const PixelInfo *p,
     If 'Sync' flag select whole pixel based on alpha weighted intensity.
     Otherwise use intensity only, but restrict copy according to channel.
   */
-  if ((channel & SyncChannels) == 0)
+  if (image->sync == MagickFalse)
     {
       MagickBooleanType
         from_p;
 
       from_p=GetPixelInfoIntensity(p) < GetPixelInfoIntensity(q) ? MagickTrue :
         MagickFalse;
-      if ((channel & RedChannel) != 0)
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         composite->red=from_p != MagickFalse ? p->red : q->red;
-      if ((channel & GreenChannel) != 0)
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         composite->green=from_p != MagickFalse ? p->green : q->green;
-      if ((channel & BlueChannel) != 0)
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         composite->blue=from_p != MagickFalse ? p->blue : q->blue;
-      if (((channel & BlackChannel) != 0) &&
+      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
           (q->colorspace == CMYKColorspace))
         composite->black=from_p != MagickFalse ? p->black : q->black;
-      if ((channel & AlphaChannel) != 0)
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         composite->alpha=from_p != MagickFalse ? p->alpha : q->alpha;
       return;
     }
@@ -418,8 +416,8 @@ static inline MagickRealType Difference(const MagickRealType p,
   return(Sa*p+Da*q-Sa*Da*2.0*MagickMin(p,q));
 }
 
-static inline void CompositeDifference(const PixelInfo *p,
-  const PixelInfo *q,const ChannelType channel,PixelInfo *composite)
+static inline void CompositeDifference(const Image *image,const PixelInfo *p,
+  const PixelInfo *q,PixelInfo *composite)
 {
   MagickRealType
     Da,
@@ -428,21 +426,21 @@ static inline void CompositeDifference(const PixelInfo *p,
 
   Sa=QuantumScale*p->alpha;  /* simplify and speed up equations */
   Da=QuantumScale*q->alpha;
-  if ((channel & SyncChannels) == 0)
+  if (image->sync == MagickFalse)
     {
       /*
         Handle channels as separate grayscale channels.
       */
-      if ((channel & RedChannel) != 0)
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         composite->red=fabs((double) (p->red-q->red));
-      if ((channel & GreenChannel) != 0)
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         composite->green=fabs((double) (p->green-q->green));
-      if ((channel & BlueChannel) != 0)
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         composite->blue=fabs((double) (p->blue-q->blue));
-      if (((channel & BlackChannel) != 0) &&
+      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
           (q->colorspace == CMYKColorspace))
         composite->black=fabs((double) (p->black-q->black));
-      if ((channel & AlphaChannel) != 0)
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         composite->alpha=fabs((double) (p->alpha-q->alpha));
      return;
    }
@@ -476,8 +474,8 @@ static MagickRealType Divide(const MagickRealType Sca,const MagickRealType Sa,
   return(Sca*Da*Da/Dca+Sca*(1.0-Da)+Dca*(1.0-Sa));
 }
 
-static inline void CompositeDivide(const PixelInfo *p,const PixelInfo *q,
-  const ChannelType channel,PixelInfo *composite)
+static inline void CompositeDivide(const Image *image,const PixelInfo *p,
+  const PixelInfo *q,PixelInfo *composite)
 {
   MagickRealType
     Da,
@@ -486,25 +484,25 @@ static inline void CompositeDivide(const PixelInfo *p,const PixelInfo *q,
 
   Sa=QuantumScale*p->alpha;  /* simplify and speed up equations */
   Da=QuantumScale*q->alpha;
-  if ((channel & SyncChannels) == 0)
+  if (image->sync == MagickFalse)
     {
       /*
         Handle channels as separate grayscale channels.
       */
-      if ((channel & RedChannel) != 0)
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         composite->red=QuantumRange*Divide(QuantumScale*p->red,1.0,
           QuantumScale*q->red,1.0);
-      if ((channel & GreenChannel) != 0)
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         composite->green=QuantumRange*Divide(QuantumScale*p->green,1.0,
           QuantumScale*q->green,1.0);
-      if ((channel & BlueChannel) != 0)
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         composite->blue=QuantumRange*Divide(QuantumScale*p->blue,1.0,
           QuantumScale*q->blue,1.0);
-      if (((channel & BlackChannel) != 0) &&
+      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
           (q->colorspace == CMYKColorspace))
         composite->black=QuantumRange*Divide(QuantumScale*p->black,1.0,
           QuantumScale*q->black,1.0);
-      if ((channel & AlphaChannel) != 0)
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         composite->alpha=QuantumRange*(1.0-Divide(Sa,1.0,Da,1.0));
       return;
     }
@@ -528,8 +526,8 @@ static MagickRealType Exclusion(const MagickRealType Sca,
   return(Sca*Da+Dca*Sa-2.0*Sca*Dca+Sca*(1.0-Da)+Dca*(1.0-Sa));
 }
 
-static inline void CompositeExclusion(const PixelInfo *p,const PixelInfo *q,
-  const ChannelType channel,PixelInfo *composite)
+static inline void CompositeExclusion(const Image *image,const PixelInfo *p,
+  const PixelInfo *q,PixelInfo *composite)
 {
   MagickRealType
     gamma,
@@ -538,25 +536,25 @@ static inline void CompositeExclusion(const PixelInfo *p,const PixelInfo *q,
 
   Sa=QuantumScale*p->alpha;  /* simplify and speed up equations */
   Da=QuantumScale*q->alpha;
-  if ((channel & SyncChannels) == 0)
+  if (image->sync == MagickFalse)
     {
       /*
         Handle channels as separate grayscale channels.
       */
-      if ((channel & RedChannel) != 0)
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         composite->red=QuantumRange*Exclusion(QuantumScale*p->red,1.0,
           QuantumScale*q->red,1.0);
-      if ((channel & GreenChannel) != 0)
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         composite->green=QuantumRange*Exclusion(QuantumScale*p->green,1.0,
           QuantumScale*q->green,1.0);
-      if ((channel & BlueChannel) != 0)
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         composite->blue=QuantumRange*Exclusion(QuantumScale*p->blue,1.0,
           QuantumScale*q->blue,1.0);
-      if (((channel & BlackChannel) != 0) &&
+      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
           (q->colorspace == CMYKColorspace))
         composite->black=QuantumRange*Exclusion(QuantumScale*p->black,1.0,
           QuantumScale*q->black,1.0);
-      if ((channel & AlphaChannel) != 0)
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         composite->alpha=QuantumRange*(1.0-Exclusion(Sa,1.0,Da,1.0));
       return;
     }
@@ -629,19 +627,19 @@ static void CompositeHSB(const MagickRealType red,const MagickRealType green,
   *hue=0.0;
   *saturation=0.0;
   *brightness=(double) (QuantumScale*max);
-  if (max == 0.0)
+  if (fabs(max) < MagickEpsilon)
     return;
   *saturation=(double) (1.0-min/max);
   delta=max-min;
-  if (delta == 0.0)
+  if (fabs(delta) < MagickEpsilon)
     return;
-  if (red == max)
+  if (fabs(red-max) < MagickEpsilon)
     *hue=(double) ((green-blue)/delta);
   else
-    if (green == max)
+    if (fabs(green-max) < MagickEpsilon)
       *hue=(double) (2.0+(blue-red)/delta);
     else
-      if (blue == max)
+      if (fabs(blue-max) < MagickEpsilon)
         *hue=(double) (4.0+(red-green)/delta);
   *hue/=6.0;
   if (*hue < 0.0)
@@ -682,8 +680,8 @@ static inline MagickRealType Lighten(const MagickRealType p,
    return(MagickOver_(q,beta,p,alpha));    /* dst-over */
 }
 
-static inline void CompositeLighten(const PixelInfo *p,const PixelInfo *q,
-  const ChannelType channel,PixelInfo *composite)
+static inline void CompositeLighten(const Image *image,const PixelInfo *p,
+  const PixelInfo *q,PixelInfo *composite)
 {
   MagickRealType
     gamma;
@@ -692,21 +690,21 @@ static inline void CompositeLighten(const PixelInfo *p,const PixelInfo *q,
     Lighten is also equvalent to a 'Maximum' method OR a greyscale version of a
     binary 'And' OR the 'Union' of pixel sets.
   */
-  if ((channel & SyncChannels) == 0)
+  if (image->sync == MagickFalse)
     {
       /*
         Handle channels as separate grayscale channels
       */
-      if ((channel & RedChannel) != 0)
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         composite->red=MagickMax(p->red,q->red);
-      if ((channel & GreenChannel) != 0)
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         composite->green=MagickMax(p->green,q->green);
-      if ((channel & BlueChannel) != 0)
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         composite->blue=MagickMax(p->blue,q->blue);
-      if (((channel & BlackChannel) != 0) &&
+      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
           (q->colorspace == CMYKColorspace))
         composite->black=MagickMax(p->black,q->black);
-      if ((channel & AlphaChannel) != 0)
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         composite->alpha=MagickMin(p->alpha,q->alpha);
       return;
     }
@@ -720,8 +718,8 @@ static inline void CompositeLighten(const PixelInfo *p,const PixelInfo *q,
     composite->black=gamma*Lighten(p->black,p->alpha,q->black,q->alpha);
 }
 
-static inline void CompositeLightenIntensity(const PixelInfo *p,
-  const PixelInfo *q,const ChannelType channel,PixelInfo *composite)
+static inline void CompositeLightenIntensity(const Image *image,
+  const PixelInfo *p,const PixelInfo *q,PixelInfo *composite)
 {
   MagickRealType
     Da,
@@ -732,23 +730,23 @@ static inline void CompositeLightenIntensity(const PixelInfo *p,
     If 'Sync' flag select whole pixel based on alpha weighted intensity.
     Otherwise use Intenisty only, but restrict copy according to channel.
   */
-  if ((channel & SyncChannels) == 0)
+  if (image->sync == MagickFalse)
     {
       MagickBooleanType
         from_p;
 
       from_p=GetPixelInfoIntensity(p) > GetPixelInfoIntensity(q) ? MagickTrue :
         MagickFalse;
-      if ((channel & RedChannel) != 0)
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         composite->red=from_p != MagickFalse ? p->red : q->red;
-      if ((channel & GreenChannel) != 0)
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         composite->green=from_p != MagickFalse ? p->green : q->green;
-      if ((channel & BlueChannel) != 0)
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         composite->blue=from_p != MagickFalse ? p->blue : q->blue;
-      if (((channel & BlackChannel) != 0) &&
+      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
           (q->colorspace == CMYKColorspace))
         composite->black=from_p != MagickFalse ? p->black : q->black;
-      if ((channel & AlphaChannel) != 0)
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         composite->alpha=from_p != MagickFalse ? p->alpha : q->alpha;
       return;
     }
@@ -882,8 +880,8 @@ static inline MagickRealType Mathematics(const MagickRealType Sca,
   return(gamma);
 }
 
-static inline void CompositeMathematics(const PixelInfo *p,const PixelInfo *q,
-  const ChannelType channel, const GeometryInfo *args, PixelInfo *composite)
+static inline void CompositeMathematics(const Image *image,const PixelInfo *p,
+  const PixelInfo *q,const GeometryInfo *args,PixelInfo *composite)
 {
   MagickRealType
     Da,
@@ -892,25 +890,25 @@ static inline void CompositeMathematics(const PixelInfo *p,const PixelInfo *q,
 
   Sa=QuantumScale*p->alpha; /* ??? - AT */
   Da=QuantumScale*q->alpha;
-  if ((channel & SyncChannels) == 0)
+  if (image->sync == MagickFalse)
     {
       /*
         Handle channels as separate grayscale channels.
       */
-      if ((channel & RedChannel) != 0)
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         composite->red=QuantumRange*Mathematics(QuantumScale*p->red,1.0,
           QuantumScale*q->red,1.0,args);
-      if ((channel & GreenChannel) != 0)
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         composite->green=QuantumRange*Mathematics(QuantumScale*p->green,1.0,
           QuantumScale*q->green,1.0,args);
-      if ((channel & BlueChannel) != 0)
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         composite->blue=QuantumRange*Mathematics(QuantumScale*p->blue,1.0,
           QuantumScale*q->blue,1.0,args);
-      if (((channel & BlackChannel) != 0) &&
+      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
           (q->colorspace == CMYKColorspace))
         composite->black=QuantumRange*Mathematics(QuantumScale*p->black,1.0,
           QuantumScale*q->black,1.0,args);
-      if ((channel & AlphaChannel) != 0)
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         composite->alpha=QuantumRange*(1.0-Mathematics(Sa,1.0,Da,1.0,args));
       return;
     }
@@ -928,8 +926,8 @@ static inline void CompositeMathematics(const PixelInfo *p,const PixelInfo *q,
       QuantumScale*q->black*Da,Da,args);
 }
 
-static inline void CompositePlus(const PixelInfo *p,const PixelInfo *q,
-  const ChannelType channel,PixelInfo *composite)
+static inline void CompositePlus(const Image *image,const PixelInfo *p,
+  const PixelInfo *q,PixelInfo *composite)
 {
   /*
     NOTE: "Plus" does not use 'over' alpha-blending but uses a special
@@ -946,21 +944,21 @@ static inline void CompositePlus(const PixelInfo *p,const PixelInfo *q,
     The CompositePixelInfoPlus() function is defined in
     "composite-private.h" so it can also be used for Image Blending.
   */
-  if ((channel & SyncChannels) == 0)
+  if (image->sync == MagickFalse)
     {
       /*
         Handle channels as separate grayscale channels.
       */
-      if ((channel & RedChannel) != 0)
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         composite->red=p->red+q->red;
-      if ((channel & GreenChannel) != 0)
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         composite->green=p->green+q->green;
-      if ((channel & BlueChannel) != 0)
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         composite->blue=p->blue+q->blue;
-      if (((channel & BlackChannel) != 0) &&
+      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
           (q->colorspace == CMYKColorspace))
         composite->black=p->black+q->black;
-      if ((channel & AlphaChannel) != 0)
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         composite->alpha=p->alpha+q->alpha-QuantumRange;
       return;
     }
@@ -979,8 +977,8 @@ static inline MagickRealType Minus(const MagickRealType Sca,
   return(Sca+Dca-2.0*Dca*Sa);
 }
 
-static inline void CompositeMinus(const PixelInfo *p,const PixelInfo *q,
-  const ChannelType channel,PixelInfo *composite)
+static inline void CompositeMinus(const Image *image,const PixelInfo *p,
+  const PixelInfo *q,PixelInfo *composite)
 {
   MagickRealType
     Da,
@@ -989,21 +987,21 @@ static inline void CompositeMinus(const PixelInfo *p,const PixelInfo *q,
 
   Sa=QuantumScale*p->alpha;  /* simplify and speed up equations */
   Da=QuantumScale*q->alpha;
-  if ((channel & SyncChannels) == 0)
+  if (image->sync == MagickFalse)
     {
       /*
         Handle channels as separate grayscale channels.
       */
-      if ((channel & RedChannel) != 0)
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         composite->red=p->red-q->red;
-      if ((channel & GreenChannel) != 0)
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         composite->green=p->green-q->green;
-      if ((channel & BlueChannel) != 0)
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         composite->blue=p->blue-q->blue;
-      if (((channel & BlackChannel) != 0) &&
+      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
           (q->colorspace == CMYKColorspace))
         composite->black=p->black-q->black;
-      if ((channel & AlphaChannel) != 0)
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         composite->alpha=QuantumRange*(1.0-(Sa-Da));
       return;
     }
@@ -1029,29 +1027,29 @@ static inline MagickRealType ModulusAdd(const MagickRealType p,
   return(pixel*Sa*Da+p*Sa*(1.0-Da)+q*Da*(1.0-Sa));
 }
 
-static inline void CompositeModulusAdd(const PixelInfo *p,const PixelInfo *q,
-  const ChannelType channel,PixelInfo *composite)
+static inline void CompositeModulusAdd(const Image *image,const PixelInfo *p,
+  const PixelInfo *q,PixelInfo *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  if ((channel & SyncChannels) == 0)
+  if (image->sync == MagickFalse)
     {
       /*
         Handle channels as separate grayscale channels.
       */
-      if ((channel & RedChannel) != 0)
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         composite->red=ModulusAdd(p->red,1.0,q->red,1.0);
-      if ((channel & GreenChannel) != 0)
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         composite->green=ModulusAdd(p->green,1.0,q->green,1.0);
-      if ((channel & BlueChannel) != 0)
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         composite->blue=ModulusAdd(p->blue,1.0,q->blue,1.0);
-      if (((channel & BlackChannel) != 0) &&
+      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
           (q->colorspace == CMYKColorspace))
         composite->black=ModulusAdd(p->black,1.0,q->black,1.0);
-      if ((channel & AlphaChannel) != 0)
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         composite->alpha=ModulusAdd(p->alpha,1.0,q->alpha,1.0);
       return;
     }
@@ -1079,29 +1077,29 @@ static inline MagickRealType ModulusSubtract(const MagickRealType p,
   return(pixel*Sa*Da+p*Sa*(1.0-Da)+q*Da*(1.0-Sa));
 }
 
-static inline void CompositeModulusSubtract(const PixelInfo *p,
-  const PixelInfo *q, const ChannelType channel,PixelInfo *composite)
+static inline void CompositeModulusSubtract(const Image *image,
+  const PixelInfo *p,const PixelInfo *q,PixelInfo *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  if ((channel & SyncChannels) == 0)
+  if (image->sync == MagickFalse)
     {
       /*
         Handle channels as separate grayscale channels,
       */
-      if ((channel & RedChannel) != 0)
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         composite->red=ModulusSubtract(p->red,1.0,q->red,1.0);
-      if ((channel & GreenChannel) != 0)
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         composite->green=ModulusSubtract(p->green,1.0,q->green,1.0);
-      if ((channel & BlueChannel) != 0)
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         composite->blue=ModulusSubtract(p->blue,1.0,q->blue,1.0);
-      if (((channel & BlackChannel) != 0) &&
+      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
           (q->colorspace == CMYKColorspace))
         composite->black=ModulusSubtract(p->black,1.0,q->black,1.0);
-      if ((channel & AlphaChannel) != 0)
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         composite->alpha=ModulusSubtract(p->alpha,1.0,q->alpha,1.0);
       return;
     }
@@ -1123,8 +1121,8 @@ static  inline MagickRealType Multiply(const MagickRealType Sca,
   return(Sca*Dca+Sca*(1.0-Da)+Dca*(1.0-Sa));
 }
 
-static inline void CompositeMultiply(const PixelInfo *p,const PixelInfo *q,
-  const ChannelType channel,PixelInfo *composite)
+static inline void CompositeMultiply(const Image *image,const PixelInfo *p,
+  const PixelInfo *q,PixelInfo *composite)
 {
   MagickRealType
     Da,
@@ -1133,21 +1131,21 @@ static inline void CompositeMultiply(const PixelInfo *p,const PixelInfo *q,
 
   Sa=QuantumScale*p->alpha;  /* simplify and speed up equations */
   Da=QuantumScale*q->alpha;
-  if ((channel & SyncChannels) == 0)
+  if (image->sync == MagickFalse)
     {
       /*
         Handle channels as separate grayscale channels.
       */
-      if ((channel & RedChannel) != 0)
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         composite->red=QuantumScale*p->red*q->red;
-      if ((channel & GreenChannel) != 0)
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         composite->green=QuantumScale*p->green*q->green;
-      if ((channel & BlueChannel) != 0)
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         composite->blue=QuantumScale*p->blue*q->blue;
-      if (((channel & BlackChannel) != 0) &&
+      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
           (q->colorspace == CMYKColorspace))
         composite->black=QuantumScale*p->black*q->black;
-      if ((channel & AlphaChannel) != 0)
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         composite->alpha=QuantumRange*(1.0-Sa*Da);
       return;
     }
@@ -1281,8 +1279,8 @@ static inline MagickRealType Screen(const MagickRealType Sca,
   return(Sca+Dca-Sca*Dca);
 }
 
-static inline void CompositeScreen(const PixelInfo *p,const PixelInfo *q,
-  const ChannelType channel,PixelInfo *composite)
+static inline void CompositeScreen(const Image *image,const PixelInfo *p,
+  const PixelInfo *q,PixelInfo *composite)
 {
   MagickRealType
     Da,
@@ -1291,25 +1289,25 @@ static inline void CompositeScreen(const PixelInfo *p,const PixelInfo *q,
 
   Sa=QuantumScale*p->alpha;  /* simplify and speed up equations */
   Da=QuantumScale*q->alpha;
-  if ((channel & SyncChannels) == 0)
+  if (image->sync == MagickFalse)
     {
       /*
         Handle channels as separate grayscale channels.
       */
-      if ((channel & RedChannel) != 0)
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         composite->red=QuantumRange*Screen(QuantumScale*p->red,
           QuantumScale*q->red);
-      if ((channel & GreenChannel) != 0)
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         composite->green=QuantumRange*Screen(QuantumScale*p->green,
           QuantumScale*q->green);
-      if ((channel & BlueChannel) != 0)
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         composite->blue=QuantumRange*Screen(QuantumScale*p->blue,
           QuantumScale*q->blue);
-      if (((channel & BlackChannel) != 0) &&
+      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
           (q->colorspace == CMYKColorspace))
         composite->black=QuantumRange*Screen(QuantumScale*p->black,
           QuantumScale*q->black);
-      if ((channel & AlphaChannel) != 0)
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         composite->alpha=QuantumRange*(1.0-Screen(Sa,Da));
       return;
     }
@@ -1549,19 +1547,7 @@ static void HSBComposite(const double hue,const double saturation,
 
 MagickExport MagickBooleanType CompositeImage(Image *image,
   const CompositeOperator compose,const Image *composite_image,
-  const ssize_t x_offset,const ssize_t y_offset)
-{
-  MagickBooleanType
-    status;
-
-  status=CompositeImageChannel(image,DefaultChannels,compose,composite_image,
-    x_offset,y_offset);
-  return(status);
-}
-
-MagickExport MagickBooleanType CompositeImageChannel(Image *image,
-  const ChannelType channel,const CompositeOperator compose,
-  const Image *composite_image,const ssize_t x_offset,const ssize_t y_offset)
+  const ssize_t x_offset,const ssize_t y_offset,ExceptionInfo *exception)
 {
 #define CompositeImageTag  "Composite/Image"
 
@@ -1575,9 +1561,6 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
   double
     sans;
 
-  ExceptionInfo
-    *exception;
-
   GeometryInfo
     geometry_info;
 
@@ -1591,9 +1574,6 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
   MagickOffsetType
     progress;
 
-  PixelInfo
-    zero;
-
   MagickRealType
     amount,
     destination_dissolve,
@@ -1606,6 +1586,9 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
   MagickStatusType
     flags;
 
+  PixelInfo
+    zero;
+
   ssize_t
     y;
 
@@ -1618,7 +1601,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(composite_image != (Image *) NULL);
   assert(composite_image->signature == MagickSignature);
-  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
+  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
     return(MagickFalse);
   GetPixelInfo(image,&zero);
   destination_image=(Image *) NULL;
@@ -1655,7 +1638,6 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
       if ((y_offset+(ssize_t) composite_image->rows) >= (ssize_t) image->rows)
         break;
       status=MagickTrue;
-      exception=(&image->exception);
       image_view=AcquireCacheView(image);
       composite_view=AcquireCacheView(composite_image);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
@@ -1726,7 +1708,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
         channel to exist, to add transparency.
       */
       if (image->matte == MagickFalse)
-        (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
+        (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
       modify_outside_overlay=MagickTrue;
       break;
     }
@@ -1756,7 +1738,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
           Y = green_channel; compose:args =  x_scale[,y_scale[,angle]].
       */
       destination_image=CloneImage(image,image->columns,image->rows,MagickTrue,
-        &image->exception);
+        exception);
       if (destination_image == (Image *) NULL)
         return(MagickFalse);
       /*
@@ -1802,8 +1784,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
         Blur Image by resampling.
       */
       pixel=zero;
-      exception=(&image->exception);
-      resample_filter=AcquireResampleFilter(image,&image->exception);
+      resample_filter=AcquireResampleFilter(image,exception);
       SetResampleFilter(resample_filter,CubicFilter,2.0);
       destination_view=AcquireCacheView(destination_image);
       composite_view=AcquireCacheView(composite_image);
@@ -1826,7 +1807,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
         p=GetCacheViewVirtualPixels(composite_view,0,y,composite_image->columns,
           1,exception);
         q=QueueCacheViewAuthenticPixels(destination_view,0,y,
-          destination_image->columns,1,&image->exception);
+          destination_image->columns,1,exception);
         if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
           break;
         for (x=0; x < (ssize_t) composite_image->columns; x++)
@@ -1894,7 +1875,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
           compose:args = x_scale[,y_scale[,center.x,center.y]]
       */
       destination_image=CloneImage(image,image->columns,image->rows,MagickTrue,
-        &image->exception);
+        exception);
       if (destination_image == (Image *) NULL)
         return(MagickFalse);
       SetGeometryInfo(&geometry_info);
@@ -1975,7 +1956,6 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
         displacement/distortion map.  -- Like a lens...
       */
       pixel=zero;
-      exception=(&image->exception);
       image_view=AcquireCacheView(image);
       destination_view=AcquireCacheView(destination_image);
       composite_view=AcquireCacheView(composite_image);
@@ -1998,7 +1978,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
         p=GetCacheViewVirtualPixels(composite_view,0,y,composite_image->columns,
           1,exception);
         q=QueueCacheViewAuthenticPixels(destination_view,0,y,
-          destination_image->columns,1,&image->exception);
+          destination_image->columns,1,exception);
         if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
           break;
         for (x=0; x < (ssize_t) composite_image->columns; x++)
@@ -2150,7 +2130,6 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
   progress=0;
   midpoint=((MagickRealType) QuantumRange+1.0)/2;
   GetPixelInfo(composite_image,&zero);
-  exception=(&image->exception);
   image_view=AcquireCacheView(image);
   composite_view=AcquireCacheView(composite_image);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
@@ -2208,7 +2187,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
           p-=x_offset*GetPixelChannels(composite_image);
       }
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
-    if (q == (const Quantum *) NULL)
+    if (q == (Quantum *) NULL)
       {
         status=MagickFalse;
         continue;
@@ -2391,82 +2370,82 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
         }
         case PlusCompositeOp:
         {
-          CompositePlus(&source,&destination,channel,&composite);
+          CompositePlus(image,&source,&destination,&composite);
           break;
         }
         case MinusDstCompositeOp:
         {
-          CompositeMinus(&source,&destination,channel,&composite);
+          CompositeMinus(image,&source,&destination,&composite);
           break;
         }
         case MinusSrcCompositeOp:
         {
-          CompositeMinus(&destination,&source,channel,&composite);
+          CompositeMinus(image,&destination,&source,&composite);
           break;
         }
         case ModulusAddCompositeOp:
         {
-          CompositeModulusAdd(&source,&destination,channel,&composite);
+          CompositeModulusAdd(image,&source,&destination,&composite);
           break;
         }
         case ModulusSubtractCompositeOp:
         {
-          CompositeModulusSubtract(&source,&destination,channel,&composite);
+          CompositeModulusSubtract(image,&source,&destination,&composite);
           break;
         }
         case DifferenceCompositeOp:
         {
-          CompositeDifference(&source,&destination,channel,&composite);
+          CompositeDifference(image,&source,&destination,&composite);
           break;
         }
         case ExclusionCompositeOp:
         {
-          CompositeExclusion(&source,&destination,channel,&composite);
+          CompositeExclusion(image,&source,&destination,&composite);
           break;
         }
         case MultiplyCompositeOp:
         {
-          CompositeMultiply(&source,&destination,channel,&composite);
+          CompositeMultiply(image,&source,&destination,&composite);
           break;
         }
         case ScreenCompositeOp:
         {
-          CompositeScreen(&source,&destination,channel,&composite);
+          CompositeScreen(image,&source,&destination,&composite);
           break;
         }
         case DivideDstCompositeOp:
         {
-          CompositeDivide(&source,&destination,channel,&composite);
+          CompositeDivide(image,&source,&destination,&composite);
           break;
         }
         case DivideSrcCompositeOp:
         {
-          CompositeDivide(&destination,&source,channel,&composite);
+          CompositeDivide(image,&destination,&source,&composite);
           break;
         }
         case DarkenCompositeOp:
         {
-          CompositeDarken(&source,&destination,channel,&composite);
+          CompositeDarken(image,&source,&destination,&composite);
           break;
         }
         case LightenCompositeOp:
         {
-          CompositeLighten(&source,&destination,channel,&composite);
+          CompositeLighten(image,&source,&destination,&composite);
           break;
         }
         case DarkenIntensityCompositeOp:
         {
-          CompositeDarkenIntensity(&source,&destination,channel,&composite);
+          CompositeDarkenIntensity(image,&source,&destination,&composite);
           break;
         }
         case LightenIntensityCompositeOp:
         {
-          CompositeLightenIntensity(&source,&destination,channel,&composite);
+          CompositeLightenIntensity(image,&source,&destination,&composite);
           break;
         }
         case MathematicsCompositeOp:
         {
-          CompositeMathematics(&source,&destination,channel,&geometry_info,
+          CompositeMathematics(image,&source,&destination,&geometry_info,
             &composite);
           break;
         }
@@ -2723,7 +2702,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_CompositeImageChannel)
+  #pragma omp critical (MagickCore_CompositeImage)
 #endif
         proceed=SetImageProgress(image,CompositeImageTag,progress++,
           image->rows);
@@ -2754,7 +2733,8 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
 %
 %  The format of the TextureImage method is:
 %
-%      MagickBooleanType TextureImage(Image *image,const Image *texture)
+%      MagickBooleanType TextureImage(Image *image,const Image *texture,
+%        ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
@@ -2763,7 +2743,8 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
 %    o texture: This image is the texture to layer on the background.
 %
 */
-MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture)
+MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture,
+  ExceptionInfo *exception)
 {
 #define TextureImageTag  "Texture/Image"
 
@@ -2771,9 +2752,6 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture)
     *image_view,
     *texture_view;
 
-  ExceptionInfo
-    *exception;
-
   MagickBooleanType
     status;
 
@@ -2787,7 +2765,7 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture)
   if (texture == (const Image *) NULL)
     return(MagickFalse);
   (void) SetImageVirtualPixelMethod(texture,TileVirtualPixelMethod);
-  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
+  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
     return(MagickFalse);
   status=MagickTrue;
   if ((image->compose != CopyCompositeOp) &&
@@ -2813,7 +2791,7 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture)
             thread_status;
 
           thread_status=CompositeImage(image,image->compose,texture,x+
-            texture->tile_offset.x,y+texture->tile_offset.y);
+            texture->tile_offset.x,y+texture->tile_offset.y,exception);
           if (thread_status == MagickFalse)
             {
               status=thread_status;
@@ -2842,7 +2820,6 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture)
     Tile texture onto the image background (optimized).
   */
   status=MagickTrue;
-  exception=(&image->exception);
   image_view=AcquireCacheView(image);
   texture_view=AcquireCacheView(texture);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)