resample.c revision 3ed852eea50f9d4cd633efb8c2b054b8e33c253
13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%           RRRR    EEEEE   SSSSS   AAA   M   M  PPPP   L      EEEEE          %
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%           R   R   E       SS     A   A  MM MM  P   P  L      E              %
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%           RRRR    EEE      SSS   AAAAA  M M M  PPPP   L      EEE            %
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%           R R     E          SS  A   A  M   M  P      L      E              %
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%           R  R    EEEEE   SSSSS  A   A  M   M  P      LLLLL  EEEEE          %
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                      MagickCore Pixel Resampling Methods                    %
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              Software Design                                %
163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                John Cristy                                  %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              Anthony Thyssen                                %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                August 2007                                  %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  dedicated to making software imaging solutions freely available.           %
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  You may not use this file except in compliance with the License.  You may  %
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  obtain a copy of the License at                                            %
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    http://www.imagemagick.org/script/license.php                            %
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Unless required by applicable law or agreed to in writing, software        %
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  See the License for the specific language governing permissions and        %
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  limitations under the License.                                             %
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Include declarations.
423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/studio.h"
443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/artifact.h"
453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/color-private.h"
463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/cache.h"
473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/draw.h"
483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/exception-private.h"
493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/gem.h"
503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/image.h"
513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/image-private.h"
523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/log.h"
533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/memory_.h"
543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/pixel-private.h"
553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/quantum.h"
563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/random_.h"
573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/resample.h"
583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/resize.h"
593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/resize-private.h"
603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/transform.h"
613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "magick/signature-private.h"
623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Typedef declarations.
643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define WLUT_WIDTH 1024
663ed852eea50f9d4cd633efb8c2b054b8e33c253cristystruct _ResampleFilter
673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  CacheView
723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *view;
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *exception;
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    debug;
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Information about image being resampled */
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  long
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image_area;
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  InterpolatePixelMethod
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    interpolate;
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  VirtualPixelMethod
883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    virtual_pixel;
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  FilterTypes
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    filter;
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* processing settings needed */
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    limit_reached,
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    do_interpolate,
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    average_defined;
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickPixelPacket
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    average_pixel;
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* current ellipitical area being resampled around center point */
1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  double
1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    A, B, C,
1053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sqrtA, sqrtC, sqrtU, slope;
1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* LUT of weights for filtered average in elliptical area */
1083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  double
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    filter_lut[WLUT_WIDTH],
1103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    support;
1113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned long
1133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    signature;
1143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy};
1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   A c q u i r e R e s a m p l e I n f o                                     %
1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  AcquireResampleFilter() initializes the information resample needs do to a
1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  scaled lookup of a color from an image, using area sampling.
1293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The algorithm is based on a Elliptical Weighted Average, where the pixels
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  found in a large elliptical area is averaged together according to a
1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  weighting (filter) function.  For more details see "Fundamentals of Texture
1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Mapping and Image Warping" a master's thesis by Paul.S.Heckbert, June 17,
1343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  1989.  Available for free from, http://www.cs.cmu.edu/~ph/
1353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  As EWA resampling (or any sort of resampling) can require a lot of
1373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  calculations to produce a distorted scaling of the source image for each
1383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  output pixel, the ResampleFilter structure generated holds that information
1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  between individual image resampling.
1403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  This function will make the appropriate AcquireCacheView() calls
1423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  to view the image, calling functions do not need to open a cache view.
1433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Usage Example...
1453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      resample_filter=AcquireResampleFilter(image,exception);
1463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      for (y=0; y < (long) image->rows; y++) {
1473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        for (x=0; x < (long) image->columns; x++) {
1483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%          X= ....;   Y= ....;
1493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%          ScaleResampleFilter(resample_filter, ... scaling vectors ...);
1503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%          (void) ResamplePixelColor(resample_filter,X,Y,&pixel);
1513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%          ... assign resampled pixel value ...
1523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        }
1533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      }
1543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      DestroyResampleFilter(resample_filter);
1553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the AcquireResampleFilter method is:
1573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%     ResampleFilter *AcquireResampleFilter(const Image *image,
1593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%       ExceptionInfo *exception)
1603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
1623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the image.
1643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport ResampleFilter *AcquireResampleFilter(const Image *image,
1693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo *exception)
1703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register ResampleFilter
1723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *resample_filter;
1733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
1753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
1773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception->signature == MagickSignature);
1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter=(ResampleFilter *) AcquireMagickMemory(
1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sizeof(*resample_filter));
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (resample_filter == (ResampleFilter *) NULL)
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetMagickMemory(resample_filter,0,sizeof(*resample_filter));
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->image=ReferenceImage((Image *) image);
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->view=AcquireCacheView(resample_filter->image);
1893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->exception=exception;
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->debug=IsEventLogging();
1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->signature=MagickSignature;
1933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->image_area = (long) resample_filter->image->columns *
1953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resample_filter->image->rows;
1963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->average_defined = MagickFalse;
1973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* initialise the resampling filter settings */
1993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  SetResampleFilter(resample_filter, resample_filter->image->filter,
2003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resample_filter->image->blur);
2013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->interpolate = resample_filter->image->interpolate;
2023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->virtual_pixel=GetImageVirtualPixelMethod(image);
2033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* init scale to a default of a unit circle */
2053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ScaleResampleFilter(resample_filter, 1.0, 0.0, 0.0, 1.0);
2063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(resample_filter);
2083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
2093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   D e s t r o y R e s a m p l e I n f o                                     %
2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  DestroyResampleFilter() finalizes and cleans up the resampling
2223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  resample_filter as returned by AcquireResampleFilter(), freeing any memory
2233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  or other information as needed.
2243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the DestroyResampleFilter method is:
2263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      ResampleFilter *DestroyResampleFilter(ResampleFilter *resample_filter)
2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
2303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o resample_filter: resampling information structure
2323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
2343ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport ResampleFilter *DestroyResampleFilter(
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ResampleFilter *resample_filter)
2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter != (ResampleFilter *) NULL);
2383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter->signature == MagickSignature);
2393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter->image != (Image *) NULL);
2403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (resample_filter->debug != MagickFalse)
2413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resample_filter->image->filename);
2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->view=DestroyCacheView(resample_filter->view);
2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->image=DestroyImage(resample_filter->image);
2453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->signature=(~MagickSignature);
2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter=(ResampleFilter *) RelinquishMagickMemory(resample_filter);
2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(resample_filter);
2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   I n t e r p o l a t e R e s a m p l e F i l t e r                         %
2563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  InterpolateResampleFilter() applies bi-linear or tri-linear interpolation
2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  between a floating point coordinate and the pixels surrounding that
2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  coordinate.  No pixel area resampling, or scaling of the result is
2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  performed.
2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the InterpolateResampleFilter method is:
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType InterpolateResampleFilter(
2693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        ResampleInfo *resample_filter,const InterpolatePixelMethod method,
2703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        const double x,const double y,MagickPixelPacket *pixel)
2713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
2733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o resample_filter: the resample filter.
2753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o method: the pixel clor interpolation method.
2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o x,y: A double representing the current (x,y) position of the pixel.
2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o pixel: return the interpolated pixel here.
2813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline double MagickMax(const double x,const double y)
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (x > y)
2873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(x);
2883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(y);
2893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void BicubicInterpolate(const MagickPixelPacket *pixels,const double dx,
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickPixelPacket *pixel)
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickRealType
2953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    dx2,
2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p,
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q,
2983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r,
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    s;
3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  dx2=dx*dx;
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=(pixels[3].red-pixels[2].red)-(pixels[0].red-pixels[1].red);
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=(pixels[0].red-pixels[1].red)-p;
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  r=pixels[2].red-pixels[0].red;
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  s=pixels[1].red;
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pixel->red=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=(pixels[3].green-pixels[2].green)-(pixels[0].green-pixels[1].green);
3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=(pixels[0].green-pixels[1].green)-p;
3093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  r=pixels[2].green-pixels[0].green;
3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  s=pixels[1].green;
3113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pixel->green=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
3123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=(pixels[3].blue-pixels[2].blue)-(pixels[0].blue-pixels[1].blue);
3133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=(pixels[0].blue-pixels[1].blue)-p;
3143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  r=pixels[2].blue-pixels[0].blue;
3153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  s=pixels[1].blue;
3163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pixel->blue=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=(pixels[3].opacity-pixels[2].opacity)-(pixels[0].opacity-pixels[1].opacity);
3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=(pixels[0].opacity-pixels[1].opacity)-p;
3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  r=pixels[2].opacity-pixels[0].opacity;
3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  s=pixels[1].opacity;
3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pixel->opacity=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (pixel->colorspace == CMYKColorspace)
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p=(pixels[3].index-pixels[2].index)-(pixels[0].index-pixels[1].index);
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      q=(pixels[0].index-pixels[1].index)-p;
3263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      r=pixels[2].index-pixels[0].index;
3273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      s=pixels[1].index;
3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      pixel->index=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3323ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline MagickRealType CubicWeightingFunction(const MagickRealType x)
3333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickRealType
3353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    alpha,
3363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    gamma;
3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  alpha=MagickMax(x+2.0,0.0);
3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  gamma=1.0*alpha*alpha*alpha;
3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  alpha=MagickMax(x+1.0,0.0);
3413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  gamma-=4.0*alpha*alpha*alpha;
3423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  alpha=MagickMax(x+0.0,0.0);
3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  gamma+=6.0*alpha*alpha*alpha;
3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  alpha=MagickMax(x-1.0,0.0);
3453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  gamma-=4.0*alpha*alpha*alpha;
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(gamma/6.0);
3473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline double MeshInterpolate(const PointInfo *delta,const double p,
3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const double x,const double y)
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline long NearestNeighbor(MagickRealType x)
3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (x >= 0.0)
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return((long) (x+0.5));
3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return((long) (x-0.5));
3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType InterpolateResampleFilter(
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ResampleFilter *resample_filter,const InterpolatePixelMethod method,
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const double x,const double y,MagickPixelPacket *pixel)
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const IndexPacket
3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *indexes;
3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const PixelPacket
3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register long
3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
3773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter != (ResampleFilter *) NULL);
3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter->signature == MagickSignature);
3803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=MagickTrue;
3813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  switch (method)
3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case AverageInterpolatePixel:
3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickPixelPacket
3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[16];
3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickRealType
3893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        alpha[16],
3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        gamma;
3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p=GetCacheViewVirtualPixels(resample_filter->view,(long) floor(x)-1,(long)
3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        floor(y)-1,4,4,resample_filter->exception);
3943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (p == (const PixelPacket *) NULL)
3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=MagickFalse;
3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
3993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; i < 16L; i++)
4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        GetMagickPixelPacket(resample_filter->image,pixels+i);
4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        SetMagickPixelPacket(resample_filter->image,p,indexes+i,pixels+i);
4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        alpha[i]=1.0;
4053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (resample_filter->image->matte != MagickFalse)
4063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            alpha[i]=QuantumScale*((MagickRealType) QuantumRange-p->opacity);
4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            pixels[i].red*=alpha[i];
4093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            pixels[i].green*=alpha[i];
4103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            pixels[i].blue*=alpha[i];
4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (resample_filter->image->colorspace == CMYKColorspace)
4123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixels[i].index*=alpha[i];
4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
4143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        gamma=alpha[i];
4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixel->red+=gamma*0.0625*pixels[i].red;
4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixel->green+=gamma*0.0625*pixels[i].green;
4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixel->blue+=gamma*0.0625*pixels[i].blue;
4193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixel->opacity+=0.0625*pixels[i].opacity;
4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (resample_filter->image->colorspace == CMYKColorspace)
4213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          pixel->index+=gamma*0.0625*pixels[i].index;
4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p++;
4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case BicubicInterpolatePixel:
4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
4283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickPixelPacket
4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[16],
4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        u[4];
4313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickRealType
4333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        alpha[16];
4343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PointInfo
4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        delta;
4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p=GetCacheViewVirtualPixels(resample_filter->view,(long) floor(x)-1,(long)
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        floor(y)-1,4,4,resample_filter->exception);
4403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (p == (const PixelPacket *) NULL)
4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=MagickFalse;
4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
4453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
4463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; i < 16L; i++)
4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
4483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        GetMagickPixelPacket(resample_filter->image,pixels+i);
4493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        SetMagickPixelPacket(resample_filter->image,p,indexes+i,pixels+i);
4503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        alpha[i]=1.0;
4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (resample_filter->image->matte != MagickFalse)
4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
4533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            alpha[i]=QuantumScale*((MagickRealType) QuantumRange-p->opacity);
4543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            pixels[i].red*=alpha[i];
4553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            pixels[i].green*=alpha[i];
4563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            pixels[i].blue*=alpha[i];
4573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (resample_filter->image->colorspace == CMYKColorspace)
4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixels[i].index*=alpha[i];
4593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
4603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p++;
4613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
4623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      delta.x=x-floor(x);
4633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; i < 4L; i++)
4643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        BicubicInterpolate(pixels+4*i,delta.x,u+i);
4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      delta.y=y-floor(y);
4663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      BicubicInterpolate(u,delta.y,pixel);
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case BilinearInterpolatePixel:
4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    default:
4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
4723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickPixelPacket
4733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[4];
4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickRealType
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        alpha[4],
4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        gamma;
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PointInfo
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        delta,
4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        epsilon;
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p=GetCacheViewVirtualPixels(resample_filter->view,(long) floor(x),(long)
4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        floor(y),2,2,resample_filter->exception);
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (p == (const PixelPacket *) NULL)
4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=MagickFalse;
4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; i < 4L; i++)
4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[i].red=(MagickRealType) p[i].red;
4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[i].green=(MagickRealType) p[i].green;
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[i].blue=(MagickRealType) p[i].blue;
4963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[i].opacity=(MagickRealType) p[i].opacity;
4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        alpha[i]=1.0;
4983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
4993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (resample_filter->image->matte != MagickFalse)
5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (i=0; i < 4L; i++)
5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
5023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          alpha[i]=QuantumScale*((MagickRealType) QuantumRange-p[i].opacity);
5033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          pixels[i].red*=alpha[i];
5043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          pixels[i].green*=alpha[i];
5053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          pixels[i].blue*=alpha[i];
5063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (indexes != (IndexPacket *) NULL)
5083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (i=0; i < 4L; i++)
5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
5103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          pixels[i].index=(MagickRealType) indexes[i];
5113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (resample_filter->image->colorspace == CMYKColorspace)
5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            pixels[i].index*=alpha[i];
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      delta.x=x-floor(x);
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      delta.y=y-floor(y);
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      epsilon.x=1.0-delta.x;
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      epsilon.y=1.0-delta.y;
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (epsilon.x*alpha[2]+delta.x*alpha[3])));
5203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x*
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[3].green));
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x*
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x*
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[3].blue));
5293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      pixel->opacity=(epsilon.y*(epsilon.x*pixels[0].opacity+delta.x*
5303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[1].opacity)+delta.y*(epsilon.x*pixels[2].opacity+delta.x*
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[3].opacity));
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (resample_filter->image->colorspace == CMYKColorspace)
5333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixel->index=gamma*(epsilon.y*(epsilon.x*pixels[0].index+delta.x*
5343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          pixels[1].index)+delta.y*(epsilon.x*pixels[2].index+delta.x*
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          pixels[3].index));
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case FilterInterpolatePixel:
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Image
5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *excerpt_image,
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *filter_image;
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickPixelPacket
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[1];
5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      RectangleInfo
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        geometry;
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      CacheView
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *filter_view;
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      geometry.width=4L;
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      geometry.height=4L;
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      geometry.x=(long) floor(x)-1L;
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      geometry.y=(long) floor(y)-1L;
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      excerpt_image=ExcerptImage(resample_filter->image,&geometry,
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        resample_filter->exception);
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (excerpt_image == (Image *) NULL)
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=MagickFalse;
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      filter_image=ResizeImage(excerpt_image,1,1,resample_filter->image->filter,
5653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        resample_filter->image->blur,resample_filter->exception);
5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      excerpt_image=DestroyImage(excerpt_image);
5673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (filter_image == (Image *) NULL)
5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
5693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      filter_view=AcquireCacheView(filter_image);
5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,
5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        resample_filter->exception);
5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (p != (const PixelPacket *) NULL)
5733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          indexes=GetVirtualIndexQueue(filter_image);
5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          GetMagickPixelPacket(resample_filter->image,pixels);
5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          SetMagickPixelPacket(resample_filter->image,p,indexes,pixel);
5773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      filter_view=DestroyCacheView(filter_view);
5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      filter_image=DestroyImage(filter_image);
5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case IntegerInterpolatePixel:
5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickPixelPacket
5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[1];
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p=GetCacheViewVirtualPixels(resample_filter->view,(long) floor(x),(long)
5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        floor(y),1,1,resample_filter->exception);
5893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (p == (const PixelPacket *) NULL)
5903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=MagickFalse;
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      GetMagickPixelPacket(resample_filter->image,pixels);
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      SetMagickPixelPacket(resample_filter->image,p,indexes,pixel);
5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case MeshInterpolatePixel:
6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickPixelPacket
6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[4];
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickRealType
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        alpha[4],
6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        gamma;
6073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PointInfo
6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        delta,
6103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        luminance;
6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p=GetCacheViewVirtualPixels(resample_filter->view,(long) floor(x),(long)
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        floor(y),2,2,resample_filter->exception);
6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (p == (const PixelPacket *) NULL)
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=MagickFalse;
6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
6183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=0; i < 4L; i++)
6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        GetMagickPixelPacket(resample_filter->image,pixels+i);
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        SetMagickPixelPacket(resample_filter->image,p,indexes+i,pixels+i);
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        alpha[i]=1.0;
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (resample_filter->image->matte != MagickFalse)
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            alpha[i]=QuantumScale*((MagickRealType) QuantumRange-p->opacity);
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            pixels[i].red*=alpha[i];
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            pixels[i].green*=alpha[i];
6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            pixels[i].blue*=alpha[i];
6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            if (resample_filter->image->colorspace == CMYKColorspace)
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixels[i].index*=alpha[i];
6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p++;
6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
6363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      delta.x=x-floor(x);
6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      delta.y=y-floor(y);
6383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      luminance.x=MagickPixelLuminance(pixels+0)-MagickPixelLuminance(pixels+3);
6393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      luminance.y=MagickPixelLuminance(pixels+1)-MagickPixelLuminance(pixels+2);
6403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (fabs(luminance.x) < fabs(luminance.y))
6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Diagonal 0-3 NW-SE.
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (delta.x <= delta.y)
6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              /*
6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Bottom-left triangle  (pixel:2, diagonal: 0-3).
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              */
6503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              delta.y=1.0-delta.y;
6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red,
6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[3].red,pixels[0].red);
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green,
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[3].green,pixels[0].green);
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue,
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[3].blue,pixels[0].blue);
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->opacity=gamma*MeshInterpolate(&delta,pixels[2].opacity,
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[3].opacity,pixels[0].opacity);
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (resample_filter->image->colorspace == CMYKColorspace)
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixel->index=gamma*MeshInterpolate(&delta,pixels[2].index,
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  pixels[3].index,pixels[0].index);
6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          else
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              /*
6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Top-right triangle (pixel:1, diagonal: 0-3).
6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              */
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              delta.x=1.0-delta.x;
6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red,
6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[0].red,pixels[3].red);
6753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green,
6763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[0].green,pixels[3].green);
6773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue,
6783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[0].blue,pixels[3].blue);
6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->opacity=gamma*MeshInterpolate(&delta,pixels[1].opacity,
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[0].opacity,pixels[3].opacity);
6813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (resample_filter->image->colorspace == CMYKColorspace)
6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixel->index=gamma*MeshInterpolate(&delta,pixels[1].index,
6833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  pixels[0].index,pixels[3].index);
6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
6853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
6873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Diagonal 1-2 NE-SW.
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (delta.x <= (1.0-delta.y))
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
6933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              /*
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Top-left triangle (pixel 0, diagonal: 1-2).
6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              */
6963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red,
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[1].red,pixels[2].red);
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green,
7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[1].green,pixels[2].green);
7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue,
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[1].blue,pixels[2].blue);
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->opacity=gamma*MeshInterpolate(&delta,pixels[0].opacity,
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[1].opacity,pixels[2].opacity);
7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (resample_filter->image->colorspace == CMYKColorspace)
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixel->index=gamma*MeshInterpolate(&delta,pixels[0].index,
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  pixels[1].index,pixels[2].index);
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          else
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              /*
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                Bottom-right triangle (pixel: 3, diagonal: 1-2).
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              */
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              delta.x=1.0-delta.x;
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              delta.y=1.0-delta.y;
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red,
7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[2].red,pixels[1].red);
7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green,
7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[2].green,pixels[1].green);
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue,
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[2].blue,pixels[1].blue);
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixel->opacity=gamma*MeshInterpolate(&delta,pixels[3].opacity,
7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[2].opacity,pixels[1].opacity);
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (resample_filter->image->colorspace == CMYKColorspace)
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixel->index=gamma*MeshInterpolate(&delta,pixels[3].index,
7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                  pixels[2].index,pixels[1].index);
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case NearestNeighborInterpolatePixel:
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickPixelPacket
7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[1];
7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p=GetCacheViewVirtualPixels(resample_filter->view,NearestNeighbor(x),
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        NearestNeighbor(y),1,1,resample_filter->exception);
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (p == (const PixelPacket *) NULL)
7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=MagickFalse;
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      GetMagickPixelPacket(resample_filter->image,pixels);
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      SetMagickPixelPacket(resample_filter->image,p,indexes,pixel);
7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
7513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case SplineInterpolatePixel:
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      long
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        j,
7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        n;
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickPixelPacket
7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixels[16];
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickRealType
7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        alpha[16],
7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        dx,
7633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        dy,
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        gamma;
7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PointInfo
7673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        delta;
7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      p=GetCacheViewVirtualPixels(resample_filter->view,(long) floor(x)-1,(long)
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        floor(y)-1,4,4,resample_filter->exception);
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (p == (const PixelPacket *) NULL)
7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=MagickFalse;
7743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
7753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
7763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
7773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      n=0;
7783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      delta.x=x-floor(x);
7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      delta.y=y-floor(y);
7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (i=(-1); i < 3L; i++)
7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
7823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        dy=CubicWeightingFunction((MagickRealType) i-delta.y);
7833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        for (j=(-1); j < 3L; j++)
7843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
7853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          GetMagickPixelPacket(resample_filter->image,pixels+n);
7863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          SetMagickPixelPacket(resample_filter->image,p,indexes+n,pixels+n);
7873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          alpha[n]=1.0;
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (resample_filter->image->matte != MagickFalse)
7893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              alpha[n]=QuantumScale*((MagickRealType) QuantumRange-p->opacity);
7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixels[n].red*=alpha[n];
7923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixels[n].green*=alpha[n];
7933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              pixels[n].blue*=alpha[n];
7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (resample_filter->image->colorspace == CMYKColorspace)
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                pixels[n].index*=alpha[n];
7963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
7973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          dx=CubicWeightingFunction(delta.x-(MagickRealType) j);
7983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          gamma=alpha[n];
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
8003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          pixel->red+=gamma*dx*dy*pixels[n].red;
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          pixel->green+=gamma*dx*dy*pixels[n].green;
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          pixel->blue+=gamma*dx*dy*pixels[n].blue;
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (resample_filter->image->matte != MagickFalse)
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            pixel->opacity+=dx*dy*pixels[n].opacity;
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (resample_filter->image->colorspace == CMYKColorspace)
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            pixel->index+=gamma*dx*dy*pixels[n].index;
8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          n++;
8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          p++;
8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
8113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
8153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e s a m p l e P i x e l C o l o r                                       %
8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ResamplePixelColor() samples the pixel values surrounding the location
8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  given using an elliptical weighted average, at the scale previously
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  calculated, and in the most efficent manner possible for the
8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  VirtualPixelMethod setting.
8323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ResamplePixelColor method is:
8343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%     MagickBooleanType ResamplePixelColor(ResampleFilter *resample_filter,
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%       const double u0,const double v0,MagickPixelPacket *pixel)
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
8393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o resample_filter: the resample filter.
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o u0,v0: A double representing the center of the area to resample,
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        The distortion transformed transformed x,y coordinate.
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o pixel: the resampled pixel is returned here.
8463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
8483ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport MagickBooleanType ResamplePixelColor(
8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ResampleFilter *resample_filter,const double u0,const double v0,
8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickPixelPacket *pixel)
8513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
8543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  long u,v, uw,v1,v2, hit;
8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  double u1;
8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  double U,V,Q,DQ,DDQ;
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  double divisor_c,divisor_m;
8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register double weight;
8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const PixelPacket *pixels;
8613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register const IndexPacket *indexes;
8623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter != (ResampleFilter *) NULL);
8633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter->signature == MagickSignature);
8643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=MagickTrue;
8663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GetMagickPixelPacket(resample_filter->image,pixel);
8673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ( resample_filter->do_interpolate ) {
8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=InterpolateResampleFilter(resample_filter,
8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resample_filter->interpolate,u0,v0,pixel);
8703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
8713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
8723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Does resample area Miss the image?
8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    And is that area a simple solid color - then return that color
8763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  hit = 0;
8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  switch ( resample_filter->virtual_pixel ) {
8793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case BackgroundVirtualPixelMethod:
8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case ConstantVirtualPixelMethod:
8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case TransparentVirtualPixelMethod:
8823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case BlackVirtualPixelMethod:
8833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case GrayVirtualPixelMethod:
8843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case WhiteVirtualPixelMethod:
8853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case MaskVirtualPixelMethod:
8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ( resample_filter->limit_reached
8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           || u0 + resample_filter->sqrtC < 0.0
8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           || u0 - resample_filter->sqrtC > (double) resample_filter->image->columns
8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           || v0 + resample_filter->sqrtA < 0.0
8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           || v0 - resample_filter->sqrtA > (double) resample_filter->image->rows
8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           )
8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        hit++;
8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
8943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case UndefinedVirtualPixelMethod:
8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case EdgeVirtualPixelMethod:
8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (    ( u0 + resample_filter->sqrtC < 0.0 && v0 + resample_filter->sqrtA < 0.0 )
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           || ( u0 + resample_filter->sqrtC < 0.0
8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                && v0 - resample_filter->sqrtA > (double) resample_filter->image->rows )
9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           || ( u0 - resample_filter->sqrtC > (double) resample_filter->image->columns
9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                && v0 + resample_filter->sqrtA < 0.0 )
9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           || ( u0 - resample_filter->sqrtC > (double) resample_filter->image->columns
9033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                && v0 - resample_filter->sqrtA > (double) resample_filter->image->rows )
9043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           )
9053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        hit++;
9063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case HorizontalTileVirtualPixelMethod:
9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (    v0 + resample_filter->sqrtA < 0.0
9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           || v0 - resample_filter->sqrtA > (double) resample_filter->image->rows
9103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           )
9113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        hit++;  /* outside the horizontally tiled images. */
9123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
9133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case VerticalTileVirtualPixelMethod:
9143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (    u0 + resample_filter->sqrtC < 0.0
9153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           || u0 - resample_filter->sqrtC > (double) resample_filter->image->columns
9163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           )
9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        hit++;  /* outside the vertically tiled images. */
9183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
9193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case DitherVirtualPixelMethod:
9203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (    ( u0 + resample_filter->sqrtC < -32.0 && v0 + resample_filter->sqrtA < -32.0 )
9213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           || ( u0 + resample_filter->sqrtC < -32.0
9223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                && v0 - resample_filter->sqrtA > (double) resample_filter->image->rows+32.0 )
9233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           || ( u0 - resample_filter->sqrtC > (double) resample_filter->image->columns+32.0
9243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                && v0 + resample_filter->sqrtA < -32.0 )
9253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           || ( u0 - resample_filter->sqrtC > (double) resample_filter->image->columns+32.0
9263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                && v0 - resample_filter->sqrtA > (double) resample_filter->image->rows+32.0 )
9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           )
9283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        hit++;
9293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
9303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case TileVirtualPixelMethod:
9313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case MirrorVirtualPixelMethod:
9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case RandomVirtualPixelMethod:
9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case HorizontalTileEdgeVirtualPixelMethod:
9343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case VerticalTileEdgeVirtualPixelMethod:
9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case CheckerTileVirtualPixelMethod:
9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /* resampling of area is always needed - no VP limits */
9373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
9393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ( hit ) {
9403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* whole area is a solid color -- just return that color */
9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=InterpolateResampleFilter(resample_filter,IntegerInterpolatePixel,
9423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      u0,v0,pixel);
9433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
9443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
9453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
9473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Scaling limits reached, return an 'averaged' result.
9483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
9493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ( resample_filter->limit_reached ) {
9503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    switch ( resample_filter->virtual_pixel ) {
9513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*  This is always handled by the above, so no need.
9523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        case BackgroundVirtualPixelMethod:
9533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        case ConstantVirtualPixelMethod:
9543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        case TransparentVirtualPixelMethod:
9553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        case GrayVirtualPixelMethod,
9563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        case WhiteVirtualPixelMethod
9573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        case MaskVirtualPixelMethod:
9583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
9593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case UndefinedVirtualPixelMethod:
9603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case EdgeVirtualPixelMethod:
9613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case DitherVirtualPixelMethod:
9623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case HorizontalTileEdgeVirtualPixelMethod:
9633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case VerticalTileEdgeVirtualPixelMethod:
9643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /* We need an average edge pixel, for the right edge!
9653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           How should I calculate an average edge color?
9663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           Just returning an averaged neighbourhood,
9673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           works well in general, but falls down for TileEdge methods.
9683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           This needs to be done properly!!!!!!
9693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
9703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        status=InterpolateResampleFilter(resample_filter,
9713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          AverageInterpolatePixel,u0,v0,pixel);
9723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
9733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case HorizontalTileVirtualPixelMethod:
9743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case VerticalTileVirtualPixelMethod:
9753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /* just return the background pixel - Is there more direct way? */
9763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        status=InterpolateResampleFilter(resample_filter,
9773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           IntegerInterpolatePixel,(double)-1,(double)-1,pixel);
9783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
9793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case TileVirtualPixelMethod:
9803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case MirrorVirtualPixelMethod:
9813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case RandomVirtualPixelMethod:
9823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case CheckerTileVirtualPixelMethod:
9833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      default:
9843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /* generate a average color of the WHOLE image */
9853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ( resample_filter->average_defined == MagickFalse ) {
9863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Image
9873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            *average_image;
9883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          CacheView
9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            *average_view;
9913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          GetMagickPixelPacket(resample_filter->image,
9933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (MagickPixelPacket *)&(resample_filter->average_pixel));
9943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          resample_filter->average_defined = MagickTrue;
9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /* Try to get an averaged pixel color of whole image */
9973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          average_image=ResizeImage(resample_filter->image,1,1,BoxFilter,1.0,
9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           resample_filter->exception);
9993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (average_image == (Image *) NULL)
10003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
10013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              *pixel=resample_filter->average_pixel; /* FAILED */
10023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              break;
10033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
10043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          average_view=AcquireCacheView(average_image);
10053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          pixels=(PixelPacket *)GetCacheViewVirtualPixels(average_view,0,0,1,1,
10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            resample_filter->exception);
10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (pixels == (const PixelPacket *) NULL) {
10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            average_view=DestroyCacheView(average_view);
10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            average_image=DestroyImage(average_image);
10103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            *pixel=resample_filter->average_pixel; /* FAILED */
10113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            break;
10123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
10133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          indexes=(IndexPacket *) GetCacheViewAuthenticIndexQueue(average_view);
10143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          SetMagickPixelPacket(resample_filter->image,pixels,indexes,
10153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            &(resample_filter->average_pixel));
10163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          average_view=DestroyCacheView(average_view);
10173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          average_image=DestroyImage(average_image);
10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if 0
10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /* CheckerTile should average the image with background color */
10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          //if ( resample_filter->virtual_pixel == CheckerTileVirtualPixelMethod ) {
10213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if 0
10223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            resample_filter->average_pixel.red =
10233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      ( resample_filter->average_pixel.red +
10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          resample_filter->image->background_color.red ) /2;
10253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            resample_filter->average_pixel.green =
10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      ( resample_filter->average_pixel.green +
10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          resample_filter->image->background_color.green ) /2;
10283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            resample_filter->average_pixel.blue =
10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      ( resample_filter->average_pixel.blue +
10303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          resample_filter->image->background_color.blue ) /2;
10313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            resample_filter->average_pixel.matte =
10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      ( resample_filter->average_pixel.matte +
10333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          resample_filter->image->background_color.matte ) /2;
10343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            resample_filter->average_pixel.black =
10353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                      ( resample_filter->average_pixel.black +
10363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          resample_filter->image->background_color.black ) /2;
10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
10383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            resample_filter->average_pixel =
10393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                          resample_filter->image->background_color;
10403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
10423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
10433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
10443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *pixel=resample_filter->average_pixel;
10453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
10463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
10473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
10483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
10493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize weighted average data collection
10523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
10533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  hit = 0;
10543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  divisor_c = 0.0;
10553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  divisor_m = 0.0;
10563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pixel->red = pixel->green = pixel->blue = 0.0;
10573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (resample_filter->image->matte != MagickFalse) pixel->opacity = 0.0;
10583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (resample_filter->image->colorspace == CMYKColorspace) pixel->index = 0.0;
10593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Determine the parellelogram bounding box fitted to the ellipse
10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    centered at u0,v0.  This area is bounding by the lines...
10633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        v = +/- sqrt(A)
10643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        u = -By/2A  +/- sqrt(F/A)
10653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Which has been pre-calculated above.
10663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
10673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  v1 = (long)(v0 - resample_filter->sqrtA);               /* range of scan lines */
10683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  v2 = (long)(v0 + resample_filter->sqrtA + 1);
10693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  u1 = u0 + (v1-v0)*resample_filter->slope - resample_filter->sqrtU; /* start of scanline for v=v1 */
10713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  uw = (long)(2*resample_filter->sqrtU)+1;       /* width of parallelogram */
10723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Do weighted resampling of all pixels,  within the scaled ellipse,
10753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bound by a Parellelogram fitted to the ellipse.
10763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
10773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  DDQ = 2*resample_filter->A;
10783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for( v=v1; v<=v2;  v++, u1+=resample_filter->slope ) {
10793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    u = (long)u1;       /* first pixel in scanline  ( floor(u1) ) */
10803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    U = (double)u-u0;   /* location of that pixel, relative to u0,v0 */
10813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    V = (double)v-v0;
10823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* Q = ellipse quotent ( if Q<F then pixel is inside ellipse) */
10843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Q = U*(resample_filter->A*U + resample_filter->B*V) + resample_filter->C*V*V;
10853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    DQ = resample_filter->A*(2.0*U+1) + resample_filter->B*V;
10863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* get the scanline of pixels for this v */
10883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixels=GetCacheViewVirtualPixels(resample_filter->view,u,v,(unsigned long) uw,
10893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      1,resample_filter->exception);
10903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (pixels == (const PixelPacket *) NULL)
10913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(MagickFalse);
10923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
10933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* count up the weighted pixel colors */
10953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for( u=0; u<uw; u++ ) {
10963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /* Note that the ellipse has been pre-scaled so F = WLUT_WIDTH */
10973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ( Q < (double)WLUT_WIDTH ) {
10983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        weight = resample_filter->filter_lut[(int)Q];
10993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixel->opacity  += weight*pixels->opacity;
11013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        divisor_m += weight;
11023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (resample_filter->image->matte != MagickFalse)
11043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          weight *= QuantumScale*((MagickRealType)(QuantumRange-pixels->opacity));
11053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixel->red   += weight*pixels->red;
11063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixel->green += weight*pixels->green;
11073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        pixel->blue  += weight*pixels->blue;
11083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (resample_filter->image->colorspace == CMYKColorspace)
11093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          pixel->index += weight*(*indexes);
11103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        divisor_c += weight;
11113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        hit++;
11133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
11143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      pixels++;
11153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      indexes++;
11163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Q += DQ;
11173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      DQ += DDQ;
11183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
11193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
11203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
11223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Result sanity check -- this should NOT happen
11233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
11243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ( hit < 4 || divisor_c < 1.0 ) {
11253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* not enough pixels in resampling, resort to direct interpolation */
11263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=InterpolateResampleFilter(resample_filter,
11273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resample_filter->interpolate,u0,v0,pixel);
11283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return status;
11293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
11303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
11323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Finialize results of resampling
11333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
11343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  divisor_m = 1.0/divisor_m;
11353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pixel->opacity = (MagickRealType) RoundToQuantum(divisor_m*pixel->opacity);
11363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  divisor_c = 1.0/divisor_c;
11373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pixel->red   = (MagickRealType) RoundToQuantum(divisor_c*pixel->red);
11383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pixel->green = (MagickRealType) RoundToQuantum(divisor_c*pixel->green);
11393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pixel->blue  = (MagickRealType) RoundToQuantum(divisor_c*pixel->blue);
11403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (resample_filter->image->colorspace == CMYKColorspace)
11413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel->index = (MagickRealType) RoundToQuantum(divisor_c*pixel->index);
11423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
11433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
11443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
11463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
11483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
11493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
11503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   S c a l e R e s a m p l e F i l t e r                                     %
11513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
11523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
11533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
11543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ScaleResampleFilter() does all the calculations needed to resample an image
11573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  at a specific scale, defined by two scaling vectors.  This not using
11583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  a orthogonal scaling, but two distorted scaling vectors, to allow the
11593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  generation of a angled ellipse.
11603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  As only two deritive scaling vectors are used the center of the ellipse
11623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  must be the center of the lookup.  That is any curvature that the
11633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distortion may produce is discounted.
11643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The input vectors are produced by either finding the derivitives of the
11663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distortion function, or the partial derivitives from a distortion mapping.
11673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  They do not need to be the orthogonal dx,dy scaling vectors, but can be
11683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  calculated from other derivatives.  For example you could use  dr,da/r
11693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  polar coordinate vector scaling vectors
11703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  If   u,v =  DistortEquation(x,y)
11723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Then the scaling vectors dx,dy (in u,v space) are the derivitives...
11733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      du/dx, dv/dx     and    du/dy, dv/dy
11743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  If the scaling is only othogonally aligned then...
11753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      dv/dx = 0   and   du/dy  =  0
11763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Producing an othogonally alligned ellipse for the area to be resampled.
11773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Note that scaling vectors are different to argument order.  Argument order
11793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  is the general order the deritives are extracted from the distortion
11803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  equations, EG: U(x,y), V(x,y).  Caution is advised if you are trying to
11813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  define the ellipse directly from scaling vectors.
11823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ScaleResampleFilter method is:
11843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%     void ScaleResampleFilter(const ResampleFilter *resample_filter,
11863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%       const double dux,const double duy,const double dvx,const double dvy)
11873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
11893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o resample_filter: the resampling resample_filterrmation defining the
11913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      image being resampled
11923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o dux,duy,dvx,dvy:
11943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%         The partial derivitives or scaling vectors for resampling.
11953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%           dx = du/dx, dv/dx    and  dy = du/dy, dv/dy
11963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%         The values are used to define the size and angle of the
11983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%         elliptical resampling area, centered on the lookup point.
11993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
12003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
12013ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport void ScaleResampleFilter(ResampleFilter *resample_filter,
12023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const double dux,const double duy,const double dvx,const double dvy)
12033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
12043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  double A,B,C,F, area;
12053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter != (ResampleFilter *) NULL);
12073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter->signature == MagickSignature);
12083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->limit_reached = MagickFalse;
12103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->do_interpolate = MagickFalse;
12113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* A 'point' filter forces use of interpolation instead of area sampling */
12133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ( resample_filter->filter == PointFilter ) {
12143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resample_filter->do_interpolate = MagickTrue;
12153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return;
12163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
12173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Find Ellipse Coefficents such that
12193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        A*u^2 + B*u*v + C*v^2 = F
12203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     With u,v relative to point around which we are resampling.
12213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     And the given scaling dx,dy vectors in u,v space
12223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         du/dx,dv/dx   and  du/dy,dv/dy
12233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
12243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if 0
12253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Direct conversions of derivatives to elliptical coefficients
12263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     No scaling will result in F == 1.0 and a unit circle.
12273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
12283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  A = dvx*dvx+dvy*dvy;
12293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  B = (dux*dvx+duy*dvy)*-2.0;
12303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  C = dux*dux+duy*duy;
12313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  F = dux*dvy+duy*dvx;
12323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  F *= F;
12333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define F_UNITY 1.0
12343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
12353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* This Paul Heckbert's recomended "Higher Quality EWA" formula, from page
12363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     60 in his thesis, which adds a unit circle to the elliptical area so are
12373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     to do both Reconstruction and Prefiltering of the pixels in the
12383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     resampling.  It also means it is likely to have at least 4 pixels within
12393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     the area of the ellipse, for weighted averaging.
12403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     No scaling will result if F == 4.0 and a circle of radius 2.0
12413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
12423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  A = dvx*dvx+dvy*dvy+1;
12433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  B = (dux*dvx+duy*dvy)*-2.0;
12443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  C = dux*dux+duy*duy+1;
12453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  F = A*C - B*B/4;
12463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define F_UNITY 4.0
12473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
12483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* DEBUGGING OUTPUT */
12503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if 0
12513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  fprintf(stderr, "dux=%lf; dvx=%lf;   duy=%lf; dvy%lf;\n",
12523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       dux, dvx, duy, dvy);
12533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  fprintf(stderr, "A=%lf; B=%lf; C=%lf; F=%lf\n", A,B,C,F);
12543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
12553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if 0
12573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Figure out the Ellipses Major and Minor Axis, and other info.
12583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     This information currently not needed at this time, but may be
12593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     needed later for better limit determination.
12603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
12613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  { double alpha, beta, gamma, Major, Minor;
12623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    double Eccentricity, Ellipse_Area, Ellipse_angle;
12633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    double max_horizontal_cross_section, max_vertical_cross_section;
12643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    alpha = A+C;
12653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    beta  = A-C;
12663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    gamma = sqrt(beta*beta + B*B );
12673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ( alpha - gamma <= MagickEpsilon )
12693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Major = MagickHuge;
12703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
12713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Major = sqrt(2*F/(alpha - gamma));
12723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Minor = sqrt(2*F/(alpha + gamma));
12733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    fprintf(stderr, "\tMajor=%lf; Minor=%lf\n",
12753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         Major, Minor );
12763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* other information about ellipse include... */
12783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Eccentricity = Major/Minor;
12793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Ellipse_Area = MagickPI*Major*Minor;
12803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Ellipse_angle =  atan2(B, A-C);
12813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    fprintf(stderr, "\tAngle=%lf Area=%lf\n",
12833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         RadiansToDegrees(Ellipse_angle), Ellipse_Area );
12843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* Ellipse limits */
12863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* orthogonal rectangle - improved ellipse */
12883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    max_horizontal_orthogonal = sqrt(A); /* = sqrt(4*A*F/(4*A*C-B*B)) */
12893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    max_vertical_orthogonal   = sqrt(C); /* = sqrt(4*C*F/(4*A*C-B*B)) */
12903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* parallelogram bounds -- what we are using */
12923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    max_horizontal_cross_section = sqrt(F/A);
12933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    max_vertical_cross_section   = sqrt(F/C);
12943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
12953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
12963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Is default elliptical area, too small? Image being magnified?
12983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     Switch to doing pure 'point' interpolation of the pixel.
12993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     That is turn off  EWA Resampling.
13003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
13013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ( F <= F_UNITY ) {
13023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resample_filter->do_interpolate = MagickTrue;
13033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return;
13043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
13053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* If F is impossibly large, we may as well not bother doing any
13083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   * form of resampling, as you risk an infinite resampled area.
13093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
13103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ( F > MagickHuge ) {
13113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resample_filter->limit_reached = MagickTrue;
13123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return;
13133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
13143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Othogonal bounds of the ellipse */
13163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->sqrtA = sqrt(A)+1.0;     /* Vertical Orthogonal Limit */
13173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->sqrtC = sqrt(C)+1.0;     /* Horizontal Orthogonal Limit */
13183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Horizontally aligned Parallelogram fitted to ellipse */
13203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->sqrtU = sqrt(F/A)+1.0;   /* Parallelogram Width */
13213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->slope = -B/(2*A);        /* Slope of the parallelogram */
13223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* The size of the area of the parallelogram we will be sampling */
13243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  area = 4 * resample_filter->sqrtA * resample_filter->sqrtU;
13253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Absolute limit on the area to be resampled
13273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   * This limit needs more work, as it gets too slow for
13283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy   * larger images involved with tiled views of the horizon. */
13293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ( area > 20.0*resample_filter->image_area ) {
13303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resample_filter->limit_reached = MagickTrue;
13313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return;
13323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
13333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Scale ellipse formula to directly fit the Filter Lookup Table */
13353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  { register double scale;
13363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    scale = (double)WLUT_WIDTH/F;
13373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resample_filter->A = A*scale;
13383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resample_filter->B = B*scale;
13393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resample_filter->C = C*scale;
13403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* ..ple_filter->F = WLUT_WIDTH; -- hardcoded */
13413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
13423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
13433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
13453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   S e t R e s a m p l e F i l t e r                                         %
13503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  SetResampleFilter() set the resampling filter lookup table based on a
13563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  specific filter.  Note that the filter is used as a radial filter not as a
13573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  two pass othogonally aligned resampling filter.
13583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The default Filter, is Gaussian, which is the standard filter used by the
13603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  original paper on the Elliptical Weighted Everage Algorithm. However other
13613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  filters can also be used.
13623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the SetResampleFilter method is:
13643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    void SetResampleFilter(ResampleFilter *resample_filter,
13663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      const FilterTypes filter,const double blur)
13673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
13693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o resample_filter: resampling resample_filterrmation structure
13713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o filter: the resize filter for elliptical weighting LUT
13733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o blur: filter blur factor (radial scaling) for elliptical weighting LUT
13753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
13773ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport void SetResampleFilter(ResampleFilter *resample_filter,
13783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const FilterTypes filter,const double blur)
13793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
13803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register int
13813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     Q;
13823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  double
13843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     r_scale;
13853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ResizeFilter
13873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     *resize_filter;
13883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter != (ResampleFilter *) NULL);
13903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter->signature == MagickSignature);
13913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->filter = filter;
13933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /* Scale radius so it equals 1.0, at edge of ellipse when a
13953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     default blurring factor of 1.0 is used.
13963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
13973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     Note that these filters are being used as a radial filter, not as
13983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     an othoginally alligned filter. How this effects results is still
13993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     being worked out.
14003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     Future: Direct use of teh resize filters in "resize.c" to set the lookup
14023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy     table, based on the filters working support window.
14033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
14043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  r_scale = sqrt(1.0/(double)WLUT_WIDTH)/blur;
14053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  r_scale *= 2; /* for 2 pixel radius of Improved Elliptical Formula */
14063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  switch ( filter ) {
14083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  case PointFilter:
14093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* This equivelent to turning off the EWA algroithm.
14103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy       Only Interpolated lookup will be used.  */
14113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    break;
14123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  default:
14133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
14143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Fill the LUT with a 1D resize filter function
14153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      But make the Sinc/Bessel tapered window 2.0
14163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      I also normalize the result so the filter is 1.0
14173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
14183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resize_filter = AcquireResizeFilter(resample_filter->image,filter,
14193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy         (MagickRealType)1.0,MagickTrue,resample_filter->exception);
14203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (resize_filter != (ResizeFilter *) NULL) {
14213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resample_filter->support = GetResizeFilterSupport(resize_filter);
14223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resample_filter->support /= blur; /* taken into account above */
14233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resample_filter->support *= resample_filter->support;
14243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resample_filter->support *= (double)WLUT_WIDTH/4;
14253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ( resample_filter->support >= (double)WLUT_WIDTH )
14263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           resample_filter->support = (double)WLUT_WIDTH;  /* hack */
14273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for(Q=0; Q<WLUT_WIDTH; Q++)
14283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ( (double) Q < resample_filter->support )
14293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          resample_filter->filter_lut[Q] = (double)
14303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               GetResizeFilterWeight(resize_filter,sqrt((double)Q)*r_scale);
14313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        else
14323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          resample_filter->filter_lut[Q] = 0.0;
14333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resize_filter = DestroyResizeFilter(resize_filter);
14343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
14353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
14363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else {
14373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) ThrowMagickException(resample_filter->exception,GetMagickModule(),
14383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           ModuleError, "UnableToSetFilteringValue",
14393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy           "Fall back to default EWA gaussian filter");
14403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
14413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* FALLTHRU - on exception */
14423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*case GaussianFilter:*/
14433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  case UndefinedFilter:
14443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
14453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Create Normal Gaussian 2D Filter Weighted Lookup Table.
14463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      A normal EWA guassual lookup would use   exp(Q*ALPHA)
14473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      where  Q = distantce squared from 0.0 (center) to 1.0 (edge)
14483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      and    ALPHA = -4.0*ln(2.0)  ==>  -2.77258872223978123767
14493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      However the table is of length 1024, and equates to a radius of 2px
14503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      thus needs to be scaled by  ALPHA*4/1024 and any blur factor squared
14513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
14523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*r_scale = -2.77258872223978123767*4/WLUT_WIDTH/blur/blur;*/
14533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    r_scale = -2.77258872223978123767/WLUT_WIDTH/blur/blur;
14543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for(Q=0; Q<WLUT_WIDTH; Q++)
14553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resample_filter->filter_lut[Q] = exp((double)Q*r_scale);
14563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resample_filter->support = WLUT_WIDTH;
14573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    break;
14583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
14593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (GetImageArtifact(resample_filter->image,"resample:verbose")
14603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        != (const char *) NULL)
14613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* Debug output of the filter weighting LUT
14623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Gnuplot the LUT with hoizontal adjusted to 'r' using...
14633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        plot [0:2][-.2:1] "lut.dat" using (sqrt($0/1024)*2):1 with lines
14643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      THe filter values is normalized for comparision
14653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
14663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for(Q=0; Q<WLUT_WIDTH; Q++)
14673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      printf("%lf\n", resample_filter->filter_lut[Q]
14683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                        /resample_filter->filter_lut[0] );
14693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return;
14703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
14713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
14733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   S e t R e s a m p l e F i l t e r I n t e r p o l a t e M e t h o d       %
14783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  SetResampleFilterInterpolateMethod() changes the interpolation method
14843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  associated with the specified resample filter.
14853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the SetResampleFilterInterpolateMethod method is:
14873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType SetResampleFilterInterpolateMethod(
14893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        ResampleFilter *resample_filter,const InterpolateMethod method)
14903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
14923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o resample_filter: the resample filter.
14943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o method: the interpolation method.
14963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
14983ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport MagickBooleanType SetResampleFilterInterpolateMethod(
14993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ResampleFilter *resample_filter,const InterpolatePixelMethod method)
15003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
15013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter != (ResampleFilter *) NULL);
15023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter->signature == MagickSignature);
15033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter->image != (Image *) NULL);
15043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (resample_filter->debug != MagickFalse)
15053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
15063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resample_filter->image->filename);
15073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->interpolate=method;
15083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
15093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
15103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
15123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
15143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
15153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
15163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   S e t R e s a m p l e F i l t e r V i r t u a l P i x e l M e t h o d     %
15173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
15183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
15193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
15203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  SetResampleFilterVirtualPixelMethod() changes the virtual pixel method
15233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  associated with the specified resample filter.
15243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the SetResampleFilterVirtualPixelMethod method is:
15263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType SetResampleFilterVirtualPixelMethod(
15283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        ResampleFilter *resample_filter,const VirtualPixelMethod method)
15293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
15313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o resample_filter: the resample filter.
15333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o method: the virtual pixel method.
15353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
15373ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport MagickBooleanType SetResampleFilterVirtualPixelMethod(
15383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ResampleFilter *resample_filter,const VirtualPixelMethod method)
15393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
15403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter != (ResampleFilter *) NULL);
15413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter->signature == MagickSignature);
15423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(resample_filter->image != (Image *) NULL);
15433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (resample_filter->debug != MagickFalse)
15443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
15453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resample_filter->image->filename);
15463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resample_filter->virtual_pixel=method;
15473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) SetCacheViewVirtualPixelMethod(resample_filter->view,method);
15483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
15493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1550