]> granicus.if.org Git - imagemagick/blobdiff - magick/composite.c
(no commit message)
[imagemagick] / magick / composite.c
index 05cf439b11a64e6542a60ebe0e724b43e02684fb..86578c3a89e7852158b0090f9d678390c39c79b4 100644 (file)
@@ -17,7 +17,7 @@
 %                                 July 1992                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
@@ -69,6 +69,7 @@
 #include "magick/resample.h"
 #include "magick/resource_.h"
 #include "magick/string_.h"
+#include "magick/thread-private.h"
 #include "magick/utility.h"
 #include "magick/version.h"
 \f
 %
 %      MagickBooleanType CompositeImage(Image *image,
 %        const CompositeOperator compose,Image *composite_image,
-%        const long x_offset,const long y_offset)
+%        const ssize_t x_offset,const ssize_t y_offset)
 %      MagickBooleanType CompositeImageChannel(Image *image,
 %        const ChannelType channel,const CompositeOperator compose,
-%        Image *composite_image,const long x_offset,const long y_offset)
+%        Image *composite_image,const ssize_t x_offset,const ssize_t y_offset)
 %
 %  A description of each parameter follows:
 %
@@ -173,31 +174,30 @@ static inline double MagickMax(const double x,const double y)
 **   gamma = Sa+Da-Sa*Da;
 **   gamma = 1 - QuantiumScale*alpha * QuantiumScale*beta;
 **   opacity = QuantiumScale*alpha*beta;  // over blend, optimized 1-Gamma
+**
+** The above SVG definitions also definate that Mathematical Composition
+** methods should use a 'Over' blending mode for Alpha Channel.
+** It however was not applied for composition modes of 'Plus', 'Minus',
+** the modulus versions of 'Add' and 'Subtract'.
+**
+**
+** Mathematical operator changes to be applied from IM v6.7...
+**
+**  1/ Modulus modes 'Add' and 'Subtract' are obsoleted and renamed
+**     'ModulusAdd' and 'ModulusSubtract' for clarity.
+**
+**  2/ All mathematical compositions work as per the SVG specification
+**     with regard to blending.  This now includes 'ModulusAdd' and
+**     'ModulusSubtract'.
+**
+**  3/ When the special channel flag 'sync' (syncronize channel updates)
+**     is turned off (enabled by default) then mathematical compositions are
+**     only performed on the channels specified, and are applied
+**     independantally of each other.  In other words the mathematics is
+**     performed as 'pure' mathematical operations, rather than as image
+**     operations.
 */
 
