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