% July 1992 %
% %
% %
-% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2012 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 %
#include "MagickCore/image-private.h"
#include "MagickCore/list.h"
#include "MagickCore/memory_.h"
+#include "MagickCore/memory-private.h"
#include "MagickCore/magick.h"
#include "MagickCore/pixel-accessor.h"
#include "MagickCore/property.h"
#include "MagickCore/monitor-private.h"
#include "MagickCore/option.h"
#include "MagickCore/pixel.h"
+#include "MagickCore/pixel-private.h"
#include "MagickCore/quantum-private.h"
#include "MagickCore/resample.h"
#include "MagickCore/resample-private.h"
#include "MagickCore/resize.h"
#include "MagickCore/resize-private.h"
+#include "MagickCore/resource_.h"
#include "MagickCore/string_.h"
#include "MagickCore/string-private.h"
#include "MagickCore/thread-private.h"
+#include "MagickCore/token.h"
#include "MagickCore/utility.h"
+#include "MagickCore/utility-private.h"
#include "MagickCore/version.h"
#if defined(MAGICKCORE_LQR_DELEGATE)
#include <lqr.h>
*/
struct _ResizeFilter
{
- MagickRealType
- (*filter)(const MagickRealType,const ResizeFilter *),
- (*window)(const MagickRealType,const ResizeFilter *),
+ double
+ (*filter)(const double,const ResizeFilter *),
+ (*window)(const double,const ResizeFilter *),
support, /* filter region of support - the filter support limit */
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) */
- coefficient[7]; /* cubic coefficents for BC-cubic spline filters */
+ coefficient[7]; /* cubic coefficents for BC-cubic filters */
size_t
signature;
/*
Forward declaractions.
*/
-static MagickRealType
- I0(MagickRealType x),
- BesselOrderOne(MagickRealType),
- Sinc(const MagickRealType, const ResizeFilter *),
- SincFast(const MagickRealType, const ResizeFilter *);
+static double
+ I0(double x),
+ BesselOrderOne(double),
+ Sinc(const double, const ResizeFilter *),
+ SincFast(const double, const ResizeFilter *);
\f
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% The individual filter functions have this format...
%
-% static MagickRealtype *FilterName(const MagickRealType x,
-% const MagickRealType support)
+% static MagickRealtype *FilterName(const double x,
+% const double support)
%
% A description of each parameter follows:
%
%
*/
-#define MagickPIL ((MagickRealType) 3.14159265358979323846264338327950288420L)
-
-static MagickRealType Blackman(const MagickRealType x,
+static double Blackman(const double x,
const ResizeFilter *magick_unused(resize_filter))
{
/*
Refactored by Chantal Racette and Nicolas Robidoux to one trig call and
five flops.
*/
- const MagickRealType cosine=cos((double) (MagickPIL*x));
+ const double cosine=cos((double) (MagickPI*x));
return(0.34+cosine*(0.5+cosine*0.16));
}
-static MagickRealType Bohman(const MagickRealType x,
+static double Bohman(const double x,
const ResizeFilter *magick_unused(resize_filter))
{
/*
taking advantage of the fact that the support of Bohman is 1.0 (so that we
know that sin(pi x) >= 0).
*/
- const MagickRealType cosine=cos((double) (MagickPIL*x));
- const MagickRealType sine=sqrt(1.0-cosine*cosine);
- return((1.0-x)*cosine+(1.0/MagickPIL)*sine);
+ const double cosine=cos((double) (MagickPI*x));
+ const double sine=sqrt(1.0-cosine*cosine);
+ return((1.0-x)*cosine+(1.0/MagickPI)*sine);
}
-static MagickRealType Box(const MagickRealType magick_unused(x),
+static double Box(const double magick_unused(x),
const ResizeFilter *magick_unused(resize_filter))
{
/*
- A Box filter is a equal weighting function (all weights equal). DO NOT
- LIMIT results by support or resize point sampling will work as it requests
- points beyond its normal 0.0 support size.
+ A Box filter is a equal weighting function (all weights equal).
+ DO NOT LIMIT results by support or resize point sampling will work
+ as it requests points beyond its normal 0.0 support size.
*/
return(1.0);
}
-static MagickRealType CubicBC(const MagickRealType x,
+static double Cosine(const double x,
+ const ResizeFilter *magick_unused(resize_filter))
+{
+ /*
+ Cosine window function:
+ cos((pi/2)*x).
+ */
+ return((double)cos((double) (MagickPI2*x)));
+}
+
+static double CubicBC(const double x,
const ResizeFilter *resize_filter)
{
/*
Cubic Filters using B,C determined values:
- Mitchell-Netravali B= 1/3 C= 1/3 "Balanced" cubic spline filter
- Catmull-Rom B= 0 C= 1/2 Interpolatory and exact on linears
- Cubic B-Spline B= 1 C= 0 Spline approximation of Gaussian
- Hermite B= 0 C= 0 Spline with small support (= 1)
+ Mitchell-Netravali B = 1/3 C = 1/3 "Balanced" cubic spline filter
+ Catmull-Rom B = 0 C = 1/2 Interpolatory and exact on linears
+ Spline B = 1 C = 0 B-Spline Gaussian approximation
+ Hermite B = 0 C = 0 B-Spline interpolator
See paper by Mitchell and Netravali, Reconstruction Filters in Computer
Graphics Computer Graphics, Volume 22, Number 4, August 1988
which ensures function is continuous in value and derivative (slope).
*/
if (x < 1.0)
- return(resize_filter->coefficient[0]+x*(x*(resize_filter->coefficient[1]+x*
- resize_filter->coefficient[2])));
+ return(resize_filter->coefficient[0]+x*(x*
+ (resize_filter->coefficient[1]+x*resize_filter->coefficient[2])));
if (x < 2.0)
return(resize_filter->coefficient[3]+x*(resize_filter->coefficient[4]+x*
(resize_filter->coefficient[5]+x*resize_filter->coefficient[6])));
return(0.0);
}
-static MagickRealType Gaussian(const MagickRealType x,
+static double Gaussian(const double x,
const ResizeFilter *resize_filter)
{
/*
- Gaussian with a fixed sigma = 1/2
+ Gaussian with a sigma = 1/2 (or as user specified)
Gaussian Formula (1D) ...
- exp( -(x^2)/((2.0*sigma^2) ) / sqrt(2*PI)sigma^2))
+ exp( -(x^2)/((2.0*sigma^2) ) / (sqrt(2*PI)*sigma^2))
+
+ Gaussian Formula (2D) ...
+ exp( -(x^2+y^2)/(2.0*sigma^2) ) / (PI*sigma^2) )
+ or for radius
+ exp( -(r^2)/(2.0*sigma^2) ) / (PI*sigma^2) )
+
+ Note that it is only a change from 1-d to radial form is in the
+ normalization multiplier which is not needed or used when Gaussian is used
+ as a filter.
The constants are pre-calculated...
- exp( -coeff[0]*(x^2)) ) * coeff[1]
- However the multiplier coefficent (1) is not needed and not used.
+ coeff[0]=sigma;
+ coeff[1]=1.0/(2.0*sigma^2);
+ coeff[2]=1.0/(sqrt(2*PI)*sigma^2);
- Gaussian Formula (2D) ...
- exp( -(x^2)/((2.0*sigma^2) ) / (PI*sigma^2) )
+ exp( -coeff[1]*(x^2)) ) * coeff[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.
+ However the multiplier coeff[1] is need, the others are informative only.
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.
+ without the filter 'missing' pixels because the support becomes too
+ small.
*/
- return(exp((double)(-resize_filter->coefficient[0]*x*x)));
+ return(exp((double)(-resize_filter->coefficient[1]*x*x)));
}
-static MagickRealType Hanning(const MagickRealType x,
+static double Hann(const double x,
const ResizeFilter *magick_unused(resize_filter))
{
/*
Cosine window function:
0.5+0.5*cos(pi*x).
*/
- const MagickRealType cosine=cos((double) (MagickPIL*x));
+ const double cosine=cos((double) (MagickPI*x));
return(0.5+0.5*cosine);
}
-static MagickRealType Hamming(const MagickRealType x,
+static double Hamming(const double x,
const ResizeFilter *magick_unused(resize_filter))
{
/*
Offset cosine window function:
.54 + .46 cos(pi x).
*/
- const MagickRealType cosine=cos((double) (MagickPIL*x));
+ const double cosine=cos((double) (MagickPI*x));
return(0.54+0.46*cosine);
}
-static MagickRealType Jinc(const MagickRealType x,
+static double Jinc(const double x,
const ResizeFilter *magick_unused(resize_filter))
{
/*
really it is more accurately named "Jinc".
*/
if (x == 0.0)
- return(0.5*MagickPIL);
- return(BesselOrderOne(MagickPIL*x)/x);
+ return(0.5*MagickPI);
+ return(BesselOrderOne(MagickPI*x)/x);
}
-static MagickRealType Kaiser(const MagickRealType x,
- const ResizeFilter *magick_unused(resize_filter))
+static double Kaiser(const double x,
+ const ResizeFilter *resize_filter)
{
-#define Alpha 6.5
-#define I0A (1.0/I0(Alpha))
-
/*
- Kaiser Windowing Function (bessel windowing): Alpha is a free value
- from 5 to 8 (currently hardcoded to 6.5). Future: make alpha the IOA
- pre-calculation, an 'expert' setting.
+ Kaiser Windowing Function (bessel windowing)
+
+ I0( beta * sqrt( 1-x^2) ) / IO(0)
+
+ Beta (coeff[0]) is a free value from 5 to 8 (defaults to 6.5).
+ However it is typically defined in terms of Alpha*PI
+
+ The normalization factor (coeff[1]) is not actually needed,
+ but without it the filters has a large value at x=0 making it
+ difficult to compare the function with other windowing functions.
*/
- return(I0A*I0(Alpha*sqrt((double) (1.0-x*x))));
+ return(resize_filter->coefficient[1]*
+ I0(resize_filter->coefficient[0]*sqrt((double) (1.0-x*x))));
}
-static MagickRealType Lagrange(const MagickRealType x,
+static double Lagrange(const double x,
const ResizeFilter *resize_filter)
{
- MagickRealType
+ double
value;
register ssize_t
return(value);
}
-static MagickRealType Quadratic(const MagickRealType x,
+static double Quadratic(const double x,
const ResizeFilter *magick_unused(resize_filter))
{
/*
return(0.0);
}
-static MagickRealType Sinc(const MagickRealType x,
+static double Sinc(const double x,
const ResizeFilter *magick_unused(resize_filter))
{
/*
*/
if (x != 0.0)
{
- const MagickRealType alpha=(MagickRealType) (MagickPIL*x);
+ const double alpha=(double) (MagickPI*x);
return(sin((double) alpha)/alpha);
}
- return((MagickRealType) 1.0);
+ return((double) 1.0);
}
-static MagickRealType SincFast(const MagickRealType x,
+static double SincFast(const double x,
const ResizeFilter *magick_unused(resize_filter))
{
/*
*/
if (x > 4.0)
{
- const MagickRealType alpha=(MagickRealType) (MagickPIL*x);
+ const double alpha=(double) (MagickPI*x);
return(sin((double) alpha)/alpha);
}
{
/*
The approximations only depend on x^2 (sinc is an even function).
*/
- const MagickRealType xx = x*x;
+ const double xx = x*x;
#if MAGICKCORE_QUANTUM_DEPTH <= 8
/*
Maximum absolute relative error 6.3e-6 < 1/2^17.
*/
- const MagickRealType c0 = 0.173610016489197553621906385078711564924e-2L;
- const MagickRealType c1 = -0.384186115075660162081071290162149315834e-3L;
- const MagickRealType c2 = 0.393684603287860108352720146121813443561e-4L;
- const MagickRealType c3 = -0.248947210682259168029030370205389323899e-5L;
- const MagickRealType c4 = 0.107791837839662283066379987646635416692e-6L;
- const MagickRealType c5 = -0.324874073895735800961260474028013982211e-8L;
- const MagickRealType c6 = 0.628155216606695311524920882748052490116e-10L;
- const MagickRealType c7 = -0.586110644039348333520104379959307242711e-12L;
- const MagickRealType p =
+ const double c0 = 0.173610016489197553621906385078711564924e-2L;
+ const double c1 = -0.384186115075660162081071290162149315834e-3L;
+ const double c2 = 0.393684603287860108352720146121813443561e-4L;
+ const double c3 = -0.248947210682259168029030370205389323899e-5L;
+ const double c4 = 0.107791837839662283066379987646635416692e-6L;
+ const double c5 = -0.324874073895735800961260474028013982211e-8L;
+ const double c6 = 0.628155216606695311524920882748052490116e-10L;
+ const double c7 = -0.586110644039348333520104379959307242711e-12L;
+ const double p =
c0+xx*(c1+xx*(c2+xx*(c3+xx*(c4+xx*(c5+xx*(c6+xx*c7))))));
return((xx-1.0)*(xx-4.0)*(xx-9.0)*(xx-16.0)*p);
#elif MAGICKCORE_QUANTUM_DEPTH <= 16
/*
Max. abs. rel. error 2.2e-8 < 1/2^25.
*/
- const MagickRealType c0 = 0.173611107357320220183368594093166520811e-2L;
- const MagickRealType c1 = -0.384240921114946632192116762889211361285e-3L;
- const MagickRealType c2 = 0.394201182359318128221229891724947048771e-4L;
- const MagickRealType c3 = -0.250963301609117217660068889165550534856e-5L;
- const MagickRealType c4 = 0.111902032818095784414237782071368805120e-6L;
- const MagickRealType c5 = -0.372895101408779549368465614321137048875e-8L;
- const MagickRealType c6 = 0.957694196677572570319816780188718518330e-10L;
- const MagickRealType c7 = -0.187208577776590710853865174371617338991e-11L;
- const MagickRealType c8 = 0.253524321426864752676094495396308636823e-13L;
- const MagickRealType c9 = -0.177084805010701112639035485248501049364e-15L;
- const MagickRealType p =
+ const double c0 = 0.173611107357320220183368594093166520811e-2L;
+ const double c1 = -0.384240921114946632192116762889211361285e-3L;
+ const double c2 = 0.394201182359318128221229891724947048771e-4L;
+ const double c3 = -0.250963301609117217660068889165550534856e-5L;
+ const double c4 = 0.111902032818095784414237782071368805120e-6L;
+ const double c5 = -0.372895101408779549368465614321137048875e-8L;
+ const double c6 = 0.957694196677572570319816780188718518330e-10L;
+ const double c7 = -0.187208577776590710853865174371617338991e-11L;
+ const double c8 = 0.253524321426864752676094495396308636823e-13L;
+ const double c9 = -0.177084805010701112639035485248501049364e-15L;
+ const double p =
c0+xx*(c1+xx*(c2+xx*(c3+xx*(c4+xx*(c5+xx*(c6+xx*(c7+xx*(c8+xx*c9))))))));
return((xx-1.0)*(xx-4.0)*(xx-9.0)*(xx-16.0)*p);
#else
/*
Max. abs. rel. error 1.2e-12 < 1/2^39.
*/
- const MagickRealType c0 = 0.173611111110910715186413700076827593074e-2L;
- const MagickRealType c1 = -0.289105544717893415815859968653611245425e-3L;
- const MagickRealType c2 = 0.206952161241815727624413291940849294025e-4L;
- const MagickRealType c3 = -0.834446180169727178193268528095341741698e-6L;
- const MagickRealType c4 = 0.207010104171026718629622453275917944941e-7L;
- const MagickRealType c5 = -0.319724784938507108101517564300855542655e-9L;
- const MagickRealType c6 = 0.288101675249103266147006509214934493930e-11L;
- const MagickRealType c7 = -0.118218971804934245819960233886876537953e-13L;
- const MagickRealType p =
+ const double c0 = 0.173611111110910715186413700076827593074e-2L;
+ const double c1 = -0.289105544717893415815859968653611245425e-3L;
+ const double c2 = 0.206952161241815727624413291940849294025e-4L;
+ const double c3 = -0.834446180169727178193268528095341741698e-6L;
+ const double c4 = 0.207010104171026718629622453275917944941e-7L;
+ const double c5 = -0.319724784938507108101517564300855542655e-9L;
+ const double c6 = 0.288101675249103266147006509214934493930e-11L;
+ const double c7 = -0.118218971804934245819960233886876537953e-13L;
+ const double p =
c0+xx*(c1+xx*(c2+xx*(c3+xx*(c4+xx*(c5+xx*(c6+xx*c7))))));
- const MagickRealType d0 = 1.0L;
- const MagickRealType d1 = 0.547981619622284827495856984100563583948e-1L;
- const MagickRealType d2 = 0.134226268835357312626304688047086921806e-2L;
- const MagickRealType d3 = 0.178994697503371051002463656833597608689e-4L;
- const MagickRealType d4 = 0.114633394140438168641246022557689759090e-6L;
- const MagickRealType q = d0+xx*(d1+xx*(d2+xx*(d3+xx*d4)));
+ const double d0 = 1.0L;
+ const double d1 = 0.547981619622284827495856984100563583948e-1L;
+ const double d2 = 0.134226268835357312626304688047086921806e-2L;
+ const double d3 = 0.178994697503371051002463656833597608689e-4L;
+ const double d4 = 0.114633394140438168641246022557689759090e-6L;
+ const double q = d0+xx*(d1+xx*(d2+xx*(d3+xx*d4)));
return((xx-1.0)*(xx-4.0)*(xx-9.0)*(xx-16.0)/q*p);
#endif
}
}
-static MagickRealType Triangle(const MagickRealType x,
+static double Triangle(const double x,
const ResizeFilter *magick_unused(resize_filter))
{
/*
return(0.0);
}
-static MagickRealType Welsh(const MagickRealType x,
+static double Welch(const double x,
const ResizeFilter *magick_unused(resize_filter))
{
/*
- Welsh parabolic windowing filter.
+ Welch parabolic windowing filter.
*/
if (x < 1.0)
return(1.0-x*x);
% these filters:
%
% FIR (Finite impulse Response) Filters
-% Box Triangle Quadratic Cubic Hermite Catrom Mitchell
+% Box Triangle Quadratic
+% Spline Hermite Catrom
+% Mitchell
%
% IIR (Infinite impulse Response) Filters
-% Gaussian Sinc Jinc (Bessel)
+% Gaussian Sinc Jinc (Bessel)
%
% Windowed Sinc/Jinc Filters
-% Blackman Hanning Hamming Kaiser Lanczos
+% Blackman Bohman Lanczos
+% Hann Hamming Cosine
+% Kaiser Welch Parzen
+% Bartlett
%
-% Special purpose Filters
-% SincFast LanczosSharp Lanczos2D Lanczos2DSharp Robidoux
+% Special Purpose Filters
+% Cubic SincFast LanczosSharp Lanczos2 Lanczos2Sharp
+% Robidoux RobidouxSharp
%
% The users "-filter" selection is used to lookup the default 'expert'
% settings for that filter from a internal table. However any provided
% suited to this style of image resampling. This typically happens when using
% such a filter for images distortions.
%
+% SPECIFIC FILTERS:
+%
% 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
% crossing is at (36 sqrt(2) + 123)/(72 sqrt(2) + 47), almost the same as the
% first crossing of Mitchell and Lanczos2Sharp.
%
+% RodidouxSharp is a slightly sharper version of Rodidoux, some believe it
+% is too sharp. It is designed to minimize the maximum possible change in
+% a pixel value which is at one of the extremes (e.g., 0 or 255) under no-op
+% conditions. Amazingly Mitchell falls roughly between Rodidoux and
+% RodidouxSharp, though this seems to have been pure coincidence.
+%
% 'EXPERT' OPTIONS:
%
% These artifact "defines" are not recommended for production use without
% using it for Distort.
%
% "filter:b"
-% "filter:c" Override the preset B,C values for a Cubic type of filter.
+% "filter:c" Override the preset B,C values for a Cubic 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.
%
% The format of the AcquireResizeFilter method is:
%
% ResizeFilter *AcquireResizeFilter(const Image *image,
-% const FilterTypes filter_type, const MagickBooleanType radial,
+% const FilterTypes filter_type,const MagickBooleanType cylindrical,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
% o exception: return any errors or warnings in this structure.
%
*/
-MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
- const FilterTypes filter,const MagickRealType blur,
- const MagickBooleanType cylindrical,ExceptionInfo *exception)
+MagickPrivate ResizeFilter *AcquireResizeFilter(const Image *image,
+ const FilterTypes filter,const MagickBooleanType cylindrical,
+ ExceptionInfo *exception)
{
const char
*artifact;
filter_type,
window_type;
- MagickRealType
+ double
B,
C,
- sigma;
+ value;
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" is requested, unless a 'Sinc' or 'SincFast' filter was
+ specifically requested by the user.
- WARNING: The order of this tabel must match the order of the FilterTypes
+ WARNING: The order of this table 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.
+ You can check filter setups with the "filter:verbose" expert setting.
*/
static struct
{
{ BoxFilter, BoxFilter }, /* Box averaging filter */
{ TriangleFilter, BoxFilter }, /* Linear interpolation filter */
{ HermiteFilter, BoxFilter }, /* Hermite interpolation filter */
- { SincFastFilter, HanningFilter }, /* Hanning -- cosine-sinc */
- { SincFastFilter, HammingFilter }, /* Hamming -- '' variation */
+ { SincFastFilter, HannFilter }, /* Hann -- cosine-sinc */
+ { SincFastFilter, HammingFilter }, /* Hamming -- '' variation */
{ SincFastFilter, BlackmanFilter }, /* Blackman -- 2*cosine-sinc */
{ GaussianFilter, BoxFilter }, /* Gaussian blur filter */
{ QuadraticFilter, BoxFilter }, /* Quadratic Gaussian approx */
- { CubicFilter, BoxFilter }, /* Cubic B-Spline */
+ { CubicFilter, BoxFilter }, /* General Cubic Filter, Spline */
{ CatromFilter, BoxFilter }, /* Cubic-Keys interpolator */
{ MitchellFilter, BoxFilter }, /* 'Ideal' Cubic-Keys filter */
{ JincFilter, BoxFilter }, /* Raw 3-lobed Jinc function */
{ SincFilter, BoxFilter }, /* Raw 4-lobed Sinc function */
{ SincFastFilter, BoxFilter }, /* Raw fast sinc ("Pade"-type) */
{ SincFastFilter, KaiserFilter }, /* Kaiser -- square root-sinc */
- { SincFastFilter, WelshFilter }, /* Welsh -- parabolic-sinc */
+ { LanczosFilter, WelchFilter }, /* Welch -- parabolic (3 lobe) */
{ SincFastFilter, CubicFilter }, /* Parzen -- cubic-sinc */
{ SincFastFilter, BohmanFilter }, /* Bohman -- 2*cosine-sinc */
{ SincFastFilter, TriangleFilter }, /* Bartlett -- triangle-sinc */
{ Lanczos2Filter, Lanczos2Filter }, /* | special handling */
{ Lanczos2SharpFilter, Lanczos2SharpFilter },
{ RobidouxFilter, BoxFilter }, /* Cubic Keys tuned for EWA */
+ { RobidouxSharpFilter, BoxFilter }, /* Sharper Cubic Keys for EWA */
+ { LanczosFilter, CosineFilter }, /* Cosine window (3 lobes) */
+ { SplineFilter, BoxFilter }, /* Spline Cubic Filter */
};
/*
Table mapping the filter/window from the above table to an actual function.
*/
static struct
{
- MagickRealType
- (*function)(const MagickRealType,const ResizeFilter*),
- lobes, /* Default lobes/support size of the weighting filter. */
- scale, /* Support when function used as a windowing function. Typically
- equal to the location of the first zero crossing. */
- B,
- C; /* BC-spline coefficients, ignored if not a CubicBC filter. */
+ double
+ (*function)(const double,const ResizeFilter*),
+ support, /* Default lobes/support size of the weighting filter. */
+ scale, /* Support when function used as a windowing function
+ Typically equal to the location of the first zero crossing. */
+ B,C; /* BC-spline coefficients, ignored if not a CubicBC filter. */
} const filters[SentinelFilter] =
{
+ /* .--- support window (if used as Weighting Function)
+ | .--- first crossing (if used as a Windowing Function)
+ | | .--- B value for Cubic Function
+ | | | .---- C value for Cubic Function
+ | | | | */
{ Box, 0.5, 0.5, 0.0, 0.0 }, /* Undefined (default to Box) */
{ Box, 0.0, 0.5, 0.0, 0.0 }, /* Point (special handling) */
{ Box, 0.5, 0.5, 0.0, 0.0 }, /* Box */
{ Triangle, 1.0, 1.0, 0.0, 0.0 }, /* Triangle */
{ CubicBC, 1.0, 1.0, 0.0, 0.0 }, /* Hermite (cubic B=C=0) */
- { Hanning, 1.0, 1.0, 0.0, 0.0 }, /* Hanning, cosine window */
+ { Hann, 1.0, 1.0, 0.0, 0.0 }, /* Hann, cosine window */
{ Hamming, 1.0, 1.0, 0.0, 0.0 }, /* Hamming, '' variation */
{ Blackman, 1.0, 1.0, 0.0, 0.0 }, /* Blackman, 2*cosine window */
{ Gaussian, 2.0, 1.5, 0.0, 0.0 }, /* Gaussian */
{ Quadratic, 1.5, 1.5, 0.0, 0.0 }, /* Quadratic gaussian */
- { CubicBC, 2.0, 2.0, 1.0, 0.0 }, /* Cubic B-Spline (B=1,C=0) */
+ { CubicBC, 2.0, 2.0, 1.0, 0.0 }, /* General Cubic Filter */
{ CubicBC, 2.0, 1.0, 0.0, 0.5 }, /* Catmull-Rom (B=0,C=1/2) */
{ CubicBC, 2.0, 8.0/7.0, 1./3., 1./3. }, /* Mitchell (B=C=1/3) */
{ Jinc, 3.0, 1.2196698912665045, 0.0, 0.0 }, /* Raw 3-lobed Jinc */
{ Sinc, 4.0, 1.0, 0.0, 0.0 }, /* Raw 4-lobed Sinc */
{ SincFast, 4.0, 1.0, 0.0, 0.0 }, /* Raw fast sinc ("Pade"-type) */
{ Kaiser, 1.0, 1.0, 0.0, 0.0 }, /* Kaiser (square root window) */
- { Welsh, 1.0, 1.0, 0.0, 0.0 }, /* Welsh (parabolic window) */
+ { Welch, 1.0, 1.0, 0.0, 0.0 }, /* Welch (parabolic window) */
{ CubicBC, 2.0, 2.0, 1.0, 0.0 }, /* Parzen (B-Spline window) */
{ Bohman, 1.0, 1.0, 0.0, 0.0 }, /* Bohman, 2*Cosine window */
{ Triangle, 1.0, 1.0, 0.0, 0.0 }, /* Bartlett (triangle window) */
{ Lagrange, 2.0, 1.0, 0.0, 0.0 }, /* Lagrange sinc approximation */
{ SincFast, 3.0, 1.0, 0.0, 0.0 }, /* Lanczos, 3-lobed Sinc-Sinc */
- { SincFast, 3.0, 1.0, 0.0, 0.0 }, /* lanczos, Sharpened */
+ { SincFast, 3.0, 1.0, 0.0, 0.0 }, /* Lanczos, Sharpened */
{ SincFast, 2.0, 1.0, 0.0, 0.0 }, /* Lanczos, 2-lobed */
{ SincFast, 2.0, 1.0, 0.0, 0.0 }, /* Lanczos2, sharpened */
- { CubicBC, 2.0, 1.1685777620836932, 0.37821575509399867,
- 0.31089212245300067 }
- /* Robidoux: Keys cubic close to Lanczos2D sharpened */
+ /* Robidoux: Keys cubic close to Lanczos2D sharpened */
+ { CubicBC, 2.0, 1.1685777620836932,
+ 0.37821575509399867, 0.31089212245300067 },
+ /* RobidouxSharp: Sharper version of Robidoux */
+ { CubicBC, 2.0, 1.105822933719019,
+ 0.2620145123990142, 0.3689927438004929 },
+ { Cosine, 1.0, 1.0, 0.0, 0.0 }, /* Low level cosine window */
+ { CubicBC, 2.0, 2.0, 1.0, 0.0 }, /* Cubic B-Spline (B=1,C=0) */
};
/*
The known zero crossings of the Jinc() or more accurately the Jinc(x*PI)
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.
+ Values taken from
+ http://cose.math.bas.bg/webMathematica/webComputing/BesselZeros.jsp
+ using Jv-function with v=1, then dividing by PI.
*/
- static MagickRealType
+ static double
jinc_zeros[16] =
{
1.2196698912665045,
*/
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(UndefinedFilter < filter && filter < SentinelFilter);
assert(exception != (ExceptionInfo *) NULL);
*/
filter_type=mapping[filter].filter;
window_type=mapping[filter].window;
- resize_filter->blur = blur; /* function argument blur factor */
- sigma=0.5; /* gaussian sigma of half a pixel by default */
- if ((cylindrical != MagickFalse) && (filter_type == SincFastFilter) &&
+ resize_filter->blur=1.0;
+ /* Promote 1D Windowed Sinc Filters to a 2D Windowed Jinc filters */
+ if( IfMagickTrue(cylindrical) && (filter_type == SincFastFilter) &&
(filter != SincFastFilter))
filter_type=JincFilter; /* 1D Windowed Sinc => 2D Windowed Jinc filters */
+
+ /* Expert filter setting override */
artifact=GetImageArtifact(image,"filter:filter");
if (artifact != (const char *) NULL)
{
ssize_t
option;
- /*
- Expert filter setting override.
- */
option=ParseCommandOption(MagickFilterOptions,MagickFalse,artifact);
if ((UndefinedFilter < option) && (option < SentinelFilter))
- {
- /*
- Raw filter request - no window function.
- */
+ { /* Raw filter request - no window function. */
filter_type=(FilterTypes) option;
window_type=BoxFilter;
}
+ /* Filter override with a specific window function. */
artifact=GetImageArtifact(image,"filter:window");
if (artifact != (const char *) NULL)
{
- /*
- Filter override with a specific window function.
- */
option=ParseCommandOption(MagickFilterOptions,MagickFalse,artifact);
if ((UndefinedFilter < option) && (option < SentinelFilter))
window_type=(FilterTypes) option;
}
else
{
+ /* Window specified, but no filter function? Assume Sinc/Jinc. */
artifact=GetImageArtifact(image,"filter:window");
if (artifact != (const char *) NULL)
{
ssize_t
option;
- /*
- Window specified, but no filter function? Assume Sinc/Jinc.
- */
option=ParseCommandOption(MagickFilterOptions,MagickFalse,artifact);
if ((UndefinedFilter < option) && (option < SentinelFilter))
{
- filter_type=cylindrical != MagickFalse ? JincFilter :
- SincFastFilter;
+ filter_type= IfMagickTrue(cylindrical) ? JincFilter
+ : SincFastFilter;
window_type=(FilterTypes) option;
}
}
}
- /*
- Assign the real functions to use for the filters selected.
- */
+
+ /* Assign the real functions to use for the filters selected. */
resize_filter->filter=filters[filter_type].function;
- resize_filter->support=filters[filter_type].lobes;
+ resize_filter->support=filters[filter_type].support;
resize_filter->window=filters[window_type].function;
resize_filter->scale=filters[window_type].scale;
resize_filter->signature=MagickSignature;
- /*
- Filter Modifications for orthogonal/cylindrical usage.
- */
+
+ /* Filter Modifications for orthogonal/cylindrical usage */
if (cylindrical != MagickFalse)
switch (filter_type)
{
case BoxFilter:
- {
- /*
- Support for Cylindrical Box should be sqrt(2)/2.
- */
- resize_filter->support=(MagickRealType) MagickSQ1_2;
+ /* Support for Cylindrical Box should be sqrt(2)/2 */
+ resize_filter->support=(double) MagickSQ1_2;
break;
- }
case LanczosFilter:
case LanczosSharpFilter:
case Lanczos2Filter:
case Lanczos2SharpFilter:
- {
- /*
- Number of lobes (support window size) remain unchanged.
- */
resize_filter->filter=filters[JincFilter].function;
resize_filter->window=filters[JincFilter].function;
resize_filter->scale=filters[JincFilter].scale;
+ /* number of lobes (support window size) remain unchanged */
break;
- }
default:
break;
}
- /*
- Global Sharpening (regardless of orthoginal/cylindrical).
- */
+ /* Global Sharpening (regardless of orthoginal/cylindrical) */
switch (filter_type)
{
case LanczosSharpFilter:
- {
- resize_filter->blur*=0.9812505644269356;
+ resize_filter->blur *= 0.9812505644269356;
break;
- }
case Lanczos2SharpFilter:
- {
- resize_filter->blur*=0.9549963639785485;
+ resize_filter->blur *= 0.9549963639785485;
break;
- }
default:
break;
}
- artifact=GetImageArtifact(image,"filter:sigma");
- if (artifact != (const char *) NULL)
- sigma=InterpretLocaleValue(artifact,(char **) NULL); /* override sigma */
- if (GaussianFilter != (FilterTypes) NULL)
- {
- /*
- Define coefficents for Gaussian.
- */
- 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 */
- }
+
+ /*
+ Expert Option Modifications.
+ */
+
+ /* User Gaussian Sigma Override - no support change */
+ if ((resize_filter->filter == Gaussian) ||
+ (resize_filter->window == Gaussian) ) {
+ value=0.5; /* guassian sigma default, half pixel */
+ artifact=GetImageArtifact(image,"filter:sigma");
+ if (artifact != (const char *) NULL)
+ value=StringToDouble(artifact,(char **) NULL);
+ /* Define coefficents for Gaussian */
+ resize_filter->coefficient[0]=value; /* note sigma too */
+ resize_filter->coefficient[1]=MagickEpsilonReciprocal(2.0*value*value); /* sigma scaling */
+ resize_filter->coefficient[2]=MagickEpsilonReciprocal(Magick2PI*value*value);
+ /* normalization - not actually needed or used! */
+ if ( value > 0.5 )
+ resize_filter->support *= value/0.5; /* increase support */
+ }
+
+ /* User Kaiser Alpha Override - no support change */
+ if ((resize_filter->filter == Kaiser) ||
+ (resize_filter->window == Kaiser) ) {
+ value=6.5; /* default beta value for Kaiser bessel windowing function */
+ artifact=GetImageArtifact(image,"filter:alpha"); /* FUTURE: depreciate */
+ if (artifact != (const char *) NULL)
+ value=StringToDouble(artifact,(char **) NULL);
+ artifact=GetImageArtifact(image,"filter:kaiser-beta");
+ if (artifact != (const char *) NULL)
+ value=StringToDouble(artifact,(char **) NULL);
+ artifact=GetImageArtifact(image,"filter:kaiser-alpha");
+ if (artifact != (const char *) NULL)
+ value=StringToDouble(artifact,(char **) NULL)*MagickPI;
+ /* Define coefficents for Kaiser Windowing Function */
+ resize_filter->coefficient[0]=value; /* alpha */
+ resize_filter->coefficient[1]=MagickEpsilonReciprocal(I0(value)); /* normalization */
+ }
+
+ /* Blur Override */
artifact=GetImageArtifact(image,"filter:blur");
if (artifact != (const char *) NULL)
- resize_filter->blur*=InterpretLocaleValue(artifact,
- (char **) NULL); /* override blur */
+ resize_filter->blur*=StringToDouble(artifact,(char **) NULL);
if (resize_filter->blur < MagickEpsilon)
- resize_filter->blur=(MagickRealType) MagickEpsilon;
+ resize_filter->blur=(double) MagickEpsilon;
+
+ /* Support Overrides */
artifact=GetImageArtifact(image,"filter:lobes");
if (artifact != (const char *) NULL)
{
- /*
- Override lobes.
- */
- ssize_t lobes=(ssize_t) StringToLong(artifact);
+ ssize_t
+ lobes;
+
+ lobes=(ssize_t) StringToLong(artifact);
if (lobes < 1)
lobes=1;
- resize_filter->support=(MagickRealType) lobes;
+ resize_filter->support=(double) lobes;
}
+ /* Convert a Jinc function lobes value to a real support value */
if (resize_filter->filter == Jinc)
{
- /*
- Convert a Jinc function lobes value to a real support value.
- */
if (resize_filter->support > 16)
resize_filter->support=jinc_zeros[15]; /* largest entry in table */
else
resize_filter->support=jinc_zeros[((long)resize_filter->support)-1];
}
+ /* expert override of the support setting */
artifact=GetImageArtifact(image,"filter:support");
if (artifact != (const char *) NULL)
- resize_filter->support=fabs(InterpretLocaleValue(artifact,
- (char **) NULL)); /* override support */
+ resize_filter->support=fabs(StringToDouble(artifact,(char **) NULL));
/*
- Scale windowing function separately to the support 'clipping' window that
- calling operator is planning to actually use (expert override).
+ Scale windowing function separately to the support 'clipping'
+ window that calling operator is planning to actually use. (Expert
+ override)
*/
resize_filter->window_support=resize_filter->support; /* default */
artifact=GetImageArtifact(image,"filter:win-support");
if (artifact != (const char *) NULL)
- resize_filter->window_support=fabs(InterpretLocaleValue(artifact,
- (char **) NULL));
+ resize_filter->window_support=fabs(StringToDouble(artifact,(char **) NULL));
/*
- Adjust window function scaling to match windowing support for weighting
- function. This avoids a division on every filter call.
+ Adjust window function scaling to match windowing support for
+ weighting function. This avoids a division on every filter call.
*/
resize_filter->scale/=resize_filter->window_support;
+
/*
- Set Cubic Spline B,C values, calculate cubic coefficients.
+ * Set Cubic Spline B,C values, calculate Cubic coefficients.
*/
B=0.0;
C=0.0;
- if ((filters[filter_type].function == CubicBC) ||
- (filters[window_type].function == CubicBC))
+ if ((resize_filter->filter == CubicBC) ||
+ (resize_filter->window == CubicBC) )
{
B=filters[filter_type].B;
C=filters[filter_type].C;
artifact=GetImageArtifact(image,"filter:b");
if (artifact != (const char *) NULL)
{
- B=InterpretLocaleValue(artifact,(char **) NULL);
+ B=StringToDouble(artifact,(char **) NULL);
C=(1.0-B)/2.0; /* Calculate C to get a Keys cubic filter. */
artifact=GetImageArtifact(image,"filter:c"); /* user C override */
if (artifact != (const char *) NULL)
- C=InterpretLocaleValue(artifact,(char **) NULL);
+ C=StringToDouble(artifact,(char **) NULL);
}
else
{
artifact=GetImageArtifact(image,"filter:c");
if (artifact != (const char *) NULL)
{
- C=InterpretLocaleValue(artifact,(char **) NULL);
+ C=StringToDouble(artifact,(char **) NULL);
B=1.0-2.0*C; /* Calculate B to get a Keys cubic filter. */
}
}
+ /* Convert B,C values into Cubic Coefficents. See CubicBC(). */
{
- double
- B_squared;
-
- /*
- Convert B,C values into Cubic Coefficents. See CubicBC().
- */
- B_squared=B+B;
+ const double twoB = B+B;
resize_filter->coefficient[0]=1.0-(1.0/3.0)*B;
- resize_filter->coefficient[1]=-3.0+B_squared+C;
+ 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-B_squared;
+ 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;
}
}
+
/*
- Expert option request for verbose details of the resulting filter.
+ Expert Option Request for verbose details of the resulting filter.
*/
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp master
{
#endif
- artifact=GetImageArtifact(image,"filter:verbose");
- if (IsMagickTrue(artifact) != MagickFalse)
+ if (IfStringTrue(GetImageArtifact(image,"filter:verbose")))
{
double
support,
x;
/*
- Set the weighting function properly when the weighting function may
- not exactly match the filter of the same name. EG: a point filter
- really uses a box weighting function with a different support than is
- typically used.
+ Set the weighting function properly when the weighting
+ function may not exactly match the filter of the same name.
+ EG: a Point filter is really uses a Box weighting function
+ with a different support than is typically used.
*/
- if (resize_filter->filter == Box)
- filter_type=BoxFilter;
- if (resize_filter->filter == Sinc)
- filter_type=SincFilter;
- 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->window == Box)
- window_type=BoxFilter;
- if (resize_filter->window == Sinc)
- window_type=SincFilter;
- if (resize_filter->window == SincFast)
- window_type=SincFastFilter;
- if (resize_filter->window == Jinc)
- window_type=JincFilter;
- if (resize_filter->window == CubicBC)
- window_type=CubicFilter;
+ if (resize_filter->filter == Box) filter_type=BoxFilter;
+ if (resize_filter->filter == Sinc) filter_type=SincFilter;
+ 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->window == Box) window_type=BoxFilter;
+ if (resize_filter->window == Sinc) window_type=SincFilter;
+ if (resize_filter->window == SincFast) window_type=SincFastFilter;
+ if (resize_filter->window == Jinc) window_type=JincFilter;
+ if (resize_filter->window == CubicBC) window_type=CubicFilter;
/*
- Report filter details.
+ Report Filter Details.
*/
support=GetResizeFilterSupport(resize_filter); /* practical_support */
(void) FormatLocaleFile(stdout,"# Resize Filter (for graphing)\n#\n");
(void) FormatLocaleFile(stdout,"# filter = %s\n",
- CommandOptionToMnemonic(MagickFilterOptions,filter_type));
+ CommandOptionToMnemonic(MagickFilterOptions,filter_type));
(void) FormatLocaleFile(stdout,"# window = %s\n",
- CommandOptionToMnemonic(MagickFilterOptions, window_type));
+ CommandOptionToMnemonic(MagickFilterOptions,window_type));
(void) FormatLocaleFile(stdout,"# support = %.*g\n",
- GetMagickPrecision(),(double) resize_filter->support);
- (void) FormatLocaleFile(stdout,"# win-support = %.*g\n",
- GetMagickPrecision(),(double) resize_filter->window_support);
- (void) FormatLocaleFile(stdout,"# scale_blur = %.*g\n",
- GetMagickPrecision(), (double)resize_filter->blur);
- if (filter_type == GaussianFilter)
- (void) FormatLocaleFile(stdout,"# gaussian_sigma = %.*g\n",
- GetMagickPrecision(), (double)sigma);
- (void) FormatLocaleFile(stdout,"# practical_support = %.*g\n",
- GetMagickPrecision(), (double)support);
+ GetMagickPrecision(),(double) resize_filter->support);
+ (void) FormatLocaleFile(stdout,"# window-support = %.*g\n",
+ GetMagickPrecision(),(double) resize_filter->window_support);
+ (void) FormatLocaleFile(stdout,"# scale-blur = %.*g\n",
+ GetMagickPrecision(), (double)resize_filter->blur);
+ if ( filter_type == GaussianFilter || window_type == GaussianFilter )
+ (void) FormatLocaleFile(stdout,"# gaussian-sigma = %.*g\n",
+ GetMagickPrecision(), (double)resize_filter->coefficient[0]);
+ if ( filter_type == KaiserFilter || window_type == KaiserFilter )
+ (void) FormatLocaleFile(stdout,"# kaiser-beta = %.*g\n",
+ GetMagickPrecision(),
+ (double)resize_filter->coefficient[0]);
+ (void) FormatLocaleFile(stdout,"# practical-support = %.*g\n",
+ GetMagickPrecision(), (double)support);
if ( filter_type == CubicFilter || window_type == CubicFilter )
(void) FormatLocaleFile(stdout,"# B,C = %.*g,%.*g\n",
- GetMagickPrecision(),(double)B, GetMagickPrecision(),(double)C);
+ GetMagickPrecision(),(double)B, GetMagickPrecision(),(double)C);
(void) FormatLocaleFile(stdout,"\n");
/*
- Output values of resulting filter graph -- for graphing filter result.
+ Output values of resulting filter graph -- for graphing
+ filter result.
*/
for (x=0.0; x <= support; x+=0.01f)
- (void) FormatLocaleFile(stdout,"%5.2lf\t%.*g\n",x,
- GetMagickPrecision(),(double) GetResizeFilterWeight(resize_filter,
- x));
- /*
- A final value so gnuplot can graph the 'stop' properly.
- */
+ (void) FormatLocaleFile(stdout,"%5.2lf\t%.*g\n",x,GetMagickPrecision(),
+ (double) GetResizeFilterWeight(resize_filter,x));
+ /* A final value so gnuplot can graph the 'stop' properly. */
(void) FormatLocaleFile(stdout,"%5.2lf\t%.*g\n",support,
GetMagickPrecision(),0.0);
}
- /*
- Output the above once only for each image - remove setting.
- */
+ /* Output the above once only for each image - remove setting */
(void) DeleteImageArtifact((Image *) image,"filter:verbose");
#if defined(MAGICKCORE_OPENMP_SUPPORT)
}
%
% AdaptiveResizeImage() adaptively resize image with pixel resampling.
%
+% This is shortcut function for a fast interpolative resize using mesh
+% interpolation. It works well for small resizes of less than +/- 50%
+% of the original image size. For larger resizing on images a full
+% filtered and slower resize function should be used instead.
+%
% The format of the AdaptiveResizeImage method is:
%
% Image *AdaptiveResizeImage(const Image *image,const size_t columns,
MagickExport Image *AdaptiveResizeImage(const Image *image,
const size_t columns,const size_t rows,ExceptionInfo *exception)
{
-#define AdaptiveResizeImageTag "Resize/Image"
-
- CacheView
- *image_view,
- *interpolate_view,
- *resize_view;
-
- Image
- *resize_image;
-
- MagickBooleanType
- status;
-
- MagickOffsetType
- progress;
-
- ssize_t
- y;
-
- /*
- Adaptively resize image.
- */
- assert(image != (const Image *) NULL);
- assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
- assert(exception != (ExceptionInfo *) NULL);
- assert(exception->signature == MagickSignature);
- if ((columns == 0) || (rows == 0))
- return((Image *) NULL);
- if ((columns == image->columns) && (rows == image->rows))
- return(CloneImage(image,0,0,MagickTrue,exception));
- resize_image=CloneImage(image,columns,rows,MagickTrue,exception);
- if (resize_image == (Image *) NULL)
- return((Image *) NULL);
- if (SetImageStorageClass(resize_image,DirectClass,exception) == MagickFalse)
- {
- resize_image=DestroyImage(resize_image);
- return((Image *) NULL);
- }
- status=MagickTrue;
- progress=0;
- image_view=AcquireCacheView(image);
- interpolate_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++)
- {
- PointInfo
- offset;
-
- register const Quantum
- *restrict p;
-
- register Quantum
- *restrict q;
-
- register ssize_t
- x;
-
- if (status == MagickFalse)
- continue;
- p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
- q=QueueCacheViewAuthenticPixels(resize_view,0,y,resize_image->columns,1,
- exception);
- if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
- continue;
- offset.y=((MagickRealType) (y+0.5)*image->rows/resize_image->rows);
- for (x=0; x < (ssize_t) resize_image->columns; x++)
- {
- register ssize_t
- i;
-
- offset.x=((MagickRealType) (x+0.5)*image->columns/resize_image->columns);
- for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
- {
- double
- pixel;
-
- PixelChannel
- channel;
-
- PixelTrait
- resize_traits,
- traits;
-
- traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
- if (traits == UndefinedPixelTrait)
- continue;
- channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
- resize_traits=GetPixelChannelMapTraits(resize_image,channel);
- if (resize_traits == UndefinedPixelTrait)
- continue;
- if ((resize_traits & CopyPixelTrait) != 0)
- {
- q[channel]=p[i];
- continue;
- }
- status=InterpolatePixelChannel(image,interpolate_view,(PixelChannel) i,
- MeshInterpolatePixel,offset.x-0.5,offset.y-0.5,&pixel,exception);
- q[channel]=ClampToQuantum(pixel);
- }
- q+=GetPixelChannels(resize_image);
- }
- if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
- 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;
- }
- }
- resize_view=DestroyCacheView(resize_view);
- interpolate_view=DestroyCacheView(interpolate_view);
- image_view=DestroyCacheView(image_view);
- if (status == MagickFalse)
- resize_image=DestroyImage(resize_image);
- return(resize_image);
+ return(InterpolativeResizeImage(image,columns,rows,MeshInterpolatePixel,
+ exception));
}
\f
/*
%
% The format of the BesselOrderOne method is:
%
-% MagickRealType BesselOrderOne(MagickRealType x)
+% double BesselOrderOne(double x)
%
% A description of each parameter follows:
%
-% o x: MagickRealType value.
+% o x: double value.
%
*/
#undef I0
-static MagickRealType I0(MagickRealType x)
+static double I0(double x)
{
- MagickRealType
+ double
sum,
t,
y;
for (i=2; t > MagickEpsilon; i++)
{
sum+=t;
- t*=y/((MagickRealType) i*i);
+ t*=y/((double) i*i);
}
return(sum);
}
#undef J1
-static MagickRealType J1(MagickRealType x)
+static double J1(double x)
{
- MagickRealType
+ double
p,
q;
}
#undef P1
-static MagickRealType P1(MagickRealType x)
+static double P1(double x)
{
- MagickRealType
+ double
p,
q;
}
#undef Q1
-static MagickRealType Q1(MagickRealType x)
+static double Q1(double x)
{
- MagickRealType
+ double
p,
q;
return(p/q);
}
-static MagickRealType BesselOrderOne(MagickRealType x)
+static double BesselOrderOne(double x)
{
- MagickRealType
+ double
p,
q;
% o resize_filter: the resize filter.
%
*/
-MagickExport ResizeFilter *DestroyResizeFilter(ResizeFilter *resize_filter)
+MagickPrivate ResizeFilter *DestroyResizeFilter(ResizeFilter *resize_filter)
{
assert(resize_filter != (ResizeFilter *) NULL);
assert(resize_filter->signature == MagickSignature);
%
% The format of the GetResizeFilterSupport method is:
%
-% MagickRealType GetResizeFilterSupport(const ResizeFilter *resize_filter)
+% double GetResizeFilterSupport(const ResizeFilter *resize_filter)
%
% A description of each parameter follows:
%
% o filter: Image filter to use.
%
*/
-MagickExport MagickRealType GetResizeFilterSupport(
+MagickPrivate double GetResizeFilterSupport(
const ResizeFilter *resize_filter)
{
assert(resize_filter != (ResizeFilter *) NULL);
%
% The format of the GetResizeFilterWeight method is:
%
-% MagickRealType GetResizeFilterWeight(const ResizeFilter *resize_filter,
-% const MagickRealType x)
+% double GetResizeFilterWeight(const ResizeFilter *resize_filter,
+% const double x)
%
% A description of each parameter follows:
%
% o x: the point.
%
*/
-MagickExport MagickRealType GetResizeFilterWeight(
- const ResizeFilter *resize_filter,const MagickRealType x)
+MagickPrivate double GetResizeFilterWeight(
+ const ResizeFilter *resize_filter,const double x)
{
- MagickRealType
+ double
scale,
weight,
x_blur;
weight=scale*resize_filter->filter(x_blur,resize_filter);
return(weight);
}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% I n t e r p o l a t i v e R e s i z e I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% InterpolativeResizeImage() resizes an image using the specified
+% interpolation method.
+%
+% The format of the InterpolativeResizeImage method is:
+%
+% Image *InterpolativeResizeImage(const Image *image,const size_t columns,
+% const size_t rows,const PixelInterpolateMethod method,
+% ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o columns: the number of columns in the resized image.
+%
+% o rows: the number of rows in the resized image.
+%
+% o method: the pixel interpolation method.
+%
+% o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *InterpolativeResizeImage(const Image *image,
+ const size_t columns,const size_t rows,const PixelInterpolateMethod method,
+ ExceptionInfo *exception)
+{
+#define InterpolativeResizeImageTag "Resize/Image"
+
+ CacheView
+ *image_view,
+ *resize_view;
+
+ Image
+ *resize_image;
+
+ MagickBooleanType
+ status;
+
+ MagickOffsetType
+ progress;
+
+ PointInfo
+ scale;
+
+ ssize_t
+ y;
+
+ /*
+ Interpolatively resize image.
+ */
+ assert(image != (const Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if( IfMagickTrue(image->debug) )
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ assert(exception != (ExceptionInfo *) NULL);
+ assert(exception->signature == MagickSignature);
+ if ((columns == 0) || (rows == 0))
+ return((Image *) NULL);
+ if ((columns == image->columns) && (rows == image->rows))
+ return(CloneImage(image,0,0,MagickTrue,exception));
+ resize_image=CloneImage(image,columns,rows,MagickTrue,exception);
+ if (resize_image == (Image *) NULL)
+ return((Image *) NULL);
+ if( IfMagickFalse(SetImageStorageClass(resize_image,DirectClass,exception)) )
+ {
+ resize_image=DestroyImage(resize_image);
+ return((Image *) NULL);
+ }
+ status=MagickTrue;
+ progress=0;
+ image_view=AcquireVirtualCacheView(image,exception);
+ resize_view=AcquireAuthenticCacheView(resize_image,exception);
+ scale.x=(double) image->columns/resize_image->columns;
+ scale.y=(double) image->rows/resize_image->rows;
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(static,4) shared(progress,status) \
+ dynamic_number_threads(image,image->columns,image->rows,1)
+#endif
+ for (y=0; y < (ssize_t) resize_image->rows; y++)
+ {
+ PointInfo
+ offset;
+
+ register Quantum
+ *restrict q;
+
+ register ssize_t
+ x;
+
+ if( IfMagickFalse(status) )
+ continue;
+ q=QueueCacheViewAuthenticPixels(resize_view,0,y,resize_image->columns,1,
+ exception);
+ if (q == (Quantum *) NULL)
+ continue;
+ offset.y=((double) y+0.5)*scale.y-0.5;
+ for (x=0; x < (ssize_t) resize_image->columns; x++)
+ {
+ register ssize_t
+ i;
+
+ if (GetPixelMask(resize_image,q) != 0)
+ {
+ q+=GetPixelChannels(resize_image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(resize_image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ resize_traits,
+ traits;
+
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ resize_traits=GetPixelChannelTraits(resize_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (resize_traits == UndefinedPixelTrait))
+ continue;
+ offset.x=((double) x+0.5)*scale.x-0.5;
+ status=InterpolatePixelChannels(image,image_view,resize_image,method,
+ offset.x,offset.y,q,exception);
+ }
+ q+=GetPixelChannels(resize_image);
+ }
+ if( IfMagickFalse(SyncCacheViewAuthenticPixels(resize_view,exception)) )
+ continue;
+ if (image->progress_monitor != (MagickProgressMonitor) NULL)
+ {
+ MagickBooleanType
+ proceed;
+
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp critical (MagickCore_InterpolativeResizeImage)
+#endif
+ proceed=SetImageProgress(image,InterpolativeResizeImageTag,progress++,
+ image->rows);
+ if( IfMagickFalse(proceed) )
+ status=MagickFalse;
+ }
+ }
+ resize_view=DestroyCacheView(resize_view);
+ image_view=DestroyCacheView(image_view);
+ if( IfMagickFalse(status) )
+ resize_image=DestroyImage(resize_image);
+ return(resize_image);
+}
#if defined(MAGICKCORE_LQR_DELEGATE)
\f
/*
*/
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
if ((columns == image->columns) && (rows == image->rows))
return(CloneImage(image,0,0,MagickTrue,exception));
if ((columns <= 2) || (rows <= 2))
- return(ResizeImage(image,columns,rows,image->filter,image->blur,exception));
+ return(ResizeImage(image,columns,rows,image->filter,exception));
if ((columns >= (2*image->columns)) || (rows >= (2*image->rows)))
{
Image
*/
for (width=image->columns; columns >= (2*width-1); width*=2);
for (height=image->rows; rows >= (2*height-1); height*=2);
- resize_image=ResizeImage(image,width,height,image->filter,image->blur,
- exception);
+ resize_image=ResizeImage(image,width,height,image->filter,exception);
if (resize_image == (Image *) NULL)
return((Image *) NULL);
rescale_image=LiquidRescaleImage(resize_image,columns,rows,delta_x,
return((Image *) NULL);
status=MagickTrue;
q=pixels;
- image_view=AcquireCacheView(image);
+ image_view=AcquireVirtualCacheView(image,exception);
for (y=0; y < (ssize_t) image->rows; y++)
{
register const Quantum
register ssize_t
x;
- if (status == MagickFalse)
+ if( IfMagickFalse(status) )
continue;
p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
if (p == (const Quantum *) NULL)
pixels=(gfloat *) RelinquishMagickMemory(pixels);
return((Image *) NULL);
}
- if (SetImageStorageClass(rescale_image,DirectClass,exception) == MagickFalse)
+ if( IfMagickFalse(SetImageStorageClass(rescale_image,DirectClass,exception)) )
{
pixels=(gfloat *) RelinquishMagickMemory(pixels);
rescale_image=DestroyImage(rescale_image);
return((Image *) NULL);
}
- rescale_view=AcquireCacheView(rescale_image);
+ rescale_view=AcquireAuthenticCacheView(rescale_image,exception);
(void) lqr_carver_scan_reset(carver);
while (lqr_carver_scan_ext(carver,&x_offset,&y_offset,(void **) &packet) != 0)
{
rescale_traits,
traits;
- traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
- if (traits == UndefinedPixelTrait)
- continue;
- channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
- rescale_traits=GetPixelChannelMapTraits(rescale_image,channel);
- if (rescale_traits == UndefinedPixelTrait)
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ rescale_traits=GetPixelChannelTraits(rescale_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (rescale_traits == UndefinedPixelTrait))
continue;
- q[channel]=ClampToQuantum(QuantumRange*packet[i]);
+ SetPixelChannel(rescale_image,channel,ClampToQuantum(QuantumRange*
+ packet[i]),q);
}
- if (SyncCacheViewAuthenticPixels(rescale_view,exception) == MagickFalse)
+ if( IfMagickFalse(SyncCacheViewAuthenticPixels(rescale_view,exception)) )
break;
}
rescale_view=DestroyCacheView(rescale_view);
{
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
(void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
- "DelegateLibrarySupportNotBuiltIn","`%s' (LQR)",image->filename);
+ "DelegateLibrarySupportNotBuiltIn","'%s' (LQR)",image->filename);
return((Image *) NULL);
}
#endif
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
- magnify_image=ResizeImage(image,2*image->columns,2*image->rows,CubicFilter,
- 1.0,exception);
+ magnify_image=ResizeImage(image,2*image->columns,2*image->rows,SplineFilter,
+ exception);
return(magnify_image);
}
\f
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(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,
+ minify_image=ResizeImage(image,image->columns/2,image->rows/2,SplineFilter,
exception);
return(minify_image);
}
% The format of the ResampleImage method is:
%
% Image *ResampleImage(Image *image,const double x_resolution,
-% const double y_resolution,const FilterTypes filter,const double blur,
+% const double y_resolution,const FilterTypes filter,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o filter: Image filter to use.
%
-% o blur: the blur factor where > 1 is blurry, < 1 is sharp.
+% o exception: return any errors or warnings in this structure.
%
*/
MagickExport Image *ResampleImage(const Image *image,const double x_resolution,
- const double y_resolution,const FilterTypes filter,const double blur,
- ExceptionInfo *exception)
+ const double y_resolution,const FilterTypes filter,ExceptionInfo *exception)
{
#define ResampleImageTag "Resample/Image"
*/
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
- width=(size_t) (x_resolution*image->columns/(image->x_resolution == 0.0 ?
- 72.0 : image->x_resolution)+0.5);
- height=(size_t) (y_resolution*image->rows/(image->y_resolution == 0.0 ?
- 72.0 : image->y_resolution)+0.5);
- resample_image=ResizeImage(image,width,height,filter,blur,exception);
+ width=(size_t) (x_resolution*image->columns/(image->resolution.x == 0.0 ?
+ 72.0 : image->resolution.x)+0.5);
+ height=(size_t) (y_resolution*image->rows/(image->resolution.y == 0.0 ?
+ 72.0 : image->resolution.y)+0.5);
+ resample_image=ResizeImage(image,width,height,filter,exception);
if (resample_image != (Image *) NULL)
{
- resample_image->x_resolution=x_resolution;
- resample_image->y_resolution=y_resolution;
+ resample_image->resolution.x=x_resolution;
+ resample_image->resolution.y=y_resolution;
}
return(resample_image);
}
typedef struct _ContributionInfo
{
- MagickRealType
+ double
weight;
ssize_t
i;
assert(contribution != (ContributionInfo **) NULL);
- for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
+ for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
if (contribution[i] != (ContributionInfo *) NULL)
- contribution[i]=(ContributionInfo *) RelinquishMagickMemory(
+ contribution[i]=(ContributionInfo *) RelinquishAlignedMemory(
contribution[i]);
contribution=(ContributionInfo **) RelinquishMagickMemory(contribution);
return(contribution);
size_t
number_threads;
- number_threads=GetOpenMPMaximumThreads();
+ number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
contribution=(ContributionInfo **) AcquireQuantumMemory(number_threads,
sizeof(*contribution));
if (contribution == (ContributionInfo **) NULL)
(void) ResetMagickMemory(contribution,0,number_threads*sizeof(*contribution));
for (i=0; i < (ssize_t) number_threads; i++)
{
- contribution[i]=(ContributionInfo *) AcquireQuantumMemory(count,
- sizeof(**contribution));
+ contribution[i]=(ContributionInfo *) MagickAssumeAligned(
+ AcquireAlignedMemory(count,sizeof(**contribution)));
if (contribution[i] == (ContributionInfo *) NULL)
return(DestroyContributionThreadSet(contribution));
}
}
static MagickBooleanType HorizontalFilter(const ResizeFilter *resize_filter,
- const Image *image,Image *resize_image,const MagickRealType x_factor,
+ const Image *image,Image *resize_image,const double x_factor,
const MagickSizeType span,MagickOffsetType *offset,ExceptionInfo *exception)
{
#define ResizeImageTag "Resize/Image"
MagickBooleanType
status;
- MagickRealType
+ double
scale,
support;
scale=MagickMax(1.0/x_factor+MagickEpsilon,1.0);
support=scale*GetResizeFilterSupport(resize_filter);
storage_class=support > 0.5 ? DirectClass : image->storage_class;
- if (SetImageStorageClass(resize_image,storage_class,exception) == MagickFalse)
+ if( IfMagickFalse(SetImageStorageClass(resize_image,storage_class,exception)) )
return(MagickFalse);
if (support < 0.5)
{
/*
Support too small even for nearest neighbour: Reduce to point sampling.
*/
- support=(MagickRealType) 0.5;
+ support=(double) 0.5;
scale=1.0;
}
contributions=AcquireContributionThreadSet((size_t) (2.0*support+3.0));
if (contributions == (ContributionInfo **) NULL)
{
(void) ThrowMagickException(exception,GetMagickModule(),
- ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
+ ResourceLimitError,"MemoryAllocationFailed","'%s'",image->filename);
return(MagickFalse);
}
status=MagickTrue;
- scale=1.0/scale;
- image_view=AcquireCacheView(image);
- resize_view=AcquireCacheView(resize_image);
+ scale=MagickEpsilonReciprocal(scale);
+ image_view=AcquireVirtualCacheView(image,exception);
+ resize_view=AcquireAuthenticCacheView(resize_image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for shared(status)
+ #pragma omp parallel for schedule(static,4) shared(status) \
+ dynamic_number_threads(image,image->columns,image->rows,1)
#endif
for (x=0; x < (ssize_t) resize_image->columns; x++)
{
- MagickRealType
+ double
bisect,
density;
start,
stop;
- if (status == MagickFalse)
+ if( IfMagickFalse(status) )
continue;
- bisect=(MagickRealType) (x+0.5)/x_factor;
+ bisect=(double) (x+0.5)/x_factor+MagickEpsilon;
start=(ssize_t) MagickMax(bisect-support+0.5,0.0);
stop=(ssize_t) MagickMin(bisect+support+0.5,(double) image->columns);
density=0.0;
{
contribution[n].pixel=start+n;
contribution[n].weight=GetResizeFilterWeight(resize_filter,scale*
- ((MagickRealType) (start+n)-bisect+0.5));
+ ((double) (start+n)-bisect+0.5));
density+=contribution[n].weight;
}
if ((density != 0.0) && (density != 1.0))
/*
Normalize.
*/
- density=1.0/density;
+ density=MagickEpsilonReciprocal(density);
for (i=0; i < n; i++)
contribution[i].weight*=density;
}
register ssize_t
i;
- for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ for (i=0; i < (ssize_t) GetPixelChannels(resize_image); i++)
{
- MagickRealType
+ double
alpha,
gamma,
pixel;
ssize_t
k;
- traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
- if (traits == UndefinedPixelTrait)
- continue;
- channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
- resize_traits=GetPixelChannelMapTraits(resize_image,channel);
- if (resize_traits == UndefinedPixelTrait)
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ resize_traits=GetPixelChannelTraits(resize_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (resize_traits == UndefinedPixelTrait))
continue;
- if ((resize_traits & CopyPixelTrait) != 0)
+ if (((resize_traits & CopyPixelTrait) != 0) ||
+ (GetPixelMask(resize_image,q) != 0))
{
j=(ssize_t) (MagickMin(MagickMax(bisect,(double) start),(double)
stop-1.0)+0.5);
k=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
(contribution[j-start].pixel-contribution[0].pixel);
- q[channel]=p[k*GetPixelChannels(image)+i];
+ SetPixelChannel(resize_image,channel,p[k*GetPixelChannels(image)+i],
+ q);
continue;
}
pixel=0.0;
alpha=contribution[j].weight;
pixel+=alpha*p[k*GetPixelChannels(image)+i];
}
- q[channel]=ClampToQuantum(pixel);
+ SetPixelChannel(resize_image,channel,ClampToQuantum(pixel),q);
continue;
}
/*
pixel+=alpha*p[k*GetPixelChannels(image)+i];
gamma+=alpha;
}
- gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
- q[channel]=ClampToQuantum(gamma*pixel);
+ gamma=MagickEpsilonReciprocal(gamma);
+ SetPixelChannel(resize_image,channel,ClampToQuantum(gamma*pixel),q);
}
q+=GetPixelChannels(resize_image);
}
- if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
+ if( IfMagickFalse(SyncCacheViewAuthenticPixels(resize_view,exception)) )
status=MagickFalse;
if (image->progress_monitor != (MagickProgressMonitor) NULL)
{
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_HorizontalFilter)
+ #pragma omp critical (MagickCore_HorizontalFilter)
#endif
proceed=SetImageProgress(image,ResizeImageTag,(*offset)++,span);
- if (proceed == MagickFalse)
+ if( IfMagickFalse(proceed) )
status=MagickFalse;
}
}
}
static MagickBooleanType VerticalFilter(const ResizeFilter *resize_filter,
- const Image *image,Image *resize_image,const MagickRealType y_factor,
+ const Image *image,Image *resize_image,const double y_factor,
const MagickSizeType span,MagickOffsetType *offset,ExceptionInfo *exception)
{
CacheView
PixelInfo
zero;
- MagickRealType
+ double
scale,
support;
scale=MagickMax(1.0/y_factor+MagickEpsilon,1.0);
support=scale*GetResizeFilterSupport(resize_filter);
storage_class=support > 0.5 ? DirectClass : image->storage_class;
- if (SetImageStorageClass(resize_image,storage_class,exception) == MagickFalse)
+ if( IfMagickFalse(SetImageStorageClass(resize_image,storage_class,exception)) )
return(MagickFalse);
if (support < 0.5)
{
/*
Support too small even for nearest neighbour: Reduce to point sampling.
*/
- support=(MagickRealType) 0.5;
+ support=(double) 0.5;
scale=1.0;
}
contributions=AcquireContributionThreadSet((size_t) (2.0*support+3.0));
if (contributions == (ContributionInfo **) NULL)
{
(void) ThrowMagickException(exception,GetMagickModule(),
- ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
+ ResourceLimitError,"MemoryAllocationFailed","'%s'",image->filename);
return(MagickFalse);
}
status=MagickTrue;
- scale=1.0/scale;
+ scale=MagickEpsilonReciprocal(scale);
(void) ResetMagickMemory(&zero,0,sizeof(zero));
- image_view=AcquireCacheView(image);
- resize_view=AcquireCacheView(resize_image);
+ image_view=AcquireVirtualCacheView(image,exception);
+ resize_view=AcquireAuthenticCacheView(resize_image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for shared(status)
+ #pragma omp parallel for schedule(static,4) shared(status) \
+ dynamic_number_threads(image,image->columns,image->rows,1)
#endif
for (y=0; y < (ssize_t) resize_image->rows; y++)
{
- MagickRealType
+ double
bisect,
density;
start,
stop;
- if (status == MagickFalse)
+ if( IfMagickFalse(status) )
continue;
- bisect=(MagickRealType) (y+0.5)/y_factor;
+ bisect=(double) (y+0.5)/y_factor+MagickEpsilon;
start=(ssize_t) MagickMax(bisect-support+0.5,0.0);
stop=(ssize_t) MagickMin(bisect+support+0.5,(double) image->rows);
density=0.0;
{
contribution[n].pixel=start+n;
contribution[n].weight=GetResizeFilterWeight(resize_filter,scale*
- ((MagickRealType) (start+n)-bisect+0.5));
+ ((double) (start+n)-bisect+0.5));
density+=contribution[n].weight;
}
if ((density != 0.0) && (density != 1.0))
/*
Normalize.
*/
- density=1.0/density;
+ density=MagickEpsilonReciprocal(density);
for (i=0; i < n; i++)
contribution[i].weight*=density;
}
register ssize_t
i;
- for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ for (i=0; i < (ssize_t) GetPixelChannels(resize_image); i++)
{
- MagickRealType
+ double
alpha,
gamma,
pixel;
ssize_t
k;
- traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
- if (traits == UndefinedPixelTrait)
- continue;
- channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
- resize_traits=GetPixelChannelMapTraits(resize_image,channel);
- if (resize_traits == UndefinedPixelTrait)
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ resize_traits=GetPixelChannelTraits(resize_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (resize_traits == UndefinedPixelTrait))
continue;
- if ((resize_traits & CopyPixelTrait) != 0)
+ if (((resize_traits & CopyPixelTrait) != 0) ||
+ (GetPixelMask(resize_image,q) != 0))
{
j=(ssize_t) (MagickMin(MagickMax(bisect,(double) start),(double)
stop-1.0)+0.5);
k=(ssize_t) ((contribution[j-start].pixel-contribution[0].pixel)*
image->columns+x);
- q[channel]=p[k*GetPixelChannels(image)+i];
+ SetPixelChannel(resize_image,channel,p[k*GetPixelChannels(image)+i],
+ q);
continue;
}
pixel=0.0;
alpha=contribution[j].weight;
pixel+=alpha*p[k*GetPixelChannels(image)+i];
}
- q[channel]=ClampToQuantum(pixel);
+ SetPixelChannel(resize_image,channel,ClampToQuantum(pixel),q);
continue;
}
gamma=0.0;
{
k=(ssize_t) ((contribution[j].pixel-contribution[0].pixel)*
image->columns+x);
- alpha=contribution[j].weight*QuantumScale*
- GetPixelAlpha(image,p+k*GetPixelChannels(image));
+ alpha=contribution[j].weight*QuantumScale*GetPixelAlpha(image,p+k*
+ GetPixelChannels(image));
pixel+=alpha*p[k*GetPixelChannels(image)+i];
gamma+=alpha;
}
- gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
- q[channel]=ClampToQuantum(gamma*pixel);
+ gamma=MagickEpsilonReciprocal(gamma);
+ SetPixelChannel(resize_image,channel,ClampToQuantum(gamma*pixel),q);
}
q+=GetPixelChannels(resize_image);
}
- if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
+ if( IfMagickFalse(SyncCacheViewAuthenticPixels(resize_view,exception)) )
status=MagickFalse;
if (image->progress_monitor != (MagickProgressMonitor) NULL)
{
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_VerticalFilter)
+ #pragma omp critical (MagickCore_VerticalFilter)
#endif
proceed=SetImageProgress(image,ResizeImageTag,(*offset)++,span);
- if (proceed == MagickFalse)
+ if( IfMagickFalse(proceed) )
status=MagickFalse;
}
}
}
MagickExport Image *ResizeImage(const Image *image,const size_t columns,
- const size_t rows,const FilterTypes filter,const double blur,
- ExceptionInfo *exception)
+ const size_t rows,const FilterTypes filter,ExceptionInfo *exception)
{
#define WorkLoadFactor 0.265
MagickOffsetType
offset;
- MagickRealType
+ double
x_factor,
y_factor;
*/
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
if ((columns == 0) || (rows == 0))
ThrowImageException(ImageError,"NegativeOrZeroImageSize");
if ((columns == image->columns) && (rows == image->rows) &&
- (filter == UndefinedFilter) && (blur == 1.0))
+ (filter == UndefinedFilter))
return(CloneImage(image,0,0,MagickTrue,exception));
resize_image=CloneImage(image,columns,rows,MagickTrue,exception);
if (resize_image == (Image *) NULL)
/*
Acquire resize filter.
*/
- x_factor=(MagickRealType) columns/(MagickRealType) image->columns;
- y_factor=(MagickRealType) rows/(MagickRealType) image->rows;
+ x_factor=(double) columns/(double) image->columns;
+ y_factor=(double) rows/(double) image->rows;
if ((x_factor*y_factor) > WorkLoadFactor)
filter_image=CloneImage(image,columns,image->rows,MagickTrue,exception);
else
filter_type=PointFilter;
else
if ((image->storage_class == PseudoClass) ||
- (image->matte != MagickFalse) || ((x_factor*y_factor) > 1.0))
+ image->alpha_trait == BlendPixelTrait ||
+ ((x_factor*y_factor) > 1.0))
filter_type=MitchellFilter;
- resize_filter=AcquireResizeFilter(image,filter_type,blur,MagickFalse,
- exception);
+ resize_filter=AcquireResizeFilter(image,filter_type,MagickFalse,exception);
/*
Resize image.
*/
*/
filter_image=DestroyImage(filter_image);
resize_filter=DestroyResizeFilter(resize_filter);
- if ((status == MagickFalse) || (resize_image == (Image *) NULL))
- return((Image *) NULL);
+ if( IfMagickFalse(status) )
+ {
+ resize_image=DestroyImage(resize_image);
+ return((Image *) NULL);
+ }
resize_image->type=image->type;
return(resize_image);
}
*/
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
}
for (x=0; x < (ssize_t) sample_image->columns; x++)
- x_offset[x]=(ssize_t) (((MagickRealType) x+0.5)*image->columns/
+ x_offset[x]=(ssize_t) (((double) x+0.5)*image->columns/
sample_image->columns);
/*
Sample each row.
*/
status=MagickTrue;
progress=0;
- image_view=AcquireCacheView(image);
- sample_view=AcquireCacheView(sample_image);
+ image_view=AcquireVirtualCacheView(image,exception);
+ sample_view=AcquireAuthenticCacheView(sample_image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status) omp_throttle(1)
+ #pragma omp parallel for schedule(static,4) shared(progress,status) \
+ dynamic_number_threads(image,image->columns,image->rows,1)
#endif
for (y=0; y < (ssize_t) sample_image->rows; y++)
{
ssize_t
y_offset;
- if (status == MagickFalse)
+ if( IfMagickFalse(status) )
continue;
- y_offset=(ssize_t) (((MagickRealType) y+0.5)*image->rows/
+ y_offset=(ssize_t) (((double) y+0.5)*image->rows/
sample_image->rows);
p=GetCacheViewVirtualPixels(image_view,0,y_offset,image->columns,1,
exception);
register ssize_t
i;
- for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ if (GetPixelMask(sample_image,q) != 0)
+ {
+ q+=GetPixelChannels(sample_image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(sample_image); i++)
{
PixelChannel
channel;
sample_traits,
traits;
- traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
- if (traits == UndefinedPixelTrait)
- continue;
- channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
- sample_traits=GetPixelChannelMapTraits(sample_image,channel);
- if (sample_traits == UndefinedPixelTrait)
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ sample_traits=GetPixelChannelTraits(sample_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (sample_traits == UndefinedPixelTrait))
continue;
- q[channel]=p[x_offset[x]*GetPixelChannels(image)+i];
+ SetPixelChannel(sample_image,channel,p[x_offset[x]*GetPixelChannels(
+ image)+i],q);
}
q+=GetPixelChannels(sample_image);
}
- if (SyncCacheViewAuthenticPixels(sample_view,exception) == MagickFalse)
+ if( IfMagickFalse(SyncCacheViewAuthenticPixels(sample_view,exception)) )
status=MagickFalse;
if (image->progress_monitor != (MagickProgressMonitor) NULL)
{
#pragma omp critical (MagickCore_SampleImage)
#endif
proceed=SetImageProgress(image,SampleImageTag,progress++,image->rows);
- if (proceed == MagickFalse)
+ if( IfMagickFalse(proceed) )
status=MagickFalse;
}
}
next_row,
proceed;
- MagickRealType
+ double
alpha,
gamma,
- pixel[MaxPixelChannels],
+ pixel[CompositePixelChannel],
*scale_scanline,
*scanline,
*x_vector,
*/
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
scale_image=CloneImage(image,columns,rows,MagickTrue,exception);
if (scale_image == (Image *) NULL)
return((Image *) NULL);
- if (SetImageStorageClass(scale_image,DirectClass,exception) == MagickFalse)
+ if( IfMagickFalse(SetImageStorageClass(scale_image,DirectClass,exception)) )
{
scale_image=DestroyImage(scale_image);
return((Image *) NULL);
/*
Allocate memory.
*/
- x_vector=(MagickRealType *) AcquireQuantumMemory((size_t) image->columns,
+ x_vector=(double *) AcquireQuantumMemory((size_t) image->columns,
GetPixelChannels(image)*sizeof(*x_vector));
scanline=x_vector;
if (image->rows != scale_image->rows)
- scanline=(MagickRealType *) AcquireQuantumMemory((size_t) image->columns,
+ scanline=(double *) AcquireQuantumMemory((size_t) image->columns,
GetPixelChannels(image)*sizeof(*scanline));
- scale_scanline=(MagickRealType *) AcquireQuantumMemory((size_t)
- scale_image->columns,GetPixelChannels(scale_image)*sizeof(*scale_scanline));
- y_vector=(MagickRealType *) AcquireQuantumMemory((size_t) image->columns,
+ scale_scanline=(double *) AcquireQuantumMemory((size_t)
+ scale_image->columns,MaxPixelChannels*sizeof(*scale_scanline));
+ y_vector=(double *) AcquireQuantumMemory((size_t) image->columns,
GetPixelChannels(image)*sizeof(*y_vector));
- if ((scanline == (MagickRealType *) NULL) ||
- (scale_scanline == (MagickRealType *) NULL) ||
- (x_vector == (MagickRealType *) NULL) ||
- (y_vector == (MagickRealType *) NULL))
+ if ((scanline == (double *) NULL) ||
+ (scale_scanline == (double *) NULL) ||
+ (x_vector == (double *) NULL) ||
+ (y_vector == (double *) NULL))
{
scale_image=DestroyImage(scale_image);
ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
for (i=0; i < (ssize_t) (GetPixelChannels(image)*image->columns); i++)
y_vector[i]=0.0;
n=0;
- image_view=AcquireCacheView(image);
- scale_view=AcquireCacheView(scale_image);
+ image_view=AcquireVirtualCacheView(image,exception);
+ scale_view=AcquireAuthenticCacheView(scale_image,exception);
for (y=0; y < (ssize_t) scale_image->rows; y++)
{
register const Quantum
q=QueueCacheViewAuthenticPixels(scale_view,0,y,scale_image->columns,1,
exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
break;
alpha=1.0;
if (scale_image->rows == image->rows)
break;
for (x=0; x < (ssize_t) image->columns; x++)
{
+ if (GetPixelMask(image,p) != 0)
+ {
+ p+=GetPixelChannels(image);
+ continue;
+ }
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
- traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
if ((traits & BlendPixelTrait) == 0)
{
- x_vector[x*GetPixelChannels(image)+i]=(MagickRealType) p[i];
+ x_vector[x*GetPixelChannels(image)+i]=(double) p[i];
continue;
}
alpha=QuantumScale*GetPixelAlpha(image,p);
*/
while (scale.y < span.y)
{
- if ((next_row != MagickFalse) &&
- (number_rows < (ssize_t) image->rows))
+ if( IfMagickTrue(next_row) && (number_rows < (ssize_t) image->rows))
{
/*
Read a new scanline.
break;
for (x=0; x < (ssize_t) image->columns; x++)
{
+ if (GetPixelMask(image,p) != 0)
+ {
+ p+=GetPixelChannels(image);
+ continue;
+ }
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
- traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
if ((traits & BlendPixelTrait) == 0)
{
- x_vector[x*GetPixelChannels(image)+i]=(MagickRealType)
+ x_vector[x*GetPixelChannels(image)+i]=(double)
p[i];
continue;
}
scale.y=(double) scale_image->rows/(double) image->rows;
next_row=MagickTrue;
}
- if ((next_row != MagickFalse) && (number_rows < (ssize_t) image->rows))
+ if( IfMagickTrue(next_row) && (number_rows < (ssize_t) image->rows))
{
/*
Read a new scanline.
break;
for (x=0; x < (ssize_t) image->columns; x++)
{
+ if (GetPixelMask(image,p) != 0)
+ {
+ p+=GetPixelChannels(image);
+ continue;
+ }
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
- traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
if ((traits & BlendPixelTrait) == 0)
{
- x_vector[x*GetPixelChannels(image)+i]=(MagickRealType) p[i];
+ x_vector[x*GetPixelChannels(image)+i]=(double) p[i];
continue;
}
alpha=QuantumScale*GetPixelAlpha(image,p);
*/
for (x=0; x < (ssize_t) scale_image->columns; x++)
{
- for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
- {
- traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
- if (traits == UndefinedPixelTrait)
+ if (GetPixelMask(scale_image,q) != 0)
+ {
+ q+=GetPixelChannels(scale_image);
continue;
- channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
- scale_traits=GetPixelChannelMapTraits(scale_image,channel);
- if (scale_traits == UndefinedPixelTrait)
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(scale_image); i++)
+ {
+ ssize_t
+ offset;
+
+ channel=GetPixelChannelChannel(scale_image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ scale_traits=GetPixelChannelTraits(scale_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (scale_traits == UndefinedPixelTrait))
continue;
- if ((scale_traits & BlendPixelTrait) == 0)
+ offset=GetPixelChannelOffset(image,channel);
+ if ((traits & BlendPixelTrait) == 0)
{
- q[channel]=ClampToQuantum(scanline[x*
- GetPixelChannels(image)+i]);
+ SetPixelChannel(scale_image,channel,ClampToQuantum(
+ scanline[x*GetPixelChannels(image)+offset]),q);
continue;
}
alpha=QuantumScale*scanline[x*GetPixelChannels(image)+
- GetPixelChannelMapChannel(image,AlphaPixelChannel)];
- gamma=1.0/(fabs((double) alpha) <= MagickEpsilon ? 1.0 : alpha);
- q[channel]=ClampToQuantum(gamma*scanline[x*GetPixelChannels(image)+
- i]);
+ GetPixelChannelChannel(image,AlphaPixelChannel)];
+ gamma=MagickEpsilonReciprocal(alpha);
+ SetPixelChannel(scale_image,channel,ClampToQuantum(gamma*scanline[
+ x*GetPixelChannels(image)+offset]),q);
}
q+=GetPixelChannels(scale_image);
}
scale.x=(double) scale_image->columns/(double) image->columns;
while (scale.x >= span.x)
{
- if (next_column != MagickFalse)
+ if( IfMagickTrue(next_column) )
{
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
pixel[i]=0.0;
}
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
- traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
if (traits == UndefinedPixelTrait)
continue;
- channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
pixel[i]+=span.x*scanline[x*GetPixelChannels(image)+i];
- scale_scanline[n*GetPixelChannels(scale_image)+channel]=pixel[i];
+ scale_scanline[n*MaxPixelChannels+channel]=pixel[i];
}
scale.x-=span.x;
span.x=1.0;
}
if (scale.x > 0)
{
- if (next_column != MagickFalse)
+ if( IfMagickTrue(next_column) )
{
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
pixel[i]=0.0;
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
pixel[i]+=span.x*scanline[(x-1)*GetPixelChannels(image)+i];
}
- if ((next_column == MagickFalse) &&
+ if( IfMagickFalse(next_column) &&
((ssize_t) n < (ssize_t) scale_image->columns))
- for (i=0; i < (ssize_t) GetPixelChannels(scale_image); i++)
- scale_scanline[n*GetPixelChannels(scale_image)+i]=pixel[i];
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ channel=GetPixelChannelChannel(image,i);
+ scale_scanline[n*MaxPixelChannels+channel]=pixel[i];
+ }
/*
Transfer scanline to scaled image.
*/
for (x=0; x < (ssize_t) scale_image->columns; x++)
{
- for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
- {
- traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
- if (traits == UndefinedPixelTrait)
+ if (GetPixelMask(scale_image,q) != 0)
+ {
+ q+=GetPixelChannels(scale_image);
continue;
- channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
- scale_traits=GetPixelChannelMapTraits(scale_image,channel);
- if (scale_traits == UndefinedPixelTrait)
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(scale_image); i++)
+ {
+ channel=GetPixelChannelChannel(scale_image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ scale_traits=GetPixelChannelTraits(scale_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (scale_traits == UndefinedPixelTrait))
continue;
- if ((scale_traits & BlendPixelTrait) == 0)
+ if ((traits & BlendPixelTrait) == 0)
{
- q[channel]=ClampToQuantum(scale_scanline[x*
- GetPixelChannels(scale_image)+i]);
+ SetPixelChannel(scale_image,channel,ClampToQuantum(
+ scale_scanline[x*MaxPixelChannels+channel]),q);
continue;
}
- alpha=QuantumScale*scanline[x*GetPixelChannels(image)+
- GetPixelChannelMapChannel(image,AlphaPixelChannel)];
- gamma=1.0/(fabs((double) alpha) <= MagickEpsilon ? 1.0 : alpha);
- q[channel]=ClampToQuantum(gamma*scale_scanline[
- GetPixelChannels(scale_image)+i]);
+ SetPixelChannel(scale_image,channel,ClampToQuantum(
+ scale_scanline[x*MaxPixelChannels+channel]),q);
}
q+=GetPixelChannels(scale_image);
}
}
- if (SyncCacheViewAuthenticPixels(scale_view,exception) == MagickFalse)
+ if( IfMagickFalse(SyncCacheViewAuthenticPixels(scale_view,exception)) )
break;
proceed=SetImageProgress(image,ScaleImageTag,(MagickOffsetType) y,
image->rows);
- if (proceed == MagickFalse)
+ if( IfMagickFalse(proceed) )
break;
}
scale_view=DestroyCacheView(scale_view);
/*
Free allocated memory.
*/
- y_vector=(MagickRealType *) RelinquishMagickMemory(y_vector);
- scale_scanline=(MagickRealType *) RelinquishMagickMemory(scale_scanline);
+ y_vector=(double *) RelinquishMagickMemory(y_vector);
+ scale_scanline=(double *) RelinquishMagickMemory(scale_scanline);
if (scale_image->rows != image->rows)
- scanline=(MagickRealType *) RelinquishMagickMemory(scanline);
- x_vector=(MagickRealType *) RelinquishMagickMemory(x_vector);
+ scanline=(double *) RelinquishMagickMemory(scanline);
+ x_vector=(double *) RelinquishMagickMemory(x_vector);
scale_image->type=image->type;
return(scale_image);
}
Image
*thumbnail_image;
- MagickRealType
+ double
x_factor,
y_factor;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
- x_factor=(MagickRealType) columns/(MagickRealType) image->columns;
- y_factor=(MagickRealType) rows/(MagickRealType) image->rows;
+ x_factor=(double) columns/(double) image->columns;
+ y_factor=(double) rows/(double) image->rows;
if ((x_factor*y_factor) > 0.1)
- thumbnail_image=ResizeImage(image,columns,rows,image->filter,image->blur,
- exception);
+ thumbnail_image=ResizeImage(image,columns,rows,image->filter,exception);
else
if (((SampleFactor*columns) < 128) || ((SampleFactor*rows) < 128))
- thumbnail_image=ResizeImage(image,columns,rows,image->filter,
- image->blur,exception);
+ thumbnail_image=ResizeImage(image,columns,rows,image->filter,exception);
else
{
Image
if (sample_image == (Image *) NULL)
return((Image *) NULL);
thumbnail_image=ResizeImage(sample_image,columns,rows,image->filter,
- image->blur,exception);
+ exception);
sample_image=DestroyImage(sample_image);
}
if (thumbnail_image == (Image *) NULL)
return(thumbnail_image);
(void) ParseAbsoluteGeometry("0x0+0+0",&thumbnail_image->page);
- if (thumbnail_image->matte == MagickFalse)
+ if( IfMagickFalse(thumbnail_image->alpha_trait) )
(void) SetImageAlphaChannel(thumbnail_image,OpaqueAlphaChannel,exception);
thumbnail_image->depth=8;
thumbnail_image->interlace=NoInterlace;
if (strstr(image->magick_filename,"//") == (char *) NULL)
(void) FormatLocaleString(value,MaxTextExtent,"file://%s",
image->magick_filename);
- (void) SetImageProperty(thumbnail_image,"Thumb::URI",value);
+ (void) SetImageProperty(thumbnail_image,"Thumb::URI",value,exception);
(void) CopyMagickString(value,image->magick_filename,MaxTextExtent);
- if (GetPathAttributes(image->filename,&attributes) != MagickFalse)
+ if( IfMagickTrue(GetPathAttributes(image->filename,&attributes)) )
{
(void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
attributes.st_mtime);
- (void) SetImageProperty(thumbnail_image,"Thumb::MTime",value);
+ (void) SetImageProperty(thumbnail_image,"Thumb::MTime",value,exception);
}
(void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
attributes.st_mtime);
(void) FormatMagickSize(GetBlobSize(image),MagickFalse,value);
(void) ConcatenateMagickString(value,"B",MaxTextExtent);
- (void) SetImageProperty(thumbnail_image,"Thumb::Size",value);
+ (void) SetImageProperty(thumbnail_image,"Thumb::Size",value,exception);
(void) FormatLocaleString(value,MaxTextExtent,"image/%s",image->magick);
LocaleLower(value);
- (void) SetImageProperty(thumbnail_image,"Thumb::Mimetype",value);
- (void) SetImageProperty(thumbnail_image,"software",
- GetMagickVersion(&version));
+ (void) SetImageProperty(thumbnail_image,"Thumb::Mimetype",value,exception);
+ (void) SetImageProperty(thumbnail_image,"software",GetMagickVersion(&version),
+ exception);
(void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
image->magick_columns);
- (void) SetImageProperty(thumbnail_image,"Thumb::Image::Width",value);
+ (void) SetImageProperty(thumbnail_image,"Thumb::Image::Width",value,
+ exception);
(void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
image->magick_rows);
- (void) SetImageProperty(thumbnail_image,"Thumb::Image::height",value);
+ (void) SetImageProperty(thumbnail_image,"Thumb::Image::Height",value,
+ exception);
(void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
GetImageListLength(image));
- (void) SetImageProperty(thumbnail_image,"Thumb::Document::Pages",value);
+ (void) SetImageProperty(thumbnail_image,"Thumb::Document::Pages",value,
+ exception);
return(thumbnail_image);
}