-static inline MagickRealType Add(const MagickRealType p,const MagickRealType q)
-{
-  MagickRealType
-    pixel;
-
-  pixel=p+q;
-  if (pixel > QuantumRange)
-    pixel-=(QuantumRange+1.0);
-  return(pixel);
-}
-
-static inline void CompositeAdd(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
-{
-  composite->red=Add(p->red,q->red);
-  composite->green=Add(p->green,q->green);
-  composite->blue=Add(p->blue,q->blue);
-  composite->opacity=Add(alpha,beta);
-  if (q->colorspace == CMYKColorspace)
-    composite->index=Add(p->index,q->index);
-}
-
 static inline MagickRealType Atop(const MagickRealType p,
   const MagickRealType Sa,const MagickRealType q,
   const MagickRealType magick_unused(Da))
@@ -206,14 +206,13 @@ static inline MagickRealType Atop(const MagickRealType p,
 }
 
 static inline void CompositeAtop(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  composite->opacity=beta;    /* optimized  1.0-Gamma */
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  composite->opacity=q->opacity;   /* optimized  Da = 1.0-Gamma */
   composite->red=Atop(p->red,Sa,q->red,1.0);
   composite->green=Atop(p->green,Sa,q->green,1.0);
   composite->blue=Atop(p->blue,Sa,q->blue,1.0);
@@ -222,12 +221,11 @@ static inline void CompositeAtop(const MagickPixelPacket *p,
 }
 
 /*
-  What is this Composition method for, can't find any specification!
+  What is this Composition method for? Can't find any specification!
   WARNING this is not doing correct 'over' blend handling (Anthony Thyssen).
 */
 static inline void CompositeBumpmap(const MagickPixelPacket *p,
-  const MagickRealType magick_unused(alpha),const MagickPixelPacket *q,
-  const MagickRealType magick_unused(beta),MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
     intensity;
@@ -236,7 +234,8 @@ static inline void CompositeBumpmap(const MagickPixelPacket *p,
   composite->red=QuantumScale*intensity*q->red;
   composite->green=QuantumScale*intensity*q->green;
   composite->blue=QuantumScale*intensity*q->blue;
-  composite->opacity=(MagickRealType) QuantumScale*intensity*p->opacity;
+  composite->opacity=(MagickRealType) QuantumScale*intensity*
+    GetOpacityPixelComponent(p);
   if (q->colorspace == CMYKColorspace)
     composite->index=QuantumScale*intensity*q->index;
 }
@@ -275,16 +274,15 @@ static MagickRealType ColorBurn(const MagickRealType Sca,
 }
 
 static inline void CompositeColorBurn(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
   gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
   composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
   gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
@@ -338,16 +336,15 @@ static MagickRealType ColorDodge(const MagickRealType Sca,
 }
 
 static inline void CompositeColorDodge(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
   gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
   composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
   gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
@@ -371,53 +368,82 @@ static inline MagickRealType Darken(const MagickRealType p,
 }
 
 static inline void CompositeDarken(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,const ChannelType channel,
+  MagickPixelPacket *composite)
 {
+  /*
+    Darken is equivelent to a 'Minimum' method
+    OR a greyscale version of a binary 'Or'
+    OR the 'Intersection' of pixel sets.
+  */
   MagickRealType
     gamma;
 
-  gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
-  composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
-  gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
-  composite->red=gamma*Darken(p->red,alpha,q->red,beta);
-  composite->green=gamma*Darken(p->green,alpha,q->green,beta);
-  composite->blue=gamma*Darken(p->blue,alpha,q->blue,beta);
-  if (q->colorspace == CMYKColorspace)
-    composite->index=gamma*Darken(p->index,alpha,q->index,beta);
+  if ( (channel & SyncChannels) != 0 ) {
+    composite->opacity=QuantumScale*p->opacity*q->opacity; /* Over Blend */
+    gamma=1.0-QuantumScale*composite->opacity;
+    gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
+    composite->red=gamma*Darken(p->red,p->opacity,q->red,q->opacity);
+    composite->green=gamma*Darken(p->green,p->opacity,q->green,q->opacity);
+    composite->blue=gamma*Darken(p->blue,p->opacity,q->blue,q->opacity);
+    if (q->colorspace == CMYKColorspace)
+      composite->index=gamma*Darken(p->index,p->opacity,q->index,q->opacity);
+  }
+  else { /* handle channels as separate grayscale channels */
+    if ( (channel & AlphaChannel) != 0 )
+      composite->opacity=MagickMax(p->opacity,q->opacity);
+    if ( (channel & RedChannel) != 0 )
+      composite->red=MagickMin(p->red,q->red);
+    if ( (channel & GreenChannel) != 0 )
+      composite->green=MagickMin(p->green,q->green);
+    if ( (channel & BlueChannel) != 0 )
+      composite->blue=MagickMin(p->blue,q->blue);
+    if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
+      composite->index=MagickMin(p->index,q->index);
+  }
 }
 
 static inline MagickRealType Difference(const MagickRealType p,
   const MagickRealType Sa,const MagickRealType q,const MagickRealType Da)
 {
-  /*
-    Optimized by Multipling by QuantumRange (taken from gamma).
-  */
+  /* Optimized by Multipling by QuantumRange (taken from gamma).  */
   return(Sa*p+Da*q-Sa*Da*2.0*MagickMin(p,q));
 }
 
 static inline void CompositeDifference(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,const ChannelType channel,
+  MagickPixelPacket *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
-  gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
-  composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
-  /*
-    Values not normalized as an optimization.
-  */
-  gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
-  composite->red=gamma*Difference(p->red,Sa,q->red,Da);
-  composite->green=gamma*Difference(p->green,Sa,q->green,Da);
-  composite->blue=gamma*Difference(p->blue,Sa,q->blue,Da);
-  if (q->colorspace == CMYKColorspace)
-    composite->index=gamma*Difference(p->index,Sa,q->index,Da);
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
+  if ( (channel & SyncChannels) != 0 ) {
+    gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
+    composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
+    gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
+    /* Values are not normalized as an optimization.  */
+    composite->red=gamma*Difference(p->red,Sa,q->red,Da);
+    composite->green=gamma*Difference(p->green,Sa,q->green,Da);
+    composite->blue=gamma*Difference(p->blue,Sa,q->blue,Da);
+    if (q->colorspace == CMYKColorspace)
+      composite->index=gamma*Difference(p->index,Sa,q->index,Da);
+  }
+  else { /* handle channels as separate grayscale channels */
+    if ( (channel & AlphaChannel) != 0 )
+      composite->opacity=QuantumRange-fabs(p->opacity - q->opacity);
+    if ( (channel & RedChannel) != 0 )
+      composite->red=fabs(p->red - q->red);
+    if ( (channel & GreenChannel) != 0 )
+      composite->green=fabs(p->green - q->green);
+    if ( (channel & BlueChannel) != 0 )
+      composite->blue=fabs(p->blue - q->blue);
+    if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
+      composite->index=fabs(p->index - q->index);
+  }
 }
 
 static MagickRealType Divide(const MagickRealType Sca,const MagickRealType Sa,
@@ -429,9 +455,9 @@ static MagickRealType Divide(const MagickRealType Sca,const MagickRealType Sa,
       f(Sc,Dc) = Sc/Dc
 
     But with appropriate handling for special case of Dc == 0 specifically
-    f(Black,Black)  = Black and f(non-Black,Black) = White.  It is however
-    also important to correctly do 'over' alpha blending which is why it
-    becomes so complex looking.
+    so that   f(Black,Black)=Black  and  f(non-Black,Black)=White.
+    It is however also important to correctly do 'over' alpha blending which
+    is why the formula becomes so complex looking.
   */
   if ((fabs(Sca) < MagickEpsilon) && (fabs(Dca) < MagickEpsilon))
     return(Sca*(1.0-Da)+Dca*(1.0-Sa));
@@ -441,28 +467,46 @@ static MagickRealType Divide(const MagickRealType Sca,const MagickRealType Sa,
 }
 
 static inline void CompositeDivide(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,const ChannelType channel,
+  MagickPixelPacket *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
-  gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
-  composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
-  gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
-  composite->red=gamma*Divide(QuantumScale*p->red*Sa,Sa,QuantumScale*
-    q->red*Da,Da);
-  composite->green=gamma*Divide(QuantumScale*p->green*Sa,Sa,QuantumScale*
-    q->green*Da,Da);
-  composite->blue=gamma*Divide(QuantumScale*p->blue*Sa,Sa,QuantumScale*
-     q->blue*Da,Da);
-  if (q->colorspace == CMYKColorspace)
-    composite->index=gamma*Divide(QuantumScale*p->index*Sa,Sa,QuantumScale*
-      q->index*Da,Da);
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
+  if ( (channel & SyncChannels) != 0 ) {
+    gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
+    composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
+    gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
+    composite->red=gamma*Divide(QuantumScale*p->red*Sa,Sa,QuantumScale*
+      q->red*Da,Da);
+    composite->green=gamma*Divide(QuantumScale*p->green*Sa,Sa,QuantumScale*
+      q->green*Da,Da);
+    composite->blue=gamma*Divide(QuantumScale*p->blue*Sa,Sa,QuantumScale*
+      q->blue*Da,Da);
+    if (q->colorspace == CMYKColorspace)
+      composite->index=gamma*Divide(QuantumScale*p->index*Sa,Sa,QuantumScale*
+        q->index*Da,Da);
+  }
+  else { /* handle channels as separate grayscale channels */
+    if ( (channel & AlphaChannel) != 0 )
+      composite->opacity=QuantumRange*(1.0-Divide(Sa,1.0,Da,1.0));
+    if ( (channel & RedChannel) != 0 )
+      composite->red=QuantumRange*
+          Divide(QuantumScale*p->red,1.0,QuantumScale*q->red,1.0);
+    if ( (channel & GreenChannel) != 0 )
+      composite->green=QuantumRange*
+          Divide(QuantumScale*p->green,1.0,QuantumScale*q->green,1.0);
+    if ( (channel & BlueChannel) != 0 )
+      composite->blue=QuantumRange*
+          Divide(QuantumScale*p->blue,1.0,QuantumScale*q->blue,1.0);
+    if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
+      composite->index=QuantumRange*
+          Divide(QuantumScale*p->index,1.0,QuantumScale*q->index,1.0);
+  }
 }
 
 static MagickRealType Exclusion(const MagickRealType Sca,
@@ -472,28 +516,46 @@ static MagickRealType Exclusion(const MagickRealType Sca,
 }
 
 static inline void CompositeExclusion(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,const ChannelType channel,
+  MagickPixelPacket *composite)
 {
   MagickRealType
     gamma,
     Sa,
     Da;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
-  gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
-  composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
-  gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
-  composite->red=gamma*Exclusion(QuantumScale*p->red*Sa,Sa,QuantumScale*
-    q->red*Da,Da);
-  composite->green=gamma*Exclusion(QuantumScale*p->green*Sa,Sa,QuantumScale*
-    q->green*Da,Da);
-  composite->blue=gamma*Exclusion(QuantumScale*p->blue*Sa,Sa,QuantumScale*
-    q->blue*Da,Da);
-  if (q->colorspace == CMYKColorspace)
-    composite->index=gamma*Exclusion(QuantumScale*p->index*Sa,Sa,QuantumScale*
-      q->index*Da,Da);
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
+  if ( (channel & SyncChannels) != 0 ) {
+    gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
+    composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
+    gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
+    composite->red=gamma*Exclusion(QuantumScale*p->red*Sa,Sa,QuantumScale*
+      q->red*Da,Da);
+    composite->green=gamma*Exclusion(QuantumScale*p->green*Sa,Sa,QuantumScale*
+      q->green*Da,Da);
+    composite->blue=gamma*Exclusion(QuantumScale*p->blue*Sa,Sa,QuantumScale*
+      q->blue*Da,Da);
+    if (q->colorspace == CMYKColorspace)
+      composite->index=gamma*Exclusion(QuantumScale*p->index*Sa,Sa,QuantumScale*
+        q->index*Da,Da);
+  }
+  else { /* handle channels as separate grayscale channels */
+    if ( (channel & AlphaChannel) != 0 )
+      composite->opacity=QuantumRange*(1.0-Exclusion(Sa,1.0,Da,1.0));
+    if ( (channel & RedChannel) != 0 )
+      composite->red=QuantumRange*
+          Exclusion(QuantumScale*p->red,1.0,QuantumScale*q->red,1.0);
+    if ( (channel & GreenChannel) != 0 )
+      composite->green=QuantumRange*
+          Exclusion(QuantumScale*p->green,1.0,QuantumScale*q->green,1.0);
+    if ( (channel & BlueChannel) != 0 )
+      composite->blue=QuantumRange*
+          Exclusion(QuantumScale*p->blue,1.0,QuantumScale*q->blue,1.0);
+    if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
+      composite->index=QuantumRange*
+          Exclusion(QuantumScale*p->index,1.0,QuantumScale*q->index,1.0);
+  }
 }
 
 static MagickRealType HardLight(const MagickRealType Sca,
@@ -505,16 +567,15 @@ static MagickRealType HardLight(const MagickRealType Sca,
 }
 
 static inline void CompositeHardLight(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
   gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
   composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
   gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
@@ -529,7 +590,6 @@ static inline void CompositeHardLight(const MagickPixelPacket *p,
       q->index*Da,Da);
 }
 
-
 static void CompositeHSB(const MagickRealType red,const MagickRealType green,
   const MagickRealType blue,double *hue,double *saturation,double *brightness)
 {
@@ -573,27 +633,30 @@ static void CompositeHSB(const MagickRealType red,const MagickRealType green,
 }
 
 static inline MagickRealType In(const MagickRealType p,
-  const MagickRealType alpha,const MagickRealType magick_unused(q),
-  const MagickRealType beta)
+  const MagickRealType Sa,const MagickRealType magick_unused(q),
+  const MagickRealType Da)
 {
-  return((1.0-QuantumScale*alpha)*p*(1.0-QuantumScale*beta));
+  return(Sa*p*Da);
 }
 
 static inline void CompositeIn(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
-    gamma;
+    gamma,
+    Sa,
+    Da;
 
-  gamma=(1.0-QuantumScale*alpha)*(1.0-QuantumScale*beta);
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
+  gamma=Sa*Da;
   composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
   gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
-  composite->red=gamma*In(p->red,alpha,q->red,beta);
-  composite->green=gamma*In(p->green,alpha,q->green,beta);
-  composite->blue=gamma*In(p->blue,alpha,q->blue,beta);
+  composite->red=gamma*In(p->red,Sa,q->red,Da);
+  composite->green=gamma*In(p->green,Sa,q->green,Da);
+  composite->blue=gamma*In(p->blue,Sa,q->blue,Da);
   if (q->colorspace == CMYKColorspace)
-    composite->index=gamma*In(p->index,alpha,q->index,beta);
+    composite->index=gamma*In(p->index,Sa,q->index,Da);
 }
 
 static inline MagickRealType Lighten(const MagickRealType p,
@@ -605,38 +668,66 @@ static inline MagickRealType Lighten(const MagickRealType p,
 }
 
 static inline void CompositeLighten(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,const ChannelType channel,
+  MagickPixelPacket *composite)
 {
+  /*
+    Lighten is also equivelevt to a 'Maximum' method
+    OR a greyscale version of a binary 'And'
+    OR the 'Union' of pixel sets.
+  */
   MagickRealType
     gamma;
 
-  composite->opacity=QuantumScale*alpha*beta;    /* optimized 1-gamma */
-  gamma=1.0-QuantumScale*composite->opacity;
-  gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
-  composite->red=gamma*Lighten(p->red,alpha,q->red,beta);
-  composite->green=gamma*Lighten(p->green,alpha,q->green,beta);
-  composite->blue=gamma*Lighten(p->blue,alpha,q->blue,beta);
-  if (q->colorspace == CMYKColorspace)
-    composite->index=gamma*Lighten(p->index,alpha,q->index,beta);
+  if ( (channel & SyncChannels) != 0 ) {
+    composite->opacity=QuantumScale*p->opacity*q->opacity; /* Over Blend */
+    gamma=1.0-QuantumScale*composite->opacity;
+    gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
+    composite->red=gamma*Lighten(p->red,p->opacity,q->red,q->opacity);
+    composite->green=gamma*Lighten(p->green,p->opacity,q->green,q->opacity);
+    composite->blue=gamma*Lighten(p->blue,p->opacity,q->blue,q->opacity);
+    if (q->colorspace == CMYKColorspace)
+      composite->index=gamma*Lighten(p->index,p->opacity,q->index,q->opacity);
+  }
+  else { /* handle channels as separate grayscale channels */
+    if ( (channel & AlphaChannel) != 0 )
+      composite->opacity=MagickMin(p->opacity,q->opacity);
+    if ( (channel & RedChannel) != 0 )
+      composite->red=MagickMax(p->red,q->red);
+    if ( (channel & GreenChannel) != 0 )
+      composite->green=MagickMax(p->green,q->green);
+    if ( (channel & BlueChannel) != 0 )
+      composite->blue=MagickMax(p->blue,q->blue);
+    if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
+      composite->index=MagickMax(p->index,q->index);
+  }
 }
 
+#if 0
+static inline MagickRealType LinearDodge(const MagickRealType Sca,
+  const MagickRealType Sa,const MagickRealType Dca,const MagickRealType Da)
+{
+  /*
+    LinearDodge: simplifies to a trivial formula
+    f(Sc,Dc) = Sc + Dc
+    Dca' = Sca + Dca
+  */
+  return(Sca+Dca);
+}
+#endif
+
 static inline void CompositeLinearDodge(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
   gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
   composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
-  /*
-    Operation performed directly - not need for sub-routine.
-  */
   gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
   composite->red=gamma*(p->red*Sa+q->red*Da);
   composite->green=gamma*(p->green*Sa+q->green*Da);
@@ -650,25 +741,24 @@ static inline MagickRealType LinearBurn(const MagickRealType Sca,
   const MagickRealType Sa,const MagickRealType Dca,const MagickRealType Da)
 {
   /*
-    LinearLight: as defined by Abode Photoshop, according to
+    LinearBurn: as defined by Abode Photoshop, according to
     http://www.simplefilter.de/en/basics/mixmods.html is:
 
-    f(Sc,Dc) = Dc + Sc - 1
+    f(Sc,Dc) = Sc + Dc - 1
   */
   return(Sca+Dca-Sa*Da);
 }
 
 static inline void CompositeLinearBurn(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
   gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
   composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
   gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
@@ -683,13 +773,12 @@ static inline void CompositeLinearBurn(const MagickPixelPacket *p,
       q->index*Da,Da);
 }
 
-
 static inline MagickRealType LinearLight(const MagickRealType Sca,
   const MagickRealType Sa,const MagickRealType Dca,const MagickRealType Da)
 {
 #if 0
   /*
-    Previous formula, only valid for fully-opaque images.
+    Previous formula, was only valid for fully-opaque images.
   */
   return(Dca+2*Sca-1.0);
 #else
@@ -704,16 +793,15 @@ static inline MagickRealType LinearLight(const MagickRealType Sca,
 }
 
 static inline void CompositeLinearLight(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
   gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
   composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
   gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
@@ -756,55 +844,221 @@ static inline MagickRealType Mathematics(const MagickRealType Sca,
 }
 
 static inline void CompositeMathematics(const MagickPixelPacket *p,
-  const MagickPixelPacket *q,const GeometryInfo *args,
-  MagickPixelPacket *composite)
+  const MagickPixelPacket *q,const ChannelType channel, const GeometryInfo
+  *args, MagickPixelPacket *composite)
 {
   MagickRealType
+    Sa,
     Da,
-    gamma,
-    Sa;
+    gamma;
 
-  Sa=1.0-QuantumScale*p->opacity;
+  Sa=1.0-QuantumScale*GetOpacityPixelComponent(p); /* ??? - AT */
   Da=1.0-QuantumScale*q->opacity;
-  gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
-  composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
-  gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
-  composite->red=gamma*Mathematics(QuantumScale*p->red*Sa,Sa,QuantumScale*
-    q->red*Da,Da,args);
-  composite->green=gamma*Mathematics(QuantumScale*p->green*Sa,Sa,QuantumScale*
-    q->green*Da,Da,args);
-  composite->blue=gamma*Mathematics(QuantumScale*p->blue*Sa,Sa,QuantumScale*
-    q->blue*Da,Da,args);
-  if (q->colorspace == CMYKColorspace)
-    composite->index=gamma*Mathematics(QuantumScale*p->index*Sa,Sa,QuantumScale*
-      q->index*Da,Da,args);
+  if ( (channel & SyncChannels) != 0 ) {
+    gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
+    composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
+    gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
+    composite->red=gamma*Mathematics(QuantumScale*p->red*Sa,Sa,QuantumScale*
+      q->red*Da,Da,args);
+    composite->green=gamma*Mathematics(QuantumScale*p->green*Sa,Sa,QuantumScale*
+      q->green*Da,Da,args);
+    composite->blue=gamma*Mathematics(QuantumScale*p->blue*Sa,Sa,QuantumScale*
+      q->blue*Da,Da,args);
+    if (q->colorspace == CMYKColorspace)
+      composite->index=gamma*Mathematics(QuantumScale*p->index*Sa,Sa,QuantumScale*
+        q->index*Da,Da,args);
+  }
+  else { /* handle channels as separate grayscale channels */
+    if ( (channel & AlphaChannel) != 0 )
+      composite->opacity=QuantumRange*(1.0-Mathematics(Sa,1.0,Da,1.0,args));
+    if ( (channel & RedChannel) != 0 )
+      composite->red=QuantumRange*
+          Mathematics(QuantumScale*p->red,1.0,QuantumScale*q->red,1.0,args);
+    if ( (channel & GreenChannel) != 0 )
+      composite->green=QuantumRange*
+          Mathematics(QuantumScale*p->green,1.0,QuantumScale*q->green,1.0,args);
+    if ( (channel & BlueChannel) != 0 )
+      composite->blue=QuantumRange*
+          Mathematics(QuantumScale*p->blue,1.0,QuantumScale*q->blue,1.0,args);
+    if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
+      composite->index=QuantumRange*
+          Mathematics(QuantumScale*p->index,1.0,QuantumScale*q->index,1.0,args);
+  }
+
+}
+
+static inline void CompositePlus(const MagickPixelPacket *p,
+  const MagickPixelPacket *q,const ChannelType channel,
+  MagickPixelPacket *composite)
+{
+  if ( (channel & SyncChannels) != 0 ) {
+    /*
+      NOTE: "Plus" does not use 'over' alpha-blending but uses a
+      special 'plus' form of alph-blending. It is the ONLY mathematical
+      operator to do this. this is what makes it different to the
+      otherwise equivelent "LinearDodge" composition method.
+
+      Note however that color channels are still effected by the alpha channel
+      as a result of the blending, making it just as useless for independant
+      channel maths, just like all other mathematical composition methods.
+
+      As such the removal of the 'sync' flag, is still a usful convention.
+
+      The MagickPixelCompositePlus() function is defined in
+      "composite-private.h" so it can also be used for Image Blending.
+    */
+    MagickPixelCompositePlus(p,p->opacity,q,q->opacity,composite);
+  }
+  else { /* handle channels as separate grayscale channels */
+    if ( (channel & AlphaChannel) != 0 )
+      composite->opacity=p->opacity+q->opacity-QuantumRange;
+    if ( (channel & RedChannel) != 0 )
+      composite->red=p->red+q->red;
+    if ( (channel & GreenChannel) != 0 )
+      composite->green=p->green+q->green;
+    if ( (channel & BlueChannel) != 0 )
+      composite->blue=p->blue+q->blue;
+    if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
+      composite->index=p->index+q->index;
+  }
 }
 
 static inline MagickRealType Minus(const MagickRealType Sca,
-  const MagickRealType Dca)
+  const MagickRealType Sa,const MagickRealType Dca,
+  const MagickRealType magick_unused(Da))
 {
-  return(Sca-Dca);
+  return(Sca + Dca - 2*Dca*Sa);
 }
 
 static inline void CompositeMinus(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,const ChannelType channel,
+  MagickPixelPacket *composite)
 {
   MagickRealType
+    Sa,
     Da,
-    gamma,
-    Sa;
+    gamma;
 
-  Sa=1.0-QuantumScale*alpha;
-  Da=1.0-QuantumScale*beta;
-  gamma=RoundToUnity(Sa-Da);  /* is this correct?  - I do not think so! */
-  composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
-  gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
-  composite->red=gamma*Minus(p->red*Sa,q->red*Da);
-  composite->green=gamma*Minus(p->green*Sa,q->green*Da);
-  composite->blue=gamma*Minus(p->blue*Sa,q->blue*Da);
-  if (q->colorspace == CMYKColorspace)
-    composite->index=gamma*Minus(p->index*Sa,q->index*Da);
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
+  if ( (channel & SyncChannels) != 0 ) {
+    gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
+    composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
+    gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
+    composite->red=gamma*Minus(p->red*Sa,Sa,q->red*Da,Da);
+    composite->green=gamma*Minus(p->green*Sa,Sa,q->green*Da,Da);
+    composite->blue=gamma*Minus(p->blue*Sa,Sa,q->blue*Da,Da);
+    if (q->colorspace == CMYKColorspace)
+      composite->index=gamma*Minus(p->index*Sa,Sa,q->index*Da,Da);
+  }
+  else { /* handle channels as separate grayscale channels */
+    if ( (channel & AlphaChannel) != 0 )
+      composite->opacity=QuantumRange*(1.0-(Sa-Da));
+    if ( (channel & RedChannel) != 0 )
+      composite->red=p->red-q->red;
+    if ( (channel & GreenChannel) != 0 )
+      composite->green=p->green-q->green;
+    if ( (channel & BlueChannel) != 0 )
+      composite->blue=p->blue-q->blue;
+    if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
+      composite->index=p->index-q->index;
+  }
+}
+
+static inline MagickRealType ModulusAdd(const MagickRealType p,
+  const MagickRealType Sa, const MagickRealType q,  const MagickRealType Da)
+{
+  MagickRealType
+    pixel;
+
+  pixel=p+q;
+  if (pixel > QuantumRange)
+    pixel-=(QuantumRange+1.0);
+  return(pixel*Sa*Da + p*Sa*(1-Da) + q*Da*(1-Sa));
+}
+
+static inline void CompositeModulusAdd(const MagickPixelPacket *p,
+  const MagickPixelPacket *q, const ChannelType channel,
+  MagickPixelPacket *composite)
+{
+  if ( (channel & SyncChannels) != 0 ) {
+    MagickRealType
+      Sa,
+      Da,
+      gamma;
+
+    Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+    Da=1.0-QuantumScale*q->opacity;
+    gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
+    composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
+    gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
+    composite->red=ModulusAdd(p->red,Sa,q->red,Da);
+    composite->green=ModulusAdd(p->green,Sa,q->green,Da);
+    composite->blue=ModulusAdd(p->blue,Sa,q->blue,Da);
+    if (q->colorspace == CMYKColorspace)
+      composite->index=ModulusAdd(p->index,Sa,q->index,Da);
+  }
+  else { /* handle channels as separate grayscale channels */
+    if ( (channel & AlphaChannel) != 0 )
+      composite->opacity=QuantumRange-ModulusAdd(QuantumRange-p->opacity,
+           1.0,QuantumRange-q->opacity,1.0);
+    if ( (channel & RedChannel) != 0 )
+      composite->red=ModulusAdd(p->red,1.0,q->red,1.0);
+    if ( (channel & GreenChannel) != 0 )
+      composite->green=ModulusAdd(p->green,1.0,q->green,1.0);
+    if ( (channel & BlueChannel) != 0 )
+      composite->blue=ModulusAdd(p->blue,1.0,q->blue,1.0);
+    if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
+      composite->index=ModulusAdd(p->index,1.0,q->index,1.0);
+  }
+}
+
+static inline MagickRealType ModulusSubtract(const MagickRealType p,
+  const MagickRealType Sa, const MagickRealType q,  const MagickRealType Da)
+{
+  MagickRealType
+    pixel;
+
+  pixel=p-q;
+  if (pixel < 0.0)
+    pixel+=(QuantumRange+1.0);
+  return(pixel*Sa*Da + p*Sa*(1-Da) + q*Da*(1-Sa));
+}
+
+static inline void CompositeModulusSubtract(const MagickPixelPacket *p,
+  const MagickPixelPacket *q, const ChannelType channel,
+  MagickPixelPacket *composite)
+{
+  if ( (channel & SyncChannels) != 0 ) {
+    MagickRealType
+      Sa,
+      Da,
+      gamma;
+
+    Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+    Da=1.0-QuantumScale*q->opacity;
+    gamma = RoundToUnity(Sa+Da-Sa*Da);
+    composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
+    gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
+    composite->red=ModulusSubtract(p->red,Sa,q->red,Da);
+    composite->green=ModulusSubtract(p->green,Sa,q->green,Da);
+    composite->blue=ModulusSubtract(p->blue,Sa,q->blue,Da);
+    if (q->colorspace == CMYKColorspace)
+      composite->index=ModulusSubtract(p->index,Sa,q->index,Da);
+  }
+  else { /* handle channels as separate grayscale channels */
+    if ( (channel & AlphaChannel) != 0 )
+      composite->opacity=QuantumRange-ModulusSubtract(QuantumRange-p->opacity,
+           1.0,QuantumRange-q->opacity,1.0);
+    if ( (channel & RedChannel) != 0 )
+      composite->red=ModulusSubtract(p->red,1.0,q->red,1.0);
+    if ( (channel & GreenChannel) != 0 )
+      composite->green=ModulusSubtract(p->green,1.0,q->green,1.0);
+    if ( (channel & BlueChannel) != 0 )
+      composite->blue=ModulusSubtract(p->blue,1.0,q->blue,1.0);
+    if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
+      composite->index=ModulusSubtract(p->index,1.0,q->index,1.0);
+  }
 }
 
 static  inline MagickRealType Multiply(const MagickRealType Sca,
@@ -814,68 +1068,77 @@ static  inline MagickRealType Multiply(const MagickRealType Sca,
 }
 
 static inline void CompositeMultiply(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,const ChannelType channel,
+  MagickPixelPacket *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;
-  Da=1.0-QuantumScale*beta;
-  gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
-  composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
-  gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
-  composite->red=gamma*Multiply(QuantumScale*p->red*Sa,Sa,QuantumScale*
-    q->red*Da,Da);
-  composite->green=gamma*Multiply(QuantumScale*p->green*Sa,Sa,QuantumScale*
-    q->green*Da,Da);
-  composite->blue=gamma*Multiply(QuantumScale*p->blue*Sa,Sa,QuantumScale*
-    q->blue*Da,Da);
-  if (q->colorspace == CMYKColorspace)
-    composite->index=gamma*Multiply(QuantumScale*p->index*Sa,Sa,QuantumScale*
-      q->index*Da,Da);
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
+  if ( (channel & SyncChannels) != 0 ) {
+    gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
+    composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
+    gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
+    composite->red=gamma*Multiply(QuantumScale*p->red*Sa,Sa,QuantumScale*
+      q->red*Da,Da);
+    composite->green=gamma*Multiply(QuantumScale*p->green*Sa,Sa,QuantumScale*
+      q->green*Da,Da);
+    composite->blue=gamma*Multiply(QuantumScale*p->blue*Sa,Sa,QuantumScale*
+      q->blue*Da,Da);
+    if (q->colorspace == CMYKColorspace)
+      composite->index=gamma*Multiply(QuantumScale*p->index*Sa,Sa,QuantumScale*
+        q->index*Da,Da);
+  }
+  else { /* handle channels as separate grayscale channels */
+    if ( (channel & AlphaChannel) != 0 )
+      composite->opacity=QuantumRange*(1.0-Sa*Da);
+    if ( (channel & RedChannel) != 0 )
+      composite->red=QuantumScale*p->red*q->red;
+    if ( (channel & GreenChannel) != 0 )
+      composite->green=QuantumScale*p->green*q->green;
+    if ( (channel & BlueChannel) != 0 )
+      composite->blue=QuantumScale*p->blue*q->blue;
+    if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
+      composite->index=QuantumScale*p->index*q->index;
+  }
 }
 
 static inline MagickRealType Out(const MagickRealType p,
-  const MagickRealType alpha,const MagickRealType magick_unused(q),
-  const MagickRealType beta)
+  const MagickRealType Sa,const MagickRealType magick_unused(q),
+  const MagickRealType Da)
 {
-  return((1.0-QuantumScale*alpha)*p*QuantumScale*beta);
+  return(Sa*p*(1.0-Da));
 }
 
 static inline void CompositeOut(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
+    Sa,
+    Da,
     gamma;
 
-  gamma=(1.0-QuantumScale*alpha)*QuantumScale*beta;
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
+  gamma=Sa*(1.0-Da);
   composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
   gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
-  composite->red=gamma*Out(p->red,alpha,q->red,beta);
-  composite->green=gamma*Out(p->green,alpha,q->green,beta);
-  composite->blue=gamma*Out(p->blue,alpha,q->blue,beta);
+  composite->red=gamma*Out(p->red,Sa,q->red,Da);
+  composite->green=gamma*Out(p->green,Sa,q->green,Da);
+  composite->blue=gamma*Out(p->blue,Sa,q->blue,Da);
   if (q->colorspace == CMYKColorspace)
-    composite->index=gamma*Out(p->index,alpha,q->index,beta);
-}
-
-static inline void CompositeOver(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
-{
-  MagickPixelCompositeOver(p,alpha,q,beta,composite);
+    composite->index=gamma*Out(p->index,Sa,q->index,Da);
 }
 
 static MagickRealType PegtopLight(const MagickRealType Sca,
   const MagickRealType Sa,const MagickRealType Dca,const MagickRealType Da)
 {
   /*
-    PegTOP Soft-Light alternative: A continuous version of the Softlight
-    function, producing very similar results however it does not take into
-    account alpha channel.
+    PegTop: A Soft-Light alternative: A continuous version of the Softlight
+    function, producing very similar results.
 
     f(Sc,Dc) = Dc^2*(1-2*Sc) + 2*Sc*Dc
 
@@ -887,16 +1150,15 @@ static MagickRealType PegtopLight(const MagickRealType Sca,
 }
 
 static inline void CompositePegtopLight(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
   gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
   composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
   gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
@@ -928,16 +1190,15 @@ static MagickRealType PinLight(const MagickRealType Sca,
 }
 
 static inline void CompositePinLight(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
   gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
   composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
   gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
@@ -952,42 +1213,53 @@ static inline void CompositePinLight(const MagickPixelPacket *p,
       q->index*Da,Da);
 }
 
-static inline void CompositePlus(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
-{
-  MagickPixelCompositePlus(p,alpha,q,beta,composite);
-}
-
 static inline MagickRealType Screen(const MagickRealType Sca,
   const MagickRealType Dca)
 {
+  /* Screen:  A negated multiply
+     f(Sc,Dc) = 1.0-(1.0-Sc)*(1.0-Dc)
+  */
   return(Sca+Dca-Sca*Dca);
 }
 
 static inline void CompositeScreen(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,const ChannelType channel,
+  MagickPixelPacket *composite)
 {
   MagickRealType
+    Sa,
     Da,
-    gamma,
-    Sa;
+    gamma;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
-  gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
-  composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
-  gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
-  composite->red=gamma*Screen(QuantumScale*p->red*Sa,QuantumScale*
-    q->red*Da);
-  composite->green=gamma*Screen(QuantumScale*p->green*Sa,QuantumScale*
-    q->green*Da);
-  composite->blue=gamma*Screen(QuantumScale*p->blue*Sa,QuantumScale*
-    q->blue*Da);
-  if (q->colorspace == CMYKColorspace)
-    composite->index=gamma*Screen(QuantumScale*p->index*Sa,QuantumScale*
-      q->index*Da);
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
+  if ( (channel & SyncChannels) != 0 ) {
+    gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
+    composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
+    Sa*=QuantumScale; Da*=QuantumScale; /* optimization */
+    gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
+    composite->red=gamma*Screen(p->red*Sa,q->red*Da);
+    composite->green=gamma*Screen(p->green*Sa,q->green*Da);
+    composite->blue=gamma*Screen(p->blue*Sa,q->blue*Da);
+    if (q->colorspace == CMYKColorspace)
+      composite->index=gamma*Screen(p->index*Sa,q->index*Da);
+    }
+  else { /* handle channels as separate grayscale channels */
+    if ( (channel & AlphaChannel) != 0 )
+      composite->opacity=QuantumRange*(1.0-Screen(Sa,Da));
+    if ( (channel & RedChannel) != 0 )
+      composite->red=QuantumRange*Screen(QuantumScale*p->red,
+           QuantumScale*q->red);
+    if ( (channel & GreenChannel) != 0 )
+      composite->green=QuantumRange*Screen(QuantumScale*p->green,
+           QuantumScale*q->green);
+    if ( (channel & BlueChannel) != 0 )
+      composite->blue=QuantumRange*Screen(QuantumScale*p->blue,
+           QuantumScale*q->blue);
+    if ( (channel & IndexChannel) != 0 && q->colorspace == CMYKColorspace)
+      composite->index=QuantumRange*Screen(QuantumScale*p->index,
+           QuantumScale*q->index);
+  }
 }
 
 static MagickRealType SoftLight(const MagickRealType Sca,
@@ -995,7 +1267,7 @@ static MagickRealType SoftLight(const MagickRealType Sca,
 {
 #if 0
   /*
-    Oct 2004 SVG specification -- spec discovered to be incorrect
+    Oct 2004 SVG specification -- was found to be incorrect
     See  http://lists.w3.org/Archives/Public/www-svg/2009Feb/0014.html.
   */
   if (2.0*Sca < Sa)
@@ -1028,16 +1300,15 @@ static MagickRealType SoftLight(const MagickRealType Sca,
 }
 
 static inline void CompositeSoftLight(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
   gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
   composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
   gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
@@ -1052,33 +1323,14 @@ static inline void CompositeSoftLight(const MagickPixelPacket *p,
       q->index*Da,Da);
 }
 
-static inline MagickRealType Subtract(const MagickRealType p,
-  const MagickRealType magick_unused(alpha),const MagickRealType q,
-  const MagickRealType magick_unused(beta))
-{
-  MagickRealType
-    pixel;
-
-  pixel=p-q;
-  if (pixel < 0.0)
-    pixel+=(QuantumRange+1.0);
-  return(pixel);
-}
-
-static inline void CompositeSubtract(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
-{
-  composite->red=Subtract(p->red,alpha,q->red,beta);
-  composite->green=Subtract(p->green,alpha,q->green,beta);
-  composite->blue=Subtract(p->blue,alpha,q->blue,beta);
-  if (q->colorspace == CMYKColorspace)
-    composite->index=Subtract(p->index,alpha,q->index,beta);
-}
-
+/*
+  Depreciated
+  Multiply difference by amount, if differance larger than threshold???
+  What use this is is completely unknown
+  The Opacity calculation appears to be inverted  -- Anthony Thyssen
+*/
 static inline MagickRealType Threshold(const MagickRealType p,
-  const MagickRealType magick_unused(alpha),const MagickRealType q,
-  const MagickRealType magick_unused(beta),const MagickRealType threshold,
+  const MagickRealType q,const MagickRealType threshold,
   const MagickRealType amount)
 {
   MagickRealType
@@ -1091,19 +1343,19 @@ static inline MagickRealType Threshold(const MagickRealType p,
 }
 
 static inline void CompositeThreshold(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,const MagickRealType threshold,
+  const MagickPixelPacket *q,const MagickRealType threshold,
   const MagickRealType amount,MagickPixelPacket *composite)
 {
-  composite->red=Threshold(p->red,alpha,q->red,beta,threshold,amount);
-  composite->green=Threshold(p->green,alpha,q->green,beta,threshold,amount);
-  composite->blue=Threshold(p->blue,alpha,q->blue,beta,threshold,amount);
-  composite->opacity=(MagickRealType) QuantumRange-
-    Threshold(p->opacity,alpha,q->opacity,beta,threshold,amount);
+  composite->red=Threshold(p->red,q->red,threshold,amount);
+  composite->green=Threshold(p->green,q->green,threshold,amount);
+  composite->blue=Threshold(p->blue,q->blue,threshold,amount);
+  composite->opacity=QuantumRange-Threshold(p->opacity,q->opacity,
+       threshold,amount);
   if (q->colorspace == CMYKColorspace)
-    composite->index=Threshold(p->index,alpha,q->index,beta,threshold,amount);
+    composite->index=Threshold(p->index,q->index,threshold,amount);
 }
 
+
 static MagickRealType VividLight(const MagickRealType Sca,
   const MagickRealType Sa, const MagickRealType Dca, const MagickRealType Da)
 {
@@ -1121,16 +1373,15 @@ static MagickRealType VividLight(const MagickRealType Sca,
 }
 
 static inline void CompositeVividLight(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
   gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
   composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
   gamma=QuantumRange/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
@@ -1152,21 +1403,17 @@ static MagickRealType Xor(const MagickRealType Sca,const MagickRealType Sa,
 }
 
 static inline void CompositeXor(const MagickPixelPacket *p,
-  const MagickRealType alpha,const MagickPixelPacket *q,
-  const MagickRealType beta,MagickPixelPacket *composite)
+  const MagickPixelPacket *q,MagickPixelPacket *composite)
 {
   MagickRealType
     Da,
     gamma,
     Sa;
 
-  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
-  Da=1.0-QuantumScale*beta;
+  Sa=1.0-QuantumScale*p->opacity;  /* simplify and speed up equations */
+  Da=1.0-QuantumScale*q->opacity;
   gamma=Sa+Da-2*Sa*Da;        /* Xor blend mode X=0,Y=1,Z=1 */
   composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
-  /*
-    Optimized by multipling QuantumRange taken from gamma.
-  */
   gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
   composite->red=gamma*Xor(p->red*Sa,Sa,q->red*Da,Da);
   composite->green=gamma*Xor(p->green*Sa,Sa,q->green*Da,Da);
@@ -1254,7 +1501,7 @@ static void HSBComposite(const double hue,const double saturation,
 
 MagickExport MagickBooleanType CompositeImage(Image *image,
   const CompositeOperator compose,const Image *composite_image,
-  const long x_offset,const long y_offset)
+  const ssize_t x_offset,const ssize_t y_offset)
 {
   MagickBooleanType
     status;
@@ -1265,8 +1512,8 @@ MagickExport MagickBooleanType CompositeImage(Image *image,
 }
 
 MagickExport MagickBooleanType CompositeImageChannel(Image *image,
-  const ChannelType magick_unused(channel),const CompositeOperator compose,
-  const Image *composite_image,const long x_offset,const long y_offset)
+  const ChannelType channel,const CompositeOperator compose,
+  const Image *composite_image,const ssize_t x_offset,const ssize_t y_offset)
 {
 #define CompositeImageTag  "Composite/Image"
 
@@ -1289,14 +1536,13 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
   Image
     *destination_image;
 
-  long
-    progress,
-    y;
-
   MagickBooleanType
     modify_outside_overlay,
     status;
 
+  MagickOffsetType
+    progress;
+
   MagickPixelPacket
     zero;
 
@@ -1312,6 +1558,9 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
   MagickStatusType
     flags;
 
+  ssize_t
+    y;
+
   /*
     Prepare composite image.
   */
@@ -1360,18 +1609,18 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
     {
       if ((x_offset < 0) || (y_offset < 0))
         break;
-      if ((x_offset+(long) composite_image->columns) >= (long) image->columns)
+      if ((x_offset+(ssize_t) composite_image->columns) >= (ssize_t) image->columns)
         break;
-      if ((y_offset+(long) composite_image->rows) >= (long) image->rows)
+      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) && (_OPENMP >= 200203)
-#pragma omp parallel for shared(status)
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+#pragma omp parallel for schedule(dynamic,4) shared(status)
 #endif
-      for (y=0; y < (long) composite_image->rows; y++)
+      for (y=0; y < (ssize_t) composite_image->rows; y++)
       {
         MagickBooleanType
           sync;
@@ -1414,10 +1663,11 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
             MagickBooleanType
               proceed;
 
-#if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
-#pragma omp critical (MagickCore_TextureImage)
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+#pragma omp critical (MagickCore_CompositeImage)
 #endif
-            proceed=SetImageProgress(image,CompositeImageTag,y,image->rows);
+            proceed=SetImageProgress(image,CompositeImageTag,
+              (MagickOffsetType) y,image->rows);
             if (proceed == MagickFalse)
               status=MagickFalse;
           }
@@ -1440,26 +1690,28 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
     }
     case BlurCompositeOp:
     {
+      CacheView
+        *composite_view,
+        *destination_view;
+
       MagickPixelPacket
         pixel;
 
       MagickRealType
-        blur_xu,
-        blur_xv,
-        blur_yu,
-        blur_yv;
+        angle_range,
+        angle_start,
+        height,
+        width;
 
       ResampleFilter
         *resample_filter;
 
-      CacheView
-        *composite_view,
-        *dest_view;
+      SegmentInfo
+        blur;
 
       /*
-        Blur Image dictated by an overlay gradient map:
-          X = red_channel;  Y = green_channel;
-          compose:args =  x_scale[,y_scale[,angle]]
+        Blur Image dictated by an overlay gradient map: X = red_channel;
+          Y = green_channel; compose:args =  x_scale[,y_scale[,angle]].
       */
       destination_image=CloneImage(image,image->columns,image->rows,MagickTrue,
         &image->exception);
@@ -1478,25 +1730,31 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
           destination_image=DestroyImage(destination_image);
           return(MagickFalse);
         }
-      blur_xu=geometry_info.rho;
-      blur_yv=geometry_info.sigma;
-      blur_xv=blur_yu = 0.0;
+      width=geometry_info.rho;
+      height=geometry_info.sigma;
+      blur.x1=geometry_info.rho;
+      blur.x2=0.0;
+      blur.y1=0.0;
+      blur.y2=geometry_info.sigma;
+      angle_start=0.0;
+      angle_range=0.0;
       if ((flags & HeightValue) == 0)
-        blur_yv=blur_xu;
-      if ((flags & XValue) != 0)
+        blur.y2=blur.x1;
+      if ((flags & XValue) != 0 )
         {
           MagickRealType
-            angle,
-            x,
-            y;
+            angle;
 
-          x=blur_xu;
-          y=blur_yv;
           angle=DegreesToRadians(geometry_info.xi);
-          blur_xu=x*cos(angle);
-          blur_xv=x*sin(angle);
-          blur_yu=(-y*sin(angle));
-          blur_yu=y*cos(angle);
+          blur.x1=width*cos(angle);
+          blur.x2=width*sin(angle);
+          blur.y1=(-height*sin(angle));
+          blur.y2=height*cos(angle);
+        }
+      if ((flags & YValue) != 0 )
+        {
+          angle_start=DegreesToRadians(geometry_info.xi);
+          angle_range=DegreesToRadians(geometry_info.psi)-angle_start;
         }
       /*
         Blur Image by resampling;
@@ -1504,92 +1762,104 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
       pixel=zero;
       exception=(&image->exception);
       resample_filter=AcquireResampleFilter(image,&image->exception);
-      SetResampleFilter(resample_filter,GaussianFilter,1.0);
-      dest_view=AcquireCacheView(destination_image);
+      SetResampleFilter(resample_filter,GaussianFilter,sqrt(2.0));
+      destination_view=AcquireCacheView(destination_image);
       composite_view=AcquireCacheView(composite_image);
-      for (y=0; y < (long) composite_image->rows; y++)
+      for (y=0; y < (ssize_t) composite_image->rows; y++)
       {
         MagickBooleanType
           sync;
 
         register const PixelPacket
-          *__restrict p;
+          *restrict p;
 
         register PixelPacket
-          *__restrict r;
+          *restrict r;
 
         register IndexPacket
-          *__restrict destination_indexes;
+          *restrict destination_indexes;
 
-        register long
+        register ssize_t
           x;
 
-        if (((y+y_offset) < 0) || ((y+y_offset) >= (long) image->rows))
+        if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
           continue;
         p=GetCacheViewVirtualPixels(composite_view,0,y,composite_image->columns,
           1,exception);
-        r=QueueCacheViewAuthenticPixels(dest_view,0,y,
+        r=QueueCacheViewAuthenticPixels(destination_view,0,y,
           destination_image->columns,1,&image->exception);
         if ((p == (const PixelPacket *) NULL) || (r == (PixelPacket *) NULL))
           break;
-        destination_indexes=GetCacheViewAuthenticIndexQueue(dest_view);
-        for (x=0; x < (long) composite_image->columns; x++)
+        destination_indexes=GetCacheViewAuthenticIndexQueue(destination_view);
+        for (x=0; x < (ssize_t) composite_image->columns; x++)
         {
-          if (((x_offset+x) < 0) || ((x_offset+x) >= (long) image->columns))
+          if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
             {
               p++;
               continue;
             }
-          ScaleResampleFilter(resample_filter,blur_xu*QuantumScale*p->red,
-            blur_yu*QuantumScale*p->green,blur_xv*QuantumScale*p->red,
-            blur_yv*QuantumScale*p->green);
+          if (fabs(angle_range) > MagickEpsilon)
+            {
+              MagickRealType
+                angle;
+
+              angle=angle_start+angle_range*QuantumScale*
+                GetBluePixelComponent(p);
+              blur.x1=width*cos(angle);
+              blur.x2=width*sin(angle);
+              blur.y1=(-height*sin(angle));
+              blur.y2=height*cos(angle);
+            }
+          ScaleResampleFilter(resample_filter,blur.x1*QuantumScale*p->red,
+            blur.y1*QuantumScale*p->green,blur.x2*QuantumScale*p->red,
+            blur.y2*QuantumScale*GetGreenPixelComponent(p));
           (void) ResamplePixelColor(resample_filter,(double) x_offset+x,
             (double) y_offset+y,&pixel);
           SetPixelPacket(destination_image,&pixel,r,destination_indexes+x);
           p++;
           r++;
         }
-        sync=SyncCacheViewAuthenticPixels(dest_view,exception);
+        sync=SyncCacheViewAuthenticPixels(destination_view,exception);
         if (sync == MagickFalse)
           break;
       }
       resample_filter=DestroyResampleFilter(resample_filter);
       composite_view=DestroyCacheView(composite_view);
-      dest_view=DestroyCacheView(dest_view);
+      destination_view=DestroyCacheView(destination_view);
       composite_image=destination_image;
       break;
     }
     case DisplaceCompositeOp:
     case DistortCompositeOp:
     {
+      CacheView
+        *composite_view,
+        *destination_view;
+
       MagickPixelPacket
         pixel;
 
       MagickRealType
         horizontal_scale,
-        vertical_scale,
-        x_center,
-        y_center,
-        x_lookup,
-        y_lookup;
+        vertical_scale;
+
+      PointInfo
+        center,
+        offset;
 
       register IndexPacket
-        *__restrict destination_indexes;
+        *restrict destination_indexes;
 
       register PixelPacket
-        *__restrict r;
+        *restrict r;
 
       ResampleFilter
         *resample_filter;
 
-      CacheView
-        *composite_view,
-        *dest_view;
-
       /*
         Displace/Distort based on overlay gradient map:
           X = red_channel;  Y = green_channel;
-          compose:args = x_scale[,y_scale[,x_center,y_center]]
+          compose:args = x_scale[,y_scale[,center.x,center.y]]
       */
       destination_image=CloneImage(image,image->columns,image->rows,MagickTrue,
         &image->exception);
@@ -1601,17 +1871,19 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
       if (value != (char *) NULL)
         flags=ParseGeometry(value,&geometry_info);
       if ((flags & (WidthValue|HeightValue)) == 0 )
-        if ((flags & AspectValue) == 0)
-          {
-            horizontal_scale=(MagickRealType) (composite_image->columns-1.0)/
-              2.0;
-            vertical_scale=(MagickRealType) (composite_image->rows-1.0)/2.0;
-          }
-        else
-          {
-            horizontal_scale=(MagickRealType) (image->columns-1.0)/2.0;
-            vertical_scale=(MagickRealType) (image->rows-1.0)/2.0;
-          }
+        {
+          if ((flags & AspectValue) == 0)
+            {
+              horizontal_scale=(MagickRealType) (composite_image->columns-1.0)/
+                2.0;
+              vertical_scale=(MagickRealType) (composite_image->rows-1.0)/2.0;
+            }
+          else
+            {
+              horizontal_scale=(MagickRealType) (image->columns-1.0)/2.0;
+              vertical_scale=(MagickRealType) (image->rows-1.0)/2.0;
+            }
+        }
       else
         {
           horizontal_scale=geometry_info.rho;
@@ -1635,101 +1907,100 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
       /*
         Determine fixed center point for absolute distortion map
          Absolute distort ==
-           Displace lookup relative to a fixed absolute point
+           Displace offset relative to a fixed absolute point
            Select that point according to +X+Y user inputs.
            default = center of overlay image
-           flag '!' = locations/percentage relative to background image
+           arg flag '!' = locations/percentage relative to background image
       */
-      x_center=(MagickRealType) x_offset;
-      y_center=(MagickRealType) y_offset;
+      center.x=(MagickRealType) x_offset;
+      center.y=(MagickRealType) y_offset;
       if (compose == DistortCompositeOp)
         {
           if ((flags & XValue) == 0)
             if ((flags & AspectValue) == 0)
-              x_center=(MagickRealType) x_offset+ (composite_image->columns-1)/
+              center.x=(MagickRealType) x_offset+(composite_image->columns-1)/
                 2.0;
             else
-              x_center=((MagickRealType) image->columns-1)/2.0;
+              center.x=((MagickRealType) image->columns-1)/2.0;
           else
             if ((flags & AspectValue) == 0)
-              x_center=(MagickRealType) x_offset+geometry_info.xi;
+              center.x=(MagickRealType) x_offset+geometry_info.xi;
             else
-              x_center=geometry_info.xi;
+              center.x=geometry_info.xi;
           if ((flags & YValue) == 0)
             if ((flags & AspectValue) == 0)
-              y_center=(MagickRealType) y_offset+
-                (composite_image->rows-1)/2.0;
+              center.y=(MagickRealType) y_offset+(composite_image->rows-1)/2.0;
             else
-              y_center=((MagickRealType) image->rows-1)/2.0;
+              center.y=((MagickRealType) image->rows-1)/2.0;
           else
             if ((flags & AspectValue) == 0)
-              y_center=(MagickRealType) y_offset+geometry_info.psi;
+              center.y=(MagickRealType) y_offset+geometry_info.psi;
             else
-              y_center=geometry_info.psi;
+              center.y=geometry_info.psi;
         }
       /*
-        Shift the pixel lookup point as defined by the provided,
+        Shift the pixel offset point as defined by the provided,
         displacement/distortion map.  -- Like a lens...
       */
       pixel=zero;
       exception=(&image->exception);
       resample_filter=AcquireResampleFilter(image,&image->exception);
-      dest_view=AcquireCacheView(destination_image);
+      destination_view=AcquireCacheView(destination_image);
       composite_view=AcquireCacheView(composite_image);
-      for (y=0; y < (long) composite_image->rows; y++)
+      for (y=0; y < (ssize_t) composite_image->rows; y++)
       {
         MagickBooleanType
           sync;
 
         register const PixelPacket
-          *__restrict p;
+          *restrict p;
 
-        register long
+        register ssize_t
           x;
 
-        if (((y+y_offset) < 0) || ((y+y_offset) >= (long) image->rows))
+        if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
           continue;
         p=GetCacheViewVirtualPixels(composite_view,0,y,composite_image->columns,
           1,exception);
-        r=QueueCacheViewAuthenticPixels(dest_view,0,y,
+        r=QueueCacheViewAuthenticPixels(destination_view,0,y,
           destination_image->columns,1,&image->exception);
         if ((p == (const PixelPacket *) NULL) || (r == (PixelPacket *) NULL))
           break;
-        destination_indexes=GetCacheViewAuthenticIndexQueue(dest_view);
-        for (x=0; x < (long) composite_image->columns; x++)
+        destination_indexes=GetCacheViewAuthenticIndexQueue(destination_view);
+        for (x=0; x < (ssize_t) composite_image->columns; x++)
         {
-          if (((x_offset+x) < 0) || ((x_offset+x) >= (long) image->columns))
+          if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
             {
               p++;
               continue;
             }
           /*
-            Displace the lookup.
+            Displace the offset.
           */
-          x_lookup=(horizontal_scale*(p->red-(((MagickRealType) QuantumRange+
+          offset.x=(horizontal_scale*(p->red-(((MagickRealType) QuantumRange+
             1.0)/2.0)))/(((MagickRealType) QuantumRange+1.0)/2.0)+
-            x_center+((compose == DisplaceCompositeOp) ? x : 0);
-          y_lookup=(vertical_scale*(p->green-(((MagickRealType) QuantumRange+
+            center.x+((compose == DisplaceCompositeOp) ? x : 0);
+          offset.y=(vertical_scale*(p->green-(((MagickRealType) QuantumRange+
             1.0)/2.0)))/(((MagickRealType) QuantumRange+1.0)/2.0)+
-            y_center+((compose == DisplaceCompositeOp) ? y : 0);
-          (void) ResamplePixelColor(resample_filter,(double) x_lookup,
-            (double) y_lookup,&pixel);
+            center.y+((compose == DisplaceCompositeOp) ? y : 0);
+          (void) ResamplePixelColor(resample_filter,(double) offset.x,
+            (double) offset.y,&pixel);
           /*
-            Mask with 'invalid pixel mask' in alpha channel.
+            Mask with the 'invalid pixel mask' in alpha channel.
           */
-          pixel.opacity = (MagickRealType) QuantumRange*(1.0-(1.0-QuantumScale*
-            pixel.opacity)*(1.0-QuantumScale*p->opacity));
+          pixel.opacity=(MagickRealType) QuantumRange*(1.0-(1.0-QuantumScale*
+            pixel.opacity)*(1.0-QuantumScale*GetOpacityPixelComponent(p)));
           SetPixelPacket(destination_image,&pixel,r,destination_indexes+x);
           p++;
           r++;
         }
-        sync=SyncCacheViewAuthenticPixels(dest_view,exception);
+        sync=SyncCacheViewAuthenticPixels(destination_view,exception);
         if (sync == MagickFalse)
           break;
       }
       resample_filter=DestroyResampleFilter(resample_filter);
       composite_view=DestroyCacheView(composite_view);
-      dest_view=DestroyCacheView(dest_view);
+      destination_view=DestroyCacheView(destination_view);
       composite_image=destination_image;
       break;
     }
@@ -1815,6 +2086,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
     {
       /*
         Determine the amount and threshold.
+        This Composition method is depreciated
       */
       value=GetImageArtifact(composite_image,"compose:args");
       if (value != (char *) NULL)
@@ -1844,10 +2116,10 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
   exception=(&image->exception);
   image_view=AcquireCacheView(image);
   composite_view=AcquireCacheView(composite_image);
-#if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
-  #pragma omp parallel for shared(progress,status)
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
 #endif
-  for (y=0; y < (long) image->rows; y++)
+  for (y=0; y < (ssize_t) image->rows; y++)
   {
     const PixelPacket
       *pixels;
@@ -1863,19 +2135,19 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
       source;
 
     register const IndexPacket
-      *__restrict composite_indexes;
+      *restrict composite_indexes;
 
     register const PixelPacket
-      *__restrict p;
+      *restrict p;
 
     register IndexPacket
-      *__restrict indexes;
+      *restrict indexes;
 
-    register long
+    register ssize_t
       x;
 
     register PixelPacket
-      *__restrict q;
+      *restrict q;
 
     if (status == MagickFalse)
       continue;
@@ -1883,7 +2155,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
       {
         if (y < y_offset)
           continue;
-        if ((y-y_offset) >= (long) composite_image->rows)
+        if ((y-y_offset) >= (ssize_t) composite_image->rows)
           continue;
       }
     /*
@@ -1891,7 +2163,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
     */
     pixels=(PixelPacket *) NULL;
     p=(PixelPacket *) NULL;
-    if ((y >= y_offset) && ((y-y_offset) < (long) composite_image->rows))
+    if ((y >= y_offset) && ((y-y_offset) < (ssize_t) composite_image->rows))
       {
         p=GetCacheViewVirtualPixels(composite_view,0,y-y_offset,
           composite_image->columns,1,exception);
@@ -1918,7 +2190,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
     hue=0.0;
     saturation=0.0;
     brightness=0.0;
-    for (x=0; x < (long) image->columns; x++)
+    for (x=0; x < (ssize_t) image->columns; x++)
     {
       if (modify_outside_overlay == MagickFalse)
         {
@@ -1927,7 +2199,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
               q++;
               continue;
             }
-          if ((x-x_offset) >= (long) composite_image->columns)
+          if ((x-x_offset) >= (ssize_t) composite_image->columns)
             break;
         }
       destination.red=(MagickRealType) q->red;
@@ -1947,7 +2219,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
       */
       composite=destination;
       if ((pixels == (PixelPacket *) NULL) || (x < x_offset) ||
-          ((x-x_offset) >= (long) composite_image->columns))
+          ((x-x_offset) >= (ssize_t) composite_image->columns))
         {
           switch (compose)
           {
@@ -1990,24 +2262,24 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
               composite.blue=(MagickRealType) QuantumRange-composite.blue;
               composite.index=(MagickRealType) QuantumRange-composite.index;
             }
-          q->red=RoundToQuantum(composite.red);
-          q->green=RoundToQuantum(composite.green);
-          q->blue=RoundToQuantum(composite.blue);
+          q->red=ClampToQuantum(composite.red);
+          q->green=ClampToQuantum(composite.green);
+          q->blue=ClampToQuantum(composite.blue);
           if (image->matte != MagickFalse)
-            q->opacity=RoundToQuantum(composite.opacity);
+            q->opacity=ClampToQuantum(composite.opacity);
           if (image->colorspace == CMYKColorspace)
-            indexes[x]=RoundToQuantum(composite.index);
+            indexes[x]=ClampToQuantum(composite.index);
           q++;
           continue;
         }
       /*
         Handle normal overlay of source onto destination.
       */
-      source.red=(MagickRealType) p->red;
-      source.green=(MagickRealType) p->green;
-      source.blue=(MagickRealType) p->blue;
+      source.red=(MagickRealType) GetRedPixelComponent(p);
+      source.green=(MagickRealType) GetGreenPixelComponent(p);
+      source.blue=(MagickRealType) GetBluePixelComponent(p);
       if (composite_image->matte != MagickFalse)
-        source.opacity=(MagickRealType) p->opacity;
+        source.opacity=(MagickRealType) GetOpacityPixelComponent(p);
       if (composite_image->colorspace == CMYKColorspace)
         {
           source.red=(MagickRealType) QuantumRange-source.red;
@@ -2018,12 +2290,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
         }
       switch (compose)
       {
-        case AddCompositeOp:
-        {
-          CompositeAdd(&source,source.opacity,&destination,destination.opacity,
-            &composite);
-          break;
-        }
+        /* Duff-Porter Compositions */
         case ClearCompositeOp:
         {
           CompositeClear(&destination,&composite);
@@ -2036,209 +2303,200 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
           composite=source;
           break;
         }
-        case ChangeMaskCompositeOp:
-        {
-          if ((composite.opacity > ((MagickRealType) QuantumRange/2.0)) ||
-              (IsMagickColorSimilar(&source,&destination) != MagickFalse))
-            composite.opacity=(MagickRealType) TransparentOpacity;
-          else
-            composite.opacity=(MagickRealType) OpaqueOpacity;
-          break;
-        }
-        case DivideCompositeOp:
-        {
-          CompositeDivide(&source,source.opacity,&destination,
-            destination.opacity,&composite);
-          break;
-        }
+        case NoCompositeOp:
         case DstCompositeOp:
           break;
         case OverCompositeOp:
         case SrcOverCompositeOp:
         {
-          CompositeOver(&source,source.opacity,&destination,destination.opacity,
-            &composite);
+          MagickPixelCompositeOver(&source,source.opacity,
+               &destination,destination.opacity,&composite);
           break;
         }
         case DstOverCompositeOp:
         {
-          CompositeOver(&destination,destination.opacity,&source,source.opacity,
-            &composite);
+          MagickPixelCompositeOver(&destination,destination.opacity,
+               &source,source.opacity,&composite);
           break;
         }
         case SrcInCompositeOp:
         case InCompositeOp:
         {
-          CompositeIn(&source,source.opacity,&destination,destination.opacity,
-            &composite);
+          CompositeIn(&source,&destination,&composite);
           break;
         }
         case DstInCompositeOp:
         {
-          CompositeIn(&destination,destination.opacity,&source,source.opacity,
-            &composite);
+          CompositeIn(&destination,&source,&composite);
           break;
         }
         case OutCompositeOp:
         case SrcOutCompositeOp:
         {
-          CompositeOut(&source,source.opacity,&destination,destination.opacity,
-            &composite);
+          CompositeOut(&source,&destination,&composite);
           break;
         }
         case DstOutCompositeOp:
         {
-          CompositeOut(&destination,destination.opacity,&source,source.opacity,
-            &composite);
+          CompositeOut(&destination,&source,&composite);
           break;
         }
         case AtopCompositeOp:
         case SrcAtopCompositeOp:
         {
-          CompositeAtop(&source,source.opacity,&destination,destination.opacity,
-            &composite);
+          CompositeAtop(&source,&destination,&composite);
           break;
         }
         case DstAtopCompositeOp:
         {
-          CompositeAtop(&destination,destination.opacity,&source,source.opacity,
-            &composite);
+          CompositeAtop(&destination,&source,&composite);
           break;
         }
         case XorCompositeOp:
         {
-          CompositeXor(&source,source.opacity,&destination,destination.opacity,
-            &composite);
+          CompositeXor(&source,&destination,&composite);
           break;
         }
+        /* Mathematical Compositions */
         case PlusCompositeOp:
         {
-          CompositePlus(&source,source.opacity,&destination,destination.opacity,
-            &composite);
+          CompositePlus(&source,&destination,channel,&composite);
+          break;
+        }
+        case MinusCompositeOp:
+        {
+          CompositeMinus(&source,&destination,
+            channel,&composite);
+          break;
+        }
+        case ModulusAddCompositeOp:
+        {
+          CompositeModulusAdd(&source,&destination,channel,&composite);
+          break;
+        }
+        case ModulusSubtractCompositeOp:
+        {
+          CompositeModulusSubtract(&source,&destination,channel,&composite);
+          break;
+        }
+        case DifferenceCompositeOp:
+        {
+          CompositeDifference(&source,&destination,channel,&composite);
+          break;
+        }
+        case ExclusionCompositeOp:
+        {
+          CompositeExclusion(&source,&destination,channel,&composite);
           break;
         }
         case MultiplyCompositeOp:
         {
-          CompositeMultiply(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositeMultiply(&source,&destination,channel,&composite);
           break;
         }
         case ScreenCompositeOp:
         {
-          CompositeScreen(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositeScreen(&source,&destination,channel,&composite);
+          break;
+        }
+        case DivideCompositeOp:
+        {
+          CompositeDivide(&source,&destination,channel,&composite);
           break;
         }
         case DarkenCompositeOp:
         {
-          CompositeDarken(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositeDarken(&source,&destination,channel,&composite);
           break;
         }
         case LightenCompositeOp:
         {
-          CompositeLighten(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositeLighten(&source,&destination,channel,&composite);
           break;
         }
+        case MathematicsCompositeOp:
+        {
+          CompositeMathematics(&source,&destination,channel,&geometry_info,
+               &composite);
+          break;
+        }
+        /* Lighting Compositions */
         case ColorDodgeCompositeOp:
         {
-          CompositeColorDodge(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositeColorDodge(&source,&destination,&composite);
           break;
         }
         case ColorBurnCompositeOp:
         {
-          CompositeColorBurn(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositeColorBurn(&source,&destination,&composite);
           break;
         }
         case LinearDodgeCompositeOp:
         {
-          CompositeLinearDodge(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositeLinearDodge(&source,&destination,&composite);
           break;
         }
         case LinearBurnCompositeOp:
         {
-          CompositeLinearBurn(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositeLinearBurn(&source,&destination,&composite);
           break;
         }
         case HardLightCompositeOp:
         {
-          CompositeHardLight(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositeHardLight(&source,&destination,&composite);
           break;
         }
         case OverlayCompositeOp:
         {
-          /*
-            Reversed HardLight.
-          */
-          CompositeHardLight(&destination,destination.opacity,&source,
-            source.opacity,&composite);
+          /* Overlay = Reversed HardLight. */
+          CompositeHardLight(&destination,&source,&composite);
           break;
         }
         case SoftLightCompositeOp:
         {
-          CompositeSoftLight(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositeSoftLight(&source,&destination,&composite);
           break;
         }
         case LinearLightCompositeOp:
         {
-          CompositeLinearLight(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositeLinearLight(&source,&destination,&composite);
           break;
         }
         case PegtopLightCompositeOp:
         {
-          CompositePegtopLight(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositePegtopLight(&source,&destination,&composite);
           break;
         }
         case VividLightCompositeOp:
         {
-          CompositeVividLight(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositeVividLight(&source,&destination,&composite);
           break;
         }
         case PinLightCompositeOp:
         {
-          CompositePinLight(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositePinLight(&source,&destination,&composite);
           break;
         }
-        case DifferenceCompositeOp:
-        {
-          CompositeDifference(&source,source.opacity,&destination,
-            destination.opacity,&composite);
-          break;
-        }
-        case ExclusionCompositeOp:
-        {
-          CompositeExclusion(&source,source.opacity,&destination,
-            destination.opacity,&composite);
-          break;
-        }
-        case MinusCompositeOp:
+        /* Other Composition */
+        case ChangeMaskCompositeOp:
         {
-          CompositeMinus(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          if ((composite.opacity > ((MagickRealType) QuantumRange/2.0)) ||
+              (IsMagickColorSimilar(&source,&destination) != MagickFalse))
+            composite.opacity=(MagickRealType) TransparentOpacity;
+          else
+            composite.opacity=(MagickRealType) OpaqueOpacity;
           break;
         }
         case BumpmapCompositeOp:
         {
           if (source.opacity == TransparentOpacity)
             break;
-          CompositeBumpmap(&source,source.opacity,&destination,
-            destination.opacity,&composite);
+          CompositeBumpmap(&source,&destination,&composite);
           break;
         }
         case DissolveCompositeOp:
         {
-          CompositeOver(&source,(MagickRealType) (QuantumRange-source_dissolve*
+          MagickPixelCompositeOver(&source,(MagickRealType) (QuantumRange-source_dissolve*
             (QuantumRange-source.opacity)),&destination,(MagickRealType)
             (QuantumRange-destination_dissolve*(QuantumRange-
             destination.opacity)),&composite);
@@ -2250,32 +2508,19 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
             destination_dissolve,&composite);
           break;
         }
-        case MathematicsCompositeOp:
-        {
-          CompositeMathematics(&source,&destination,&geometry_info,&composite);
-          break;
-        }
-        case BlurCompositeOp:
-        case DisplaceCompositeOp:
-        case DistortCompositeOp:
-        {
-          composite=source;
-          break;
-        }
         case ThresholdCompositeOp:
         {
-          CompositeThreshold(&source,source.opacity,&destination,
-            destination.opacity,threshold,amount,&composite);
+          CompositeThreshold(&source,&destination,threshold,amount,&composite);
           break;
         }
         case ModulateCompositeOp:
         {
-          long
+          ssize_t
             offset;
 
           if (source.opacity == TransparentOpacity)
             break;
-          offset=(long) (MagickPixelIntensityToQuantum(&source)-midpoint);
+          offset=(ssize_t) (MagickPixelIntensityToQuantum(&source)-midpoint);
           if (offset == 0)
             break;
           CompositeHSB(destination.red,destination.green,destination.blue,&hue,
@@ -2323,12 +2568,6 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
             composite.opacity=source.opacity;
           break;
         }
-        case SubtractCompositeOp:
-        {
-          CompositeSubtract(&source,source.opacity,&destination,
-            destination.opacity,&composite);
-          break;
-        }
         case LuminizeCompositeOp:
         {
           if (source.opacity == TransparentOpacity)
@@ -2403,6 +2642,14 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
           composite.index=source.index;
           break;
         }
+        /* compose methods that are already handled */
+        case BlurCompositeOp:
+        case DisplaceCompositeOp:
+        case DistortCompositeOp:
+        {
+          composite=source;
+          break;
+        }
         default:
           break;
       }
@@ -2413,12 +2660,12 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
           composite.blue=(MagickRealType) QuantumRange-composite.blue;
           composite.index=(MagickRealType) QuantumRange-composite.index;
         }
-      q->red=RoundToQuantum(composite.red);
-      q->green=RoundToQuantum(composite.green);
-      q->blue=RoundToQuantum(composite.blue);
-      q->opacity=RoundToQuantum(composite.opacity);
+      q->red=ClampToQuantum(composite.red);
+      q->green=ClampToQuantum(composite.green);
+      q->blue=ClampToQuantum(composite.blue);
+      q->opacity=ClampToQuantum(composite.opacity);
       if (image->colorspace == CMYKColorspace)
-        indexes[x]=RoundToQuantum(composite.index);
+        indexes[x]=ClampToQuantum(composite.index);
       p++;
       if (p >= (pixels+composite_image->columns))
         p=pixels;
@@ -2431,7 +2678,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image,
         MagickBooleanType
           proceed;
 
-#if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
   #pragma omp critical (MagickCore_CompositeImageChannel)
 #endif
         proceed=SetImageProgress(image,CompositeImageTag,progress++,
@@ -2483,7 +2730,7 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture)
   ExceptionInfo
     *exception;
 
-  long
+  ssize_t
     y;
 
   MagickBooleanType
@@ -2495,6 +2742,7 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture)
   assert(image->signature == MagickSignature);
   if (texture == (const Image *) NULL)
     return(MagickFalse);
+  (void) SetImageVirtualPixelMethod(texture,TileVirtualPixelMethod);
   if (SetImageStorageClass(image,DirectClass) == MagickFalse)
     return(MagickFalse);
   status=MagickTrue;
@@ -2505,17 +2753,17 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture)
       /*
         Tile texture onto the image background.
       */
-#if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
-  #pragma omp parallel for shared(status)
+#if defined(MAGICKCORE_OPENMP_SUPPORT) 
+      #pragma omp parallel for schedule(dynamic,4) shared(status) omp_throttle(1)
 #endif
-      for (y=0; y < (long) image->rows; y+=texture->rows)
+      for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) texture->rows)
       {
-        register long
+        register ssize_t
           x;
 
         if (status == MagickFalse)
           continue;
-        for (x=0; x < (long) image->columns; x+=texture->columns)
+        for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture->columns)
         {
           MagickBooleanType
             thread_status;
@@ -2533,10 +2781,11 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture)
             MagickBooleanType
               proceed;
 
-#if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
+#if defined(MAGICKCORE_OPENMP_SUPPORT) 
   #pragma omp critical (MagickCore_TextureImage)
 #endif
-            proceed=SetImageProgress(image,TextureImageTag,y,image->rows);
+            proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType)
+              y,image->rows);
             if (proceed == MagickFalse)
               status=MagickFalse;
           }
@@ -2552,10 +2801,10 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture)
   exception=(&image->exception);
   image_view=AcquireCacheView(image);
   texture_view=AcquireCacheView(texture);
-#if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
-#pragma omp parallel for shared(status)
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+  #pragma omp parallel for schedule(dynamic,4) shared(status) omp_throttle(1)
 #endif
-  for (y=0; y < (long) image->rows; y++)
+  for (y=0; y < (ssize_t) image->rows; y++)
   {
     MagickBooleanType
       sync;
@@ -2569,19 +2818,19 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture)
     register IndexPacket
       *indexes;
 
-    register long
+    register ssize_t
       x;
 
     register PixelPacket
       *q;
 
-    unsigned long
+    size_t
       width;
 
     if (status == MagickFalse)
       continue;
-    p=GetCacheViewVirtualPixels(texture_view,0,y % texture->rows,
-      texture->columns,1,exception);
+    p=GetCacheViewVirtualPixels(texture_view,texture->tile_offset.x,(y+
+      texture->tile_offset.y) % texture->rows,texture->columns,1,exception);
     q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
       exception);
     if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
@@ -2591,10 +2840,10 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture)
       }
     texture_indexes=GetCacheViewVirtualIndexQueue(texture_view);
     indexes=GetCacheViewAuthenticIndexQueue(image_view);
-    for (x=0; x < (long) image->columns; x+=texture->columns)
+    for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture->columns)
     {
       width=texture->columns;
-      if ((x+(long) width) > (long) image->columns)
+      if ((x+(ssize_t) width) > (ssize_t) image->columns)
         width=image->columns-x;
       (void) CopyMagickMemory(q,p,width*sizeof(*p));
       if ((image->colorspace == CMYKColorspace) &&
@@ -2614,10 +2863,11 @@ MagickExport MagickBooleanType TextureImage(Image *image,const Image *texture)
         MagickBooleanType
           proceed;
 
-#if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
-#pragma omp critical (MagickCore_TextureImage)
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+        #pragma omp critical (MagickCore_TextureImage)
 #endif
-        proceed=SetImageProgress(image,TextureImageTag,y,image->rows);
+        proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
+          image->rows);
         if (proceed == MagickFalse)
           status=MagickFalse;
       }