X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=magick%2Fresize.c;h=9546935df4fae7a6a094232e979c334ee8e3e287;hb=042ee78fa9004bf1ac6a95f09d9d1faca631dda1;hp=b42c30e2709b475232526a4c4b9788b5778d2d8e;hpb=029ba0e5ffa91b831f3ffeb0539cbd699c9bbe0c;p=imagemagick diff --git a/magick/resize.c b/magick/resize.c index b42c30e27..9546935df 100644 --- a/magick/resize.c +++ b/magick/resize.c @@ -17,7 +17,7 @@ % July 1992 % % % % % -% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization % +% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization % % dedicated to making software imaging solutions freely available. % % % % You may not use this file except in compliance with the License. You may % @@ -62,6 +62,7 @@ #include "magick/pixel.h" #include "magick/option.h" #include "magick/resample.h" +#include "magick/resample-private.h" #include "magick/resize.h" #include "magick/resize-private.h" #include "magick/string_.h" @@ -85,7 +86,7 @@ struct _ResizeFilter window_support, /* window support, usally equal to support (expert only) */ scale, /* dimension scaling to fit window support (usally 1.0) */ blur, /* x-scale (blur-sharpen) */ - coeff[7]; /* cubic coefficents for BC-cubic spline filters */ + coefficient[7]; /* cubic coefficents for BC-cubic spline filters */ size_t signature; @@ -224,11 +225,11 @@ static MagickRealType CubicBC(const MagickRealType x, (slope). */ if (x < 1.0) - return(resize_filter->coeff[0]+x*(x* - (resize_filter->coeff[1]+x*resize_filter->coeff[2]))); + return(resize_filter->coefficient[0]+x*(x* + (resize_filter->coefficient[1]+x*resize_filter->coefficient[2]))); if (x < 2.0) - return(resize_filter->coeff[3]+x*(resize_filter->coeff[4]+x* - (resize_filter->coeff[5]+x*resize_filter->coeff[6]))); + return(resize_filter->coefficient[3]+x*(resize_filter->coefficient[4]+x* + (resize_filter->coefficient[5]+x*resize_filter->coefficient[6]))); return(0.0); } @@ -238,17 +239,23 @@ static MagickRealType Gaussian(const MagickRealType x, /* Gaussian with a fixed sigma = 1/2 - Gaussian Formula... - exp( -(x^2)/((2.0*sigma^2) ) / sqrt(2*PI*sigma^2))) + Gaussian Formula (1D) ... + exp( -(x^2)/((2.0*sigma^2) ) / sqrt(2*PI)sigma^2)) The constants are pre-calculated... exp( -coeff[0]*(x^2)) ) * coeff[1] However the multiplier coefficent (1) is not needed and not used. - This separates the gaussian 'sigma' value from the 'blur/support' settings - allowing for its use in special 'small sigma' gaussians, without the filter - 'missing' pixels when blurring because the support is too small. + Gaussian Formula (2D) ... + exp( -(x^2)/((2.0*sigma^2) ) / (PI*sigma^2) ) + Note that it is only a change in the normalization multiplier + which is not needed or used when gausian is used as a filter. + + This separates the gaussian 'sigma' value from the 'blur/support' + settings allowing for its use in special 'small sigma' gaussians, + without the filter 'missing' pixels because the support becomes too + small. */ - return(exp((double)(-resize_filter->coeff[0]*x*x))); + return(exp((double)(-resize_filter->coefficient[0]*x*x))); } static MagickRealType Hanning(const MagickRealType x, @@ -487,8 +494,8 @@ static MagickRealType Welsh(const MagickRealType x, % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% AcquireResizeFilter() allocates the ResizeFilter structure. Choose -% from these filters: +% AcquireResizeFilter() allocates the ResizeFilter structure. Choose from +% these filters: % % FIR (Finite impulse Response) Filters % Box Triangle Quadratic @@ -509,129 +516,114 @@ static MagickRealType Welsh(const MagickRealType x, % settings for that filter from a internal table. However any provided % 'expert' settings (see below) may override this selection. % -% FIR filters are used as is, and are limited to that filters support -% window (unless over-ridden). 'Gaussian' while classed as an IIR -% filter, is also simply clipped by its support size (currently 1.5 -% or approximatally 3*sigma as recommended by many references) -% -% The special a 'cylindrical' filter flag will promote the default -% 4-lobed Windowed Sinc filter to a 3-lobed Windowed Jinc equivelent, -% which is better suited to this style of image resampling. This -% typically happens when using such a filter for images distortions. -% -% Directly requesting 'Sinc', 'Jinc' function as a filter will force -% the use of function without any windowing, or promotion for -% cylindrical usage. This is not recommended, except by image -% processing experts, especially as part of expert option filter -% function selection. -% -% Two forms of the 'Sinc' function are available: Sinc and SincFast. -% Sinc is computed using the traditional sin(pi*x)/(pi*x); it is -% selected if the user specifically specifies the use of a Sinc -% filter. SincFast uses highly accurate (and fast) polynomial (low Q) -% and rational (high Q) approximations, and will be used by default in -% most cases. -% -% Lanczos filter is a special 3-lobed Sinc windowed Sinc filter, -% (or cylindrical promoted Jinc-Jinc filter). This filter is -% probably the most popular windowed filter. -% -% LanczosSharp is a slightly sharpened (blur=0.98303932214489908) -% form of the Lanczos filter. It was designed specifically for -% cylindrical EWA (Elliptical Weighted Average) distortion (as a -% Jinc-Jinc filter), but can used as a slightly sharper orthogonal -% Lanczos (Sinc-Sinc) filter. The chosen blur value comes as close as -% possible to satisfying the following condition without changing the -% character of the corresponding EWA filter: -% -% 'No-Op' Vertical and Horizontal Line Preservation Condition: -% Images with only vertical or horizontal features are preserved -% when performing 'no-op" with EWA distortion. -% -% The Lanczos2 and Lanczos2Sharp filters are simply 2-lobe versions -% of the Lanczos filters. The 'sharp' version uses a blur factor of -% 0.958027803631219, again chosen because the resulting EWA filter -% comes as close as possible to preserving vertical and horizontal -% lines without changing its character. (There are other optimal -% values; we use the least sharpening one). -% -% Robidoux is another filter tuned for EWA. It is the Keys cubic -% filter defined by B=(228 - 108 sqrt(2))/199. Robidoux satisfies the -% "'No-Op' Vertical and Horizontal Line Preservation Condition" -% exactly. It also seems to provide only minimal bluring of a low -% level 'pixel-hash' pattern in the 'No-Op Distort' case. It turns -% out to be close to both plain Mitchell and Lanczos2Sharp filters. -% For example, its first crossing is at (36 sqrt(2) + 123)/(72 -% sqrt(2) + 47) which is almost the same as the first crossing -% of the other two. -% +% FIR filters are used as is, and are limited to that filters support window +% (unless over-ridden). 'Gaussian' while classed as an IIR filter, is also +% simply clipped by its support size (currently 1.5 or approximatally 3*sigma +% as recommended by many references) +% +% The special a 'cylindrical' filter flag will promote the default 4-lobed +% Windowed Sinc filter to a 3-lobed Windowed Jinc equivelent, which is better +% suited to this style of image resampling. This typically happens when using +% such a filter for images distortions. +% +% Directly requesting 'Sinc', 'Jinc' function as a filter will force the use +% of function without any windowing, or promotion for cylindrical usage. This +% is not recommended, except by image processing experts, especially as part +% of expert option filter function selection. +% +% Two forms of the 'Sinc' function are available: Sinc and SincFast. Sinc is +% computed using the traditional sin(pi*x)/(pi*x); it is selected if the user +% specifically specifies the use of a Sinc filter. SincFast uses highly +% accurate (and fast) polynomial (low Q) and rational (high Q) approximations, +% and will be used by default in most cases. +% +% The Lanczos filter is a special 3-lobed Sinc-windowed Sinc filter (promoted +% to Jinc-windowed Jinc for cylindrical (Elliptical Weighted Average) use). +% The Sinc version is the most popular windowed filter. +% +% LanczosSharp is a slightly sharpened (blur=0.9812505644269356 < 1) form of +% the Lanczos filter, specifically designed for EWA distortion (as a +% Jinc-Jinc); it can also be used as a slightly sharper orthogonal Lanczos +% (Sinc-Sinc) filter. The chosen blur value comes as close as possible to +% satisfying the following condition without changing the character of the +% corresponding EWA filter: +% +% 'No-Op' Vertical and Horizontal Line Preservation Condition: Images with +% only vertical or horizontal features are preserved when performing 'no-op" +% with EWA distortion. +% +% The Lanczos2 and Lanczos2Sharp filters are 2-lobe versions of the Lanczos +% filters. The 'sharp' version uses a blur factor of 0.9549963639785485, +% again chosen because the resulting EWA filter comes as close as possible to +% satisfying the above condition. +% +% Robidoux is another filter tuned for EWA. It is the Keys cubic filter +% defined by B=(228 - 108 sqrt(2))/199. Robidoux satisfies the "'No-Op' +% Vertical and Horizontal Line Preservation Condition" exactly, and it +% moderately blurs high frequency 'pixel-hash' patterns under no-op. It turns +% out to be close to both Mitchell and Lanczos2Sharp. For example, its first +% crossing is at (36 sqrt(2) + 123)/(72 sqrt(2) + 47), almost the same as the +% first crossing of Mitchell and Lanczos2Sharp. % % 'EXPERT' OPTIONS: % -% These artifact "defines" are not recommended for production use -% without expert knowledge of resampling, filtering, and the effects -% they have on the resulting resampled (resize ro distorted) image. +% These artifact "defines" are not recommended for production use without +% expert knowledge of resampling, filtering, and the effects they have on the +% resulting resampled (resize ro distorted) image. % % They can be used to override any and all filter default, and it is -% recommended you make good use of "filter:verbose" to make sure that -% the overall effect of your selection (before and after) is as -% expected. -% -% "filter:verbose" controls whether to output the exact results of -% the filter selections made, as well as plotting data for -% graphing the resulting filter over the filters support range. -% -% "filter:filter" Select the main function associated with -% this filter name, as the weighting function of the filter. -% This can be used to set a windowing function as a weighting -% function, for special purposes, such as graphing. -% -% If a "filter:window" operation has not been provided, then a -% 'Box' windowing function will be set to denote that no -% windowing function is being used. -% -% "filter:window" Select this windowing function for the filter. -% While any filter could be used as a windowing function, using -% the 'first lobe' of that filter over the whole support -% window, using a non-windowing function is not advisible. If -% no weighting filter function is specifed a 'SincFast' filter -% will be used. -% -% "filter:lobes" Number of lobes to use for the Sinc/Jinc filter. -% This a simpler method of setting filter support size that -% will correctly handle the Sinc/Jinc switch for an operators -% filtering requirements. Only integers should be given. -% -% "filter:support" Set the support size for filtering to the size -% given This not recommended for Sinc/Jinc windowed filters -% (lobes should be used instead). This will override any -% 'filter:lobes' option. -% -% "filter:win-support" Scale windowing function to this size -% instead. This causes the windowing (or self-windowing -% Lagrange filter) to act is if the support window it much much -% larger than what is actually supplied to the calling -% operator. The filter however is still clipped to the real -% support size given, by the support range suppiled to the -% caller. If unset this will equal the normal filter support -% size. -% -% "filter:blur" Scale the filter and support window by this amount. -% A value >1 will generally result in a more burred image with -% more ringing effects, while a value <1 will sharpen the -% resulting image with more aliasing effects. -% -% "filter:sigma" The sigma value to use for the Gaussian filter -% only. Defaults to '1/2' for orthogonal and 'sqrt(2)/2' for -% cylindrical usage. It effectially provides a alturnative to -% 'blur' for Gaussians without it also effecting the final -% 'practical support' size. +% recommended you make good use of "filter:verbose" to make sure that the +% overall effect of your selection (before and after) is as expected. +% +% "filter:verbose" controls whether to output the exact results of the +% filter selections made, as well as plotting data for graphing the +% resulting filter over the filters support range. +% +% "filter:filter" select the main function associated with this filter +% name, as the weighting function of the filter. This can be used to +% set a windowing function as a weighting function, for special +% purposes, such as graphing. +% +% If a "filter:window" operation has not been provided, a 'Box' +% windowing function will be set to denote that no windowing function is +% being used. +% +% "filter:window" Select this windowing function for the filter. While any +% filter could be used as a windowing function, using the 'first lobe' of +% that filter over the whole support window, using a non-windowing +% function is not advisible. If no weighting filter function is specifed +% a 'SincFast' filter is used. +% +% "filter:lobes" Number of lobes to use for the Sinc/Jinc filter. This a +% simpler method of setting filter support size that will correctly +% handle the Sinc/Jinc switch for an operators filtering requirements. +% Only integers should be given. +% +% "filter:support" Set the support size for filtering to the size given. +% This not recommended for Sinc/Jinc windowed filters (lobes should be +% used instead). This will override any 'filter:lobes' option. +% +% "filter:win-support" Scale windowing function to this size instead. This +% causes the windowing (or self-windowing Lagrange filter) to act is if +% the support window it much much larger than what is actually supplied +% to the calling operator. The filter however is still clipped to the +% real support size given, by the support range suppiled to the caller. +% If unset this will equal the normal filter support size. +% +% "filter:blur" Scale the filter and support window by this amount. A value +% > 1 will generally result in a more burred image with more ringing +% effects, while a value <1 will sharpen the resulting image with more +% aliasing effects. +% +% "filter:sigma" The sigma value to use for the Gaussian filter only. +% Defaults to '1/2'. Using a different sigma effectively provides a +% method of using the filter as a 'blur' convolution. Particularly when +% using it for Distort. % % "filter:b" -% "filter:c" Override the preset B,C values for a Cubic type of -% filter If only one of these are given it is assumes to be a -% 'Keys' type of filter such that B+2C=1, where Keys 'alpha' -% value = C +% "filter:c" Override the preset B,C values for a Cubic type of filter. +% If only one of these are given it is assumes to be a 'Keys' type of +% filter such that B+2C=1, where Keys 'alpha' value = C. % % Examples: % @@ -643,7 +635,6 @@ static MagickRealType Welsh(const MagickRealType x, % -filter Lanczos % -define filter:lobes=8 % -% % The format of the AcquireResizeFilter method is: % % ResizeFilter *AcquireResizeFilter(const Image *image, @@ -654,16 +645,15 @@ static MagickRealType Welsh(const MagickRealType x, % % o image: the image. % -% o filter: the filter type, defining a preset filter, window and -% support. The artifact settings listed above will override -% those selections. +% o filter: the filter type, defining a preset filter, window and support. +% The artifact settings listed above will override those selections. % % o blur: blur the filter by this amount, use 1.0 if unknown. Image -% artifact "filter:blur" will override this API call usage, including -% any internal change (such as for cylindrical usage). +% artifact "filter:blur" will override this API call usage, including any +% internal change (such as for cylindrical usage). % -% o radial: use a 1D orthogonal filter (Sinc) or 2D cylindrical -% (radial) filter (Jinc) +% o radial: use a 1D orthogonal filter (Sinc) or 2D cylindrical (radial) +% filter (Jinc). % % o exception: return any errors or warnings in this structure. % @@ -687,17 +677,16 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, register ResizeFilter *resize_filter; - /* - Table Mapping given Filter, into Weighting and Windowing functions. - A 'Box' windowing function means its a simble non-windowed filter. - An 'SincFast' filter function could be upgraded to a 'Jinc' filter - if a "cylindrical", unless a 'Sinc' or 'SincFast' filter was - specifically requested. + Table Mapping given Filter, into Weighting and Windowing functions. A + 'Box' windowing function means its a simble non-windowed filter. An + 'SincFast' filter function could be upgraded to a 'Jinc' filter if a + "cylindrical", unless a 'Sinc' or 'SincFast' filter was specifically + requested. - WARNING: The order of this tabel must match the order of the - FilterTypes enumeration specified in "resample.h", or the filter - names will not match the filter being setup. + WARNING: The order of this tabel must match the order of the FilterTypes + enumeration specified in "resample.h", or the filter names will not match + the filter being setup. You can check filter setups with the "filter:verbose" setting. */ @@ -737,17 +726,15 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, { RobidouxFilter, BoxFilter }, /* Cubic Keys tuned for EWA */ }; /* - Table mapping the filter/window from the above table to an actual - function. The default support size for that filter as a weighting - function, the range to scale with to use that function as a sinc - windowing function, (typ 1.0). + Table mapping the filter/window from the above table to an actual function. + The default support size for that filter as a weighting function, the range + to scale with to use that function as a sinc windowing function, (typ 1.0). Note that the filter_type -> function is 1 to 1 except for Sinc(), - SincFast(), and CubicBC() functions, which may have multiple - filter to function associations. + SincFast(), and CubicBC() functions, which may have multiple filter to + function associations. - See "filter:verbose" handling below for the function -> filter - mapping. + See "filter:verbose" handling below for the function -> filter mapping. */ static struct { @@ -792,13 +779,13 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, /* The known zero crossings of the Jinc() or more accurately the Jinc(x*PI) function being used as a filter. It is used by the "filter:lobes" expert - setting and for 'lobes' for Jinc functions in the previous table. This - way users do not have to deal with the highly irrational lobe sizes of the - Jinc filter. + setting and for 'lobes' for Jinc functions in the previous table. This way + users do not have to deal with the highly irrational lobe sizes of the Jinc + filter. Values taken from - http://cose.math.bas.bg/webMathematica/webComputing/BesselZeros.jsp - using Jv-function with v=1, then dividing by PI. + http://cose.math.bas.bg/webMathematica/webComputing/BesselZeros.jsp using + Jv-function with v=1, then dividing by PI. */ static MagickRealType jinc_zeros[16] = @@ -839,8 +826,8 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, */ filter_type=mapping[filter].filter; window_type=mapping[filter].window; - resize_filter->blur = blur; - sigma = 0.5; + resize_filter->blur = blur; /* function argument blur factor */ + sigma = 0.5; /* guassian sigma of half a pixel by default */ /* Promote 1D Windowed Sinc Filters to a 2D Windowed Jinc filters */ if (cylindrical != MagickFalse && filter_type == SincFastFilter && filter != SincFastFilter ) @@ -852,7 +839,8 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, { ssize_t option; - option=ParseMagickOption(MagickFilterOptions,MagickFalse,artifact); + + option=ParseCommandOption(MagickFilterOptions,MagickFalse,artifact); if ((UndefinedFilter < option) && (option < SentinelFilter)) { /* Raw filter request - no window function. */ filter_type=(FilterTypes) option; @@ -862,7 +850,7 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, artifact=GetImageArtifact(image,"filter:window"); if (artifact != (const char *) NULL) { - option=ParseMagickOption(MagickFilterOptions,MagickFalse,artifact); + option=ParseCommandOption(MagickFilterOptions,MagickFalse,artifact); if ((UndefinedFilter < option) && (option < SentinelFilter)) window_type=(FilterTypes) option; } @@ -875,7 +863,8 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, { ssize_t option; - option=ParseMagickOption(MagickFilterOptions,MagickFalse, + + option=ParseCommandOption(MagickFilterOptions,MagickFalse, artifact); if ((UndefinedFilter < option) && (option < SentinelFilter)) { @@ -910,10 +899,6 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, resize_filter->scale=filters[JincFilter].scale; /* number of lobes (support window size) remain unchanged */ break; - case GaussianFilter: - /* Cylindrical Gaussian sigma is sqrt(2)/2. */ - sigma = (MagickRealType) (MagickSQ2/2.0); - break; default: break; } @@ -921,10 +906,10 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, switch (filter_type) { case LanczosSharpFilter: - resize_filter->blur *= 0.98303932214489908; + resize_filter->blur *= 0.9812505644269356; break; case Lanczos2SharpFilter: - resize_filter->blur *= 0.958027803631219; + resize_filter->blur *= 0.9549963639785485; break; default: break; @@ -938,16 +923,17 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, artifact=GetImageArtifact(image,"filter:sigma"); if (artifact != (const char *) NULL) sigma=StringToDouble(artifact); - /* Define coefficents for Gaussian (assumes no cubic window) */ + /* Define coefficents for Gaussian */ if ( GaussianFilter ) { - resize_filter->coeff[0] = 1.0/(2.0*sigma*sigma); - resize_filter->coeff[1] = (MagickRealType) (1.0/(Magick2PI*sigma*sigma)); /* unused */ + resize_filter->coefficient[0]=1.0/(2.0*sigma*sigma); + resize_filter->coefficient[1]=(MagickRealType) (1.0/(Magick2PI*sigma* + sigma)); /* Normalization Multiplier - unneeded for filters */ } /* Blur Override */ artifact=GetImageArtifact(image,"filter:blur"); if (artifact != (const char *) NULL) - resize_filter->blur=StringToDouble(artifact); + resize_filter->blur *= StringToDouble(artifact); if (resize_filter->blur < MagickEpsilon) resize_filter->blur=(MagickRealType) MagickEpsilon; @@ -1026,13 +1012,13 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, /* Convert B,C values into Cubic Coefficents. See CubicBC(). */ { const double twoB = B+B; - resize_filter->coeff[0]=1.0-(1.0/3.0)*B; - resize_filter->coeff[1]=-3.0+twoB+C; - resize_filter->coeff[2]=2.0-1.5*B-C; - resize_filter->coeff[3]=(4.0/3.0)*B+4.0*C; - resize_filter->coeff[4]=-8.0*C-twoB; - resize_filter->coeff[5]=B+5.0*C; - resize_filter->coeff[6]=(-1.0/6.0)*B-C; + resize_filter->coefficient[0]=1.0-(1.0/3.0)*B; + resize_filter->coefficient[1]=-3.0+twoB+C; + resize_filter->coefficient[2]=2.0-1.5*B-C; + resize_filter->coefficient[3]=(4.0/3.0)*B+4.0*C; + resize_filter->coefficient[4]=-8.0*C-twoB; + resize_filter->coefficient[5]=B+5.0*C; + resize_filter->coefficient[6]=(-1.0/6.0)*B-C; } } @@ -1061,10 +1047,10 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, if (resize_filter->filter == SincFast) filter_type=SincFastFilter; if (resize_filter->filter == Jinc) filter_type=JincFilter; if (resize_filter->filter == CubicBC) filter_type=CubicFilter; - if (resize_filter->filter == Box) window_type=BoxFilter; + if (resize_filter->window == Box) window_type=BoxFilter; if (resize_filter->window == Sinc) window_type=SincFilter; if (resize_filter->window == SincFast) window_type=SincFastFilter; - if (resize_filter->filter == Jinc) window_type=JincFilter; + if (resize_filter->window == Jinc) window_type=JincFilter; if (resize_filter->window == CubicBC) window_type=CubicFilter; /* Report Filter Details. @@ -1072,9 +1058,9 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image, support=GetResizeFilterSupport(resize_filter); /* practical_support */ (void) fprintf(stdout,"# Resize Filter (for graphing)\n#\n"); (void) fprintf(stdout,"# filter = %s\n", - MagickOptionToMnemonic(MagickFilterOptions,filter_type)); + CommandOptionToMnemonic(MagickFilterOptions,filter_type)); (void) fprintf(stdout,"# window = %s\n", - MagickOptionToMnemonic(MagickFilterOptions, window_type)); + CommandOptionToMnemonic(MagickFilterOptions, window_type)); (void) fprintf(stdout,"# support = %.*g\n", GetMagickPrecision(),(double) resize_filter->support); (void) fprintf(stdout,"# win-support = %.*g\n", @@ -1144,22 +1130,17 @@ MagickExport Image *AdaptiveResizeImage(const Image *image, #define AdaptiveResizeImageTag "Resize/Image" CacheView + *image_view, *resize_view; Image *resize_image; MagickBooleanType - proceed; - - MagickPixelPacket - pixel; - - PointInfo - offset; + status; - ResampleFilter - *resample_filter; + MagickOffsetType + progress; ssize_t y; @@ -1186,46 +1167,67 @@ MagickExport Image *AdaptiveResizeImage(const Image *image, resize_image=DestroyImage(resize_image); return((Image *) NULL); } - GetMagickPixelPacket(image,&pixel); - resample_filter=AcquireResampleFilter(image,exception); - (void) SetResampleFilter(resample_filter,PointFilter,1.0); - (void) SetResampleFilterInterpolateMethod(resample_filter, - MeshInterpolatePixel); + status=MagickTrue; + progress=0; + image_view=AcquireCacheView(image); resize_view=AcquireCacheView(resize_image); +#if defined(MAGICKCORE_OPENMP_SUPPORT) + #pragma omp parallel for schedule(dynamic,4) shared(progress,status) omp_throttle(1) +#endif for (y=0; y < (ssize_t) resize_image->rows; y++) { + MagickPixelPacket + pixel; + + PointInfo + offset; + register IndexPacket *restrict resize_indexes; - register ssize_t - x; - register PixelPacket *restrict q; + register ssize_t + x; + + if (status == MagickFalse) + continue; q=QueueCacheViewAuthenticPixels(resize_view,0,y,resize_image->columns,1, exception); if (q == (PixelPacket *) NULL) - break; + continue; resize_indexes=GetCacheViewAuthenticIndexQueue(resize_view); - offset.y=((MagickRealType) y*image->rows/resize_image->rows); + offset.y=((MagickRealType) (y+0.5)*image->rows/resize_image->rows); + GetMagickPixelPacket(image,&pixel); for (x=0; x < (ssize_t) resize_image->columns; x++) { - offset.x=((MagickRealType) x*image->columns/resize_image->columns); - (void) ResamplePixelColor(resample_filter,offset.x-0.5,offset.y-0.5, - &pixel); + offset.x=((MagickRealType) (x+0.5)*image->columns/resize_image->columns); + (void) InterpolateMagickPixelPacket(image,image_view, + MeshInterpolatePixel,offset.x-0.5,offset.y-0.5,&pixel,exception); SetPixelPacket(resize_image,&pixel,q,resize_indexes+x); q++; } if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse) - break; - proceed=SetImageProgress(image,AdaptiveResizeImageTag,(MagickOffsetType) y, - image->rows); - if (proceed == MagickFalse) - break; + continue; + if (image->progress_monitor != (MagickProgressMonitor) NULL) + { + MagickBooleanType + proceed; + +#if defined(MAGICKCORE_OPENMP_SUPPORT) + #pragma omp critical (MagickCore_AdaptiveResizeImage) +#endif + proceed=SetImageProgress(image,AdaptiveResizeImageTag,progress++, + image->rows); + if (proceed == MagickFalse) + status=MagickFalse; + } } - resample_filter=DestroyResampleFilter(resample_filter); resize_view=DestroyCacheView(resize_view); + image_view=DestroyCacheView(image_view); + if (status == MagickFalse) + resize_image=DestroyImage(resize_image); return(resize_image); } @@ -1534,6 +1536,7 @@ MagickExport MagickRealType GetResizeFilterWeight( { MagickRealType scale, + weight, x_blur; /* @@ -1550,7 +1553,8 @@ MagickExport MagickRealType GetResizeFilterWeight( scale=resize_filter->scale; scale=resize_filter->window(x_blur*scale,resize_filter); } - return(scale*resize_filter->filter(x_blur,resize_filter)); + weight=scale*resize_filter->filter(x_blur,resize_filter); + return(weight); } /* @@ -1630,8 +1634,8 @@ MagickExport Image *MinifyImage(const Image *image,ExceptionInfo *exception) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); - minify_image=ResizeImage(image,image->columns/2,image->rows/2,CubicFilter, - 1.0,exception); + minify_image=ResizeImage(image,image->columns/2,image->rows/2,CubicFilter,1.0, + exception); return(minify_image); } @@ -2230,7 +2234,7 @@ static MagickBooleanType HorizontalFilter(const ResizeFilter *resize_filter, pixel.index+=alpha*indexes[j]; } resize_indexes[y]=(IndexPacket) ClampToQuantum(gamma* - GetIndexPixelComponent(&pixel)); + GetIndexPixelComponent(&pixel)); } } if ((resize_image->storage_class == PseudoClass) && @@ -2916,7 +2920,7 @@ MagickExport Image *ScaleImage(const Image *image,const size_t columns, exception); if (q == (PixelPacket *) NULL) break; - scale_indexes=GetAuthenticIndexQueue(scale_image); + scale_indexes=GetCacheViewAuthenticIndexQueue(scale_view); if (scale_image->rows == image->rows) { /*