10b3cd894449ef55209b831c27b05746e8eece387cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        CCCC   OOO   M   M  PPPP    OOO   SSSSS  IIIII  TTTTT  EEEEE         %
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%       C      O   O  MM MM  P   P  O   O  SS       I      T    E             %
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%       C      O   O  M M M  PPPP   O   O   SSS     I      T    EEE           %
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%       C      O   O  M   M  P      O   O     SS    I      T    E             %
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        CCCC   OOO   M   M  P       OOO   SSSSS  IIIII    T    EEEEE         %
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                     MagickCore Image Composite Methods                      %
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              Software Design                                %
16de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy%                                   Cristy                                    %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                 July 1992                                   %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
207ce65e7125a4e1df1a274ce373c537a9df9c16cdCristy%  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  dedicated to making software imaging solutions freely available.           %
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  You may not use this file except in compliance with the License.  You may  %
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  obtain a copy of the License at                                            %
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    http://www.imagemagick.org/script/license.php                            %
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Unless required by applicable law or agreed to in writing, software        %
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  See the License for the specific language governing permissions and        %
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  limitations under the License.                                             %
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Include declarations.
423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
434c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h"
444c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/artifact.h"
454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache.h"
465201002e1ba0118594060d26142b48bdfb1320a2cristy#include "MagickCore/cache-private.h"
474c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache-view.h"
486a2180cee55312a7c0c633670803f9face88a82acristy#include "MagickCore/channel.h"
494c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/client.h"
504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color.h"
514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color-private.h"
524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colorspace.h"
534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colorspace-private.h"
544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/composite.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/composite-private.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/constitute.h"
574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/draw.h"
584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/fx.h"
594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/gem.h"
604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/geometry.h"
614c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image.h"
624c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h"
634c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/list.h"
644c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/log.h"
654c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor.h"
664c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor-private.h"
674c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h"
684c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/option.h"
694c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h"
704c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/property.h"
714c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum.h"
724c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/resample.h"
734c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/resource_.h"
744c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h"
754c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/thread-private.h"
76191c0b74324ab2ee84cf3c426285ecc07ef57394cristy#include "MagickCore/threshold.h"
7763a81879d3568083e4ee4f78ebcae2bc831cb764cristy#include "MagickCore/token.h"
784c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/utility.h"
79d1dd6e4fefa0810b9893e6ac9418f79c97c1b39acristy#include "MagickCore/utility-private.h"
804c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/version.h"
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
87f4ad9df69835f9ed5c687a9f93e8a53e23a3258fcristy%   C o m p o s i t e I m a g e                                               %
883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
91e29f70ab001fe353d9fa73ff8c0d6d52daab3379anthony%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
92e29f70ab001fe353d9fa73ff8c0d6d52daab3379anthony%
93f4ad9df69835f9ed5c687a9f93e8a53e23a3258fcristy%  CompositeImage() returns the second image composited onto the first
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  at the specified offset, using the specified composite method.
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
96f4ad9df69835f9ed5c687a9f93e8a53e23a3258fcristy%  The format of the CompositeImage method is:
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType CompositeImage(Image *image,
99e8e8eff5f2414d6096195a41934fc0edee9d9212cristy%        const Image *source_image,const CompositeOperator compose,
100feb3e9695150978a5d2372d3fe2f60466a7c8066cristy%        const MagickBooleanType clip_to_self,const ssize_t x_offset,
101feb3e9695150978a5d2372d3fe2f60466a7c8066cristy%        const ssize_t y_offset,ExceptionInfo *exception)
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
105e8e8eff5f2414d6096195a41934fc0edee9d9212cristy%    o image: the canvas image, modified by he composition
1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
107e8e8eff5f2414d6096195a41934fc0edee9d9212cristy%    o source_image: the source image.
108feb3e9695150978a5d2372d3fe2f60466a7c8066cristy%
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o compose: This operator affects how the composite is applied to
1103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      the image.  The operators and how they are utilized are listed here
1113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      http://www.w3.org/TR/SVG12/#compositing.
1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
113feb3e9695150978a5d2372d3fe2f60466a7c8066cristy%    o clip_to_self: set to MagickTrue to limit composition to area composed.
1143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o x_offset: the column offset of the composited image.
1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o y_offset: the row offset of the composited image.
1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11955a83c75eeede1662a9e6c43c3af201502c9442fdirk%  Extra Controls from Image meta-data in 'image' (artifacts)
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o "compose:args"
1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        A string containing extra numerical arguments for specific compose
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        methods, generally expressed as a 'geometry' or a comma separated list
1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        of numbers.
1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        Compose methods needing such arguments include "BlendCompositeOp" and
1273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        "DisplaceCompositeOp".
1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
129e941a75fe8bf344bc5c06a7f74bb5173c87db115cristy%    o exception: return any errors or warnings in this structure.
130e941a75fe8bf344bc5c06a7f74bb5173c87db115cristy%
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
133ea068a53d23d6dca08f1bce44c8937d54f83b983anthony/*
134ea068a53d23d6dca08f1bce44c8937d54f83b983anthony   Composition based on the SVG specification:
135ea068a53d23d6dca08f1bce44c8937d54f83b983anthony
136ea068a53d23d6dca08f1bce44c8937d54f83b983anthony   A Composition is defined by...
137ea068a53d23d6dca08f1bce44c8937d54f83b983anthony      Color Function :  f(Sc,Dc)  where Sc and Dc are the normizalized colors
138ea068a53d23d6dca08f1bce44c8937d54f83b983anthony      Blending areas :  X = 1     for area of overlap, ie: f(Sc,Dc)
139ea068a53d23d6dca08f1bce44c8937d54f83b983anthony                        Y = 1     for source preserved
140e8e8eff5f2414d6096195a41934fc0edee9d9212cristy                        Z = 1     for canvas preserved
141ea068a53d23d6dca08f1bce44c8937d54f83b983anthony
142ea068a53d23d6dca08f1bce44c8937d54f83b983anthony   Conversion to transparency (then optimized)
143ea068a53d23d6dca08f1bce44c8937d54f83b983anthony      Dca' = f(Sc, Dc)*Sa*Da + Y*Sca*(1-Da) + Z*Dca*(1-Sa)
144ea068a53d23d6dca08f1bce44c8937d54f83b983anthony      Da'  = X*Sa*Da + Y*Sa*(1-Da) + Z*Da*(1-Sa)
145ea068a53d23d6dca08f1bce44c8937d54f83b983anthony
146ea068a53d23d6dca08f1bce44c8937d54f83b983anthony   Where...
147ea068a53d23d6dca08f1bce44c8937d54f83b983anthony      Sca = Sc*Sa     normalized Source color divided by Source alpha
148ea068a53d23d6dca08f1bce44c8937d54f83b983anthony      Dca = Dc*Da     normalized Dest color divided by Dest alpha
149ea068a53d23d6dca08f1bce44c8937d54f83b983anthony      Dc' = Dca'/Da'  the desired color value for this channel.
150ea068a53d23d6dca08f1bce44c8937d54f83b983anthony
151ea068a53d23d6dca08f1bce44c8937d54f83b983anthony   Da' in in the follow formula as 'gamma'  The resulting alpla value.
152ea068a53d23d6dca08f1bce44c8937d54f83b983anthony
153ea068a53d23d6dca08f1bce44c8937d54f83b983anthony   Most functions use a blending mode of over (X=1,Y=1,Z=1) this results in
154ea068a53d23d6dca08f1bce44c8937d54f83b983anthony   the following optimizations...
155ea068a53d23d6dca08f1bce44c8937d54f83b983anthony      gamma = Sa+Da-Sa*Da;
156ea068a53d23d6dca08f1bce44c8937d54f83b983anthony      gamma = 1 - QuantiumScale*alpha * QuantiumScale*beta;
157ea068a53d23d6dca08f1bce44c8937d54f83b983anthony      opacity = QuantiumScale*alpha*beta;  // over blend, optimized 1-Gamma
158ea068a53d23d6dca08f1bce44c8937d54f83b983anthony
159ea068a53d23d6dca08f1bce44c8937d54f83b983anthony   The above SVG definitions also definate that Mathematical Composition
160ea068a53d23d6dca08f1bce44c8937d54f83b983anthony   methods should use a 'Over' blending mode for Alpha Channel.
161ea068a53d23d6dca08f1bce44c8937d54f83b983anthony   It however was not applied for composition modes of 'Plus', 'Minus',
162ea068a53d23d6dca08f1bce44c8937d54f83b983anthony   the modulus versions of 'Add' and 'Subtract'.
163ea068a53d23d6dca08f1bce44c8937d54f83b983anthony
164ea068a53d23d6dca08f1bce44c8937d54f83b983anthony   Mathematical operator changes to be applied from IM v6.7...
165ea068a53d23d6dca08f1bce44c8937d54f83b983anthony
166ea068a53d23d6dca08f1bce44c8937d54f83b983anthony    1) Modulus modes 'Add' and 'Subtract' are obsoleted and renamed
167ea068a53d23d6dca08f1bce44c8937d54f83b983anthony       'ModulusAdd' and 'ModulusSubtract' for clarity.
168ea068a53d23d6dca08f1bce44c8937d54f83b983anthony
169ea068a53d23d6dca08f1bce44c8937d54f83b983anthony    2) All mathematical compositions work as per the SVG specification
170ea068a53d23d6dca08f1bce44c8937d54f83b983anthony       with regard to blending.  This now includes 'ModulusAdd' and
171ea068a53d23d6dca08f1bce44c8937d54f83b983anthony       'ModulusSubtract'.
172ea068a53d23d6dca08f1bce44c8937d54f83b983anthony
173ea068a53d23d6dca08f1bce44c8937d54f83b983anthony    3) When the special channel flag 'sync' (syncronize channel updates)
174ea068a53d23d6dca08f1bce44c8937d54f83b983anthony       is turned off (enabled by default) then mathematical compositions are
175ea068a53d23d6dca08f1bce44c8937d54f83b983anthony       only performed on the channels specified, and are applied
176ea068a53d23d6dca08f1bce44c8937d54f83b983anthony       independantally of each other.  In other words the mathematics is
177ea068a53d23d6dca08f1bce44c8937d54f83b983anthony       performed as 'pure' mathematical operations, rather than as image
178ea068a53d23d6dca08f1bce44c8937d54f83b983anthony       operations.
179ea068a53d23d6dca08f1bce44c8937d54f83b983anthony*/
180d8f16f7357707bfee6a939d39b5b312d1486d5c5cristy
1817159f66759ae05f052aad309915b9784f7aca927cristystatic void HCLComposite(const MagickRealType hue,const MagickRealType chroma,
1827159f66759ae05f052aad309915b9784f7aca927cristy  const MagickRealType luma,MagickRealType *red,MagickRealType *green,
1837159f66759ae05f052aad309915b9784f7aca927cristy  MagickRealType *blue)
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1857159f66759ae05f052aad309915b9784f7aca927cristy  MagickRealType
186d8f16f7357707bfee6a939d39b5b312d1486d5c5cristy    b,
1877133e649ea494c1286ff16bcb02342d660097219cristy    c,
188d8f16f7357707bfee6a939d39b5b312d1486d5c5cristy    g,
1897133e649ea494c1286ff16bcb02342d660097219cristy    h,
1907133e649ea494c1286ff16bcb02342d660097219cristy    m,
191d8f16f7357707bfee6a939d39b5b312d1486d5c5cristy    r,
192398fd02612ac738cc5c950c0e5df20a6db3db001cristy    x;
1933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1944c08aed51c5899665ade97263692328eea4af106cristy  /*
1957133e649ea494c1286ff16bcb02342d660097219cristy    Convert HCL to RGB colorspace.
1964c08aed51c5899665ade97263692328eea4af106cristy  */
1977159f66759ae05f052aad309915b9784f7aca927cristy  assert(red != (MagickRealType *) NULL);
1987159f66759ae05f052aad309915b9784f7aca927cristy  assert(green != (MagickRealType *) NULL);
1997159f66759ae05f052aad309915b9784f7aca927cristy  assert(blue != (MagickRealType *) NULL);
2007133e649ea494c1286ff16bcb02342d660097219cristy  h=6.0*hue;
2017133e649ea494c1286ff16bcb02342d660097219cristy  c=chroma;
2027133e649ea494c1286ff16bcb02342d660097219cristy  x=c*(1.0-fabs(fmod(h,2.0)-1.0));
2037133e649ea494c1286ff16bcb02342d660097219cristy  r=0.0;
2047133e649ea494c1286ff16bcb02342d660097219cristy  g=0.0;
2057133e649ea494c1286ff16bcb02342d660097219cristy  b=0.0;
2067133e649ea494c1286ff16bcb02342d660097219cristy  if ((0.0 <= h) && (h < 1.0))
2074c08aed51c5899665ade97263692328eea4af106cristy    {
208e171528c27d8cf01c41f7601969cf56379224d47cristy      r=c;
209e171528c27d8cf01c41f7601969cf56379224d47cristy      g=x;
2104c08aed51c5899665ade97263692328eea4af106cristy    }
211d8f16f7357707bfee6a939d39b5b312d1486d5c5cristy  else
2127133e649ea494c1286ff16bcb02342d660097219cristy    if ((1.0 <= h) && (h < 2.0))
2137133e649ea494c1286ff16bcb02342d660097219cristy      {
214e171528c27d8cf01c41f7601969cf56379224d47cristy        r=x;
215e171528c27d8cf01c41f7601969cf56379224d47cristy        g=c;
2167133e649ea494c1286ff16bcb02342d660097219cristy      }
2177133e649ea494c1286ff16bcb02342d660097219cristy    else
2187133e649ea494c1286ff16bcb02342d660097219cristy      if ((2.0 <= h) && (h < 3.0))
2197133e649ea494c1286ff16bcb02342d660097219cristy        {
220e171528c27d8cf01c41f7601969cf56379224d47cristy          g=c;
221e171528c27d8cf01c41f7601969cf56379224d47cristy          b=x;
2227133e649ea494c1286ff16bcb02342d660097219cristy        }
2237133e649ea494c1286ff16bcb02342d660097219cristy      else
2247133e649ea494c1286ff16bcb02342d660097219cristy        if ((3.0 <= h) && (h < 4.0))
2257133e649ea494c1286ff16bcb02342d660097219cristy          {
226e171528c27d8cf01c41f7601969cf56379224d47cristy            g=x;
227e171528c27d8cf01c41f7601969cf56379224d47cristy            b=c;
2287133e649ea494c1286ff16bcb02342d660097219cristy          }
2297133e649ea494c1286ff16bcb02342d660097219cristy        else
2307133e649ea494c1286ff16bcb02342d660097219cristy          if ((4.0 <= h) && (h < 5.0))
2317133e649ea494c1286ff16bcb02342d660097219cristy            {
232e171528c27d8cf01c41f7601969cf56379224d47cristy              r=x;
233e171528c27d8cf01c41f7601969cf56379224d47cristy              b=c;
2347133e649ea494c1286ff16bcb02342d660097219cristy            }
2357133e649ea494c1286ff16bcb02342d660097219cristy          else
2367133e649ea494c1286ff16bcb02342d660097219cristy            if ((5.0 <= h) && (h < 6.0))
2377133e649ea494c1286ff16bcb02342d660097219cristy              {
238e171528c27d8cf01c41f7601969cf56379224d47cristy                r=c;
239e171528c27d8cf01c41f7601969cf56379224d47cristy                b=x;
2407133e649ea494c1286ff16bcb02342d660097219cristy              }
2419e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  m=luma-(0.298839*r+0.586811*g+0.114350*b);
242398fd02612ac738cc5c950c0e5df20a6db3db001cristy  *red=QuantumRange*(r+m);
243398fd02612ac738cc5c950c0e5df20a6db3db001cristy  *green=QuantumRange*(g+m);
244398fd02612ac738cc5c950c0e5df20a6db3db001cristy  *blue=QuantumRange*(b+m);
245c5d68fe2846b7ed7b866c8a5d9287264d75458caanthony}
246c5d68fe2846b7ed7b866c8a5d9287264d75458caanthony
2477159f66759ae05f052aad309915b9784f7aca927cristystatic void CompositeHCL(const MagickRealType red,const MagickRealType green,
2487159f66759ae05f052aad309915b9784f7aca927cristy  const MagickRealType blue,MagickRealType *hue,MagickRealType *chroma,
2497159f66759ae05f052aad309915b9784f7aca927cristy  MagickRealType *luma)
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2517159f66759ae05f052aad309915b9784f7aca927cristy  MagickRealType
252d8f16f7357707bfee6a939d39b5b312d1486d5c5cristy    b,
2537133e649ea494c1286ff16bcb02342d660097219cristy    c,
254d8f16f7357707bfee6a939d39b5b312d1486d5c5cristy    g,
2557133e649ea494c1286ff16bcb02342d660097219cristy    h,
256d8f16f7357707bfee6a939d39b5b312d1486d5c5cristy    max,
257d8f16f7357707bfee6a939d39b5b312d1486d5c5cristy    r;
258ddeeea23285164a7029e2f28475642f26882f2d7cristy
259d8f16f7357707bfee6a939d39b5b312d1486d5c5cristy  /*
2607133e649ea494c1286ff16bcb02342d660097219cristy    Convert RGB to HCL colorspace.
261d8f16f7357707bfee6a939d39b5b312d1486d5c5cristy  */
2627159f66759ae05f052aad309915b9784f7aca927cristy  assert(hue != (MagickRealType *) NULL);
2637159f66759ae05f052aad309915b9784f7aca927cristy  assert(chroma != (MagickRealType *) NULL);
2647159f66759ae05f052aad309915b9784f7aca927cristy  assert(luma != (MagickRealType *) NULL);
2657133e649ea494c1286ff16bcb02342d660097219cristy  r=red;
2667133e649ea494c1286ff16bcb02342d660097219cristy  g=green;
2677133e649ea494c1286ff16bcb02342d660097219cristy  b=blue;
268d8f16f7357707bfee6a939d39b5b312d1486d5c5cristy  max=MagickMax(r,MagickMax(g,b));
2697159f66759ae05f052aad309915b9784f7aca927cristy  c=max-(MagickRealType) MagickMin(r,MagickMin(g,b));
2707133e649ea494c1286ff16bcb02342d660097219cristy  h=0.0;
2717133e649ea494c1286ff16bcb02342d660097219cristy  if (c == 0)
2727133e649ea494c1286ff16bcb02342d660097219cristy    h=0.0;
273d8f16f7357707bfee6a939d39b5b312d1486d5c5cristy  else
2747133e649ea494c1286ff16bcb02342d660097219cristy    if (red == max)
2759e2436a78bdabef900e018dc77c0cc497bf6fbafcristy      h=fmod((g-b)/c+6.0,6.0);
276d8f16f7357707bfee6a939d39b5b312d1486d5c5cristy    else
2777133e649ea494c1286ff16bcb02342d660097219cristy      if (green == max)
2787133e649ea494c1286ff16bcb02342d660097219cristy        h=((b-r)/c)+2.0;
2797133e649ea494c1286ff16bcb02342d660097219cristy      else
2807133e649ea494c1286ff16bcb02342d660097219cristy        if (blue == max)
2817133e649ea494c1286ff16bcb02342d660097219cristy          h=((r-g)/c)+4.0;
2827133e649ea494c1286ff16bcb02342d660097219cristy  *hue=(h/6.0);
2837133e649ea494c1286ff16bcb02342d660097219cristy  *chroma=QuantumScale*c;
2849e2436a78bdabef900e018dc77c0cc497bf6fbafcristy  *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
287e4a404711bf20d9062d11ab28bc12e5acd307f9ccristystatic MagickBooleanType CompositeOverImage(Image *image,
288e8e8eff5f2414d6096195a41934fc0edee9d9212cristy  const Image *source_image,const MagickBooleanType clip_to_self,
289feb3e9695150978a5d2372d3fe2f60466a7c8066cristy  const ssize_t x_offset,const ssize_t y_offset,ExceptionInfo *exception)
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
291e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy#define CompositeImageTag  "Composite/Image"
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
293e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  CacheView
2945e6f3783f4f9fa7d6a7b5cd2399841c3c5eb4af9Cristy    *image_view,
2955e6f3783f4f9fa7d6a7b5cd2399841c3c5eb4af9Cristy    *source_view;
2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
29747c61c996128275174b8a120ab6a88a5c1bec3d3cristy  const char
2985e6f3783f4f9fa7d6a7b5cd2399841c3c5eb4af9Cristy    *value;
29947c61c996128275174b8a120ab6a88a5c1bec3d3cristy
300e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  MagickBooleanType
30147c61c996128275174b8a120ab6a88a5c1bec3d3cristy    clamp,
302e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    status;
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
304e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  MagickOffsetType
305e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    progress;
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
307e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  ssize_t
308e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    y;
309c5d68fe2846b7ed7b866c8a5d9287264d75458caanthony
3104c08aed51c5899665ade97263692328eea4af106cristy  /*
311e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    Composite image.
3127c9eaf7cdb3640167dc0978406eb4a4a42a0ff3aanthony  */
313e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  status=MagickTrue;
314e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  progress=0;
31547c61c996128275174b8a120ab6a88a5c1bec3d3cristy  clamp=MagickTrue;
31647c61c996128275174b8a120ab6a88a5c1bec3d3cristy  value=GetImageArtifact(image,"compose:clamp");
31747c61c996128275174b8a120ab6a88a5c1bec3d3cristy  if (value != (const char *) NULL)
31847c61c996128275174b8a120ab6a88a5c1bec3d3cristy    clamp=IsStringTrue(value);
319e8e8eff5f2414d6096195a41934fc0edee9d9212cristy  source_view=AcquireVirtualCacheView(source_image,exception);
32046ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  image_view=AcquireAuthenticCacheView(image,exception);
321e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
322ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy  #pragma omp parallel for schedule(static,4) shared(progress,status) \
323e8e8eff5f2414d6096195a41934fc0edee9d9212cristy    magick_threads(source_image,image,image->rows,1)
324e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy#endif
325e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  for (y=0; y < (ssize_t) image->rows; y++)
326e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  {
327e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    const Quantum
328e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      *pixels;
329c5d68fe2846b7ed7b866c8a5d9287264d75458caanthony
330e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    register const Quantum
33105d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict p;
332c5d68fe2846b7ed7b866c8a5d9287264d75458caanthony
333e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    register Quantum
33405d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict q;
335c5d68fe2846b7ed7b866c8a5d9287264d75458caanthony
336e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    register ssize_t
337e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      x;
3384c08aed51c5899665ade97263692328eea4af106cristy
339564a56979706a30a3d0f920fd5f538a408efd4f1cristy    size_t
340564a56979706a30a3d0f920fd5f538a408efd4f1cristy      channels;
341564a56979706a30a3d0f920fd5f538a408efd4f1cristy
342e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    if (status == MagickFalse)
343e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      continue;
344feb3e9695150978a5d2372d3fe2f60466a7c8066cristy    if (clip_to_self != MagickFalse)
345e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      {
346e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        if (y < y_offset)
347e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          continue;
348e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        if ((y-y_offset) >= (ssize_t) source_image->rows)
349e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          continue;
350e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      }
351e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    /*
352e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      If pixels is NULL, y is outside overlay region.
353e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    */
354e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    pixels=(Quantum *) NULL;
355e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    p=(Quantum *) NULL;
356e8e8eff5f2414d6096195a41934fc0edee9d9212cristy    if ((y >= y_offset) && ((y-y_offset) < (ssize_t) source_image->rows))
357e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      {
358e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        p=GetCacheViewVirtualPixels(source_view,0,y-y_offset,
359e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          source_image->columns,1,exception);
360e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        if (p == (const Quantum *) NULL)
361e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          {
362e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            status=MagickFalse;
363e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            continue;
364e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          }
365e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        pixels=p;
366e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        if (x_offset < 0)
367e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          p-=x_offset*GetPixelChannels(source_image);
368e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      }
369e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
370e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    if (q == (Quantum *) NULL)
371e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      {
372e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        status=MagickFalse;
373e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        continue;
374e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      }
375e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    for (x=0; x < (ssize_t) image->columns; x++)
3764c08aed51c5899665ade97263692328eea4af106cristy    {
3777159f66759ae05f052aad309915b9784f7aca927cristy      MagickRealType
378e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        Da,
379e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        Dc,
3802bd6f5be4b25c2b325a18a49cc10cfcb358070edcristy        Dca,
38195a92efd222d2268b66bf4fbb3bd5167437ba466cristy        gamma,
382e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        Sa,
3832bd6f5be4b25c2b325a18a49cc10cfcb358070edcristy        Sc,
3842bd6f5be4b25c2b325a18a49cc10cfcb358070edcristy        Sca;
385c5d68fe2846b7ed7b866c8a5d9287264d75458caanthony
386e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      register ssize_t
387e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        i;
388c5d68fe2846b7ed7b866c8a5d9287264d75458caanthony
389feb3e9695150978a5d2372d3fe2f60466a7c8066cristy      if (clip_to_self != MagickFalse)
390e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
391e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          if (x < x_offset)
392e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            {
393e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              q+=GetPixelChannels(image);
394e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              continue;
395e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            }
396e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          if ((x-x_offset) >= (ssize_t) source_image->columns)
397e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            break;
398e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        }
399e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
400e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          ((x-x_offset) >= (ssize_t) source_image->columns))
401e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
402e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          Quantum
403e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            source[MaxPixelChannels];
4044c08aed51c5899665ade97263692328eea4af106cristy
405e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          /*
406e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            Virtual composite:
407e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              Sc: source color.
408e8e8eff5f2414d6096195a41934fc0edee9d9212cristy              Dc: canvas color.
409e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          */
410883fde11debec15cedb05dc5d7228d8588066bc0cristy          if (GetPixelReadMask(image,q) == 0)
41110a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy            {
41210a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy              q+=GetPixelChannels(image);
41310a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy              continue;
41410a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy            }
415e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          (void) GetOneVirtualPixel(source_image,x-x_offset,y-y_offset,
416c94ba6f2e80cce201ffaf24ce7534019b6353dfecristy            source,exception);
417e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
418e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          {
4195a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy            PixelChannel channel=GetPixelChannelChannel(image,i);
4205a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy            PixelTrait traits=GetPixelChannelTraits(image,channel);
421e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            PixelTrait source_traits=GetPixelChannelTraits(source_image,
4225a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy              channel);
423e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            if ((traits == UndefinedPixelTrait) ||
424e8e8eff5f2414d6096195a41934fc0edee9d9212cristy                (source_traits == UndefinedPixelTrait))
425e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              continue;
426e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            q[i]=source[channel];
427e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          }
428e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          q+=GetPixelChannels(image);
429e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          continue;
430e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        }
4314c08aed51c5899665ade97263692328eea4af106cristy      /*
432e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        Authentic composite:
433e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          Sa:  normalized source alpha.
434e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          Da:  normalized canvas alpha.
4354c08aed51c5899665ade97263692328eea4af106cristy      */
436e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      if (GetPixelReadMask(source_image,p) == 0)
437c94ba6f2e80cce201ffaf24ce7534019b6353dfecristy        {
438e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          p+=GetPixelChannels(source_image);
439e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          channels=GetPixelChannels(source_image);
440e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          if (p >= (pixels+channels*source_image->columns))
441c94ba6f2e80cce201ffaf24ce7534019b6353dfecristy            p=pixels;
442c94ba6f2e80cce201ffaf24ce7534019b6353dfecristy          q+=GetPixelChannels(image);
443c94ba6f2e80cce201ffaf24ce7534019b6353dfecristy          continue;
444c94ba6f2e80cce201ffaf24ce7534019b6353dfecristy        }
445e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      Sa=QuantumScale*GetPixelAlpha(source_image,p);
446e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      Da=QuantumScale*GetPixelAlpha(image,q);
44795a92efd222d2268b66bf4fbb3bd5167437ba466cristy      gamma=Sa+Da-Sa*Da;
44895a92efd222d2268b66bf4fbb3bd5167437ba466cristy      gamma=PerceptibleReciprocal(gamma);
449e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
450e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      {
4515a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelChannel channel=GetPixelChannelChannel(image,i);
4525a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelTrait traits=GetPixelChannelTraits(image,channel);
453e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        PixelTrait source_traits=GetPixelChannelTraits(source_image,
4545a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy          channel);
455e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        if ((traits == UndefinedPixelTrait) ||
456e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            (source_traits == UndefinedPixelTrait))
457e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          continue;
458e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        if ((traits & CopyPixelTrait) != 0)
459e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          {
460e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            /*
461e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy              Copy channel.
462e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            */
463e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            q[i]=GetPixelChannel(source_image,channel,p);
464e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            continue;
465e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy          }
466e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy        if (channel == AlphaPixelChannel)
467e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy          {
468e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            /*
469e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              Set alpha channel.
470e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            */
47147c61c996128275174b8a120ab6a88a5c1bec3d3cristy            q[i]=clamp != MagickFalse ?
47247c61c996128275174b8a120ab6a88a5c1bec3d3cristy              ClampPixel(QuantumRange*(Sa+Da-Sa*Da)) :
47347c61c996128275174b8a120ab6a88a5c1bec3d3cristy              ClampToQuantum(QuantumRange*(Sa+Da-Sa*Da));
474e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            continue;
475e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          }
476e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        /*
477e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          Sc: source color.
478e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          Dc: canvas color.
479e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        */
480e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        Sc=(MagickRealType) GetPixelChannel(source_image,channel,p);
4817159f66759ae05f052aad309915b9784f7aca927cristy        Dc=(MagickRealType) q[i];
4822bd6f5be4b25c2b325a18a49cc10cfcb358070edcristy        Sca=QuantumScale*Sa*Sc;
4832bd6f5be4b25c2b325a18a49cc10cfcb358070edcristy        Dca=QuantumScale*Da*Dc;
48447c61c996128275174b8a120ab6a88a5c1bec3d3cristy        q[i]=clamp != MagickFalse ?
48595a92efd222d2268b66bf4fbb3bd5167437ba466cristy          ClampPixel(gamma*QuantumRange*(Sca+Dca*(1.0-Sa))) :
48695a92efd222d2268b66bf4fbb3bd5167437ba466cristy          ClampToQuantum(gamma*QuantumRange*(Sca+Dca*(1.0-Sa)));
487e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      }
488e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      p+=GetPixelChannels(source_image);
489e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      channels=GetPixelChannels(source_image);
490e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      if (p >= (pixels+channels*source_image->columns))
491e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        p=pixels;
492e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      q+=GetPixelChannels(image);
4934c08aed51c5899665ade97263692328eea4af106cristy    }
494e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
495e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      status=MagickFalse;
496e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    if (image->progress_monitor != (MagickProgressMonitor) NULL)
497e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      {
498e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        MagickBooleanType
499e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          proceed;
5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
501e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
502ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy        #pragma omp critical (MagickCore_CompositeImage)
503e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy#endif
504e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        proceed=SetImageProgress(image,CompositeImageTag,progress++,
505e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          image->rows);
506e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        if (proceed == MagickFalse)
507e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          status=MagickFalse;
508e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      }
509e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  }
510e8e8eff5f2414d6096195a41934fc0edee9d9212cristy  source_view=DestroyCacheView(source_view);
511e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  image_view=DestroyCacheView(image_view);
512e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  return(status);
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
515e4a404711bf20d9062d11ab28bc12e5acd307f9ccristyMagickExport MagickBooleanType CompositeImage(Image *image,
516a865ccd68cbccfdf00a5fdd40bc491c5f5390303cristy  const Image *composite,const CompositeOperator compose,
51744c9841ae88065e1a321ec8564293859101e7b49cristy  const MagickBooleanType clip_to_self,const ssize_t x_offset,
51844c9841ae88065e1a321ec8564293859101e7b49cristy  const ssize_t y_offset,ExceptionInfo *exception)
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
520e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy#define CompositeImageTag  "Composite/Image"
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
522e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  CacheView
523e8e8eff5f2414d6096195a41934fc0edee9d9212cristy    *source_view,
524e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    *image_view;
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
52647c61c996128275174b8a120ab6a88a5c1bec3d3cristy  const char
52747c61c996128275174b8a120ab6a88a5c1bec3d3cristy    *value;
52847c61c996128275174b8a120ab6a88a5c1bec3d3cristy
529e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  GeometryInfo
530e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    geometry_info;
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
532e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  Image
533e8e8eff5f2414d6096195a41934fc0edee9d9212cristy    *canvas_image,
534e8e8eff5f2414d6096195a41934fc0edee9d9212cristy    *source_image;
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
536e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  MagickBooleanType
53747c61c996128275174b8a120ab6a88a5c1bec3d3cristy    clamp,
538e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    status;
539e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
540e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  MagickOffsetType
541e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    progress;
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5437159f66759ae05f052aad309915b9784f7aca927cristy  MagickRealType
544e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    amount,
545e8e8eff5f2414d6096195a41934fc0edee9d9212cristy    canvas_dissolve,
546e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    midpoint,
5477133e649ea494c1286ff16bcb02342d660097219cristy    percent_luma,
5487133e649ea494c1286ff16bcb02342d660097219cristy    percent_chroma,
549e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    source_dissolve,
550e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    threshold;
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
552e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  MagickStatusType
553e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    flags;
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
555d197cbbbde474ea2cbdd56d0defa45f100e44cd0cristy  ssize_t
556d197cbbbde474ea2cbdd56d0defa45f100e44cd0cristy    y;
557d197cbbbde474ea2cbdd56d0defa45f100e44cd0cristy
558e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  assert(image != (Image *) NULL);
559e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
560e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  if (image->debug != MagickFalse)
561e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
562a865ccd68cbccfdf00a5fdd40bc491c5f5390303cristy  assert(composite!= (Image *) NULL);
563e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(composite->signature == MagickCoreSignature);
564e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
565e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    return(MagickFalse);
566e8e8eff5f2414d6096195a41934fc0edee9d9212cristy  source_image=CloneImage(composite,0,0,MagickTrue,exception);
567e8e8eff5f2414d6096195a41934fc0edee9d9212cristy  if (source_image == (const Image *) NULL)
568a865ccd68cbccfdf00a5fdd40bc491c5f5390303cristy    return(MagickFalse);
569de067e9672d8873c45d0f1f5aabf9e5b0bb13293cristy  if (IsGrayColorspace(image->colorspace) != MagickFalse)
570de067e9672d8873c45d0f1f5aabf9e5b0bb13293cristy    (void) SetImageColorspace(image,sRGBColorspace,exception);
571e8e8eff5f2414d6096195a41934fc0edee9d9212cristy  (void) SetImageColorspace(source_image,image->colorspace,exception);
572597358bb71c59d54a67f64b76644b5436365733bdirk  if ((image->alpha_trait != UndefinedPixelTrait) &&
573e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      (source_image->alpha_trait == UndefinedPixelTrait))
574e8e8eff5f2414d6096195a41934fc0edee9d9212cristy    (void) SetImageAlphaChannel(source_image,SetAlphaChannel,exception);
575e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy  if ((compose == OverCompositeOp) || (compose == SrcOverCompositeOp))
5764c08aed51c5899665ade97263692328eea4af106cristy    {
577e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      status=CompositeOverImage(image,source_image,clip_to_self,x_offset,
578feb3e9695150978a5d2372d3fe2f60466a7c8066cristy        y_offset,exception);
579e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_image=DestroyImage(source_image);
580e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      return(status);
581c5d68fe2846b7ed7b866c8a5d9287264d75458caanthony    }
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  amount=0.5;
58347c61c996128275174b8a120ab6a88a5c1bec3d3cristy  canvas_image=(Image *) NULL;
584e8e8eff5f2414d6096195a41934fc0edee9d9212cristy  canvas_dissolve=1.0;
58547c61c996128275174b8a120ab6a88a5c1bec3d3cristy  clamp=MagickTrue;
58647c61c996128275174b8a120ab6a88a5c1bec3d3cristy  value=GetImageArtifact(image,"compose:clamp");
58747c61c996128275174b8a120ab6a88a5c1bec3d3cristy  if (value != (const char *) NULL)
58847c61c996128275174b8a120ab6a88a5c1bec3d3cristy    clamp=IsStringTrue(value);
589e92d6b54a3f0971ac57523d4a1786f4f8fbe3fe8cristy  SetGeometryInfo(&geometry_info);
5907133e649ea494c1286ff16bcb02342d660097219cristy  percent_luma=100.0;
5917133e649ea494c1286ff16bcb02342d660097219cristy  percent_chroma=100.0;
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  source_dissolve=1.0;
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  threshold=0.05f;
5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  switch (compose)
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
596308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy    case CopyCompositeOp:
597308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy    {
598b41560a2138121a95d9a02465e98355fd6fdd27fcristy      if ((x_offset < 0) || (y_offset < 0))
599308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy        break;
600e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      if ((x_offset+(ssize_t) source_image->columns) > (ssize_t) image->columns)
601308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy        break;
602e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      if ((y_offset+(ssize_t) source_image->rows) > (ssize_t) image->rows)
603308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy        break;
604308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy      status=MagickTrue;
605e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_view=AcquireVirtualCacheView(source_image,exception);
60646ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy      image_view=AcquireAuthenticCacheView(image,exception);
607b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
608ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy      #pragma omp parallel for schedule(static,4) shared(status) \
609e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        magick_threads(source_image,image,source_image->rows,1)
610308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy#endif
611e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      for (y=0; y < (ssize_t) source_image->rows; y++)
612308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy      {
613308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy        MagickBooleanType
614308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy          sync;
615308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy
6164c08aed51c5899665ade97263692328eea4af106cristy        register const Quantum
617308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy          *p;
618308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy
6194c08aed51c5899665ade97263692328eea4af106cristy        register Quantum
620308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy          *q;
621308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy
6224c08aed51c5899665ade97263692328eea4af106cristy        register ssize_t
6234c08aed51c5899665ade97263692328eea4af106cristy          x;
6244c08aed51c5899665ade97263692328eea4af106cristy
625308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy        if (status == MagickFalse)
626308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy          continue;
6272fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy        p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
6282fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy          exception);
629e1c18e93d64dd07e6deb00400c7f1e4d8b96ecd9cristy        q=GetCacheViewAuthenticPixels(image_view,x_offset,y+y_offset,
630e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          source_image->columns,1,exception);
6314c08aed51c5899665ade97263692328eea4af106cristy        if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
632308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy          {
633308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy            status=MagickFalse;
634308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy            continue;
635308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy          }
636e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        for (x=0; x < (ssize_t) source_image->columns; x++)
6374c08aed51c5899665ade97263692328eea4af106cristy        {
638bdecccc80762c4bd28cd68cfd0c8279f45624c69cristy          register ssize_t
639bdecccc80762c4bd28cd68cfd0c8279f45624c69cristy            i;
640bdecccc80762c4bd28cd68cfd0c8279f45624c69cristy
641e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          if (GetPixelReadMask(source_image,p) == 0)
64210a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy            {
643e8e8eff5f2414d6096195a41934fc0edee9d9212cristy              p+=GetPixelChannels(source_image);
64410a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy              q+=GetPixelChannels(image);
64510a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy              continue;
64610a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy            }
647e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          for (i=0; i < (ssize_t) GetPixelChannels(source_image); i++)
648bdecccc80762c4bd28cd68cfd0c8279f45624c69cristy          {
649e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            PixelChannel channel=GetPixelChannelChannel(source_image,i);
650e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            PixelTrait source_traits=GetPixelChannelTraits(source_image,
6515a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy              channel);
6525a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy            PixelTrait traits=GetPixelChannelTraits(image,channel);
653bdecccc80762c4bd28cd68cfd0c8279f45624c69cristy            if ((traits == UndefinedPixelTrait) ||
654e8e8eff5f2414d6096195a41934fc0edee9d9212cristy                (source_traits == UndefinedPixelTrait))
655bdecccc80762c4bd28cd68cfd0c8279f45624c69cristy              continue;
656bdecccc80762c4bd28cd68cfd0c8279f45624c69cristy            SetPixelChannel(image,channel,p[i],q);
657bdecccc80762c4bd28cd68cfd0c8279f45624c69cristy          }
658e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          p+=GetPixelChannels(source_image);
659ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy          q+=GetPixelChannels(image);
6604c08aed51c5899665ade97263692328eea4af106cristy        }
661308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy        sync=SyncCacheViewAuthenticPixels(image_view,exception);
662308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy        if (sync == MagickFalse)
663308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy          status=MagickFalse;
664308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy        if (image->progress_monitor != (MagickProgressMonitor) NULL)
665308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy          {
666308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy            MagickBooleanType
667308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy              proceed;
668308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy
669b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
670bd0435bb0fa5e2e20ec8d3c5288a5edc44aba9a0cristy            #pragma omp critical (MagickCore_CompositeImage)
671308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy#endif
672cee9711bbc334b5677d5ec4ea1cc70340d35ee35cristy            proceed=SetImageProgress(image,CompositeImageTag,
673cee9711bbc334b5677d5ec4ea1cc70340d35ee35cristy              (MagickOffsetType) y,image->rows);
674308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy            if (proceed == MagickFalse)
675308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy              status=MagickFalse;
676308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy          }
677308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy      }
678e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_view=DestroyCacheView(source_view);
679308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy      image_view=DestroyCacheView(image_view);
680e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_image=DestroyImage(source_image);
681308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy      return(status);
682308b4e68536c39f0a3d7fe55c4c04bfd0ba2ce9bcristy    }
68317a88593850db8b76af9e1389670ac5f1163514ccristy    case IntensityCompositeOp:
68417a88593850db8b76af9e1389670ac5f1163514ccristy    {
68517a88593850db8b76af9e1389670ac5f1163514ccristy      if ((x_offset < 0) || (y_offset < 0))
68617a88593850db8b76af9e1389670ac5f1163514ccristy        break;
687e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      if ((x_offset+(ssize_t) source_image->columns) > (ssize_t) image->columns)
68817a88593850db8b76af9e1389670ac5f1163514ccristy        break;
689e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      if ((y_offset+(ssize_t) source_image->rows) > (ssize_t) image->rows)
69017a88593850db8b76af9e1389670ac5f1163514ccristy        break;
69117a88593850db8b76af9e1389670ac5f1163514ccristy      status=MagickTrue;
692e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_view=AcquireVirtualCacheView(source_image,exception);
69317a88593850db8b76af9e1389670ac5f1163514ccristy      image_view=AcquireAuthenticCacheView(image,exception);
69417a88593850db8b76af9e1389670ac5f1163514ccristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
69517a88593850db8b76af9e1389670ac5f1163514ccristy      #pragma omp parallel for schedule(static,4) shared(status) \
696e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        magick_threads(source_image,image,source_image->rows,1)
69717a88593850db8b76af9e1389670ac5f1163514ccristy#endif
698e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      for (y=0; y < (ssize_t) source_image->rows; y++)
69917a88593850db8b76af9e1389670ac5f1163514ccristy      {
70017a88593850db8b76af9e1389670ac5f1163514ccristy        MagickBooleanType
70117a88593850db8b76af9e1389670ac5f1163514ccristy          sync;
70217a88593850db8b76af9e1389670ac5f1163514ccristy
70317a88593850db8b76af9e1389670ac5f1163514ccristy        register const Quantum
70417a88593850db8b76af9e1389670ac5f1163514ccristy          *p;
70517a88593850db8b76af9e1389670ac5f1163514ccristy
70617a88593850db8b76af9e1389670ac5f1163514ccristy        register Quantum
70717a88593850db8b76af9e1389670ac5f1163514ccristy          *q;
70817a88593850db8b76af9e1389670ac5f1163514ccristy
70917a88593850db8b76af9e1389670ac5f1163514ccristy        register ssize_t
71017a88593850db8b76af9e1389670ac5f1163514ccristy          x;
71117a88593850db8b76af9e1389670ac5f1163514ccristy
71217a88593850db8b76af9e1389670ac5f1163514ccristy        if (status == MagickFalse)
71317a88593850db8b76af9e1389670ac5f1163514ccristy          continue;
7142fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy        p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
7152fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy          exception);
71617a88593850db8b76af9e1389670ac5f1163514ccristy        q=GetCacheViewAuthenticPixels(image_view,x_offset,y+y_offset,
717e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          source_image->columns,1,exception);
71817a88593850db8b76af9e1389670ac5f1163514ccristy        if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
71917a88593850db8b76af9e1389670ac5f1163514ccristy          {
72017a88593850db8b76af9e1389670ac5f1163514ccristy            status=MagickFalse;
72117a88593850db8b76af9e1389670ac5f1163514ccristy            continue;
72217a88593850db8b76af9e1389670ac5f1163514ccristy          }
723e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        for (x=0; x < (ssize_t) source_image->columns; x++)
72417a88593850db8b76af9e1389670ac5f1163514ccristy        {
725e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          if (GetPixelReadMask(source_image,p) == 0)
72617a88593850db8b76af9e1389670ac5f1163514ccristy            {
727e8e8eff5f2414d6096195a41934fc0edee9d9212cristy              p+=GetPixelChannels(source_image);
72817a88593850db8b76af9e1389670ac5f1163514ccristy              q+=GetPixelChannels(image);
72917a88593850db8b76af9e1389670ac5f1163514ccristy              continue;
73017a88593850db8b76af9e1389670ac5f1163514ccristy            }
73147c61c996128275174b8a120ab6a88a5c1bec3d3cristy          SetPixelAlpha(image,clamp != MagickFalse ?
73247c61c996128275174b8a120ab6a88a5c1bec3d3cristy            ClampPixel(GetPixelIntensity(source_image,p)) :
73347c61c996128275174b8a120ab6a88a5c1bec3d3cristy            ClampToQuantum(GetPixelIntensity(source_image,p)),q);
734e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          p+=GetPixelChannels(source_image);
73517a88593850db8b76af9e1389670ac5f1163514ccristy          q+=GetPixelChannels(image);
73617a88593850db8b76af9e1389670ac5f1163514ccristy        }
73717a88593850db8b76af9e1389670ac5f1163514ccristy        sync=SyncCacheViewAuthenticPixels(image_view,exception);
73817a88593850db8b76af9e1389670ac5f1163514ccristy        if (sync == MagickFalse)
73917a88593850db8b76af9e1389670ac5f1163514ccristy          status=MagickFalse;
74017a88593850db8b76af9e1389670ac5f1163514ccristy        if (image->progress_monitor != (MagickProgressMonitor) NULL)
74117a88593850db8b76af9e1389670ac5f1163514ccristy          {
74217a88593850db8b76af9e1389670ac5f1163514ccristy            MagickBooleanType
74317a88593850db8b76af9e1389670ac5f1163514ccristy              proceed;
74417a88593850db8b76af9e1389670ac5f1163514ccristy
74517a88593850db8b76af9e1389670ac5f1163514ccristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
74617a88593850db8b76af9e1389670ac5f1163514ccristy            #pragma omp critical (MagickCore_CompositeImage)
74717a88593850db8b76af9e1389670ac5f1163514ccristy#endif
74817a88593850db8b76af9e1389670ac5f1163514ccristy            proceed=SetImageProgress(image,CompositeImageTag,
74917a88593850db8b76af9e1389670ac5f1163514ccristy              (MagickOffsetType) y,image->rows);
75017a88593850db8b76af9e1389670ac5f1163514ccristy            if (proceed == MagickFalse)
75117a88593850db8b76af9e1389670ac5f1163514ccristy              status=MagickFalse;
75217a88593850db8b76af9e1389670ac5f1163514ccristy          }
75317a88593850db8b76af9e1389670ac5f1163514ccristy      }
754e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_view=DestroyCacheView(source_view);
75517a88593850db8b76af9e1389670ac5f1163514ccristy      image_view=DestroyCacheView(image_view);
756e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_image=DestroyImage(source_image);
75717a88593850db8b76af9e1389670ac5f1163514ccristy      return(status);
75817a88593850db8b76af9e1389670ac5f1163514ccristy    }
759e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    case CopyAlphaCompositeOp:
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case ChangeMaskCompositeOp:
7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
763e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        Modify canvas outside the overlaid region and require an alpha
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        channel to exist, to add transparency.
7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
76617f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy      if (image->alpha_trait == UndefinedPixelTrait)
76742c41dead2898886d6330544548f859da29ce8c0cristy        (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case BlurCompositeOp:
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
772559401046eb333547a09fb8b67b11fd7f1b05faccristy      CacheView
773fa589d6096099562cbc2bc14e508931968a8c055dirk        *canvas_view;
774feb3e9695150978a5d2372d3fe2f60466a7c8066cristy
7757159f66759ae05f052aad309915b9784f7aca927cristy      MagickRealType
776559401046eb333547a09fb8b67b11fd7f1b05faccristy        angle_range,
777173ad0fb5d2718a7f47d7f576ad61c0bbd9f3bbdanthony        angle_start,
778559401046eb333547a09fb8b67b11fd7f1b05faccristy        height,
779559401046eb333547a09fb8b67b11fd7f1b05faccristy        width;
7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
781bce4f4a707e7a4d956df6e36e14f31c5e162f8aecristy      PixelInfo
782bce4f4a707e7a4d956df6e36e14f31c5e162f8aecristy        pixel;
783bce4f4a707e7a4d956df6e36e14f31c5e162f8aecristy
7843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ResampleFilter
7853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *resample_filter;
7863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
787559401046eb333547a09fb8b67b11fd7f1b05faccristy      SegmentInfo
788559401046eb333547a09fb8b67b11fd7f1b05faccristy        blur;
7893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
7919cb63ccb02272521283da6d251068d91196cc5bfanthony        Blur Image by resampling.
7929cb63ccb02272521283da6d251068d91196cc5bfanthony
793559401046eb333547a09fb8b67b11fd7f1b05faccristy        Blur Image dictated by an overlay gradient map: X = red_channel;
794559401046eb333547a09fb8b67b11fd7f1b05faccristy          Y = green_channel; compose:args =  x_scale[,y_scale[,angle]].
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
796e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      canvas_image=CloneImage(image,image->columns,image->rows,MagickTrue,
7978a11cb146177680bfc1b7d89a8cd0c8f2befe468cristy        exception);
798e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      if (canvas_image == (Image *) NULL)
79944886b9874b0dc62e49d0c26f16aa4fbcb2407f0cristy        {
800e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          source_image=DestroyImage(source_image);
80144886b9874b0dc62e49d0c26f16aa4fbcb2407f0cristy          return(MagickFalse);
80244886b9874b0dc62e49d0c26f16aa4fbcb2407f0cristy        }
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
8049cb63ccb02272521283da6d251068d91196cc5bfanthony        Gather the maximum blur sigma values from user.
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      flags=NoValue;
8071a78095355e735d713d5994eb662b36037ce69f2cristy      value=GetImageArtifact(image,"compose:args");
8081a78095355e735d713d5994eb662b36037ce69f2cristy      if (value != (const char *) NULL)
8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        flags=ParseGeometry(value,&geometry_info);
8101a78095355e735d713d5994eb662b36037ce69f2cristy      if ((flags & WidthValue) == 0)
8111a78095355e735d713d5994eb662b36037ce69f2cristy        {
8121a78095355e735d713d5994eb662b36037ce69f2cristy          (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
8131a78095355e735d713d5994eb662b36037ce69f2cristy            "InvalidSetting","'%s' '%s'","compose:args",value);
814e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          source_image=DestroyImage(source_image);
815e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          canvas_image=DestroyImage(canvas_image);
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
8189cb63ccb02272521283da6d251068d91196cc5bfanthony      /*
8199cb63ccb02272521283da6d251068d91196cc5bfanthony        Users input sigma now needs to be converted to the EWA ellipse size.
8209cb63ccb02272521283da6d251068d91196cc5bfanthony        The filter defaults to a sigma of 0.5 so to make this match the
8219cb63ccb02272521283da6d251068d91196cc5bfanthony        users input the ellipse size needs to be doubled.
822d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony      */
823d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony      width=height=geometry_info.rho*2.0;
824d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony      if ((flags & HeightValue) != 0 )
825d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony        height=geometry_info.sigma*2.0;
8267159f66759ae05f052aad309915b9784f7aca927cristy      /*
8277159f66759ae05f052aad309915b9784f7aca927cristy        Default the unrotated ellipse width and height axis vectors.
8287159f66759ae05f052aad309915b9784f7aca927cristy      */
829d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony      blur.x1=width;
830559401046eb333547a09fb8b67b11fd7f1b05faccristy      blur.x2=0.0;
831559401046eb333547a09fb8b67b11fd7f1b05faccristy      blur.y1=0.0;
832d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony      blur.y2=height;
833d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony      /* rotate vectors if a rotation angle is given */
834173ad0fb5d2718a7f47d7f576ad61c0bbd9f3bbdanthony      if ((flags & XValue) != 0 )
8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
8367159f66759ae05f052aad309915b9784f7aca927cristy          MagickRealType
837173ad0fb5d2718a7f47d7f576ad61c0bbd9f3bbdanthony            angle;
838173ad0fb5d2718a7f47d7f576ad61c0bbd9f3bbdanthony
839559401046eb333547a09fb8b67b11fd7f1b05faccristy          angle=DegreesToRadians(geometry_info.xi);
840dff7476eed3fa4bc0095561868c3d4d1710d0641anthony          blur.x1=width*cos(angle);
841dff7476eed3fa4bc0095561868c3d4d1710d0641anthony          blur.x2=width*sin(angle);
842dff7476eed3fa4bc0095561868c3d4d1710d0641anthony          blur.y1=(-height*sin(angle));
843dff7476eed3fa4bc0095561868c3d4d1710d0641anthony          blur.y2=height*cos(angle);
844173ad0fb5d2718a7f47d7f576ad61c0bbd9f3bbdanthony        }
845d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony      /* Otherwise lets set a angle range and calculate in the loop */
846d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony      angle_start=0.0;
847d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony      angle_range=0.0;
848173ad0fb5d2718a7f47d7f576ad61c0bbd9f3bbdanthony      if ((flags & YValue) != 0 )
849173ad0fb5d2718a7f47d7f576ad61c0bbd9f3bbdanthony        {
850559401046eb333547a09fb8b67b11fd7f1b05faccristy          angle_start=DegreesToRadians(geometry_info.xi);
851559401046eb333547a09fb8b67b11fd7f1b05faccristy          angle_range=DegreesToRadians(geometry_info.psi)-angle_start;
8523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
8549cb63ccb02272521283da6d251068d91196cc5bfanthony        Set up a gaussian cylindrical filter for EWA Bluring.
855d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony
8569cb63ccb02272521283da6d251068d91196cc5bfanthony        As the minimum ellipse radius of support*1.0 the EWA algorithm
8579cb63ccb02272521283da6d251068d91196cc5bfanthony        can only produce a minimum blur of 0.5 for Gaussian (support=2.0)
8589cb63ccb02272521283da6d251068d91196cc5bfanthony        This means that even 'No Blur' will be still a little blurry!
859d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony
8609cb63ccb02272521283da6d251068d91196cc5bfanthony        The solution (as well as the problem of preventing any user
8619cb63ccb02272521283da6d251068d91196cc5bfanthony        expert filter settings, is to set our own user settings, then
8629cb63ccb02272521283da6d251068d91196cc5bfanthony        restore them afterwards.
8633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
8648a11cb146177680bfc1b7d89a8cd0c8f2befe468cristy      resample_filter=AcquireResampleFilter(image,exception);
865d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony      SetResampleFilter(resample_filter,GaussianFilter);
8669cb63ccb02272521283da6d251068d91196cc5bfanthony
8679cb63ccb02272521283da6d251068d91196cc5bfanthony      /* do the variable blurring of each pixel in image */
8689cb63ccb02272521283da6d251068d91196cc5bfanthony      GetPixelInfo(image,&pixel);
869e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_view=AcquireVirtualCacheView(source_image,exception);
870e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
871e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      for (y=0; y < (ssize_t) source_image->rows; y++)
8723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
8733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        MagickBooleanType
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          sync;
8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8764c08aed51c5899665ade97263692328eea4af106cristy        register const Quantum
87705d2ff7ebf21f659f5b11e45afb294e152f4330cdirk          *magick_restrict p;
8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8794c08aed51c5899665ade97263692328eea4af106cristy        register Quantum
88005d2ff7ebf21f659f5b11e45afb294e152f4330cdirk          *magick_restrict q;
8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
882bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        register ssize_t
8833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          x;
8843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
885bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          continue;
8872fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy        p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
8882fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy          exception);
8892fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy        q=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,1,
8902fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy          exception);
8914c08aed51c5899665ade97263692328eea4af106cristy        if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
893e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        for (x=0; x < (ssize_t) source_image->columns; x++)
8943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
895bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
897e8e8eff5f2414d6096195a41934fc0edee9d9212cristy              p+=GetPixelChannels(source_image);
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              continue;
8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
9003bdd925dbb0804df99e548c50667670319655816cristy          if (fabs((double) angle_range) > MagickEpsilon)
901173ad0fb5d2718a7f47d7f576ad61c0bbd9f3bbdanthony            {
9027159f66759ae05f052aad309915b9784f7aca927cristy              MagickRealType
903173ad0fb5d2718a7f47d7f576ad61c0bbd9f3bbdanthony                angle;
904173ad0fb5d2718a7f47d7f576ad61c0bbd9f3bbdanthony
905559401046eb333547a09fb8b67b11fd7f1b05faccristy              angle=angle_start+angle_range*QuantumScale*
906e8e8eff5f2414d6096195a41934fc0edee9d9212cristy                GetPixelBlue(source_image,p);
907dff7476eed3fa4bc0095561868c3d4d1710d0641anthony              blur.x1=width*cos(angle);
908dff7476eed3fa4bc0095561868c3d4d1710d0641anthony              blur.x2=width*sin(angle);
909dff7476eed3fa4bc0095561868c3d4d1710d0641anthony              blur.y1=(-height*sin(angle));
910dff7476eed3fa4bc0095561868c3d4d1710d0641anthony              blur.y2=height*cos(angle);
911173ad0fb5d2718a7f47d7f576ad61c0bbd9f3bbdanthony            }
912d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony#if 0
913d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony          if ( x == 10 && y == 60 ) {
9147159f66759ae05f052aad309915b9784f7aca927cristy            (void) fprintf(stderr, "blur.x=%lf,%lf, blur.y=%lf,%lf\n",blur.x1,
9157159f66759ae05f052aad309915b9784f7aca927cristy              blur.x2,blur.y1, blur.y2);
9167159f66759ae05f052aad309915b9784f7aca927cristy            (void) fprintf(stderr, "scaled by=%lf,%lf\n",QuantumScale*
9177159f66759ae05f052aad309915b9784f7aca927cristy              GetPixelRed(p),QuantumScale*GetPixelGreen(p));
918d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony#endif
919d2923915a5f0e17e3f1ea511cddbf7d3cb8b6c99anthony          ScaleResampleFilter(resample_filter,
920e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            blur.x1*QuantumScale*GetPixelRed(source_image,p),
921e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            blur.y1*QuantumScale*GetPixelGreen(source_image,p),
922e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            blur.x2*QuantumScale*GetPixelRed(source_image,p),
923e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            blur.y2*QuantumScale*GetPixelGreen(source_image,p) );
9243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) ResamplePixelColor(resample_filter,(double) x_offset+x,
925db070957cf6bf959df9283a482377e8854c3d4d2cristy            (double) y_offset+y,&pixel,exception);
926e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          SetPixelViaPixelInfo(canvas_image,&pixel,q);
927e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          p+=GetPixelChannels(source_image);
928e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          q+=GetPixelChannels(canvas_image);
9293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
930e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
9313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (sync == MagickFalse)
9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
9343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resample_filter=DestroyResampleFilter(resample_filter);
935e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_view=DestroyCacheView(source_view);
936e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      canvas_view=DestroyCacheView(canvas_view);
937e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_image=DestroyImage(source_image);
938e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_image=canvas_image;
9393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
9403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case DisplaceCompositeOp:
9423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case DistortCompositeOp:
9433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
944559401046eb333547a09fb8b67b11fd7f1b05faccristy      CacheView
945fa589d6096099562cbc2bc14e508931968a8c055dirk        *canvas_view;
946feb3e9695150978a5d2372d3fe2f60466a7c8066cristy
9477159f66759ae05f052aad309915b9784f7aca927cristy      MagickRealType
9483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        horizontal_scale,
949559401046eb333547a09fb8b67b11fd7f1b05faccristy        vertical_scale;
950559401046eb333547a09fb8b67b11fd7f1b05faccristy
9514f60be50be2ee99d6ea941c702b6789fd7ca68cfcristy      PixelInfo
9524f60be50be2ee99d6ea941c702b6789fd7ca68cfcristy        pixel;
9534f60be50be2ee99d6ea941c702b6789fd7ca68cfcristy
954559401046eb333547a09fb8b67b11fd7f1b05faccristy      PointInfo
955559401046eb333547a09fb8b67b11fd7f1b05faccristy        center,
956559401046eb333547a09fb8b67b11fd7f1b05faccristy        offset;
9573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
9593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Displace/Distort based on overlay gradient map:
9603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          X = red_channel;  Y = green_channel;
961559401046eb333547a09fb8b67b11fd7f1b05faccristy          compose:args = x_scale[,y_scale[,center.x,center.y]]
9623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
963e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      canvas_image=CloneImage(image,image->columns,image->rows,MagickTrue,
9648a11cb146177680bfc1b7d89a8cd0c8f2befe468cristy        exception);
965e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      if (canvas_image == (Image *) NULL)
96644886b9874b0dc62e49d0c26f16aa4fbcb2407f0cristy        {
967e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          source_image=DestroyImage(source_image);
96844886b9874b0dc62e49d0c26f16aa4fbcb2407f0cristy          return(MagickFalse);
96944886b9874b0dc62e49d0c26f16aa4fbcb2407f0cristy        }
9703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      SetGeometryInfo(&geometry_info);
9713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      flags=NoValue;
97255a83c75eeede1662a9e6c43c3af201502c9442fdirk      value=GetImageArtifact(image,"compose:args");
9733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (value != (char *) NULL)
9743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        flags=ParseGeometry(value,&geometry_info);
97548054f3dcda89dd0764c43571a95b41a7deeee6ecristy      if ((flags & (WidthValue | HeightValue)) == 0 )
976559401046eb333547a09fb8b67b11fd7f1b05faccristy        {
977559401046eb333547a09fb8b67b11fd7f1b05faccristy          if ((flags & AspectValue) == 0)
978559401046eb333547a09fb8b67b11fd7f1b05faccristy            {
979ad1b65039ac9430edfe2a79ed4187729e6f0a4eccristy              horizontal_scale=(MagickRealType) (source_image->columns-1)/2.0;
980ad1b65039ac9430edfe2a79ed4187729e6f0a4eccristy              vertical_scale=(MagickRealType) (source_image->rows-1)/2.0;
981559401046eb333547a09fb8b67b11fd7f1b05faccristy            }
982559401046eb333547a09fb8b67b11fd7f1b05faccristy          else
983559401046eb333547a09fb8b67b11fd7f1b05faccristy            {
984ad1b65039ac9430edfe2a79ed4187729e6f0a4eccristy              horizontal_scale=(MagickRealType) (image->columns-1)/2.0;
985ad1b65039ac9430edfe2a79ed4187729e6f0a4eccristy              vertical_scale=(MagickRealType) (image->rows-1)/2.0;
986559401046eb333547a09fb8b67b11fd7f1b05faccristy            }
987559401046eb333547a09fb8b67b11fd7f1b05faccristy        }
9883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
9893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          horizontal_scale=geometry_info.rho;
9913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          vertical_scale=geometry_info.sigma;
9923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((flags & PercentValue) != 0)
9933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
9943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if ((flags & AspectValue) == 0)
9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
996ad1b65039ac9430edfe2a79ed4187729e6f0a4eccristy                  horizontal_scale*=(source_image->columns-1)/200.0;
997ad1b65039ac9430edfe2a79ed4187729e6f0a4eccristy                  vertical_scale*=(source_image->rows-1)/200.0;
9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
9993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              else
10003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                {
1001ad1b65039ac9430edfe2a79ed4187729e6f0a4eccristy                  horizontal_scale*=(image->columns-1)/200.0;
1002ad1b65039ac9430edfe2a79ed4187729e6f0a4eccristy                  vertical_scale*=(image->rows-1)/200.0;
10033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                }
10043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
10053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((flags & HeightValue) == 0)
10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            vertical_scale=horizontal_scale;
10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Determine fixed center point for absolute distortion map
10103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         Absolute distort ==
1011559401046eb333547a09fb8b67b11fd7f1b05faccristy           Displace offset relative to a fixed absolute point
10123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           Select that point according to +X+Y user inputs.
10133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           default = center of overlay image
1014d37a5cb8553a1e408ffd22a51c2fc0ec17dfce5eanthony           arg flag '!' = locations/percentage relative to background image
10153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
10167159f66759ae05f052aad309915b9784f7aca927cristy      center.x=(MagickRealType) x_offset;
10177159f66759ae05f052aad309915b9784f7aca927cristy      center.y=(MagickRealType) y_offset;
10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (compose == DistortCompositeOp)
10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((flags & XValue) == 0)
1021190f47988052d03eb6b79c49cce4404eca4e353bcristy            if ((flags & AspectValue) != 0)
1022190f47988052d03eb6b79c49cce4404eca4e353bcristy              center.x=(MagickRealType) ((image->columns-1)/2.0);
1023190f47988052d03eb6b79c49cce4404eca4e353bcristy            else
1024e8e8eff5f2414d6096195a41934fc0edee9d9212cristy              center.x=(MagickRealType) (x_offset+(source_image->columns-1)/
10257159f66759ae05f052aad309915b9784f7aca927cristy                2.0);
10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          else
1027190f47988052d03eb6b79c49cce4404eca4e353bcristy            if ((flags & AspectValue) != 0)
1028559401046eb333547a09fb8b67b11fd7f1b05faccristy              center.x=geometry_info.xi;
10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
1030190f47988052d03eb6b79c49cce4404eca4e353bcristy              center.x=(MagickRealType) (x_offset+geometry_info.xi);
1031190f47988052d03eb6b79c49cce4404eca4e353bcristy          if ((flags & YValue) == 0)
1032190f47988052d03eb6b79c49cce4404eca4e353bcristy            if ((flags & AspectValue) != 0)
1033ad1b65039ac9430edfe2a79ed4187729e6f0a4eccristy              center.y=(MagickRealType) ((image->rows-1)/2.0);
10343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            else
1035190f47988052d03eb6b79c49cce4404eca4e353bcristy              center.y=(MagickRealType) (y_offset+(source_image->rows-1)/2.0);
1036190f47988052d03eb6b79c49cce4404eca4e353bcristy          else
1037190f47988052d03eb6b79c49cce4404eca4e353bcristy            if ((flags & AspectValue) != 0)
1038559401046eb333547a09fb8b67b11fd7f1b05faccristy              center.y=geometry_info.psi;
1039190f47988052d03eb6b79c49cce4404eca4e353bcristy            else
1040190f47988052d03eb6b79c49cce4404eca4e353bcristy              center.y=(MagickRealType) (y_offset+geometry_info.psi);
10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
10423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
1043559401046eb333547a09fb8b67b11fd7f1b05faccristy        Shift the pixel offset point as defined by the provided,
10443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        displacement/distortion map.  -- Like a lens...
10453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
1046e10859aa31abb52913175e089e5d25cbd670499fcristy      GetPixelInfo(image,&pixel);
104746ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy      image_view=AcquireVirtualCacheView(image,exception);
1048e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_view=AcquireVirtualCacheView(source_image,exception);
1049e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      canvas_view=AcquireAuthenticCacheView(canvas_image,exception);
1050e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      for (y=0; y < (ssize_t) source_image->rows; y++)
10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
10523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        MagickBooleanType
10533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          sync;
10543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10554c08aed51c5899665ade97263692328eea4af106cristy        register const Quantum
105605d2ff7ebf21f659f5b11e45afb294e152f4330cdirk          *magick_restrict p;
10573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10584c08aed51c5899665ade97263692328eea4af106cristy        register Quantum
105905d2ff7ebf21f659f5b11e45afb294e152f4330cdirk          *magick_restrict q;
10604c08aed51c5899665ade97263692328eea4af106cristy
1061bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        register ssize_t
10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          x;
10633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1064bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        if (((y+y_offset) < 0) || ((y+y_offset) >= (ssize_t) image->rows))
10653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          continue;
1066ad1b65039ac9430edfe2a79ed4187729e6f0a4eccristy        p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
1067ad1b65039ac9430edfe2a79ed4187729e6f0a4eccristy          exception);
1068ad1b65039ac9430edfe2a79ed4187729e6f0a4eccristy        q=QueueCacheViewAuthenticPixels(canvas_view,0,y,canvas_image->columns,1,
1069ad1b65039ac9430edfe2a79ed4187729e6f0a4eccristy          exception);
10704c08aed51c5899665ade97263692328eea4af106cristy        if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
10713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
1072e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        for (x=0; x < (ssize_t) source_image->columns; x++)
10733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
1074bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          if (((x_offset+x) < 0) || ((x_offset+x) >= (ssize_t) image->columns))
10753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
1076e8e8eff5f2414d6096195a41934fc0edee9d9212cristy              p+=GetPixelChannels(source_image);
10773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              continue;
10783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
10793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
1080559401046eb333547a09fb8b67b11fd7f1b05faccristy            Displace the offset.
10813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
1082e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          offset.x=(double) (horizontal_scale*(GetPixelRed(source_image,p)-
10837159f66759ae05f052aad309915b9784f7aca927cristy            (((MagickRealType) QuantumRange+1.0)/2.0)))/(((MagickRealType)
10847159f66759ae05f052aad309915b9784f7aca927cristy            QuantumRange+1.0)/2.0)+center.x+((compose == DisplaceCompositeOp) ?
10857159f66759ae05f052aad309915b9784f7aca927cristy            x : 0);
1086e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          offset.y=(double) (vertical_scale*(GetPixelGreen(source_image,p)-
10877159f66759ae05f052aad309915b9784f7aca927cristy            (((MagickRealType) QuantumRange+1.0)/2.0)))/(((MagickRealType)
10887159f66759ae05f052aad309915b9784f7aca927cristy            QuantumRange+1.0)/2.0)+center.y+((compose == DisplaceCompositeOp) ?
10897159f66759ae05f052aad309915b9784f7aca927cristy            y : 0);
1090c692a833300c9d5a58c221c7fb87cf369f54e16ecristy          (void) InterpolatePixelInfo(image,image_view,
1091c692a833300c9d5a58c221c7fb87cf369f54e16ecristy            UndefinedInterpolatePixel,(double) offset.x,(double) offset.y,
1092c692a833300c9d5a58c221c7fb87cf369f54e16ecristy            &pixel,exception);
10933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
1094c5d68fe2846b7ed7b866c8a5d9287264d75458caanthony            Mask with the 'invalid pixel mask' in alpha channel.
10953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
10964f60be50be2ee99d6ea941c702b6789fd7ca68cfcristy          pixel.alpha=(MagickRealType) QuantumRange*(QuantumScale*pixel.alpha)*
10974f60be50be2ee99d6ea941c702b6789fd7ca68cfcristy            (QuantumScale*GetPixelAlpha(source_image,p));
1098e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          SetPixelViaPixelInfo(canvas_image,&pixel,q);
1099e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          p+=GetPixelChannels(source_image);
1100e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          q+=GetPixelChannels(canvas_image);
11013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
1102e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        sync=SyncCacheViewAuthenticPixels(canvas_view,exception);
11033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (sync == MagickFalse)
11043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
11053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
1106e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      canvas_view=DestroyCacheView(canvas_view);
1107e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_view=DestroyCacheView(source_view);
1108d76c51ed30cf4084f4434ba08925d16001d1e340cristy      image_view=DestroyCacheView(image_view);
1109e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_image=DestroyImage(source_image);
1110e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      source_image=canvas_image;
11113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
11123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
11133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case DissolveCompositeOp:
11143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
11153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
11163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Geometry arguments to dissolve factors.
11173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
111855a83c75eeede1662a9e6c43c3af201502c9442fdirk      value=GetImageArtifact(image,"compose:args");
11193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (value != (char *) NULL)
11203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
11213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          flags=ParseGeometry(value,&geometry_info);
11223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          source_dissolve=geometry_info.rho/100.0;
1123e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          canvas_dissolve=1.0;
11243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((source_dissolve-MagickEpsilon) < 0.0)
11253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            source_dissolve=0.0;
11263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((source_dissolve+MagickEpsilon) > 1.0)
11273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
1128e8e8eff5f2414d6096195a41934fc0edee9d9212cristy              canvas_dissolve=2.0-source_dissolve;
11293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              source_dissolve=1.0;
11303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
11313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((flags & SigmaValue) != 0)
1132e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            canvas_dissolve=geometry_info.sigma/100.0;
1133e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          if ((canvas_dissolve-MagickEpsilon) < 0.0)
1134e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            canvas_dissolve=0.0;
11353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
11363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
11373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
11383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case BlendCompositeOp:
11393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
114055a83c75eeede1662a9e6c43c3af201502c9442fdirk      value=GetImageArtifact(image,"compose:args");
11413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (value != (char *) NULL)
11423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
11433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          flags=ParseGeometry(value,&geometry_info);
11443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          source_dissolve=geometry_info.rho/100.0;
1145e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          canvas_dissolve=1.0-source_dissolve;
11463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((flags & SigmaValue) != 0)
1147e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            canvas_dissolve=geometry_info.sigma/100.0;
11483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
11493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
11503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
11513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case MathematicsCompositeOp:
11523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
11533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
11543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Just collect the values from "compose:args", setting.
11553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Unused values are set to zero automagically.
11563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Arguments are normally a comma separated list, so this probably should
11583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        be changed to some 'general comma list' parser, (with a minimum
11593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        number of values)
11603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
11613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      SetGeometryInfo(&geometry_info);
116255a83c75eeede1662a9e6c43c3af201502c9442fdirk      value=GetImageArtifact(image,"compose:args");
11633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (value != (char *) NULL)
11643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ParseGeometry(value,&geometry_info);
11653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
11663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
11673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case ModulateCompositeOp:
11683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
11693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
11707133e649ea494c1286ff16bcb02342d660097219cristy        Determine the luma and chroma scale.
11713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
117255a83c75eeede1662a9e6c43c3af201502c9442fdirk      value=GetImageArtifact(image,"compose:args");
11733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (value != (char *) NULL)
11743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
11753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          flags=ParseGeometry(value,&geometry_info);
11767133e649ea494c1286ff16bcb02342d660097219cristy          percent_luma=geometry_info.rho;
11773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((flags & SigmaValue) != 0)
11787133e649ea494c1286ff16bcb02342d660097219cristy            percent_chroma=geometry_info.sigma;
11793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
11803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
11813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
11823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case ThresholdCompositeOp:
11833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
11843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
11853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Determine the amount and threshold.
11863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
118755a83c75eeede1662a9e6c43c3af201502c9442fdirk      value=GetImageArtifact(image,"compose:args");
11883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (value != (char *) NULL)
11893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
11903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          flags=ParseGeometry(value,&geometry_info);
11913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          amount=geometry_info.rho;
11923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          threshold=geometry_info.sigma;
11933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ((flags & SigmaValue) == 0)
11943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            threshold=0.05f;
11953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
11963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      threshold*=QuantumRange;
11973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
11983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
11993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    default:
12003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
12013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
12023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
12033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Composite image.
12043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
12053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=MagickTrue;
12063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  progress=0;
12077159f66759ae05f052aad309915b9784f7aca927cristy  midpoint=((MagickRealType) QuantumRange+1.0)/2;
1208e8e8eff5f2414d6096195a41934fc0edee9d9212cristy  source_view=AcquireVirtualCacheView(source_image,exception);
120946ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  image_view=AcquireAuthenticCacheView(image,exception);
1210b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
1211ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy  #pragma omp parallel for schedule(static,4) shared(progress,status) \
1212e8e8eff5f2414d6096195a41934fc0edee9d9212cristy    magick_threads(source_image,image,image->rows,1)
12133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
1214bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
12153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
12164c08aed51c5899665ade97263692328eea4af106cristy    const Quantum
12173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *pixels;
12183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12197159f66759ae05f052aad309915b9784f7aca927cristy    MagickRealType
1220e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      blue,
122112e4d2e452fe147da90070df55b10dfbd88b7067cristy      chroma,
1222e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      green,
1223e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      hue,
122412e4d2e452fe147da90070df55b10dfbd88b7067cristy      luma,
122512e4d2e452fe147da90070df55b10dfbd88b7067cristy      red;
1226e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
1227ddeeea23285164a7029e2f28475642f26882f2d7cristy    PixelInfo
1228e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      canvas_pixel,
1229ddeeea23285164a7029e2f28475642f26882f2d7cristy      source_pixel;
1230ddeeea23285164a7029e2f28475642f26882f2d7cristy
1231e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    register const Quantum
123205d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict p;
1233e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
1234e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    register Quantum
123505d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict q;
1236e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
1237e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    register ssize_t
1238e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      x;
1239e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
1240e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    if (status == MagickFalse)
1241e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      continue;
1242feb3e9695150978a5d2372d3fe2f60466a7c8066cristy    if (clip_to_self != MagickFalse)
1243e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      {
1244e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        if (y < y_offset)
1245e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          continue;
1246e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        if ((y-y_offset) >= (ssize_t) source_image->rows)
1247e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          continue;
1248e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      }
1249e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    /*
1250e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      If pixels is NULL, y is outside overlay region.
1251e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    */
1252e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    pixels=(Quantum *) NULL;
1253e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    p=(Quantum *) NULL;
1254e8e8eff5f2414d6096195a41934fc0edee9d9212cristy    if ((y >= y_offset) && ((y-y_offset) < (ssize_t) source_image->rows))
1255e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      {
1256e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        p=GetCacheViewVirtualPixels(source_view,0,y-y_offset,
1257e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          source_image->columns,1,exception);
1258e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        if (p == (const Quantum *) NULL)
1259e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          {
1260e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            status=MagickFalse;
1261e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            continue;
1262e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          }
1263e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        pixels=p;
1264e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        if (x_offset < 0)
1265e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          p-=x_offset*GetPixelChannels(source_image);
1266e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      }
1267e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1268e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    if (q == (Quantum *) NULL)
1269e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      {
1270e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        status=MagickFalse;
1271e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        continue;
1272e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      }
1273e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    hue=0.0;
12747133e649ea494c1286ff16bcb02342d660097219cristy    chroma=0.0;
12757133e649ea494c1286ff16bcb02342d660097219cristy    luma=0.0;
1276e8e8eff5f2414d6096195a41934fc0edee9d9212cristy    GetPixelInfo(image,&canvas_pixel);
1277e8e8eff5f2414d6096195a41934fc0edee9d9212cristy    GetPixelInfo(source_image,&source_pixel);
1278e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    for (x=0; x < (ssize_t) image->columns; x++)
1279e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy    {
128017028dccbf579855c1805d9e62561ad83104bb56cristy      double
128117028dccbf579855c1805d9e62561ad83104bb56cristy        gamma;
128217028dccbf579855c1805d9e62561ad83104bb56cristy
12837159f66759ae05f052aad309915b9784f7aca927cristy      MagickRealType
1284e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        alpha,
1285e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        Da,
1286e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        Dc,
1287e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        Dca,
1288e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        Sa,
1289e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        Sc,
1290e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        Sca;
1291e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
1292e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      register ssize_t
1293e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        i;
1294e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
1295564a56979706a30a3d0f920fd5f538a408efd4f1cristy      size_t
1296564a56979706a30a3d0f920fd5f538a408efd4f1cristy        channels;
1297564a56979706a30a3d0f920fd5f538a408efd4f1cristy
1298feb3e9695150978a5d2372d3fe2f60466a7c8066cristy      if (clip_to_self != MagickFalse)
1299e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
1300e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          if (x < x_offset)
13013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
1302e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              q+=GetPixelChannels(image);
1303e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              continue;
13043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
1305e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          if ((x-x_offset) >= (ssize_t) source_image->columns)
1306e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            break;
1307e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        }
1308e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      if ((pixels == (Quantum *) NULL) || (x < x_offset) ||
1309e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          ((x-x_offset) >= (ssize_t) source_image->columns))
1310e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
1311e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          Quantum
1312e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            source[MaxPixelChannels];
1313e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
1314e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          /*
1315e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            Virtual composite:
1316e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              Sc: source color.
1317e8e8eff5f2414d6096195a41934fc0edee9d9212cristy              Dc: canvas color.
1318e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          */
13192fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy          (void) GetOneVirtualPixel(source_image,x-x_offset,y-y_offset,source,
13202fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy            exception);
1321883fde11debec15cedb05dc5d7228d8588066bc0cristy          if (GetPixelReadMask(image,q) == 0)
132210a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy            {
132310a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy              q+=GetPixelChannels(image);
132410a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy              continue;
132510a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy            }
1326e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1327e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          {
13287159f66759ae05f052aad309915b9784f7aca927cristy            MagickRealType
1329e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              pixel;
1330e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
13315a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy            PixelChannel channel=GetPixelChannelChannel(image,i);
13325a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy            PixelTrait traits=GetPixelChannelTraits(image,channel);
1333e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            PixelTrait source_traits=GetPixelChannelTraits(source_image,
13345a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy              channel);
1335e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            if ((traits == UndefinedPixelTrait) ||
1336e8e8eff5f2414d6096195a41934fc0edee9d9212cristy                (source_traits == UndefinedPixelTrait))
1337e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              continue;
1338e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            switch (compose)
133943e26daee2f110555b6fe976a58a89775c03508fcristy            {
1340c8d636784204aa4d970c212b156bffc387836b93cristy              case AlphaCompositeOp:
1341e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case ChangeMaskCompositeOp:
1342e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case CopyAlphaCompositeOp:
1343e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case DstAtopCompositeOp:
1344e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case DstInCompositeOp:
1345e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case InCompositeOp:
1346e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case OutCompositeOp:
1347e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case SrcInCompositeOp:
1348e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case SrcOutCompositeOp:
1349e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
1350e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                if (channel == AlphaPixelChannel)
13517159f66759ae05f052aad309915b9784f7aca927cristy                  pixel=(MagickRealType) TransparentAlpha;
13521474c08cbd2d489254a9b41a22fab1e4c698740bdirk                else
13531474c08cbd2d489254a9b41a22fab1e4c698740bdirk                  pixel=(MagickRealType) q[i];
1354e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1355e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
1356e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case ClearCompositeOp:
1357e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case CopyCompositeOp:
1358e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case ReplaceCompositeOp:
1359e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case SrcCompositeOp:
1360e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
1361e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                if (channel == AlphaPixelChannel)
13621474c08cbd2d489254a9b41a22fab1e4c698740bdirk                  pixel=(MagickRealType) TransparentAlpha;
13631474c08cbd2d489254a9b41a22fab1e4c698740bdirk                else
13641474c08cbd2d489254a9b41a22fab1e4c698740bdirk                  pixel=0.0;
1365e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1366e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
136799abff36ae5d479bfd76652d166a4894ceada102cristy              case BlendCompositeOp:
1368e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case DissolveCompositeOp:
1369e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
1370e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                if (channel == AlphaPixelChannel)
137112e4d2e452fe147da90070df55b10dfbd88b7067cristy                  pixel=canvas_dissolve*GetPixelAlpha(source_image,source);
13721474c08cbd2d489254a9b41a22fab1e4c698740bdirk                else
13731474c08cbd2d489254a9b41a22fab1e4c698740bdirk                  pixel=(MagickRealType) source[channel];
1374e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1375e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
1376e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              default:
1377e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
13787159f66759ae05f052aad309915b9784f7aca927cristy                pixel=(MagickRealType) source[channel];
1379e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1380e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
138143e26daee2f110555b6fe976a58a89775c03508fcristy            }
138247c61c996128275174b8a120ab6a88a5c1bec3d3cristy            q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
138347c61c996128275174b8a120ab6a88a5c1bec3d3cristy              ClampToQuantum(pixel);
13843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
1385e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          q+=GetPixelChannels(image);
1386e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          continue;
1387e10859aa31abb52913175e089e5d25cbd670499fcristy        }
1388e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      /*
1389e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        Authentic composite:
1390e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          Sa:  normalized source alpha.
1391e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          Da:  normalized canvas alpha.
1392e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      */
1393e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      Sa=QuantumScale*GetPixelAlpha(source_image,p);
1394e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      Da=QuantumScale*GetPixelAlpha(image,q);
1395e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      switch (compose)
1396e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      {
1397e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case BumpmapCompositeOp:
1398e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
1399e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          alpha=GetPixelIntensity(source_image,p)*Sa;
1400e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          break;
1401e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        }
1402e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case ColorBurnCompositeOp:
1403e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case ColorDodgeCompositeOp:
140430dac202caf1ded0e356ab1c2b67ec8d7929e06dcristy        case DarkenCompositeOp:
1405e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case DifferenceCompositeOp:
1406e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case DivideDstCompositeOp:
1407e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case DivideSrcCompositeOp:
1408e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case ExclusionCompositeOp:
1409e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case HardLightCompositeOp:
141099fc217dffe2ed10ebefd0ac85900df37b60e3fdcristy        case HardMixCompositeOp:
1411e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case LinearBurnCompositeOp:
1412e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case LinearDodgeCompositeOp:
1413e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case LinearLightCompositeOp:
141430dac202caf1ded0e356ab1c2b67ec8d7929e06dcristy        case LightenCompositeOp:
1415e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case MathematicsCompositeOp:
1416e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case MinusDstCompositeOp:
1417e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case MinusSrcCompositeOp:
1418e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case ModulusAddCompositeOp:
1419e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case ModulusSubtractCompositeOp:
1420e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case MultiplyCompositeOp:
1421e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case OverlayCompositeOp:
1422e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case PegtopLightCompositeOp:
1423e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case PinLightCompositeOp:
1424e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case ScreenCompositeOp:
1425e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case SoftLightCompositeOp:
1426e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case VividLightCompositeOp:
1427e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
1428e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          alpha=RoundToUnity(Sa+Da-Sa*Da);
1429e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          break;
1430e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        }
1431e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case DstAtopCompositeOp:
1432e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case DstInCompositeOp:
1433e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case InCompositeOp:
1434e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case SrcInCompositeOp:
1435e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
1436e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          alpha=Sa*Da;
1437e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          break;
1438e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        }
1439e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case DissolveCompositeOp:
1440e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
14412fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy          alpha=source_dissolve*Sa*(-canvas_dissolve*Da)+source_dissolve*Sa+
14422fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy            canvas_dissolve*Da;
1443e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          break;
1444e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        }
1445e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case DstOverCompositeOp:
14461749597845aafe5e61783d9a1b43d333f7071ccddirk        case OverCompositeOp:
14471749597845aafe5e61783d9a1b43d333f7071ccddirk        case SrcOverCompositeOp:
1448e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
144930dac202caf1ded0e356ab1c2b67ec8d7929e06dcristy          alpha=Sa+Da-Sa*Da;
1450e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          break;
1451e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        }
1452e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case DstOutCompositeOp:
1453e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
1454e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          alpha=Da*(1.0-Sa);
1455e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          break;
1456e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        }
1457e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case OutCompositeOp:
1458e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case SrcOutCompositeOp:
1459e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
1460e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          alpha=Sa*(1.0-Da);
1461e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          break;
1462e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        }
146399abff36ae5d479bfd76652d166a4894ceada102cristy        case BlendCompositeOp:
1464e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case PlusCompositeOp:
1465e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
1466b37bf1647d1a963a149a082366d81445217bd754cristy          alpha=RoundToUnity(source_dissolve*Sa+canvas_dissolve*Da);
1467e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          break;
1468e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        }
1469e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        case XorCompositeOp:
1470e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
1471e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          alpha=Sa+Da-2.0*Sa*Da;
1472e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          break;
1473e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        }
1474e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        default:
1475e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
1476e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          alpha=1.0;
1477e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          break;
1478e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        }
1479e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      }
1480883fde11debec15cedb05dc5d7228d8588066bc0cristy      if (GetPixelReadMask(image,q) == 0)
148110a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy        {
1482e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          p+=GetPixelChannels(source_image);
148310a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy          q+=GetPixelChannels(image);
148410a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy          continue;
148510a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy        }
14869d3d279297b7248caacd9f37f433974b92df5fedcristy      switch (compose)
14879d3d279297b7248caacd9f37f433974b92df5fedcristy      {
14889d3d279297b7248caacd9f37f433974b92df5fedcristy        case ColorizeCompositeOp:
14899d3d279297b7248caacd9f37f433974b92df5fedcristy        case HueCompositeOp:
14909d3d279297b7248caacd9f37f433974b92df5fedcristy        case LuminizeCompositeOp:
14919d3d279297b7248caacd9f37f433974b92df5fedcristy        case ModulateCompositeOp:
14929d3d279297b7248caacd9f37f433974b92df5fedcristy        case SaturateCompositeOp:
14939d3d279297b7248caacd9f37f433974b92df5fedcristy        {
1494e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          GetPixelInfoPixel(source_image,p,&source_pixel);
1495e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          GetPixelInfoPixel(image,q,&canvas_pixel);
14969d3d279297b7248caacd9f37f433974b92df5fedcristy          break;
14979d3d279297b7248caacd9f37f433974b92df5fedcristy        }
14989d3d279297b7248caacd9f37f433974b92df5fedcristy        default:
14999d3d279297b7248caacd9f37f433974b92df5fedcristy          break;
15009d3d279297b7248caacd9f37f433974b92df5fedcristy      }
1501e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1502e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy      {
15037159f66759ae05f052aad309915b9784f7aca927cristy        MagickRealType
15047159f66759ae05f052aad309915b9784f7aca927cristy          pixel,
1505564a56979706a30a3d0f920fd5f538a408efd4f1cristy          sans;
1506564a56979706a30a3d0f920fd5f538a408efd4f1cristy
15075a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelChannel channel=GetPixelChannelChannel(image,i);
15085a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelTrait traits=GetPixelChannelTraits(image,channel);
15092fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy        PixelTrait source_traits=GetPixelChannelTraits(source_image,channel);
15100cd1f214a416f7827dbd000cecd6687f1df3cef6cristy        if (traits == UndefinedPixelTrait)
15110cd1f214a416f7827dbd000cecd6687f1df3cef6cristy          continue;
1512e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        if ((source_traits == UndefinedPixelTrait) &&
1513597358bb71c59d54a67f64b76644b5436365733bdirk             (((compose != CopyAlphaCompositeOp) &&
1514597358bb71c59d54a67f64b76644b5436365733bdirk               (compose != ChangeMaskCompositeOp)) ||
151595ef69591ab25c59c552584384ad3cd5cc5b358bdirk               (channel != AlphaPixelChannel)))
1516597358bb71c59d54a67f64b76644b5436365733bdirk            continue;
1517e10859aa31abb52913175e089e5d25cbd670499fcristy        /*
1518e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          Sc: source color.
1519e8e8eff5f2414d6096195a41934fc0edee9d9212cristy          Dc: canvas color.
1520e10859aa31abb52913175e089e5d25cbd670499fcristy        */
1521e8e8eff5f2414d6096195a41934fc0edee9d9212cristy        Sc=(MagickRealType) GetPixelChannel(source_image,channel,p);
15227159f66759ae05f052aad309915b9784f7aca927cristy        Dc=(MagickRealType) q[i];
1523e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        if ((traits & CopyPixelTrait) != 0)
1524e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1525e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            /*
1526e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy              Copy channel.
1527e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            */
152847c61c996128275174b8a120ab6a88a5c1bec3d3cristy            q[i]=Sc;
1529e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            continue;
1530e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy          }
1531e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy        if (channel == AlphaPixelChannel)
1532e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy          {
1533e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            /*
1534e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              Set alpha channel.
1535e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            */
1536e10859aa31abb52913175e089e5d25cbd670499fcristy            switch (compose)
15373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
1538c8d636784204aa4d970c212b156bffc387836b93cristy              case AlphaCompositeOp:
1539c8d636784204aa4d970c212b156bffc387836b93cristy              {
1540a7b079186ad7e0943fa65611a8978531bb612eeccristy                pixel=QuantumRange*Sa;
1541c8d636784204aa4d970c212b156bffc387836b93cristy                break;
1542c8d636784204aa4d970c212b156bffc387836b93cristy              }
1543e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case AtopCompositeOp:
154499abff36ae5d479bfd76652d166a4894ceada102cristy              case CopyBlackCompositeOp:
154599abff36ae5d479bfd76652d166a4894ceada102cristy              case CopyBlueCompositeOp:
154699abff36ae5d479bfd76652d166a4894ceada102cristy              case CopyCyanCompositeOp:
154799abff36ae5d479bfd76652d166a4894ceada102cristy              case CopyGreenCompositeOp:
154899abff36ae5d479bfd76652d166a4894ceada102cristy              case CopyMagentaCompositeOp:
154999abff36ae5d479bfd76652d166a4894ceada102cristy              case CopyRedCompositeOp:
155099abff36ae5d479bfd76652d166a4894ceada102cristy              case CopyYellowCompositeOp:
1551e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case SrcAtopCompositeOp:
1552e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case DstCompositeOp:
1553e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case NoCompositeOp:
1554e10859aa31abb52913175e089e5d25cbd670499fcristy              {
1555e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=QuantumRange*Da;
1556e10859aa31abb52913175e089e5d25cbd670499fcristy                break;
1557e10859aa31abb52913175e089e5d25cbd670499fcristy              }
1558e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case ChangeMaskCompositeOp:
1559e10859aa31abb52913175e089e5d25cbd670499fcristy              {
1560e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                MagickBooleanType
1561e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                  equivalent;
1562e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
1563f32657d0171432253bfcbc52a031734ac9bcd9cbdirk                if (Da < 0.5)
156499abff36ae5d479bfd76652d166a4894ceada102cristy                  {
15657159f66759ae05f052aad309915b9784f7aca927cristy                    pixel=(MagickRealType) TransparentAlpha;
156699abff36ae5d479bfd76652d166a4894ceada102cristy                    break;
156799abff36ae5d479bfd76652d166a4894ceada102cristy                  }
1568e8e8eff5f2414d6096195a41934fc0edee9d9212cristy                equivalent=IsFuzzyEquivalencePixel(source_image,p,image,q);
156999abff36ae5d479bfd76652d166a4894ceada102cristy                if (equivalent != MagickFalse)
157040e1cb503f5f973a02d9bf139ce68690ac41c915dirk                  pixel=(MagickRealType) TransparentAlpha;
157140e1cb503f5f973a02d9bf139ce68690ac41c915dirk                else
157240e1cb503f5f973a02d9bf139ce68690ac41c915dirk                  pixel=(MagickRealType) OpaqueAlpha;
1573e10859aa31abb52913175e089e5d25cbd670499fcristy                break;
1574e10859aa31abb52913175e089e5d25cbd670499fcristy              }
157599abff36ae5d479bfd76652d166a4894ceada102cristy              case ClearCompositeOp:
157699abff36ae5d479bfd76652d166a4894ceada102cristy              {
15777159f66759ae05f052aad309915b9784f7aca927cristy                pixel=(MagickRealType) TransparentAlpha;
157899abff36ae5d479bfd76652d166a4894ceada102cristy                break;
157999abff36ae5d479bfd76652d166a4894ceada102cristy              }
158099abff36ae5d479bfd76652d166a4894ceada102cristy              case ColorizeCompositeOp:
158199abff36ae5d479bfd76652d166a4894ceada102cristy              case HueCompositeOp:
158299abff36ae5d479bfd76652d166a4894ceada102cristy              case LuminizeCompositeOp:
158399abff36ae5d479bfd76652d166a4894ceada102cristy              case SaturateCompositeOp:
158499abff36ae5d479bfd76652d166a4894ceada102cristy              {
15853bdd925dbb0804df99e548c50667670319655816cristy                if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon)
158699abff36ae5d479bfd76652d166a4894ceada102cristy                  {
158799abff36ae5d479bfd76652d166a4894ceada102cristy                    pixel=QuantumRange*Da;
158899abff36ae5d479bfd76652d166a4894ceada102cristy                    break;
158999abff36ae5d479bfd76652d166a4894ceada102cristy                  }
15903bdd925dbb0804df99e548c50667670319655816cristy                if (fabs((double) (QuantumRange*Da-TransparentAlpha)) < MagickEpsilon)
159199abff36ae5d479bfd76652d166a4894ceada102cristy                  {
159299abff36ae5d479bfd76652d166a4894ceada102cristy                    pixel=QuantumRange*Sa;
159399abff36ae5d479bfd76652d166a4894ceada102cristy                    break;
159499abff36ae5d479bfd76652d166a4894ceada102cristy                  }
159599abff36ae5d479bfd76652d166a4894ceada102cristy                if (Sa < Da)
159699abff36ae5d479bfd76652d166a4894ceada102cristy                  {
159799abff36ae5d479bfd76652d166a4894ceada102cristy                    pixel=QuantumRange*Da;
159899abff36ae5d479bfd76652d166a4894ceada102cristy                    break;
159999abff36ae5d479bfd76652d166a4894ceada102cristy                  }
160099abff36ae5d479bfd76652d166a4894ceada102cristy                pixel=QuantumRange*Sa;
160199abff36ae5d479bfd76652d166a4894ceada102cristy                break;
160299abff36ae5d479bfd76652d166a4894ceada102cristy              }
160399abff36ae5d479bfd76652d166a4894ceada102cristy              case CopyAlphaCompositeOp:
160424d5d722cf4ba0767eb0d790e1b228a518d737cfcristy              {
16054659893fa7803753e0300a0bde92ede4905aa496cristy                if ((source_traits & BlendPixelTrait) == 0)
1606e8e8eff5f2414d6096195a41934fc0edee9d9212cristy                  pixel=GetPixelIntensity(source_image,p);
160740e1cb503f5f973a02d9bf139ce68690ac41c915dirk                else
160840e1cb503f5f973a02d9bf139ce68690ac41c915dirk                  pixel=QuantumRange*Sa;
160924d5d722cf4ba0767eb0d790e1b228a518d737cfcristy                break;
161024d5d722cf4ba0767eb0d790e1b228a518d737cfcristy              }
161124d5d722cf4ba0767eb0d790e1b228a518d737cfcristy              case CopyCompositeOp:
161299abff36ae5d479bfd76652d166a4894ceada102cristy              case DisplaceCompositeOp:
161399abff36ae5d479bfd76652d166a4894ceada102cristy              case DistortCompositeOp:
1614e10859aa31abb52913175e089e5d25cbd670499fcristy              case DstAtopCompositeOp:
1615e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case ReplaceCompositeOp:
1616e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case SrcCompositeOp:
1617e10859aa31abb52913175e089e5d25cbd670499fcristy              {
1618e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=QuantumRange*Sa;
1619e10859aa31abb52913175e089e5d25cbd670499fcristy                break;
1620e10859aa31abb52913175e089e5d25cbd670499fcristy              }
1621e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case DarkenIntensityCompositeOp:
1622e10859aa31abb52913175e089e5d25cbd670499fcristy              {
1623e8e8eff5f2414d6096195a41934fc0edee9d9212cristy                pixel=Sa*GetPixelIntensity(source_image,p) <
1624076d0c9a787cf3054f29089d5bced8b08b606b94cristy                  Da*GetPixelIntensity(image,q) ? Sa : Da;
1625e10859aa31abb52913175e089e5d25cbd670499fcristy                break;
1626e10859aa31abb52913175e089e5d25cbd670499fcristy              }
1627e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case LightenIntensityCompositeOp:
1628e10859aa31abb52913175e089e5d25cbd670499fcristy              {
1629e8e8eff5f2414d6096195a41934fc0edee9d9212cristy                pixel=Sa*GetPixelIntensity(source_image,p) >
1630e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                  Da*GetPixelIntensity(image,q) ? Sa : Da;
1631e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1632e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
163399abff36ae5d479bfd76652d166a4894ceada102cristy              case ModulateCompositeOp:
163499abff36ae5d479bfd76652d166a4894ceada102cristy              {
163599abff36ae5d479bfd76652d166a4894ceada102cristy                pixel=QuantumRange*Da;
163699abff36ae5d479bfd76652d166a4894ceada102cristy                break;
163799abff36ae5d479bfd76652d166a4894ceada102cristy              }
1638e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              default:
1639e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
1640e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=QuantumRange*alpha;
1641e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1642e10859aa31abb52913175e089e5d25cbd670499fcristy              }
1643e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            }
164447c61c996128275174b8a120ab6a88a5c1bec3d3cristy            q[i]=clamp != MagickFalse ? ClampPixel(pixel) :
164547c61c996128275174b8a120ab6a88a5c1bec3d3cristy              ClampToQuantum(pixel);
1646e10859aa31abb52913175e089e5d25cbd670499fcristy            continue;
1647e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1648e10859aa31abb52913175e089e5d25cbd670499fcristy        /*
164999abff36ae5d479bfd76652d166a4894ceada102cristy          Porter-Duff compositions:
165099abff36ae5d479bfd76652d166a4894ceada102cristy            Sca: source normalized color multiplied by alpha.
1651e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            Dca: normalized canvas color multiplied by alpha.
1652e10859aa31abb52913175e089e5d25cbd670499fcristy        */
165399abff36ae5d479bfd76652d166a4894ceada102cristy        Sca=QuantumScale*Sa*Sc;
165499abff36ae5d479bfd76652d166a4894ceada102cristy        Dca=QuantumScale*Da*Dc;
1655e10859aa31abb52913175e089e5d25cbd670499fcristy        switch (compose)
1656e10859aa31abb52913175e089e5d25cbd670499fcristy        {
1657e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case DarkenCompositeOp:
1658e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case LightenCompositeOp:
165999abff36ae5d479bfd76652d166a4894ceada102cristy          case ModulusSubtractCompositeOp:
1660e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1661f0202bea5f6551326ceaf416ab0f748fe862f245cristy            gamma=PerceptibleReciprocal(1.0-alpha);
16623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
1663e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1664e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          default:
16651749597845aafe5e61783d9a1b43d333f7071ccddirk          {
1666f0202bea5f6551326ceaf416ab0f748fe862f245cristy            gamma=PerceptibleReciprocal(alpha);
1667e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            break;
1668f0202bea5f6551326ceaf416ab0f748fe862f245cristy          }
1669e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        }
1670d197cbbbde474ea2cbdd56d0defa45f100e44cd0cristy        pixel=Dc;
1671e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        switch (compose)
1672e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy        {
1673a7b079186ad7e0943fa65611a8978531bb612eeccristy          case AlphaCompositeOp:
1674a7b079186ad7e0943fa65611a8978531bb612eeccristy          {
1675a7b079186ad7e0943fa65611a8978531bb612eeccristy            pixel=QuantumRange*Sa;
1676a7b079186ad7e0943fa65611a8978531bb612eeccristy            break;
1677a7b079186ad7e0943fa65611a8978531bb612eeccristy          }
1678e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case AtopCompositeOp:
1679e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case SrcAtopCompositeOp:
1680e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1681e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            pixel=QuantumRange*(Sca*Da+Dca*(1.0-Sa));
16823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
1683e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1684e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case BlendCompositeOp:
1685e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          {
1686e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            pixel=gamma*(source_dissolve*Sa*Sc+canvas_dissolve*Da*Dc);
1687e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1688e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          }
1689e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case BlurCompositeOp:
1690e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case CopyCompositeOp:
1691e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case ReplaceCompositeOp:
1692e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case SrcCompositeOp:
1693e10859aa31abb52913175e089e5d25cbd670499fcristy          {
169430dac202caf1ded0e356ab1c2b67ec8d7929e06dcristy            pixel=QuantumRange*Sca;
1695e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1696e10859aa31abb52913175e089e5d25cbd670499fcristy          }
16978e028780f2ba885f17f75ec6927f6d59cc90f37fcristy          case DisplaceCompositeOp:
16988e028780f2ba885f17f75ec6927f6d59cc90f37fcristy          case DistortCompositeOp:
16998e028780f2ba885f17f75ec6927f6d59cc90f37fcristy          {
17008e028780f2ba885f17f75ec6927f6d59cc90f37fcristy            pixel=Sc;
17018e028780f2ba885f17f75ec6927f6d59cc90f37fcristy            break;
17028e028780f2ba885f17f75ec6927f6d59cc90f37fcristy          }
1703e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case BumpmapCompositeOp:
1704e10859aa31abb52913175e089e5d25cbd670499fcristy          {
17053bdd925dbb0804df99e548c50667670319655816cristy            if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon)
1706e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
1707e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=Dc;
1708e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1709e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
1710e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            pixel=QuantumScale*GetPixelIntensity(source_image,p)*Dc;
1711e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1712e10859aa31abb52913175e089e5d25cbd670499fcristy          }
171399abff36ae5d479bfd76652d166a4894ceada102cristy          case ChangeMaskCompositeOp:
171499abff36ae5d479bfd76652d166a4894ceada102cristy          {
171599abff36ae5d479bfd76652d166a4894ceada102cristy            pixel=Dc;
171699abff36ae5d479bfd76652d166a4894ceada102cristy            break;
171799abff36ae5d479bfd76652d166a4894ceada102cristy          }
171899abff36ae5d479bfd76652d166a4894ceada102cristy          case ClearCompositeOp:
171999abff36ae5d479bfd76652d166a4894ceada102cristy          {
172099abff36ae5d479bfd76652d166a4894ceada102cristy            pixel=0.0;
172199abff36ae5d479bfd76652d166a4894ceada102cristy            break;
172299abff36ae5d479bfd76652d166a4894ceada102cristy          }
1723e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case ColorBurnCompositeOp:
1724e10859aa31abb52913175e089e5d25cbd670499fcristy          {
172530dac202caf1ded0e356ab1c2b67ec8d7929e06dcristy            if ((Sca == 0.0) && (Dca == Da))
1726e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
172795a92efd222d2268b66bf4fbb3bd5167437ba466cristy                pixel=QuantumRange*gamma*(Sa*Da+Dca*(1.0-Sa));
1728e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1729e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
173030dac202caf1ded0e356ab1c2b67ec8d7929e06dcristy            if (Sca == 0.0)
1731e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
173295a92efd222d2268b66bf4fbb3bd5167437ba466cristy                pixel=QuantumRange*gamma*(Dca*(1.0-Sa));
1733e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1734e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
173595a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Sa*Da-Sa*Da*MagickMin(1.0,(1.0-Dca/Da)*Sa/
173695a92efd222d2268b66bf4fbb3bd5167437ba466cristy              Sca)+Sca*(1.0-Da)+Dca*(1.0-Sa));
1737e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1738e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1739e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case ColorDodgeCompositeOp:
1740e10859aa31abb52913175e089e5d25cbd670499fcristy          {
17415379e0c0b6f55b8ac9f7c867b4234b6ec239545bdirk            if ((Sca*Da+Dca*Sa) >= Sa*Da)
17425379e0c0b6f55b8ac9f7c867b4234b6ec239545bdirk              pixel=QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
17435379e0c0b6f55b8ac9f7c867b4234b6ec239545bdirk            else
174489bfadafcca84f2839410175c63192cb2dc59111Cristy              pixel=QuantumRange*gamma*(Dca*Sa*Sa/(Sa-Sca)+Sca*(1.0-Da)+Dca*
174589bfadafcca84f2839410175c63192cb2dc59111Cristy                (1.0-Sa));
1746e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1747e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1748e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case ColorizeCompositeOp:
1749e10859aa31abb52913175e089e5d25cbd670499fcristy          {
17503bdd925dbb0804df99e548c50667670319655816cristy            if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon)
1751e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
1752e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=Dc;
1753e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1754e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
17553bdd925dbb0804df99e548c50667670319655816cristy            if (fabs((double) (QuantumRange*Da-TransparentAlpha)) < MagickEpsilon)
1756e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
1757e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=Sc;
1758e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1759e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
17602fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy            CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
17612fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy              &sans,&sans,&luma);
17627133e649ea494c1286ff16bcb02342d660097219cristy            CompositeHCL(source_pixel.red,source_pixel.green,source_pixel.blue,
17637133e649ea494c1286ff16bcb02342d660097219cristy              &hue,&chroma,&sans);
17647133e649ea494c1286ff16bcb02342d660097219cristy            HCLComposite(hue,chroma,luma,&red,&green,&blue);
1765e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            switch (channel)
1766e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            {
1767e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case RedPixelChannel: pixel=red; break;
1768e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case GreenPixelChannel: pixel=green; break;
1769e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case BluePixelChannel: pixel=blue; break;
1770e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              default: pixel=Dc; break;
1771e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            }
1772e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1773e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1774e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case CopyAlphaCompositeOp:
1775e10859aa31abb52913175e089e5d25cbd670499fcristy          {
177624d5d722cf4ba0767eb0d790e1b228a518d737cfcristy            pixel=Dc;
1777e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1778e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1779e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case CopyBlackCompositeOp:
1780e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1781d197cbbbde474ea2cbdd56d0defa45f100e44cd0cristy            if (channel == BlackPixelChannel)
17822fda00b7affa23c29e86e8218b7e1c5fe7785705cristy              pixel=(MagickRealType) (QuantumRange-
1783e8e8eff5f2414d6096195a41934fc0edee9d9212cristy                GetPixelBlack(source_image,p));
1784e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1785e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1786e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case CopyBlueCompositeOp:
1787e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case CopyYellowCompositeOp:
1788e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1789d197cbbbde474ea2cbdd56d0defa45f100e44cd0cristy            if (channel == BluePixelChannel)
1790e8e8eff5f2414d6096195a41934fc0edee9d9212cristy              pixel=(MagickRealType) GetPixelBlue(source_image,p);
1791e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1792e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1793e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case CopyGreenCompositeOp:
1794e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case CopyMagentaCompositeOp:
1795e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1796d197cbbbde474ea2cbdd56d0defa45f100e44cd0cristy            if (channel == GreenPixelChannel)
1797e8e8eff5f2414d6096195a41934fc0edee9d9212cristy              pixel=(MagickRealType) GetPixelGreen(source_image,p);
1798e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1799e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1800e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case CopyRedCompositeOp:
1801e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case CopyCyanCompositeOp:
1802e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1803d197cbbbde474ea2cbdd56d0defa45f100e44cd0cristy            if (channel == RedPixelChannel)
1804e8e8eff5f2414d6096195a41934fc0edee9d9212cristy              pixel=(MagickRealType) GetPixelRed(source_image,p);
1805e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1806e10859aa31abb52913175e089e5d25cbd670499fcristy          }
180799abff36ae5d479bfd76652d166a4894ceada102cristy          case DarkenCompositeOp:
180899abff36ae5d479bfd76652d166a4894ceada102cristy          {
180999abff36ae5d479bfd76652d166a4894ceada102cristy            /*
181099abff36ae5d479bfd76652d166a4894ceada102cristy              Darken is equivalent to a 'Minimum' method
181199abff36ae5d479bfd76652d166a4894ceada102cristy                OR a greyscale version of a binary 'Or'
181299abff36ae5d479bfd76652d166a4894ceada102cristy                OR the 'Intersection' of pixel sets.
181399abff36ae5d479bfd76652d166a4894ceada102cristy            */
181430dac202caf1ded0e356ab1c2b67ec8d7929e06dcristy            if ((Sca*Da) < (Dca*Sa))
181599abff36ae5d479bfd76652d166a4894ceada102cristy              {
1816e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy                pixel=QuantumRange*(Sca+Dca*(1.0-Sa));
181799abff36ae5d479bfd76652d166a4894ceada102cristy                break;
181899abff36ae5d479bfd76652d166a4894ceada102cristy              }
1819e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            pixel=QuantumRange*(Dca+Sca*(1.0-Da));
182099abff36ae5d479bfd76652d166a4894ceada102cristy            break;
182199abff36ae5d479bfd76652d166a4894ceada102cristy          }
1822e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case DarkenIntensityCompositeOp:
1823e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1824e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            pixel=Sa*GetPixelIntensity(source_image,p) <
1825076d0c9a787cf3054f29089d5bced8b08b606b94cristy              Da*GetPixelIntensity(image,q) ? Sc : Dc;
1826e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1827e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1828e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case DifferenceCompositeOp:
1829e10859aa31abb52913175e089e5d25cbd670499fcristy          {
183095a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Sca+Dca-2.0*MagickMin(Sca*Da,Dca*Sa));
1831e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1832e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1833e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case DissolveCompositeOp:
1834e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1835e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            pixel=gamma*(source_dissolve*Sa*Sc-source_dissolve*Sa*
1836e8e8eff5f2414d6096195a41934fc0edee9d9212cristy              canvas_dissolve*Da*Dc+canvas_dissolve*Da*Dc);
1837e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1838e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1839e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case DivideDstCompositeOp:
1840e10859aa31abb52913175e089e5d25cbd670499fcristy          {
18413bdd925dbb0804df99e548c50667670319655816cristy            if ((fabs((double) Sca) < MagickEpsilon) &&
18423bdd925dbb0804df99e548c50667670319655816cristy                (fabs((double) Dca) < MagickEpsilon))
1843e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
184495a92efd222d2268b66bf4fbb3bd5167437ba466cristy                pixel=QuantumRange*gamma*(Sca*(1.0-Da)+Dca*(1.0-Sa));
1845e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1846e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
18473bdd925dbb0804df99e548c50667670319655816cristy            if (fabs((double) Dca) < MagickEpsilon)
1848e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
184995a92efd222d2268b66bf4fbb3bd5167437ba466cristy                pixel=QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
1850e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1851e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
185295a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Sca*Da*Da/Dca+Sca*(1.0-Da)+Dca*(1.0-Sa));
1853e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1854e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1855e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case DivideSrcCompositeOp:
1856e10859aa31abb52913175e089e5d25cbd670499fcristy          {
18573bdd925dbb0804df99e548c50667670319655816cristy            if ((fabs((double) Dca) < MagickEpsilon) &&
18583bdd925dbb0804df99e548c50667670319655816cristy                (fabs((double) Sca) < MagickEpsilon))
1859e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
186095a92efd222d2268b66bf4fbb3bd5167437ba466cristy                pixel=QuantumRange*gamma*(Dca*(1.0-Sa)+Sca*(1.0-Da));
1861e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1862e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
18633bdd925dbb0804df99e548c50667670319655816cristy            if (fabs((double) Sca) < MagickEpsilon)
1864e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
186595a92efd222d2268b66bf4fbb3bd5167437ba466cristy                pixel=QuantumRange*gamma*(Da*Sa+Dca*(1.0-Sa)+Sca*(1.0-Da));
1866e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1867e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
186895a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Dca*Sa*Sa/Sca+Dca*(1.0-Sa)+Sca*(1.0-Da));
1869e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1870e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1871e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case DstAtopCompositeOp:
1872e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1873e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            pixel=QuantumRange*(Dca*Sa+Sca*(1.0-Da));
1874e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1875e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1876e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case DstCompositeOp:
1877e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case NoCompositeOp:
1878e10859aa31abb52913175e089e5d25cbd670499fcristy          {
187930dac202caf1ded0e356ab1c2b67ec8d7929e06dcristy            pixel=QuantumRange*Dca;
1880e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1881e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1882e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case DstInCompositeOp:
1883e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1884e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            pixel=QuantumRange*(Dca*Sa);
1885e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1886e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1887e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case DstOutCompositeOp:
1888e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1889e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            pixel=QuantumRange*(Dca*(1.0-Sa));
1890e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1891e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1892e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case DstOverCompositeOp:
1893e10859aa31abb52913175e089e5d25cbd670499fcristy          {
189495a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Dca+Sca*(1.0-Da));
1895e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1896e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1897e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case ExclusionCompositeOp:
1898e10859aa31abb52913175e089e5d25cbd670499fcristy          {
189995a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Sca*Da+Dca*Sa-2.0*Sca*Dca+Sca*(1.0-Da)+
190095a92efd222d2268b66bf4fbb3bd5167437ba466cristy              Dca*(1.0-Sa));
1901e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1902e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1903e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case HardLightCompositeOp:
1904e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1905e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            if ((2.0*Sca) < Sa)
1906e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
190795a92efd222d2268b66bf4fbb3bd5167437ba466cristy                pixel=QuantumRange*gamma*(2.0*Sca*Dca+Sca*(1.0-Da)+Dca*(1.0-
190895a92efd222d2268b66bf4fbb3bd5167437ba466cristy                  Sa));
1909e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1910e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
191195a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Sa*Da-2.0*(Da-Dca)*(Sa-Sca)+Sca*(1.0-Da)+
191295a92efd222d2268b66bf4fbb3bd5167437ba466cristy              Dca*(1.0-Sa));
191399fc217dffe2ed10ebefd0ac85900df37b60e3fdcristy            break;
191499fc217dffe2ed10ebefd0ac85900df37b60e3fdcristy          }
191599fc217dffe2ed10ebefd0ac85900df37b60e3fdcristy          case HardMixCompositeOp:
191699fc217dffe2ed10ebefd0ac85900df37b60e3fdcristy          {
19171749597845aafe5e61783d9a1b43d333f7071ccddirk            pixel=gamma*(((Sca+Dca) < 1.0) ? 0.0 : QuantumRange);
1918e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1919e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1920e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case HueCompositeOp:
1921e10859aa31abb52913175e089e5d25cbd670499fcristy          {
19223bdd925dbb0804df99e548c50667670319655816cristy            if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon)
1923e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
1924e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=Dc;
1925e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1926e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
19273bdd925dbb0804df99e548c50667670319655816cristy            if (fabs((double) (QuantumRange*Da-TransparentAlpha)) < MagickEpsilon)
1928e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
1929e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=Sc;
1930e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1931e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
19322fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy            CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
19332fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy              &hue,&chroma,&luma);
19347133e649ea494c1286ff16bcb02342d660097219cristy            CompositeHCL(source_pixel.red,source_pixel.green,source_pixel.blue,
1935e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              &hue,&sans,&sans);
19367133e649ea494c1286ff16bcb02342d660097219cristy            HCLComposite(hue,chroma,luma,&red,&green,&blue);
1937e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            switch (channel)
1938e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            {
1939e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case RedPixelChannel: pixel=red; break;
1940e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case GreenPixelChannel: pixel=green; break;
1941e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case BluePixelChannel: pixel=blue; break;
1942e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              default: pixel=Dc; break;
1943e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            }
1944e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1945e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1946e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case InCompositeOp:
1947e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case SrcInCompositeOp:
1948e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1949e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            pixel=QuantumRange*(Sca*Da);
1950e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1951e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1952e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case LinearBurnCompositeOp:
1953e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1954e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            /*
1955e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              LinearBurn: as defined by Abode Photoshop, according to
1956e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              http://www.simplefilter.de/en/basics/mixmods.html is:
1957e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
1958e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                f(Sc,Dc) = Sc + Dc - 1
1959e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            */
196095a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Sca+Dca-Sa*Da);
1961e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1962e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1963e10859aa31abb52913175e089e5d25cbd670499fcristy          case LinearDodgeCompositeOp:
1964e10859aa31abb52913175e089e5d25cbd670499fcristy          {
196595a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=gamma*(Sa*Sc+Da*Dc);
1966e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1967e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1968e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case LinearLightCompositeOp:
1969e10859aa31abb52913175e089e5d25cbd670499fcristy          {
1970e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            /*
1971e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              LinearLight: as defined by Abode Photoshop, according to
1972e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              http://www.simplefilter.de/en/basics/mixmods.html is:
1973e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
1974e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                f(Sc,Dc) = Dc + 2*Sc - 1
1975e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            */
197695a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*((Sca-Sa)*Da+Sca+Dca);
1977e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1978e10859aa31abb52913175e089e5d25cbd670499fcristy          }
1979e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case LightenCompositeOp:
1980e10859aa31abb52913175e089e5d25cbd670499fcristy          {
198130dac202caf1ded0e356ab1c2b67ec8d7929e06dcristy            if ((Sca*Da) > (Dca*Sa))
1982e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
1983e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy                pixel=QuantumRange*(Sca+Dca*(1.0-Sa));
1984e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
1985e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
1986e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            pixel=QuantumRange*(Dca+Sca*(1.0-Da));
198799abff36ae5d479bfd76652d166a4894ceada102cristy            break;
198899abff36ae5d479bfd76652d166a4894ceada102cristy          }
198999abff36ae5d479bfd76652d166a4894ceada102cristy          case LightenIntensityCompositeOp:
199099abff36ae5d479bfd76652d166a4894ceada102cristy          {
199199abff36ae5d479bfd76652d166a4894ceada102cristy            /*
199299abff36ae5d479bfd76652d166a4894ceada102cristy              Lighten is equivalent to a 'Maximum' method
199399abff36ae5d479bfd76652d166a4894ceada102cristy                OR a greyscale version of a binary 'And'
199499abff36ae5d479bfd76652d166a4894ceada102cristy                OR the 'Union' of pixel sets.
199599abff36ae5d479bfd76652d166a4894ceada102cristy            */
1996e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            pixel=Sa*GetPixelIntensity(source_image,p) >
199799abff36ae5d479bfd76652d166a4894ceada102cristy              Da*GetPixelIntensity(image,q) ? Sc : Dc;
1998e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
1999e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2000e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case LuminizeCompositeOp:
2001e10859aa31abb52913175e089e5d25cbd670499fcristy          {
20023bdd925dbb0804df99e548c50667670319655816cristy            if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon)
2003e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
2004e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=Dc;
2005e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
2006e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
20073bdd925dbb0804df99e548c50667670319655816cristy            if (fabs((double) (QuantumRange*Da-TransparentAlpha)) < MagickEpsilon)
2008e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
2009e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=Sc;
2010e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
2011e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
20122fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy            CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
20132fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy              &hue,&chroma,&luma);
20147133e649ea494c1286ff16bcb02342d660097219cristy            CompositeHCL(source_pixel.red,source_pixel.green,source_pixel.blue,
20157133e649ea494c1286ff16bcb02342d660097219cristy              &sans,&sans,&luma);
20167133e649ea494c1286ff16bcb02342d660097219cristy            HCLComposite(hue,chroma,luma,&red,&green,&blue);
2017e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            switch (channel)
2018e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            {
2019e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case RedPixelChannel: pixel=red; break;
2020e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case GreenPixelChannel: pixel=green; break;
2021e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case BluePixelChannel: pixel=blue; break;
2022e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              default: pixel=Dc; break;
2023e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            }
2024e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2025e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2026e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case MathematicsCompositeOp:
2027e10859aa31abb52913175e089e5d25cbd670499fcristy          {
2028e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            /*
2029e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              'Mathematics' a free form user control mathematical composition
2030e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              is defined as...
2031e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
2032e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                f(Sc,Dc) = A*Sc*Dc + B*Sc + C*Dc + D
2033e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
2034e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              Where the arguments A,B,C,D are (currently) passed to composite
2035e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              as a command separated 'geometry' string in "compose:args" image
2036e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              artifact.
2037e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
2038e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                 A = a->rho,   B = a->sigma,  C = a->xi,  D = a->psi
2039e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
2040e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              Applying the SVG transparency formula (see above), we get...
2041e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
2042e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy               Dca' = Sa*Da*f(Sc,Dc) + Sca*(1.0-Da) + Dca*(1.0-Sa)
2043e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
2044e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy               Dca' = A*Sca*Dca + B*Sca*Da + C*Dca*Sa + D*Sa*Da + Sca*(1.0-Da) +
2045e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                 Dca*(1.0-Sa)
2046e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            */
204793af61fba92ced57cbbb2b13ff1a026c9bb1e1cdcristy            pixel=QuantumRange*gamma*(geometry_info.rho*Sca*Dca+
2048744051e2f5398cc1a8f6c1154f4c419dcf996a3dcristy              geometry_info.sigma*Sca*Da+geometry_info.xi*Dca*Sa+
2049744051e2f5398cc1a8f6c1154f4c419dcf996a3dcristy              geometry_info.psi*Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
2050e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2051e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2052e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case MinusDstCompositeOp:
2053e10859aa31abb52913175e089e5d25cbd670499fcristy          {
2054ecf950212ff9019e8778789d0f83722b320c6519cristy            pixel=gamma*(Sa*Sc+Da*Dc-2.0*Da*Dc*Sa);
2055e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2056e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2057e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case MinusSrcCompositeOp:
2058e10859aa31abb52913175e089e5d25cbd670499fcristy          {
2059e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            /*
2060e8e8eff5f2414d6096195a41934fc0edee9d9212cristy              Minus source from canvas.
2061e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
2062e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                f(Sc,Dc) = Sc - Dc
2063e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            */
2064ecf950212ff9019e8778789d0f83722b320c6519cristy            pixel=gamma*(Da*Dc+Sa*Sc-2.0*Sa*Sc*Da);
2065e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2066e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2067e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case ModulateCompositeOp:
2068e10859aa31abb52913175e089e5d25cbd670499fcristy          {
2069e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            ssize_t
2070e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              offset;
2071e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
20723bdd925dbb0804df99e548c50667670319655816cristy            if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon)
2073e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
2074e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=Dc;
2075e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
2076e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
2077e8e8eff5f2414d6096195a41934fc0edee9d9212cristy            offset=(ssize_t) (GetPixelIntensity(source_image,p)-midpoint);
2078e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            if (offset == 0)
2079e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
2080e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=Dc;
2081e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
2082e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
20832fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy            CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
20842fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy              &hue,&chroma,&luma);
20857133e649ea494c1286ff16bcb02342d660097219cristy            luma+=(0.01*percent_luma*offset)/midpoint;
20867133e649ea494c1286ff16bcb02342d660097219cristy            chroma*=0.01*percent_chroma;
20877133e649ea494c1286ff16bcb02342d660097219cristy            HCLComposite(hue,chroma,luma,&red,&green,&blue);
2088e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            switch (channel)
2089e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            {
2090e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case RedPixelChannel: pixel=red; break;
2091e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case GreenPixelChannel: pixel=green; break;
2092e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case BluePixelChannel: pixel=blue; break;
2093e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              default: pixel=Dc; break;
2094e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            }
2095e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2096e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2097e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case ModulusAddCompositeOp:
2098e10859aa31abb52913175e089e5d25cbd670499fcristy          {
2099e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            pixel=Sc+Dc;
2100b0c753681b67213741db6355930bf4a6881170dfCristy            while (pixel > QuantumRange)
2101516edc171c30bf475761914bcc3db3a6e298e103cristy              pixel-=QuantumRange;
2102b0c753681b67213741db6355930bf4a6881170dfCristy            while (pixel < 0.0)
2103b0c753681b67213741db6355930bf4a6881170dfCristy              pixel+=QuantumRange;
21047a91a5e606a33d0624d750e50a04b6fa9b995199cristy            pixel=(Sa*Da*pixel+Sa*Sc*(1.0-Da)+Da*Dc*(1.0-Sa));
2105e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2106e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2107e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case ModulusSubtractCompositeOp:
2108e10859aa31abb52913175e089e5d25cbd670499fcristy          {
210999abff36ae5d479bfd76652d166a4894ceada102cristy            pixel=Sc-Dc;
2110b0c753681b67213741db6355930bf4a6881170dfCristy            while (pixel > QuantumRange)
2111b0c753681b67213741db6355930bf4a6881170dfCristy              pixel-=QuantumRange;
2112b0c753681b67213741db6355930bf4a6881170dfCristy            while (pixel < 0.0)
2113516edc171c30bf475761914bcc3db3a6e298e103cristy              pixel+=QuantumRange;
21147a91a5e606a33d0624d750e50a04b6fa9b995199cristy            pixel=(Sa*Da*pixel+Sa*Sc*(1.0-Da)+Da*Dc*(1.0-Sa));
2115e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2116e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2117e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case MultiplyCompositeOp:
2118e10859aa31abb52913175e089e5d25cbd670499fcristy          {
211995a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Sca*Dca+Sca*(1.0-Da)+Dca*(1.0-Sa));
21203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2121e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2122e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case OutCompositeOp:
2123e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case SrcOutCompositeOp:
2124e10859aa31abb52913175e089e5d25cbd670499fcristy          {
2125e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            pixel=QuantumRange*(Sca*(1.0-Da));
2126e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2127e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2128e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case OverCompositeOp:
2129e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case SrcOverCompositeOp:
2130e10859aa31abb52913175e089e5d25cbd670499fcristy          {
213195a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Sca+Dca*(1.0-Sa));
2132e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2133e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2134e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case OverlayCompositeOp:
2135e10859aa31abb52913175e089e5d25cbd670499fcristy          {
21360bd8cb4808b9ff3811fc4a73cae38e061f8a96ffdirk            if ((2.0*Dca) < Da)
213799abff36ae5d479bfd76652d166a4894ceada102cristy              {
21380bd8cb4808b9ff3811fc4a73cae38e061f8a96ffdirk                pixel=QuantumRange*gamma*(2.0*Dca*Sca+Dca*(1.0-Sa)+Sca*(1.0-
21390bd8cb4808b9ff3811fc4a73cae38e061f8a96ffdirk                  Da));
214099abff36ae5d479bfd76652d166a4894ceada102cristy                break;
214199abff36ae5d479bfd76652d166a4894ceada102cristy              }
21420bd8cb4808b9ff3811fc4a73cae38e061f8a96ffdirk            pixel=QuantumRange*gamma*(Da*Sa-2.0*(Sa-Sca)*(Da-Dca)+Dca*(1.0-Sa)+
21430bd8cb4808b9ff3811fc4a73cae38e061f8a96ffdirk              Sca*(1.0-Da));
2144e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2145e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2146e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case PegtopLightCompositeOp:
2147e10859aa31abb52913175e089e5d25cbd670499fcristy          {
2148e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            /*
2149e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              PegTop: A Soft-Light alternative: A continuous version of the
2150e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              Softlight function, producing very similar results.
2151e10859aa31abb52913175e089e5d25cbd670499fcristy
2152e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                f(Sc,Dc) = Dc^2*(1-2*Sc) + 2*Sc*Dc
2153e10859aa31abb52913175e089e5d25cbd670499fcristy
2154e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              http://www.pegtop.net/delphi/articles/blendmodes/softlight.htm.
2155e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            */
21563bdd925dbb0804df99e548c50667670319655816cristy            if (fabs((double) Da) < MagickEpsilon)
2157e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
215895a92efd222d2268b66bf4fbb3bd5167437ba466cristy                pixel=QuantumRange*gamma*(Sca);
2159e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
2160e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
216195a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Dca*Dca*(Sa-2.0*Sca)/Da+Sca*(2.0*Dca+1.0-
216295a92efd222d2268b66bf4fbb3bd5167437ba466cristy              Da)+Dca*(1.0-Sa));
21633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2164e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2165e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case PinLightCompositeOp:
2166e10859aa31abb52913175e089e5d25cbd670499fcristy          {
2167e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            /*
2168e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              PinLight: A Photoshop 7 composition method
2169e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              http://www.simplefilter.de/en/basics/mixmods.html
2170e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
2171e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                f(Sc,Dc) = Dc<2*Sc-1 ? 2*Sc-1 : Dc>2*Sc   ? 2*Sc : Dc
2172e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            */
2173e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            if ((Dca*Sa) < (Da*(2.0*Sca-Sa)))
2174e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
217595a92efd222d2268b66bf4fbb3bd5167437ba466cristy                pixel=QuantumRange*gamma*(Sca*(Da+1.0)-Sa*Da+Dca*(1.0-Sa));
2176e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
2177e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
2178e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            if ((Dca*Sa) > (2.0*Sca*Da))
2179e10859aa31abb52913175e089e5d25cbd670499fcristy              {
218095a92efd222d2268b66bf4fbb3bd5167437ba466cristy                pixel=QuantumRange*gamma*(Sca*Da+Sca+Dca*(1.0-Sa));
2181e10859aa31abb52913175e089e5d25cbd670499fcristy                break;
2182e10859aa31abb52913175e089e5d25cbd670499fcristy              }
218395a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Sca*(1.0-Da)+Dca);
2184e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            break;
2185e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          }
2186e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case PlusCompositeOp:
2187e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          {
2188e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            pixel=QuantumRange*(Sca+Dca);
21893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
2190e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2191e10859aa31abb52913175e089e5d25cbd670499fcristy          case SaturateCompositeOp:
2192e10859aa31abb52913175e089e5d25cbd670499fcristy          {
21933bdd925dbb0804df99e548c50667670319655816cristy            if (fabs((double) (QuantumRange*Sa-TransparentAlpha)) < MagickEpsilon)
2194e10859aa31abb52913175e089e5d25cbd670499fcristy              {
2195e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=Dc;
2196e10859aa31abb52913175e089e5d25cbd670499fcristy                break;
2197e10859aa31abb52913175e089e5d25cbd670499fcristy              }
21983bdd925dbb0804df99e548c50667670319655816cristy            if (fabs((double) (QuantumRange*Da-TransparentAlpha)) < MagickEpsilon)
2199e10859aa31abb52913175e089e5d25cbd670499fcristy              {
2200e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=Sc;
2201e10859aa31abb52913175e089e5d25cbd670499fcristy                break;
2202e10859aa31abb52913175e089e5d25cbd670499fcristy              }
22032fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy            CompositeHCL(canvas_pixel.red,canvas_pixel.green,canvas_pixel.blue,
22042fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy              &hue,&chroma,&luma);
22057133e649ea494c1286ff16bcb02342d660097219cristy            CompositeHCL(source_pixel.red,source_pixel.green,source_pixel.blue,
22067133e649ea494c1286ff16bcb02342d660097219cristy              &sans,&chroma,&sans);
22077133e649ea494c1286ff16bcb02342d660097219cristy            HCLComposite(hue,chroma,luma,&red,&green,&blue);
2208e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            switch (channel)
2209e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            {
2210e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case RedPixelChannel: pixel=red; break;
2211e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case GreenPixelChannel: pixel=green; break;
2212e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              case BluePixelChannel: pixel=blue; break;
2213e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              default: pixel=Dc; break;
2214e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            }
2215e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2216e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2217e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case ScreenCompositeOp:
2218e10859aa31abb52913175e089e5d25cbd670499fcristy          {
2219e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            /*
2220e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              Screen:  a negated multiply:
2221e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
2222e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                f(Sc,Dc) = 1.0-(1.0-Sc)*(1.0-Dc)
2223e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            */
222495a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Sca+Dca-Sca*Dca);
2225e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2226e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2227e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case SoftLightCompositeOp:
2228e10859aa31abb52913175e089e5d25cbd670499fcristy          {
2229e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            if ((2.0*Sca) < Sa)
2230e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
223195a92efd222d2268b66bf4fbb3bd5167437ba466cristy                pixel=QuantumRange*gamma*(Dca*(Sa+(2.0*Sca-Sa)*(1.0-(Dca/Da)))+
223295a92efd222d2268b66bf4fbb3bd5167437ba466cristy                  Sca*(1.0-Da)+Dca*(1.0-Sa));
2233e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
2234e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
2235e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            if (((2.0*Sca) > Sa) && ((4.0*Dca) <= Da))
2236e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
223795a92efd222d2268b66bf4fbb3bd5167437ba466cristy                pixel=QuantumRange*gamma*(Dca*Sa+Da*(2.0*Sca-Sa)*(4.0*(Dca/Da)*
223895a92efd222d2268b66bf4fbb3bd5167437ba466cristy                  (4.0*(Dca/Da)+1.0)*((Dca/Da)-1.0)+7.0*(Dca/Da))+Sca*(1.0-Da)+
223995a92efd222d2268b66bf4fbb3bd5167437ba466cristy                  Dca*(1.0-Sa));
2240e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
2241e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
224295a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Dca*Sa+Da*(2.0*Sca-Sa)*(pow((Dca/Da),0.5)-
224395a92efd222d2268b66bf4fbb3bd5167437ba466cristy              (Dca/Da))+Sca*(1.0-Da)+Dca*(1.0-Sa));
2244e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2245e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2246e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case ThresholdCompositeOp:
2247e10859aa31abb52913175e089e5d25cbd670499fcristy          {
22487159f66759ae05f052aad309915b9784f7aca927cristy            MagickRealType
2249e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              delta;
2250e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
2251e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            delta=Sc-Dc;
22527159f66759ae05f052aad309915b9784f7aca927cristy            if ((MagickRealType) fabs((double) (2.0*delta)) < threshold)
2253e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
2254e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                pixel=gamma*Dc;
2255e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
2256e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
2257e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            pixel=gamma*(Dc+delta*amount);
2258e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2259e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2260e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case VividLightCompositeOp:
2261e10859aa31abb52913175e089e5d25cbd670499fcristy          {
2262e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            /*
2263e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              VividLight: A Photoshop 7 composition method.  See
2264e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              http://www.simplefilter.de/en/basics/mixmods.html.
2265e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy
2266e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                f(Sc,Dc) = (2*Sc < 1) ? 1-(1-Dc)/(2*Sc) : Dc/(2*(1-Sc))
2267e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            */
22683bdd925dbb0804df99e548c50667670319655816cristy            if ((fabs((double) Sa) < MagickEpsilon) ||
22693bdd925dbb0804df99e548c50667670319655816cristy                (fabs((double) (Sca-Sa)) < MagickEpsilon))
2270e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              {
227195a92efd222d2268b66bf4fbb3bd5167437ba466cristy                pixel=QuantumRange*gamma*(Sa*Da+Sca*(1.0-Da)+Dca*(1.0-Sa));
2272e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy                break;
2273e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy              }
2274e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            if ((2.0*Sca) <= Sa)
2275e10859aa31abb52913175e089e5d25cbd670499fcristy              {
227695a92efd222d2268b66bf4fbb3bd5167437ba466cristy                pixel=QuantumRange*gamma*(Sa*(Da+Sa*(Dca-Da)/(2.0*Sca))+Sca*
227795a92efd222d2268b66bf4fbb3bd5167437ba466cristy                  (1.0-Da)+Dca*(1.0-Sa));
2278e10859aa31abb52913175e089e5d25cbd670499fcristy                break;
2279e10859aa31abb52913175e089e5d25cbd670499fcristy              }
228095a92efd222d2268b66bf4fbb3bd5167437ba466cristy            pixel=QuantumRange*gamma*(Dca*Sa*Sa/(2.0*(Sa-Sca))+Sca*(1.0-Da)+Dca*
2281e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy              (1.0-Sa));
2282e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2283e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2284e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          case XorCompositeOp:
2285e10859aa31abb52913175e089e5d25cbd670499fcristy          {
2286e224ed7f0f18bb06d91c18aea7919de623fbd8b3cristy            pixel=QuantumRange*(Sca*(1.0-Da)+Dca*(1.0-Sa));
2287e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2288e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2289e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy          default:
2290e10859aa31abb52913175e089e5d25cbd670499fcristy          {
2291e4a404711bf20d9062d11ab28bc12e5acd307f9ccristy            pixel=Sc;
2292e10859aa31abb52913175e089e5d25cbd670499fcristy            break;
2293e10859aa31abb52913175e089e5d25cbd670499fcristy          }
2294c5d68fe2846b7ed7b866c8a5d9287264d75458caanthony        }
229547c61c996128275174b8a120ab6a88a5c1bec3d3cristy        q[i]=clamp != MagickFalse ? ClampPixel(pixel) : ClampToQuantum(pixel);
22963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
2297e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      p+=GetPixelChannels(source_image);
2298e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      channels=GetPixelChannels(source_image);
2299e8e8eff5f2414d6096195a41934fc0edee9d9212cristy      if (p >= (pixels+channels*source_image->columns))
23003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p=pixels;
2301ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      q+=GetPixelChannels(image);
23023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
23033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
23043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      status=MagickFalse;
23053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (image->progress_monitor != (MagickProgressMonitor) NULL)
23063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
23073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        MagickBooleanType
23083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          proceed;
23093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2310b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
2311bd0435bb0fa5e2e20ec8d3c5288a5edc44aba9a0cristy        #pragma omp critical (MagickCore_CompositeImage)
23123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
23133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        proceed=SetImageProgress(image,CompositeImageTag,progress++,
23143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image->rows);
23153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (proceed == MagickFalse)
23163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=MagickFalse;
23173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
23183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
2319e8e8eff5f2414d6096195a41934fc0edee9d9212cristy  source_view=DestroyCacheView(source_view);
23203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image_view=DestroyCacheView(image_view);
2321e8e8eff5f2414d6096195a41934fc0edee9d9212cristy  if (canvas_image != (Image * ) NULL)
2322e8e8eff5f2414d6096195a41934fc0edee9d9212cristy    canvas_image=DestroyImage(canvas_image);
2323f661c4d04693ffdf83b5a8a300a9ac4a38a9c762cristy  else
2324e8e8eff5f2414d6096195a41934fc0edee9d9212cristy    source_image=DestroyImage(source_image);
23253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
23263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
2327316d51773c093e74e15de805e8bf620d6b56bc8bcristy
2328316d51773c093e74e15de805e8bf620d6b56bc8bcristy/*
2329316d51773c093e74e15de805e8bf620d6b56bc8bcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2330316d51773c093e74e15de805e8bf620d6b56bc8bcristy%                                                                             %
2331316d51773c093e74e15de805e8bf620d6b56bc8bcristy%                                                                             %
2332316d51773c093e74e15de805e8bf620d6b56bc8bcristy%                                                                             %
2333316d51773c093e74e15de805e8bf620d6b56bc8bcristy%     T e x t u r e I m a g e                                                 %
2334316d51773c093e74e15de805e8bf620d6b56bc8bcristy%                                                                             %
2335316d51773c093e74e15de805e8bf620d6b56bc8bcristy%                                                                             %
2336316d51773c093e74e15de805e8bf620d6b56bc8bcristy%                                                                             %
2337316d51773c093e74e15de805e8bf620d6b56bc8bcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2338316d51773c093e74e15de805e8bf620d6b56bc8bcristy%
2339316d51773c093e74e15de805e8bf620d6b56bc8bcristy%  TextureImage() repeatedly tiles the texture image across and down the image
2340316d51773c093e74e15de805e8bf620d6b56bc8bcristy%  canvas.
2341316d51773c093e74e15de805e8bf620d6b56bc8bcristy%
2342316d51773c093e74e15de805e8bf620d6b56bc8bcristy%  The format of the TextureImage method is:
2343316d51773c093e74e15de805e8bf620d6b56bc8bcristy%
234430d8c94aa45a8a386d4ce3b3340ddfed3aa2421ecristy%      MagickBooleanType TextureImage(Image *image,const Image *texture,
2345e941a75fe8bf344bc5c06a7f74bb5173c87db115cristy%        ExceptionInfo *exception)
2346316d51773c093e74e15de805e8bf620d6b56bc8bcristy%
2347316d51773c093e74e15de805e8bf620d6b56bc8bcristy%  A description of each parameter follows:
2348316d51773c093e74e15de805e8bf620d6b56bc8bcristy%
2349316d51773c093e74e15de805e8bf620d6b56bc8bcristy%    o image: the image.
2350316d51773c093e74e15de805e8bf620d6b56bc8bcristy%
2351e6178503e4d6d3260666d42080d6f02545413685cristy%    o texture_image: This image is the texture to layer on the background.
2352316d51773c093e74e15de805e8bf620d6b56bc8bcristy%
2353316d51773c093e74e15de805e8bf620d6b56bc8bcristy*/
235430d8c94aa45a8a386d4ce3b3340ddfed3aa2421ecristyMagickExport MagickBooleanType TextureImage(Image *image,const Image *texture,
235530d8c94aa45a8a386d4ce3b3340ddfed3aa2421ecristy  ExceptionInfo *exception)
2356316d51773c093e74e15de805e8bf620d6b56bc8bcristy{
2357316d51773c093e74e15de805e8bf620d6b56bc8bcristy#define TextureImageTag  "Texture/Image"
2358316d51773c093e74e15de805e8bf620d6b56bc8bcristy
2359fcb1a668b974425a0378c278db25aca29ec70894cristy  CacheView
2360fcb1a668b974425a0378c278db25aca29ec70894cristy    *image_view,
2361fcb1a668b974425a0378c278db25aca29ec70894cristy    *texture_view;
2362fcb1a668b974425a0378c278db25aca29ec70894cristy
236330d8c94aa45a8a386d4ce3b3340ddfed3aa2421ecristy  Image
236430d8c94aa45a8a386d4ce3b3340ddfed3aa2421ecristy    *texture_image;
236530d8c94aa45a8a386d4ce3b3340ddfed3aa2421ecristy
2366fcb1a668b974425a0378c278db25aca29ec70894cristy  MagickBooleanType
2367316d51773c093e74e15de805e8bf620d6b56bc8bcristy    status;
2368316d51773c093e74e15de805e8bf620d6b56bc8bcristy
23699d314ff2c17a77996c05413c2013880387e50f0ecristy  ssize_t
23709d314ff2c17a77996c05413c2013880387e50f0ecristy    y;
23719d314ff2c17a77996c05413c2013880387e50f0ecristy
2372316d51773c093e74e15de805e8bf620d6b56bc8bcristy  assert(image != (Image *) NULL);
2373316d51773c093e74e15de805e8bf620d6b56bc8bcristy  if (image->debug != MagickFalse)
2374316d51773c093e74e15de805e8bf620d6b56bc8bcristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2375e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
237630d8c94aa45a8a386d4ce3b3340ddfed3aa2421ecristy  if (texture == (const Image *) NULL)
237730d8c94aa45a8a386d4ce3b3340ddfed3aa2421ecristy    return(MagickFalse);
237830d8c94aa45a8a386d4ce3b3340ddfed3aa2421ecristy  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
237930d8c94aa45a8a386d4ce3b3340ddfed3aa2421ecristy    return(MagickFalse);
238030d8c94aa45a8a386d4ce3b3340ddfed3aa2421ecristy  texture_image=CloneImage(texture,0,0,MagickTrue,exception);
2381e6178503e4d6d3260666d42080d6f02545413685cristy  if (texture_image == (const Image *) NULL)
2382316d51773c093e74e15de805e8bf620d6b56bc8bcristy    return(MagickFalse);
2383a865ccd68cbccfdf00a5fdd40bc491c5f5390303cristy  (void) TransformImageColorspace(texture_image,image->colorspace,exception);
2384387430f111ba7864990ca03fbc89968e20074ecdcristy  (void) SetImageVirtualPixelMethod(texture_image,TileVirtualPixelMethod,
2385387430f111ba7864990ca03fbc89968e20074ecdcristy    exception);
2386fcb1a668b974425a0378c278db25aca29ec70894cristy  status=MagickTrue;
2387fcb1a668b974425a0378c278db25aca29ec70894cristy  if ((image->compose != CopyCompositeOp) &&
2388974a2a89b5345623d899221fc6bb3b82ca97b10fcristy      ((image->compose != OverCompositeOp) ||
238917f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy       (image->alpha_trait != UndefinedPixelTrait) ||
239017f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy       (texture_image->alpha_trait != UndefinedPixelTrait)))
2391fcb1a668b974425a0378c278db25aca29ec70894cristy    {
2392fcb1a668b974425a0378c278db25aca29ec70894cristy      /*
2393fcb1a668b974425a0378c278db25aca29ec70894cristy        Tile texture onto the image background.
2394fcb1a668b974425a0378c278db25aca29ec70894cristy      */
2395e6178503e4d6d3260666d42080d6f02545413685cristy      for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) texture_image->rows)
2396fcb1a668b974425a0378c278db25aca29ec70894cristy      {
2397bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        register ssize_t
2398fcb1a668b974425a0378c278db25aca29ec70894cristy          x;
239982b1583d4ca9179180de2754e6c25eef115cc181cristy
2400fcb1a668b974425a0378c278db25aca29ec70894cristy        if (status == MagickFalse)
2401fcb1a668b974425a0378c278db25aca29ec70894cristy          continue;
2402e6178503e4d6d3260666d42080d6f02545413685cristy        for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
2403fcb1a668b974425a0378c278db25aca29ec70894cristy        {
2404fcb1a668b974425a0378c278db25aca29ec70894cristy          MagickBooleanType
2405fcb1a668b974425a0378c278db25aca29ec70894cristy            thread_status;
240682b1583d4ca9179180de2754e6c25eef115cc181cristy
2407feb3e9695150978a5d2372d3fe2f60466a7c8066cristy          thread_status=CompositeImage(image,texture_image,image->compose,
24083de10e80ee511dd3e9e2eaa6a5d45b1d46ffe13cCristy            MagickTrue,x+texture_image->tile_offset.x,y+
2409feb3e9695150978a5d2372d3fe2f60466a7c8066cristy            texture_image->tile_offset.y,exception);
2410fcb1a668b974425a0378c278db25aca29ec70894cristy          if (thread_status == MagickFalse)
2411fcb1a668b974425a0378c278db25aca29ec70894cristy            {
2412fcb1a668b974425a0378c278db25aca29ec70894cristy              status=thread_status;
2413fcb1a668b974425a0378c278db25aca29ec70894cristy              break;
2414fcb1a668b974425a0378c278db25aca29ec70894cristy            }
2415fcb1a668b974425a0378c278db25aca29ec70894cristy        }
2416fcb1a668b974425a0378c278db25aca29ec70894cristy        if (image->progress_monitor != (MagickProgressMonitor) NULL)
2417fcb1a668b974425a0378c278db25aca29ec70894cristy          {
2418fcb1a668b974425a0378c278db25aca29ec70894cristy            MagickBooleanType
2419fcb1a668b974425a0378c278db25aca29ec70894cristy              proceed;
242082b1583d4ca9179180de2754e6c25eef115cc181cristy
24212fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy            proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
24222fb92284dc08cba0f635ccced4635f9b8f71fcf7cristy              image->rows);
2423fcb1a668b974425a0378c278db25aca29ec70894cristy            if (proceed == MagickFalse)
2424fcb1a668b974425a0378c278db25aca29ec70894cristy              status=MagickFalse;
2425fcb1a668b974425a0378c278db25aca29ec70894cristy          }
2426fcb1a668b974425a0378c278db25aca29ec70894cristy      }
2427fcb1a668b974425a0378c278db25aca29ec70894cristy      (void) SetImageProgress(image,TextureImageTag,(MagickOffsetType)
2428fcb1a668b974425a0378c278db25aca29ec70894cristy        image->rows,image->rows);
242930d8c94aa45a8a386d4ce3b3340ddfed3aa2421ecristy      texture_image=DestroyImage(texture_image);
2430fcb1a668b974425a0378c278db25aca29ec70894cristy      return(status);
2431fcb1a668b974425a0378c278db25aca29ec70894cristy    }
2432316d51773c093e74e15de805e8bf620d6b56bc8bcristy  /*
2433fcb1a668b974425a0378c278db25aca29ec70894cristy    Tile texture onto the image background (optimized).
2434316d51773c093e74e15de805e8bf620d6b56bc8bcristy  */
2435316d51773c093e74e15de805e8bf620d6b56bc8bcristy  status=MagickTrue;
243646ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  texture_view=AcquireVirtualCacheView(texture_image,exception);
243746ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  image_view=AcquireAuthenticCacheView(image,exception);
2438e89143995d3c70f2b172e615d1915b1373ab835bcristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
2439d643247965337aae790abe62ef297abc3cc63c3dcristy  #pragma omp parallel for schedule(static,4) shared(status) \
2440d643247965337aae790abe62ef297abc3cc63c3dcristy    magick_threads(texture_image,image,1,1)
2441e89143995d3c70f2b172e615d1915b1373ab835bcristy#endif
2442bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
2443316d51773c093e74e15de805e8bf620d6b56bc8bcristy  {
2444fcb1a668b974425a0378c278db25aca29ec70894cristy    MagickBooleanType
2445fcb1a668b974425a0378c278db25aca29ec70894cristy      sync;
2446fcb1a668b974425a0378c278db25aca29ec70894cristy
24474c08aed51c5899665ade97263692328eea4af106cristy    register const Quantum
24484c08aed51c5899665ade97263692328eea4af106cristy      *p,
24494c08aed51c5899665ade97263692328eea4af106cristy      *pixels;
2450fcb1a668b974425a0378c278db25aca29ec70894cristy
2451bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    register ssize_t
2452316d51773c093e74e15de805e8bf620d6b56bc8bcristy      x;
2453316d51773c093e74e15de805e8bf620d6b56bc8bcristy
24544c08aed51c5899665ade97263692328eea4af106cristy    register Quantum
2455fcb1a668b974425a0378c278db25aca29ec70894cristy      *q;
2456fcb1a668b974425a0378c278db25aca29ec70894cristy
2457bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    size_t
2458fcb1a668b974425a0378c278db25aca29ec70894cristy      width;
2459fcb1a668b974425a0378c278db25aca29ec70894cristy
2460fcb1a668b974425a0378c278db25aca29ec70894cristy    if (status == MagickFalse)
2461fcb1a668b974425a0378c278db25aca29ec70894cristy      continue;
2462e6178503e4d6d3260666d42080d6f02545413685cristy    pixels=GetCacheViewVirtualPixels(texture_view,texture_image->tile_offset.x,
2463e6178503e4d6d3260666d42080d6f02545413685cristy      (y+texture_image->tile_offset.y) % texture_image->rows,
2464e6178503e4d6d3260666d42080d6f02545413685cristy      texture_image->columns,1,exception);
2465e6178503e4d6d3260666d42080d6f02545413685cristy    q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
24664c08aed51c5899665ade97263692328eea4af106cristy    if ((pixels == (const Quantum *) NULL) || (q == (Quantum *) NULL))
2467fcb1a668b974425a0378c278db25aca29ec70894cristy      {
2468fcb1a668b974425a0378c278db25aca29ec70894cristy        status=MagickFalse;
2469fcb1a668b974425a0378c278db25aca29ec70894cristy        continue;
2470fcb1a668b974425a0378c278db25aca29ec70894cristy      }
2471e6178503e4d6d3260666d42080d6f02545413685cristy    for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) texture_image->columns)
2472fcb1a668b974425a0378c278db25aca29ec70894cristy    {
24734c08aed51c5899665ade97263692328eea4af106cristy      register ssize_t
2474e6178503e4d6d3260666d42080d6f02545413685cristy        j;
24754c08aed51c5899665ade97263692328eea4af106cristy
24764c08aed51c5899665ade97263692328eea4af106cristy      p=pixels;
2477e6178503e4d6d3260666d42080d6f02545413685cristy      width=texture_image->columns;
2478bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      if ((x+(ssize_t) width) > (ssize_t) image->columns)
2479fcb1a668b974425a0378c278db25aca29ec70894cristy        width=image->columns-x;
2480e6178503e4d6d3260666d42080d6f02545413685cristy      for (j=0; j < (ssize_t) width; j++)
24814c08aed51c5899665ade97263692328eea4af106cristy      {
2482e6178503e4d6d3260666d42080d6f02545413685cristy        register ssize_t
2483e6178503e4d6d3260666d42080d6f02545413685cristy          i;
2484e6178503e4d6d3260666d42080d6f02545413685cristy
2485883fde11debec15cedb05dc5d7228d8588066bc0cristy        if (GetPixelReadMask(image,q) == 0)
248610a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy          {
248710a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy            p+=GetPixelChannels(texture_image);
248810a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy            q+=GetPixelChannels(image);
248910a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy            continue;
249010a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy          }
2491e6178503e4d6d3260666d42080d6f02545413685cristy        for (i=0; i < (ssize_t) GetPixelChannels(texture_image); i++)
2492e6178503e4d6d3260666d42080d6f02545413685cristy        {
24935a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy          PixelChannel channel=GetPixelChannelChannel(texture_image,i);
24945a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy          PixelTrait traits=GetPixelChannelTraits(image,channel);
24955a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy          PixelTrait texture_traits=GetPixelChannelTraits(texture_image,
24965a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy            channel);
2497e6178503e4d6d3260666d42080d6f02545413685cristy          if ((traits == UndefinedPixelTrait) ||
2498e6178503e4d6d3260666d42080d6f02545413685cristy              (texture_traits == UndefinedPixelTrait))
2499e6178503e4d6d3260666d42080d6f02545413685cristy            continue;
2500e6178503e4d6d3260666d42080d6f02545413685cristy          SetPixelChannel(image,channel,p[i],q);
2501e6178503e4d6d3260666d42080d6f02545413685cristy        }
2502e6178503e4d6d3260666d42080d6f02545413685cristy        p+=GetPixelChannels(texture_image);
2503ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy        q+=GetPixelChannels(image);
25044c08aed51c5899665ade97263692328eea4af106cristy      }
2505fcb1a668b974425a0378c278db25aca29ec70894cristy    }
2506fcb1a668b974425a0378c278db25aca29ec70894cristy    sync=SyncCacheViewAuthenticPixels(image_view,exception);
2507fcb1a668b974425a0378c278db25aca29ec70894cristy    if (sync == MagickFalse)
2508fcb1a668b974425a0378c278db25aca29ec70894cristy      status=MagickFalse;
2509316d51773c093e74e15de805e8bf620d6b56bc8bcristy    if (image->progress_monitor != (MagickProgressMonitor) NULL)
2510316d51773c093e74e15de805e8bf620d6b56bc8bcristy      {
2511316d51773c093e74e15de805e8bf620d6b56bc8bcristy        MagickBooleanType
2512316d51773c093e74e15de805e8bf620d6b56bc8bcristy          proceed;
2513316d51773c093e74e15de805e8bf620d6b56bc8bcristy
2514cee9711bbc334b5677d5ec4ea1cc70340d35ee35cristy        proceed=SetImageProgress(image,TextureImageTag,(MagickOffsetType) y,
2515cee9711bbc334b5677d5ec4ea1cc70340d35ee35cristy          image->rows);
2516316d51773c093e74e15de805e8bf620d6b56bc8bcristy        if (proceed == MagickFalse)
2517316d51773c093e74e15de805e8bf620d6b56bc8bcristy          status=MagickFalse;
2518316d51773c093e74e15de805e8bf620d6b56bc8bcristy      }
2519316d51773c093e74e15de805e8bf620d6b56bc8bcristy  }
2520fcb1a668b974425a0378c278db25aca29ec70894cristy  texture_view=DestroyCacheView(texture_view);
2521fcb1a668b974425a0378c278db25aca29ec70894cristy  image_view=DestroyCacheView(image_view);
252230d8c94aa45a8a386d4ce3b3340ddfed3aa2421ecristy  texture_image=DestroyImage(texture_image);
2523fcb1a668b974425a0378c278db25aca29ec70894cristy  return(status);
2524316d51773c093e74e15de805e8bf620d6b56bc8bcristy}
2525