% 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/property.h"
#include "MagickCore/monitor.h"
#include "MagickCore/monitor-private.h"
-#include "MagickCore/pixel.h"
#include "MagickCore/option.h"
+#include "MagickCore/pixel.h"
+#include "MagickCore/quantum-private.h"
#include "MagickCore/resample.h"
#include "MagickCore/resample-private.h"
#include "MagickCore/resize.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>
#define MagickPIL ((MagickRealType) 3.14159265358979323846264338327950288420L)
-static MagickRealType Jinc(const MagickRealType x,
- const ResizeFilter *magick_unused(resize_filter))
-{
- /*
- See Pratt "Digital Image Processing" p.97 for Jinc/Bessel functions.
- http://mathworld.wolfram.com/JincFunction.html and page 11 of
- http://www.ph.ed.ac.uk/%7ewjh/teaching/mo/slides/lens/lens.pdf
-
- The original "zoom" program by Paul Heckbert called this "Bessel".
- But really it is more accurately named "Jinc".
- */
- if (x == 0.0)
- return(0.5*MagickPIL);
- return(BesselOrderOne(MagickPIL*x)/x);
-}
-
static MagickRealType Blackman(const MagickRealType x,
const ResizeFilter *magick_unused(resize_filter))
{
/*
Blackman: 2nd order cosine windowing function:
0.42 + 0.5 cos(pi x) + 0.08 cos(2pi x)
- Refactored by Chantal Racette and Nicolas Robidoux to one trig
- call and five flops.
+
+ Refactored by Chantal Racette and Nicolas Robidoux to one trig call and
+ five flops.
*/
- const MagickRealType cospix = cos((double) (MagickPIL*x));
- return(0.34+cospix*(0.5+cospix*0.16));
+ const MagickRealType cosine=cos((double) (MagickPIL*x));
+ return(0.34+cosine*(0.5+cosine*0.16));
}
static MagickRealType Bohman(const MagickRealType x,
/*
Bohman: 2rd Order cosine windowing function:
(1-x) cos(pi x) + sin(pi x) / pi.
- Refactored by Nicolas Robidoux to one trig call, one sqrt call,
- and 7 flops, taking advantage of the fact that the support of
- Bohman is 1 (so that we know that sin(pi x) >= 0).
+
+ Refactored by Nicolas Robidoux to one trig call, one sqrt call, and 7 flops,
+ taking advantage of the fact that the support of Bohman is 1.0 (so that we
+ know that sin(pi x) >= 0).
*/
- const double cospix = cos((double) (MagickPIL*x));
- const double sinpix = sqrt(1.0-cospix*cospix);
- return((1.0-x)*cospix+(1.0/MagickPIL)*sinpix);
+ const MagickRealType cosine=cos((double) (MagickPIL*x));
+ const MagickRealType sine=sqrt(1.0-cosine*cosine);
+ return((1.0-x)*cosine+(1.0/MagickPIL)*sine);
}
static MagickRealType Box(const MagickRealType 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);
}
P0 + P1*x + P2*x^2 + P3*x^3 0 <= x < 1
Q0 + Q1*x + Q2*x^2 + Q3*x^3 1 <= x < 2
- which ensures function is continuous in value and derivative
- (slope).
+ 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])));
Gaussian with a fixed sigma = 1/2
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))
+
The constants are pre-calculated...
- exp( -coeff[0]*(x^2)) ) * coeff[1]
+ exp( -coeff[0]*(x^2)) ) * coeff[1]
+
However the multiplier coefficent (1) is not needed and not used.
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.
+ 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.
+ without the filter 'missing' pixels because the support becomes too small.
*/
return(exp((double)(-resize_filter->coefficient[0]*x*x)));
}
{
/*
Cosine window function:
- .5+.5cos(pi x).
+ 0.5+0.5*cos(pi*x).
*/
- const MagickRealType cospix = cos((double) (MagickPIL*x));
- return(0.5+0.5*cospix);
+ const MagickRealType cosine=cos((double) (MagickPIL*x));
+ return(0.5+0.5*cosine);
}
static MagickRealType Hamming(const MagickRealType x,
Offset cosine window function:
.54 + .46 cos(pi x).
*/
- const MagickRealType cospix = cos((double) (MagickPIL*x));
- return(0.54+0.46*cospix);
+ const MagickRealType cosine=cos((double) (MagickPIL*x));
+ return(0.54+0.46*cosine);
}
-static MagickRealType Kaiser(const MagickRealType x,
+static MagickRealType Jinc(const MagickRealType x,
const ResizeFilter *magick_unused(resize_filter))
{
-#define Alpha 6.5
-#define I0A (1.0/I0(Alpha))
+ /*
+ See Pratt "Digital Image Processing" p.97 for Jinc/Bessel functions.
+ http://mathworld.wolfram.com/JincFunction.html and page 11 of
+ http://www.ph.ed.ac.uk/%7ewjh/teaching/mo/slides/lens/lens.pdf
+
+ The original "zoom" program by Paul Heckbert called this "Bessel". But
+ really it is more accurately named "Jinc".
+ */
+ if (x == 0.0)
+ return(0.5*MagickPIL);
+ return(BesselOrderOne(MagickPIL*x)/x);
+}
+static MagickRealType Kaiser(const MagickRealType x,
+ const ResizeFilter *resize_filter)
+{
/*
- 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)
+ Alpha (c[0]) is a free value from 5 to 8 (defaults to 6.5).
+ A scaling factor (c[1]) is not needed as filter is normalized
*/
- 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,
order;
/*
- Lagrange piecewise polynomial fit of sinc: N is the 'order' of the
- lagrange function and depends on the overall support window size
- of the filter. That is: for a support of 2, it gives a lagrange-4
- (piecewise cubic function).
+ Lagrange piecewise polynomial fit of sinc: N is the 'order' of the lagrange
+ function and depends on the overall support window size of the filter. That
+ is: for a support of 2, it gives a lagrange-4 (piecewise cubic function).
"n" identifies the piece of the piecewise polynomial.
- See Survey: Interpolation Methods, IEEE Transactions on Medical
- Imaging, Vol 18, No 11, November 1999, p1049-1075, -- Equation 27
- on p1064.
+ See Survey: Interpolation Methods, IEEE Transactions on Medical Imaging,
+ Vol 18, No 11, November 1999, p1049-1075, -- Equation 27 on p1064.
*/
if (x > resize_filter->support)
return(0.0);
order=(ssize_t) (2.0*resize_filter->window_support); /* number of pieces */
- /*n=(ssize_t)((1.0*order)/2.0+x); -- which piece does x belong to */
- n = (ssize_t)(resize_filter->window_support + x);
+ n=(ssize_t) (resize_filter->window_support+x);
value=1.0f;
for (i=0; i < order; i++)
if (i != n)
sinc(x) == sin(pi x)/(pi x).
*/
if (x != 0.0)
- {
- const MagickRealType pix = (MagickRealType) (MagickPIL*x);
- return(sin((double) pix)/pix);
- }
+ {
+ const MagickRealType alpha=(MagickRealType) (MagickPIL*x);
+ return(sin((double) alpha)/alpha);
+ }
return((MagickRealType) 1.0);
}
const ResizeFilter *magick_unused(resize_filter))
{
/*
- Approximations of the sinc function sin(pi x)/(pi x) over the
- interval [-4,4] constructed by Nicolas Robidoux and Chantal
- Racette with funding from the Natural Sciences and Engineering
- Research Council of Canada.
+ Approximations of the sinc function sin(pi x)/(pi x) over the interval
+ [-4,4] constructed by Nicolas Robidoux and Chantal Racette with funding
+ from the Natural Sciences and Engineering Research Council of Canada.
Although the approximations are polynomials (for low order of
approximation) and quotients of polynomials (for higher order of
- approximation) and consequently are similar in form to Taylor
- polynomials/Pade approximants, the approximations are computed
- with a completely different technique.
-
- Summary: These approximations are "the best" in terms of bang
- (accuracy) for the buck (flops). More specifically: Among the
- polynomial quotients that can be computed using a fixed number of
- flops (with a given "+ - * / budget"), the chosen polynomial
- quotient is the one closest to the approximated function with
- respect to maximum absolute relative error over the given
- interval.
-
- The Remez algorithm, as implemented in the boost library's minimax
- package, is the key to the construction:
- http://www.boost.org/doc/libs/1_36_0/libs/math/doc/...
- ...sf_and_dist/html/math_toolkit/backgrounders/remez.html
- */
- /*
- If outside of the interval of approximation, use the standard trig
- formula.
+ approximation) and consequently are similar in form to Taylor polynomials /
+ Pade approximants, the approximations are computed with a completely
+ different technique.
+
+ Summary: These approximations are "the best" in terms of bang (accuracy)
+ for the buck (flops). More specifically: Among the polynomial quotients
+ that can be computed using a fixed number of flops (with a given "+ - * /
+ budget"), the chosen polynomial quotient is the one closest to the
+ approximated function with respect to maximum absolute relative error over
+ the given interval.
+
+ The Remez algorithm, as implemented in the boost library's minimax package,
+ is the key to the construction: http://www.boost.org/doc/libs/1_36_0/libs/
+ math/doc/sf_and_dist/html/math_toolkit/backgrounders/remez.html
+
+ If outside of the interval of approximation, use the standard trig formula.
*/
if (x > 4.0)
{
- const MagickRealType pix = (MagickRealType) (MagickPIL*x);
- return(sin((double) pix)/pix);
+ const MagickRealType alpha=(MagickRealType) (MagickPIL*x);
+ return(sin((double) alpha)/alpha);
}
{
/*
- The approximations only depend on x^2 (sinc is an even
- function).
+ The approximations only depend on x^2 (sinc is an even function).
*/
const MagickRealType xx = x*x;
#if MAGICKCORE_QUANTUM_DEPTH <= 8
const ResizeFilter *magick_unused(resize_filter))
{
/*
- 1st order (linear) B-Spline, bilinear interpolation, Tent 1D
- filter, or a Bartlett 2D Cone filter. Also used as a
- Bartlett Windowing function for Sinc().
+ 1st order (linear) B-Spline, bilinear interpolation, Tent 1D filter, or
+ a Bartlett 2D Cone filter. Also used as a Bartlett Windowing function
+ for Sinc().
*/
if (x < 1.0)
return(1.0-x);
% these filters:
%
% FIR (Finite impulse Response) Filters
-% Box Triangle Quadratic
-% Cubic Hermite Catrom
-% Mitchell
+% Box Triangle Quadratic Cubic 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 Hanning Hamming Kaiser Lanczos
%
% Special purpose Filters
-% SincFast LanczosSharp Lanczos2D Lanczos2DSharp Robidoux
+% SincFast LanczosSharp Lanczos2D Lanczos2DSharp Robidoux
%
% The users "-filter" selection is used to lookup the default 'expert'
% settings for that filter from a internal table. However any provided
% 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 radial,
% 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;
MagickRealType
B,
C,
- sigma;
+ value;
register ResizeFilter
*resize_filter;
/*
- Table Mapping given Filter, into Weighting and Windowing functions. A
+ 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
window;
} const mapping[SentinelFilter] =
{
- { UndefinedFilter, BoxFilter }, /* Undefined (default to Box) */
- { PointFilter, BoxFilter }, /* SPECIAL: Nearest neighbour */
- { 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, BlackmanFilter }, /* Blackman -- 2*cosine-sinc */
- { GaussianFilter, BoxFilter }, /* Gaussian blur filter */
- { QuadraticFilter, BoxFilter }, /* Quadratic Gaussian approx */
- { CubicFilter, BoxFilter }, /* Cubic B-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 */
- { SincFastFilter, CubicFilter }, /* Parzen -- cubic-sinc */
- { SincFastFilter, BohmanFilter }, /* Bohman -- 2*cosine-sinc */
- { SincFastFilter, TriangleFilter }, /* Bartlett -- triangle-sinc */
- { LagrangeFilter, BoxFilter }, /* Lagrange self-windowing */
- { LanczosFilter, LanczosFilter }, /* Lanczos Sinc-Sinc filters */
- { LanczosSharpFilter, LanczosSharpFilter }, /* | these require */
- { Lanczos2Filter, Lanczos2Filter }, /* | special handling */
- { Lanczos2SharpFilter,Lanczos2SharpFilter },
- { RobidouxFilter, BoxFilter }, /* Cubic Keys tuned for EWA */
+ { UndefinedFilter, BoxFilter }, /* Undefined (default to Box) */
+ { PointFilter, BoxFilter }, /* SPECIAL: Nearest neighbour */
+ { 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, BlackmanFilter }, /* Blackman -- 2*cosine-sinc */
+ { GaussianFilter, BoxFilter }, /* Gaussian blur filter */
+ { QuadraticFilter, BoxFilter }, /* Quadratic Gaussian approx */
+ { CubicFilter, BoxFilter }, /* Cubic B-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 */
+ { SincFastFilter, CubicFilter }, /* Parzen -- cubic-sinc */
+ { SincFastFilter, BohmanFilter }, /* Bohman -- 2*cosine-sinc */
+ { SincFastFilter, TriangleFilter }, /* Bartlett -- triangle-sinc */
+ { LagrangeFilter, BoxFilter }, /* Lagrange self-windowing */
+ { LanczosFilter, LanczosFilter }, /* Lanczos Sinc-Sinc filters */
+ { LanczosSharpFilter, LanczosSharpFilter }, /* | these require */
+ { Lanczos2Filter, Lanczos2Filter }, /* | special handling */
+ { Lanczos2SharpFilter, Lanczos2SharpFilter },
+ { RobidouxFilter, BoxFilter }, /* Cubic Keys tuned for EWA */
};
/*
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. */
+ (*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. */
} const filters[SentinelFilter] =
{
- { 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 */
- { 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, 1.0, 0.0, 0.5 }, /* Catmull-Rom (B=0,C=1/2) */
+ { 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 */
+ { 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, 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) */
- { 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, 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 */
+ { 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) */
+ { 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, 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 */
};
/*
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
jinc_zeros[16] =
4.2410628637960699,
5.2427643768701817,
6.2439216898644877,
- 7.244759868719957,
+ 7.2447598687199570,
8.2453949139520427,
9.2458926849494673,
10.246293348754916,
12.246898461138105,
13.247132522181061,
14.247333735806849,
- 15.2475085630373,
+ 15.247508563037300,
16.247661874700962
};
*/
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);
resize_filter=(ResizeFilter *) AcquireMagickMemory(sizeof(*resize_filter));
if (resize_filter == (ResizeFilter *) NULL)
ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
+ (void) ResetMagickMemory(resize_filter,0,sizeof(*resize_filter));
+ resize_filter->blur=1.0;
/*
Defaults for the requested filter.
*/
filter_type=mapping[filter].filter;
window_type=mapping[filter].window;
- 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 )
- filter_type=JincFilter;
-
+ 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)
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. */
+ /*
+ Filter override with a specific window function.
+ */
artifact=GetImageArtifact(image,"filter:window");
if (artifact != (const char *) NULL)
{
}
else
{
- /* Window specified, but no filter function? Assume Sinc/Jinc. */
+ /*
+ Window specified, but no filter function? Assume Sinc/Jinc.
+ */
artifact=GetImageArtifact(image,"filter:window");
if (artifact != (const char *) NULL)
{
ssize_t
option;
- option=ParseCommandOption(MagickFilterOptions,MagickFalse,
- artifact);
+ 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->window=filters[window_type].function;
resize_filter->scale=filters[window_type].scale;
resize_filter->signature=MagickSignature;
-
- /* Filter Modifications for orthogonal/cylindrical usage */
- if (cylindrical != MagickFalse)
+ /*
+ Filter Modifications for orthogonal/cylindrical usage.
+ */
+ if( IfMagickTrue(cylindrical) )
switch (filter_type)
{
case BoxFilter:
- /* Support for Cylindrical Box should be sqrt(2)/2 */
+ {
+ /*
+ Support for Cylindrical Box should be sqrt(2)/2.
+ */
resize_filter->support=(MagickRealType) 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;
}
-
/*
- ** Other Expert Option Modifications
+ Expert Option Modifications.
*/
-
- /* User Sigma Override - no support change */
+ /* User Gaussian Sigma Override - no support change */
+ value=0.5; /* guassian sigma default, half pixel */
+ if ( GaussianFilter ) {
artifact=GetImageArtifact(image,"filter:sigma");
if (artifact != (const char *) NULL)
- sigma=InterpretLocaleValue(artifact,(char **) NULL);
- /* Define coefficents for Gaussian */
- if ( GaussianFilter ) {
- 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 */
+ value=StringToDouble(artifact,(char **) NULL);
+ /* Define coefficents for Gaussian */
+ resize_filter->coefficient[0]=1.0/(2.0*value*value); /* X scaling */
+ resize_filter->coefficient[1]=(MagickRealType) (1.0/(Magick2PI*value*
+ value)); /* normalization */
+ }
+ /* User Kaiser Alpha Override - no support change */
+ if ( KaiserFilter ) {
+ value=6.5; /* default alpha value for Kaiser bessel windowing function */
+ artifact=GetImageArtifact(image,"filter:alpha");
+ if (artifact != (const char *) NULL)
+ value=StringToDouble(artifact,(char **) NULL);
+ /* Define coefficents for Kaiser Windowing Function */
+ resize_filter->coefficient[0]=value; /* X scaling */
+ resize_filter->coefficient[1]=1.0/I0(value); /* normalization */
}
/* Blur Override */
artifact=GetImageArtifact(image,"filter:blur");
if (artifact != (const char *) NULL)
- resize_filter->blur *= InterpretLocaleValue(artifact,(char **) NULL);
+ resize_filter->blur*=StringToDouble(artifact,(char **) NULL);
if (resize_filter->blur < MagickEpsilon)
resize_filter->blur=(MagickRealType) MagickEpsilon;
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];
+ 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));
+ 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
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.
*/
- resize_filter->scale /= resize_filter->window_support;
+ resize_filter->scale/=resize_filter->window_support;
/*
* Set Cubic Spline B,C values, calculate Cubic coefficients.
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(). */
- {
- const double twoB = B+B;
+ {
+ double
+ B_squared;
+
+ B_squared=B+B;
resize_filter->coefficient[0]=1.0-(1.0/3.0)*B;
- resize_filter->coefficient[1]=-3.0+twoB+C;
+ resize_filter->coefficient[1]=-3.0+B_squared+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[4]=-8.0*C-B_squared;
resize_filter->coefficient[5]=B+5.0*C;
resize_filter->coefficient[6]=(-1.0/6.0)*B-C;
- }
+ }
}
/*
#pragma omp master
{
#endif
- artifact=GetImageArtifact(image,"filter:verbose");
- if (IsMagickTrue(artifact))
+ if (IfMagickTrue(GetImageArtifact(image,"filter:verbose")))
{
double
support,
/*
Report Filter Details.
*/
- support=GetResizeFilterSupport(resize_filter); /* practical_support */
+ 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);
+ GetMagickPrecision(),(double) resize_filter->support);
(void) FormatLocaleFile(stdout,"# win-support = %.*g\n",
- GetMagickPrecision(),(double) resize_filter->window_support);
+ GetMagickPrecision(),(double) resize_filter->window_support);
(void) FormatLocaleFile(stdout,"# scale_blur = %.*g\n",
- GetMagickPrecision(), (double)resize_filter->blur);
- if ( filter_type == GaussianFilter )
+ GetMagickPrecision(), (double)resize_filter->blur);
+ if (filter_type == GaussianFilter)
(void) FormatLocaleFile(stdout,"# gaussian_sigma = %.*g\n",
- GetMagickPrecision(), (double)sigma);
+ GetMagickPrecision(), (double)value);
+ if ( filter_type == KaiserFilter )
+ (void) FormatLocaleFile(stdout,"# kaiser_alpha = %.*g\n",
+ GetMagickPrecision(), (double)value);
(void) FormatLocaleFile(stdout,"# practical_support = %.*g\n",
- GetMagickPrecision(), (double)support);
+ 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.
*/
for (x=0.0; x <= support; x+=0.01f)
- (void) FormatLocaleFile(stdout,"%5.2lf\t%.*g\n",x,GetMagickPrecision(),
- (double) GetResizeFilterWeight(resize_filter,x));
+ (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);
%
% 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,
-% const size_t rows,ExceptionInfo *exception)
+% const size_t rows, ExceptionInfo *exception)
%
% A description of each parameter follows:
%
MagickExport Image *AdaptiveResizeImage(const Image *image,
const size_t columns,const size_t rows,ExceptionInfo *exception)
{
-#define AdaptiveResizeImageTag "Resize/Image"
-
- CacheView
- *image_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) == MagickFalse)
- {
- InheritException(exception,&resize_image->exception);
- resize_image=DestroyImage(resize_image);
- return((Image *) NULL);
- }
- 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++)
- {
- PixelInfo
- pixel;
-
- PointInfo
- offset;
-
- register Quantum
- *restrict q;
-
- register ssize_t
- x;
-
- if (status == MagickFalse)
- continue;
- q=QueueCacheViewAuthenticPixels(resize_view,0,y,resize_image->columns,1,
- exception);
- if (q == (const Quantum *) NULL)
- continue;
- offset.y=((MagickRealType) (y+0.5)*image->rows/resize_image->rows);
- GetPixelInfo(image,&pixel);
- for (x=0; x < (ssize_t) resize_image->columns; x++)
- {
- offset.x=((MagickRealType) (x+0.5)*image->columns/resize_image->columns);
- (void) InterpolatePixelInfo(image,image_view,
- MeshInterpolatePixel,offset.x-0.5,offset.y-0.5,&pixel,exception);
- SetPixelPixelInfo(resize_image,&pixel,q);
- q+=GetPixelComponents(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);
- image_view=DestroyCacheView(image_view);
- if (status == MagickFalse)
- resize_image=DestroyImage(resize_image);
+ resize_image=InterpolativeResizeImage(image,columns,rows,MeshInterpolatePixel,
+ exception);
return(resize_image);
}
\f
% 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);
% o filter: Image filter to use.
%
*/
-MagickExport MagickRealType GetResizeFilterSupport(
+MagickPrivate MagickRealType GetResizeFilterSupport(
const ResizeFilter *resize_filter)
{
assert(resize_filter != (ResizeFilter *) NULL);
% o x: the point.
%
*/
-MagickExport MagickRealType GetResizeFilterWeight(
+MagickPrivate MagickRealType GetResizeFilterWeight(
const ResizeFilter *resize_filter,const MagickRealType x)
{
MagickRealType
% %
% %
% %
-% M a g n i f y I m a g e %
+% I n t e r p o l a t i v e R e s i z e I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% MagnifyImage() is a convenience method that scales an image proportionally
-% to twice its size.
+% InterpolativeResizeImage() resizes an image using the specified
+% interpolation method.
%
-% The format of the MagnifyImage method is:
+% The format of the InterpolativeResizeImage method is:
%
-% Image *MagnifyImage(const Image *image,ExceptionInfo *exception)
+% 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 *MagnifyImage(const Image *image,ExceptionInfo *exception)
+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
- *magnify_image;
+ *resize_image;
- assert(image != (Image *) NULL);
+ MagickBooleanType
+ status;
+
+ MagickOffsetType
+ progress;
+
+ PointInfo
+ scale;
+
+ ssize_t
+ y;
+
+ /*
+ Interpolatively 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);
- magnify_image=ResizeImage(image,2*image->columns,2*image->rows,CubicFilter,
- 1.0,exception);
- return(magnify_image);
+ 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=AcquireCacheView(image);
+ resize_view=AcquireCacheView(resize_image);
+ 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) shared(progress,status)
+#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=((MagickRealType) 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=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ resize_traits=GetPixelChannelMapTraits(resize_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (resize_traits == UndefinedPixelTrait))
+ continue;
+ offset.x=((MagickRealType) 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
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
-% M i n i f y I m a g e %
+% L i q u i d R e s c a l e I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% MinifyImage() is a convenience method that scales an image proportionally
-% to half its size.
-%
-% The format of the MinifyImage method is:
-%
-% Image *MinifyImage(const Image *image,ExceptionInfo *exception)
-%
-% A description of each parameter follows:
-%
-% o image: the image.
-%
-% o exception: return any errors or warnings in this structure.
-%
-*/
-MagickExport Image *MinifyImage(const Image *image,ExceptionInfo *exception)
-{
- Image
- *minify_image;
-
- assert(image != (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);
- minify_image=ResizeImage(image,image->columns/2,image->rows/2,CubicFilter,1.0,
- exception);
- return(minify_image);
-}
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% %
-% %
-% R e s a m p l e I m a g e %
-% %
-% %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-% ResampleImage() resize image in terms of its pixel size, so that when
-% displayed at the given resolution it will be the same size in terms of
-% real world units as the original image at the original resolution.
-%
-% 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,
-% ExceptionInfo *exception)
-%
-% A description of each parameter follows:
-%
-% o image: the image to be resized to fit the given resolution.
-%
-% o x_resolution: the new image x resolution.
-%
-% o y_resolution: the new image y resolution.
-%
-% o filter: Image filter to use.
-%
-% o blur: the blur factor where > 1 is blurry, < 1 is sharp.
-%
-*/
-MagickExport Image *ResampleImage(const Image *image,const double x_resolution,
- const double y_resolution,const FilterTypes filter,const double blur,
- ExceptionInfo *exception)
-{
-#define ResampleImageTag "Resample/Image"
-
- Image
- *resample_image;
-
- size_t
- height,
- width;
-
- /*
- Initialize sampled image attributes.
- */
- 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);
- 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);
- if (resample_image != (Image *) NULL)
- {
- resample_image->x_resolution=x_resolution;
- resample_image->y_resolution=y_resolution;
- }
- return(resample_image);
-}
-#if defined(MAGICKCORE_LQR_DELEGATE)
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% %
-% %
-% L i q u i d R e s c a l e I m a g e %
-% %
-% %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-% LiquidRescaleImage() rescales image with seam carving.
+% LiquidRescaleImage() rescales image with seam carving.
%
% The format of the LiquidRescaleImage method is:
%
-% Image *LiquidRescaleImage(const Image *image,
-% const size_t columns,const size_t rows,
-% const double delta_x,const double rigidity,ExceptionInfo *exception)
+% Image *LiquidRescaleImage(const Image *image,const size_t columns,
+% const size_t rows,const double delta_x,const double rigidity,
+% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
#define LiquidRescaleImageTag "Rescale/Image"
CacheView
+ *image_view,
*rescale_view;
- const char
- *map;
-
- guchar
- *packet;
+ gfloat
+ *packet,
+ *pixels;
Image
*rescale_image;
int
- x,
- y;
+ x_offset,
+ y_offset;
LqrCarver
*carver;
MagickBooleanType
status;
- PixelInfo
- pixel;
+ register gfloat
+ *q;
- unsigned char
- *pixels;
+ ssize_t
+ y;
/*
Liquid rescale 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);
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,
resize_image=DestroyImage(resize_image);
return(rescale_image);
}
- map="RGB";
- if (image->matte == MagickFalse)
- map="RGBA";
- if (image->colorspace == CMYKColorspace)
- {
- map="CMYK";
- if (image->matte == MagickFalse)
- map="CMYKA";
- }
- pixels=(unsigned char *) AcquireQuantumMemory(image->columns,image->rows*
- strlen(map)*sizeof(*pixels));
- if (pixels == (unsigned char *) NULL)
+ pixels=(gfloat *) AcquireQuantumMemory(image->columns,image->rows*
+ GetPixelChannels(image)*sizeof(*pixels));
+ if (pixels == (gfloat *) NULL)
return((Image *) NULL);
- status=ExportImagePixels(image,0,0,image->columns,image->rows,map,CharPixel,
- pixels,exception);
- if (status == MagickFalse)
+ status=MagickTrue;
+ q=pixels;
+ image_view=AcquireCacheView(image);
+ for (y=0; y < (ssize_t) image->rows; y++)
+ {
+ register const Quantum
+ *restrict p;
+
+ register ssize_t
+ x;
+
+ if( IfMagickFalse(status) )
+ continue;
+ p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
+ if (p == (const Quantum *) NULL)
+ {
+ status=MagickFalse;
+ continue;
+ }
+ for (x=0; x < (ssize_t) image->columns; x++)
{
- pixels=(unsigned char *) RelinquishMagickMemory(pixels);
- ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
+ register ssize_t
+ i;
+
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ *q++=QuantumScale*p[i];
+ p+=GetPixelChannels(image);
}
- carver=lqr_carver_new(pixels,image->columns,image->rows,strlen(map));
+ }
+ image_view=DestroyCacheView(image_view);
+ carver=lqr_carver_new_ext(pixels,image->columns,image->rows,
+ GetPixelChannels(image),LQR_COLDEPTH_32F);
if (carver == (LqrCarver *) NULL)
{
- pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+ pixels=(gfloat *) RelinquishMagickMemory(pixels);
ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
}
lqr_status=lqr_carver_init(carver,(int) delta_x,rigidity);
lqr_carver_get_height(carver),MagickTrue,exception);
if (rescale_image == (Image *) NULL)
{
- pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+ pixels=(gfloat *) RelinquishMagickMemory(pixels);
return((Image *) NULL);
}
- if (SetImageStorageClass(rescale_image,DirectClass) == MagickFalse)
+ if( IfMagickFalse(SetImageStorageClass(rescale_image,DirectClass,exception)) )
{
- InheritException(exception,&rescale_image->exception);
+ pixels=(gfloat *) RelinquishMagickMemory(pixels);
rescale_image=DestroyImage(rescale_image);
return((Image *) NULL);
}
- GetPixelInfo(rescale_image,&pixel);
- (void) lqr_carver_scan_reset(carver);
rescale_view=AcquireCacheView(rescale_image);
- while (lqr_carver_scan(carver,&x,&y,&packet) != 0)
+ (void) lqr_carver_scan_reset(carver);
+ while (lqr_carver_scan_ext(carver,&x_offset,&y_offset,(void **) &packet) != 0)
{
register Quantum
*restrict q;
- q=QueueCacheViewAuthenticPixels(rescale_view,x,y,1,1,exception);
- if (q == (const Quantum *) NULL)
+ register ssize_t
+ i;
+
+ q=QueueCacheViewAuthenticPixels(rescale_view,x_offset,y_offset,1,1,
+ exception);
+ if (q == (Quantum *) NULL)
break;
- pixel.red=QuantumRange*(packet[0]/255.0);
- pixel.green=QuantumRange*(packet[1]/255.0);
- pixel.blue=QuantumRange*(packet[2]/255.0);
- if (image->colorspace != CMYKColorspace)
- {
- if (image->matte == MagickFalse)
- pixel.alpha=QuantumRange*(packet[3]/255.0);
- }
- else
- {
- pixel.black=QuantumRange*(packet[3]/255.0);
- if (image->matte == MagickFalse)
- pixel.alpha=QuantumRange*(packet[4]/255.0);
- }
- SetPixelPixelInfo(rescale_image,&pixel,q);
- if (SyncCacheViewAuthenticPixels(rescale_view,exception) == MagickFalse)
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ rescale_traits,
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ rescale_traits=GetPixelChannelMapTraits(rescale_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (rescale_traits == UndefinedPixelTrait))
+ continue;
+ SetPixelChannel(rescale_image,channel,ClampToQuantum(QuantumRange*
+ packet[i]),q);
+ }
+ if( IfMagickFalse(SyncCacheViewAuthenticPixels(rescale_view,exception)) )
break;
}
rescale_view=DestroyCacheView(rescale_view);
- /*
- Relinquish resources.
- */
lqr_carver_destroy(carver);
return(rescale_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);
% %
% %
% %
+% M a g n i f y I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% MagnifyImage() is a convenience method that scales an image proportionally
+% to twice its size.
+%
+% The format of the MagnifyImage method is:
+%
+% Image *MagnifyImage(const Image *image,ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *MagnifyImage(const Image *image,ExceptionInfo *exception)
+{
+ Image
+ *magnify_image;
+
+ assert(image != (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);
+ magnify_image=ResizeImage(image,2*image->columns,2*image->rows,CubicFilter,
+ exception);
+ return(magnify_image);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% M i n i f y I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% MinifyImage() is a convenience method that scales an image proportionally to
+% half its size.
+%
+% The format of the MinifyImage method is:
+%
+% Image *MinifyImage(const Image *image,ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *MinifyImage(const Image *image,ExceptionInfo *exception)
+{
+ Image
+ *minify_image;
+
+ assert(image != (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);
+ minify_image=ResizeImage(image,image->columns/2,image->rows/2,CubicFilter,
+ exception);
+ return(minify_image);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% R e s a m p l e I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ResampleImage() resize image in terms of its pixel size, so that when
+% displayed at the given resolution it will be the same size in terms of
+% real world units as the original image at the original resolution.
+%
+% The format of the ResampleImage method is:
+%
+% Image *ResampleImage(Image *image,const double x_resolution,
+% const double y_resolution,const FilterTypes filter,
+% ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: the image to be resized to fit the given resolution.
+%
+% o x_resolution: the new image x resolution.
+%
+% o y_resolution: the new image y resolution.
+%
+% o filter: Image filter to use.
+%
+% 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,ExceptionInfo *exception)
+{
+#define ResampleImageTag "Resample/Image"
+
+ Image
+ *resample_image;
+
+ size_t
+ height,
+ width;
+
+ /*
+ Initialize sampled image attributes.
+ */
+ 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);
+ 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->resolution.x=x_resolution;
+ resample_image->resolution.y=y_resolution;
+ }
+ return(resample_image);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% R e s i z e I m a g e %
% %
% %
assert(contribution != (ContributionInfo **) NULL);
for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
if (contribution[i] != (ContributionInfo *) NULL)
- contribution[i]=(ContributionInfo *) RelinquishMagickMemory(
+ contribution[i]=(ContributionInfo *) RelinquishAlignedMemory(
contribution[i]);
contribution=(ContributionInfo **) RelinquishMagickMemory(contribution);
return(contribution);
(void) ResetMagickMemory(contribution,0,number_threads*sizeof(*contribution));
for (i=0; i < (ssize_t) number_threads; i++)
{
- contribution[i]=(ContributionInfo *) AcquireQuantumMemory(count,
+ contribution[i]=(ContributionInfo *) AcquireAlignedMemory(count,
sizeof(**contribution));
if (contribution[i] == (ContributionInfo *) NULL)
return(DestroyContributionThreadSet(contribution));
MagickBooleanType
status;
- PixelInfo
- zero;
-
MagickRealType
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) == MagickFalse)
- {
- InheritException(exception,&resize_image->exception);
- return(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 too small even for nearest neighbour: Reduce to point sampling.
*/
support=(MagickRealType) 0.5;
scale=1.0;
}
status=MagickTrue;
scale=1.0/scale;
- (void) ResetMagickMemory(&zero,0,sizeof(zero));
image_view=AcquireCacheView(image);
resize_view=AcquireCacheView(resize_image);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for shared(status)
+ #pragma omp parallel for schedule(static,4) shared(status)
#endif
for (x=0; x < (ssize_t) resize_image->columns; x++)
{
MagickRealType
- center,
+ bisect,
density;
-
register const Quantum
*restrict p;
start,
stop;
- if (status == MagickFalse)
+ if( IfMagickFalse(status) )
continue;
- center=(MagickRealType) (x+0.5)/x_factor;
- start=(ssize_t) MagickMax(center-support+0.5,0.0);
- stop=(ssize_t) MagickMin(center+support+0.5,(double) image->columns);
+ bisect=(MagickRealType) (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=contributions[GetOpenMPThreadId()];
for (n=0; n < (stop-start); n++)
{
contribution[n].pixel=start+n;
contribution[n].weight=GetResizeFilterWeight(resize_filter,scale*
- ((MagickRealType) (start+n)-center+0.5));
+ ((MagickRealType) (start+n)-bisect+0.5));
density+=contribution[n].weight;
}
if ((density != 0.0) && (density != 1.0))
}
for (y=0; y < (ssize_t) resize_image->rows; y++)
{
- PixelInfo
- pixel;
-
- MagickRealType
- alpha;
-
register ssize_t
i;
- ssize_t
- j;
-
- pixel=zero;
- if (image->matte == MagickFalse)
+ if (GetPixelMask(resize_image,q) != 0)
{
- for (i=0; i < n; i++)
- {
- j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
- (contribution[i].pixel-contribution[0].pixel);
- alpha=contribution[i].weight;
- pixel.red+=alpha*GetPixelRed(image,p+j*
- GetPixelComponents(image));
- pixel.green+=alpha*GetPixelGreen(image,p+j*
- GetPixelComponents(image));
- pixel.blue+=alpha*GetPixelBlue(image,p+j*
- GetPixelComponents(image));
- if ((image->colorspace == CMYKColorspace) &&
- (resize_image->colorspace == CMYKColorspace))
- pixel.black+=alpha*GetPixelBlue(image,p+j*
- GetPixelComponents(image));
- pixel.alpha+=alpha*GetPixelAlpha(image,p+j*
- GetPixelComponents(image));
- }
- SetPixelRed(resize_image,ClampToQuantum(pixel.red),q);
- SetPixelGreen(resize_image,ClampToQuantum(pixel.green),q);
- SetPixelBlue(resize_image,ClampToQuantum(pixel.blue),q);
- if ((image->colorspace == CMYKColorspace) &&
- (resize_image->colorspace == CMYKColorspace))
- SetPixelBlack(resize_image,ClampToQuantum(pixel.black),q);
- SetPixelAlpha(resize_image,ClampToQuantum(pixel.alpha),q);
+ q+=GetPixelChannels(resize_image);
+ continue;
}
- else
- {
- MagickRealType
- gamma;
+ for (i=0; i < (ssize_t) GetPixelChannels(resize_image); i++)
+ {
+ MagickRealType
+ alpha,
+ gamma,
+ pixel;
+
+ PixelChannel
+ channel;
- gamma=0.0;
- for (i=0; i < n; i++)
+ PixelTrait
+ resize_traits,
+ traits;
+
+ register ssize_t
+ j;
+
+ ssize_t
+ k;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ resize_traits=GetPixelChannelMapTraits(resize_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (resize_traits == UndefinedPixelTrait))
+ continue;
+ if ((resize_traits & CopyPixelTrait) != 0)
{
- j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
- (contribution[i].pixel-contribution[0].pixel);
- alpha=contribution[i].weight*QuantumScale*
- GetPixelAlpha(image,p+j*GetPixelComponents(image));
- pixel.red+=alpha*GetPixelRed(image,p+j*
- GetPixelComponents(image));
- pixel.green+=alpha*GetPixelGreen(image,p+j*
- GetPixelComponents(image));
- pixel.blue+=alpha*GetPixelBlue(image,p+j*
- GetPixelComponents(image));
- if ((image->colorspace == CMYKColorspace) &&
- (resize_image->colorspace == CMYKColorspace))
- pixel.black+=alpha*GetPixelBlack(image,p+j*
- GetPixelComponents(image));
- pixel.alpha+=contribution[i].weight*
- GetPixelAlpha(image,p+j*GetPixelComponents(image));
- gamma+=alpha;
+ 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);
+ SetPixelChannel(resize_image,channel,p[k*GetPixelChannels(image)+i],
+ q);
+ continue;
}
- gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
- SetPixelRed(resize_image,ClampToQuantum(gamma*pixel.red),q);
- SetPixelGreen(resize_image,ClampToQuantum(gamma*pixel.green),q);
- SetPixelBlue(resize_image,ClampToQuantum(gamma*pixel.blue),q);
- if ((image->colorspace == CMYKColorspace) &&
- (resize_image->colorspace == CMYKColorspace))
- SetPixelBlack(resize_image,ClampToQuantum(gamma*pixel.black),q);
- SetPixelAlpha(resize_image,ClampToQuantum(pixel.alpha),q);
- }
- if ((resize_image->storage_class == PseudoClass) &&
- (image->storage_class == PseudoClass))
+ pixel=0.0;
+ if ((resize_traits & BlendPixelTrait) == 0)
+ {
+ /*
+ No alpha blending.
+ */
+ for (j=0; j < n; j++)
+ {
+ k=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
+ (contribution[j].pixel-contribution[0].pixel);
+ alpha=contribution[j].weight;
+ pixel+=alpha*p[k*GetPixelChannels(image)+i];
+ }
+ SetPixelChannel(resize_image,channel,ClampToQuantum(pixel),q);
+ continue;
+ }
+ /*
+ Alpha blending.
+ */
+ gamma=0.0;
+ for (j=0; j < n; j++)
{
- i=(ssize_t) (MagickMin(MagickMax(center,(double) start),(double) stop-
- 1.0)+0.5);
- j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
- (contribution[i-start].pixel-contribution[0].pixel);
- SetPixelIndex(resize_image,GetPixelIndex(image,p+j*
- GetPixelComponents(image)),q);
+ k=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
+ (contribution[j].pixel-contribution[0].pixel);
+ alpha=contribution[j].weight*QuantumScale*
+ GetPixelAlpha(image,p+k*GetPixelChannels(image));
+ pixel+=alpha*p[k*GetPixelChannels(image)+i];
+ gamma+=alpha;
}
- q+=GetPixelComponents(resize_image);
+ gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : 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)
{
#pragma omp critical (MagickCore_HorizontalFilter)
#endif
proceed=SetImageProgress(image,ResizeImageTag,(*offset)++,span);
- if (proceed == MagickFalse)
+ if( IfMagickFalse(proceed) )
status=MagickFalse;
}
}
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) == MagickFalse)
- {
- InheritException(exception,&resize_image->exception);
- return(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 too small even for nearest neighbour: Reduce to point sampling.
*/
support=(MagickRealType) 0.5;
scale=1.0;
image_view=AcquireCacheView(image);
resize_view=AcquireCacheView(resize_image);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for shared(status)
+ #pragma omp parallel for schedule(static,4) shared(status)
#endif
for (y=0; y < (ssize_t) resize_image->rows; y++)
{
MagickRealType
- center,
+ bisect,
density;
register const Quantum
start,
stop;
- if (status == MagickFalse)
+ if( IfMagickFalse(status) )
continue;
- center=(MagickRealType) (y+0.5)/y_factor;
- start=(ssize_t) MagickMax(center-support+0.5,0.0);
- stop=(ssize_t) MagickMin(center+support+0.5,(double) image->rows);
+ bisect=(MagickRealType) (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=contributions[GetOpenMPThreadId()];
for (n=0; n < (stop-start); n++)
{
contribution[n].pixel=start+n;
contribution[n].weight=GetResizeFilterWeight(resize_filter,scale*
- ((MagickRealType) (start+n)-center+0.5));
+ ((MagickRealType) (start+n)-bisect+0.5));
density+=contribution[n].weight;
}
if ((density != 0.0) && (density != 1.0))
}
for (x=0; x < (ssize_t) resize_image->columns; x++)
{
- PixelInfo
- pixel;
-
- MagickRealType
- alpha;
-
register ssize_t
i;
- ssize_t
- j;
-
- pixel=zero;
- if (image->matte == MagickFalse)
+ if (GetPixelMask(resize_image,q) != 0)
{
- for (i=0; i < n; i++)
- {
- j=(ssize_t) ((contribution[i].pixel-contribution[0].pixel)*
- image->columns+x);
- alpha=contribution[i].weight;
- pixel.red+=alpha*GetPixelRed(image,p+j*
- GetPixelComponents(image));
- pixel.green+=alpha*GetPixelGreen(image,p+j*
- GetPixelComponents(image));
- pixel.blue+=alpha*GetPixelBlue(image,p+j*
- GetPixelComponents(image));
- if ((image->colorspace == CMYKColorspace) &&
- (resize_image->colorspace == CMYKColorspace))
- pixel.black+=alpha*GetPixelBlack(image,p+j*
- GetPixelComponents(image));
- pixel.alpha+=alpha*GetPixelAlpha(image,p+j*
- GetPixelComponents(image));
- }
- SetPixelRed(resize_image,ClampToQuantum(pixel.red),q);
- SetPixelGreen(resize_image,ClampToQuantum(pixel.green),q);
- SetPixelBlue(resize_image,ClampToQuantum(pixel.blue),q);
- if ((image->colorspace == CMYKColorspace) &&
- (resize_image->colorspace == CMYKColorspace))
- SetPixelBlack(resize_image,ClampToQuantum(pixel.black),q);
- SetPixelAlpha(resize_image,ClampToQuantum(pixel.alpha),q);
+ q+=GetPixelChannels(resize_image);
+ continue;
}
- else
- {
- MagickRealType
- gamma;
+ for (i=0; i < (ssize_t) GetPixelChannels(resize_image); i++)
+ {
+ MagickRealType
+ alpha,
+ gamma,
+ pixel;
+
+ PixelChannel
+ channel;
+
+ PixelTrait
+ resize_traits,
+ traits;
- gamma=0.0;
- for (i=0; i < n; i++)
+ register ssize_t
+ j;
+
+ ssize_t
+ k;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ resize_traits=GetPixelChannelMapTraits(resize_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (resize_traits == UndefinedPixelTrait))
+ continue;
+ if ((resize_traits & CopyPixelTrait) != 0)
{
- j=(ssize_t) ((contribution[i].pixel-contribution[0].pixel)*
+ 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);
- alpha=contribution[i].weight*QuantumScale*
- GetPixelAlpha(image,p+j*GetPixelComponents(image));
- pixel.red+=alpha*GetPixelRed(image,p+j*
- GetPixelComponents(image));
- pixel.green+=alpha*GetPixelGreen(image,p+j*
- GetPixelComponents(image));
- pixel.blue+=alpha*GetPixelBlue(image,p+j*
- GetPixelComponents(image));
- if ((image->colorspace == CMYKColorspace) &&
- (resize_image->colorspace == CMYKColorspace))
- pixel.black+=alpha*GetPixelBlack(image,p+j*
- GetPixelComponents(image));
- pixel.alpha+=contribution[i].weight*GetPixelAlpha(image,p+j*
- GetPixelComponents(image));
- gamma+=alpha;
+ SetPixelChannel(resize_image,channel,p[k*GetPixelChannels(image)+i],
+ q);
+ continue;
}
- gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
- SetPixelRed(resize_image,ClampToQuantum(gamma*pixel.red),q);
- SetPixelGreen(resize_image,ClampToQuantum(gamma*pixel.green),q);
- SetPixelBlue(resize_image,ClampToQuantum(gamma*pixel.blue),q);
- if ((image->colorspace == CMYKColorspace) &&
- (resize_image->colorspace == CMYKColorspace))
- SetPixelBlack(resize_image,ClampToQuantum(gamma*pixel.black),q);
- SetPixelAlpha(resize_image,ClampToQuantum(pixel.alpha),q);
- }
- if ((resize_image->storage_class == PseudoClass) &&
- (image->storage_class == PseudoClass))
+ pixel=0.0;
+ if ((resize_traits & BlendPixelTrait) == 0)
+ {
+ /*
+ No alpha blending.
+ */
+ for (j=0; j < n; j++)
+ {
+ k=(ssize_t) ((contribution[j].pixel-contribution[0].pixel)*
+ image->columns+x);
+ alpha=contribution[j].weight;
+ pixel+=alpha*p[k*GetPixelChannels(image)+i];
+ }
+ SetPixelChannel(resize_image,channel,ClampToQuantum(pixel),q);
+ continue;
+ }
+ gamma=0.0;
+ for (j=0; j < n; j++)
{
- i=(ssize_t) (MagickMin(MagickMax(center,(double) start),(double) stop-
- 1.0)+0.5);
- j=(ssize_t) ((contribution[i-start].pixel-contribution[0].pixel)*
+ k=(ssize_t) ((contribution[j].pixel-contribution[0].pixel)*
image->columns+x);
- SetPixelIndex(resize_image,GetPixelIndex(image,p+j*
- GetPixelComponents(image)),q);
+ alpha=contribution[j].weight*QuantumScale*
+ GetPixelAlpha(image,p+k*GetPixelChannels(image));
+ pixel+=alpha*p[k*GetPixelChannels(image)+i];
+ gamma+=alpha;
}
- q+=GetPixelComponents(resize_image);
+ gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : 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)
{
#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
*/
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)
filter_type=PointFilter;
else
if ((image->storage_class == PseudoClass) ||
- (image->matte != MagickFalse) || ((x_factor*y_factor) > 1.0))
+ IfMagickTrue(image->matte) ||
+ ((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);
image_view=AcquireCacheView(image);
sample_view=AcquireCacheView(sample_image);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static) shared(progress,status)
#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/
sample_image->rows);
*/
for (x=0; x < (ssize_t) sample_image->columns; x++)
{
- SetPixelRed(sample_image,GetPixelRed(image,p+x_offset[x]*
- GetPixelComponents(image)),q);
- SetPixelGreen(sample_image,GetPixelGreen(image,p+x_offset[x]*
- GetPixelComponents(image)),q);
- SetPixelBlue(sample_image,GetPixelBlue(image,p+x_offset[x]*
- GetPixelComponents(image)),q);
- if (image->colorspace == CMYKColorspace)
- SetPixelBlack(sample_image,GetPixelBlack(image,p+x_offset[x]*
- GetPixelComponents(image)),q);
- if (image->matte != MagickFalse)
- SetPixelAlpha(sample_image,GetPixelAlpha(image,p+x_offset[x]*
- GetPixelComponents(image)),q);
- if (image->storage_class == PseudoClass)
- SetPixelIndex(sample_image,GetPixelIndex(image,p+x_offset[x]*
- GetPixelComponents(image)),q);
- q+=GetPixelComponents(sample_image);
+ register ssize_t
+ i;
+
+ if (GetPixelMask(sample_image,q) != 0)
+ {
+ q+=GetPixelChannels(sample_image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(sample_image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ sample_traits,
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ sample_traits=GetPixelChannelMapTraits(sample_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (sample_traits == UndefinedPixelTrait))
+ continue;
+ 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;
- PixelInfo
- pixel,
+ MagickRealType
+ alpha,
+ gamma,
+ pixel[CompositePixelChannel],
*scale_scanline,
*scanline,
*x_vector,
- *y_vector,
- zero;
+ *y_vector;
- MagickRealType
- alpha;
+ PixelChannel
+ channel;
+
+ PixelTrait
+ scale_traits,
+ traits;
PointInfo
scale,
i;
ssize_t
+ n,
number_rows,
y;
*/
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) == MagickFalse)
+ if( IfMagickFalse(SetImageStorageClass(scale_image,DirectClass,exception)) )
{
- InheritException(exception,&scale_image->exception);
scale_image=DestroyImage(scale_image);
return((Image *) NULL);
}
/*
Allocate memory.
*/
- x_vector=(PixelInfo *) AcquireQuantumMemory((size_t) image->columns,
- sizeof(*x_vector));
+ x_vector=(MagickRealType *) AcquireQuantumMemory((size_t) image->columns,
+ GetPixelChannels(image)*sizeof(*x_vector));
scanline=x_vector;
if (image->rows != scale_image->rows)
- scanline=(PixelInfo *) AcquireQuantumMemory((size_t) image->columns,
- sizeof(*scanline));
- scale_scanline=(PixelInfo *) AcquireQuantumMemory((size_t)
- scale_image->columns,sizeof(*scale_scanline));
- y_vector=(PixelInfo *) AcquireQuantumMemory((size_t) image->columns,
- sizeof(*y_vector));
- if ((scanline == (PixelInfo *) NULL) ||
- (scale_scanline == (PixelInfo *) NULL) ||
- (x_vector == (PixelInfo *) NULL) ||
- (y_vector == (PixelInfo *) NULL))
+ scanline=(MagickRealType *) AcquireQuantumMemory((size_t) image->columns,
+ GetPixelChannels(image)*sizeof(*scanline));
+ scale_scanline=(MagickRealType *) AcquireQuantumMemory((size_t)
+ scale_image->columns,MaxPixelChannels*sizeof(*scale_scanline));
+ y_vector=(MagickRealType *) 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))
{
scale_image=DestroyImage(scale_image);
ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
next_row=MagickTrue;
span.y=1.0;
scale.y=(double) scale_image->rows/(double) image->rows;
- (void) ResetMagickMemory(y_vector,0,(size_t) image->columns*
- sizeof(*y_vector));
- GetPixelInfo(image,&pixel);
- (void) ResetMagickMemory(&zero,0,sizeof(zero));
- i=0;
+ 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);
for (y=0; y < (ssize_t) scale_image->rows; y++)
register const Quantum
*restrict p;
- register PixelInfo
- *restrict s,
- *restrict t;
-
register Quantum
*restrict q;
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)
/*
Read a new scanline.
*/
- p=GetCacheViewVirtualPixels(image_view,0,i++,image->columns,1,
+ p=GetCacheViewVirtualPixels(image_view,0,n++,image->columns,1,
exception);
if (p == (const Quantum *) NULL)
break;
for (x=0; x < (ssize_t) image->columns; x++)
{
- if (image->matte != MagickFalse)
+ if (GetPixelMask(image,p) != 0)
+ {
+ p+=GetPixelChannels(image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if ((traits & BlendPixelTrait) == 0)
+ {
+ x_vector[x*GetPixelChannels(image)+i]=(MagickRealType) p[i];
+ continue;
+ }
alpha=QuantumScale*GetPixelAlpha(image,p);
- x_vector[x].red=(MagickRealType) (alpha*GetPixelRed(image,p));
- x_vector[x].green=(MagickRealType) (alpha*GetPixelGreen(image,p));
- x_vector[x].blue=(MagickRealType) (alpha*GetPixelBlue(image,p));
- if (image->matte != MagickFalse)
- x_vector[x].alpha=(MagickRealType) GetPixelAlpha(image,p);
- if (image->colorspace == CMYKColorspace)
- x_vector[x].black=(MagickRealType) (alpha*GetPixelBlack(image,p));
- p+=GetPixelComponents(image);
+ x_vector[x*GetPixelChannels(image)+i]=alpha*p[i];
+ }
+ p+=GetPixelChannels(image);
}
}
else
*/
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.
*/
- p=GetCacheViewVirtualPixels(image_view,0,i++,image->columns,1,
+ p=GetCacheViewVirtualPixels(image_view,0,n++,image->columns,1,
exception);
if (p == (const Quantum *) NULL)
break;
for (x=0; x < (ssize_t) image->columns; x++)
{
- if (image->matte != MagickFalse)
- alpha=QuantumScale*
- GetPixelAlpha(image,p);
- x_vector[x].red=(MagickRealType) (alpha*
- GetPixelRed(image,p));
- x_vector[x].green=(MagickRealType) (alpha*
- GetPixelGreen(image,p));
- x_vector[x].blue=(MagickRealType) (alpha*
- GetPixelBlue(image,p));
- if (image->colorspace == CMYKColorspace)
- x_vector[x].black=(MagickRealType) (alpha*
- GetPixelBlack(image,p));
- if (image->matte != MagickFalse)
- x_vector[x].alpha=(MagickRealType)
- GetPixelAlpha(image,p);
- p+=GetPixelComponents(image);
+ if (GetPixelMask(image,p) != 0)
+ {
+ p+=GetPixelChannels(image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if ((traits & BlendPixelTrait) == 0)
+ {
+ x_vector[x*GetPixelChannels(image)+i]=(MagickRealType)
+ p[i];
+ continue;
+ }
+ alpha=QuantumScale*GetPixelAlpha(image,p);
+ x_vector[x*GetPixelChannels(image)+i]=alpha*p[i];
+ }
+ p+=GetPixelChannels(image);
}
number_rows++;
}
for (x=0; x < (ssize_t) image->columns; x++)
- {
- y_vector[x].red+=scale.y*x_vector[x].red;
- y_vector[x].green+=scale.y*x_vector[x].green;
- y_vector[x].blue+=scale.y*x_vector[x].blue;
- if (scale_image->colorspace == CMYKColorspace)
- y_vector[x].black+=scale.y*x_vector[x].black;
- if (scale_image->matte != MagickFalse)
- y_vector[x].alpha+=scale.y*x_vector[x].alpha;
- }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ y_vector[x*GetPixelChannels(image)+i]+=scale.y*
+ x_vector[x*GetPixelChannels(image)+i];
span.y-=scale.y;
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.
*/
- p=GetCacheViewVirtualPixels(image_view,0,i++,image->columns,1,
+ p=GetCacheViewVirtualPixels(image_view,0,n++,image->columns,1,
exception);
if (p == (const Quantum *) NULL)
break;
for (x=0; x < (ssize_t) image->columns; x++)
{
- if (image->matte != MagickFalse)
+ if (GetPixelMask(image,p) != 0)
+ {
+ p+=GetPixelChannels(image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if ((traits & BlendPixelTrait) == 0)
+ {
+ x_vector[x*GetPixelChannels(image)+i]=(MagickRealType)
+ p[i];
+ continue;
+ }
alpha=QuantumScale*GetPixelAlpha(image,p);
- x_vector[x].red=(MagickRealType) (alpha*GetPixelRed(image,p));
- x_vector[x].green=(MagickRealType) (alpha*GetPixelGreen(image,p));
- x_vector[x].blue=(MagickRealType) (alpha*GetPixelBlue(image,p));
- if (image->colorspace == CMYKColorspace)
- x_vector[x].black=(MagickRealType) (alpha*
- GetPixelBlack(image,p));
- if (image->matte != MagickFalse)
- x_vector[x].alpha=(MagickRealType) GetPixelAlpha(image,p);
- p+=GetPixelComponents(image);
+ x_vector[x*GetPixelChannels(image)+i]=alpha*p[i];
+ }
+ p+=GetPixelChannels(image);
}
number_rows++;
next_row=MagickFalse;
}
- s=scanline;
for (x=0; x < (ssize_t) image->columns; x++)
{
- pixel.red=y_vector[x].red+span.y*x_vector[x].red;
- pixel.green=y_vector[x].green+span.y*x_vector[x].green;
- pixel.blue=y_vector[x].blue+span.y*x_vector[x].blue;
- if (image->colorspace == CMYKColorspace)
- pixel.black=y_vector[x].black+span.y*x_vector[x].black;
- if (image->matte != MagickFalse)
- pixel.alpha=y_vector[x].alpha+span.y*x_vector[x].alpha;
- s->red=pixel.red;
- s->green=pixel.green;
- s->blue=pixel.blue;
- if (scale_image->colorspace == CMYKColorspace)
- s->black=pixel.black;
- if (scale_image->matte != MagickFalse)
- s->alpha=pixel.alpha;
- s++;
- y_vector[x]=zero;
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ pixel[i]=y_vector[x*GetPixelChannels(image)+i]+span.y*
+ x_vector[x*GetPixelChannels(image)+i];
+ scanline[x*GetPixelChannels(image)+i]=pixel[i];
+ y_vector[x*GetPixelChannels(image)+i]=0.0;
+ }
}
scale.y-=span.y;
if (scale.y <= 0)
/*
Transfer scanline to scaled image.
*/
- s=scanline;
for (x=0; x < (ssize_t) scale_image->columns; x++)
{
- if (scale_image->matte != MagickFalse)
- alpha=QuantumScale*s->alpha;
- alpha=1.0/(fabs(alpha) <= MagickEpsilon ? 1.0 : alpha);
- SetPixelRed(scale_image,ClampToQuantum(alpha*s->red),q);
- SetPixelGreen(scale_image,ClampToQuantum(alpha*s->green),q);
- SetPixelBlue(scale_image,ClampToQuantum(alpha*s->blue),q);
- if (scale_image->colorspace == CMYKColorspace)
- SetPixelBlack(scale_image,ClampToQuantum(alpha*s->black),q);
- if (scale_image->matte != MagickFalse)
- SetPixelAlpha(scale_image,ClampToQuantum(s->alpha),q);
- q+=GetPixelComponents(scale_image);
- s++;
+ if (GetPixelMask(scale_image,q) != 0)
+ {
+ q+=GetPixelChannels(scale_image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(scale_image); i++)
+ {
+ ssize_t
+ offset;
+
+ channel=GetPixelChannelMapChannel(scale_image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ scale_traits=GetPixelChannelMapTraits(scale_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (scale_traits == UndefinedPixelTrait))
+ continue;
+ offset=GetPixelChannelMapOffset(image,channel);
+ if ((traits & BlendPixelTrait) == 0)
+ {
+ 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);
+ SetPixelChannel(scale_image,channel,ClampToQuantum(gamma*scanline[
+ x*GetPixelChannels(image)+offset]),q);
+ }
+ q+=GetPixelChannels(scale_image);
}
}
else
{
+ ssize_t
+ n;
+
/*
Scale X direction.
*/
- pixel=zero;
next_column=MagickFalse;
+ n=0;
span.x=1.0;
- s=scanline;
- t=scale_scanline;
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ pixel[i]=0.0;
for (x=0; x < (ssize_t) image->columns; x++)
{
scale.x=(double) scale_image->columns/(double) image->columns;
while (scale.x >= span.x)
{
- if (next_column != MagickFalse)
+ if( IfMagickTrue(next_column) )
{
- pixel=zero;
- t++;
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ pixel[i]=0.0;
+ n++;
}
- pixel.red+=span.x*s->red;
- pixel.green+=span.x*s->green;
- pixel.blue+=span.x*s->blue;
- if (scale_image->colorspace == CMYKColorspace)
- pixel.black+=span.x*s->black;
- if (image->matte != MagickFalse)
- pixel.alpha+=span.x*s->alpha;
- t->red=pixel.red;
- t->green=pixel.green;
- t->blue=pixel.blue;
- if (scale_image->colorspace == CMYKColorspace)
- t->black=pixel.black;
- if (scale_image->matte != MagickFalse)
- t->alpha=pixel.alpha;
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if (traits == UndefinedPixelTrait)
+ continue;
+ pixel[i]+=span.x*scanline[x*GetPixelChannels(image)+i];
+ scale_scanline[n*MaxPixelChannels+channel]=pixel[i];
+ }
scale.x-=span.x;
span.x=1.0;
next_column=MagickTrue;
}
if (scale.x > 0)
{
- if (next_column != MagickFalse)
+ if( IfMagickTrue(next_column) )
{
- pixel=zero;
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ pixel[i]=0.0;
+ n++;
next_column=MagickFalse;
- t++;
}
- pixel.red+=scale.x*s->red;
- pixel.green+=scale.x*s->green;
- pixel.blue+=scale.x*s->blue;
- if (scale_image->colorspace == CMYKColorspace)
- pixel.black+=scale.x*s->black;
- if (scale_image->matte != MagickFalse)
- pixel.alpha+=scale.x*s->alpha;
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ pixel[i]+=scale.x*scanline[x*GetPixelChannels(image)+i];
span.x-=scale.x;
}
- s++;
}
if (span.x > 0)
{
- s--;
- pixel.red+=span.x*s->red;
- pixel.green+=span.x*s->green;
- pixel.blue+=span.x*s->blue;
- if (scale_image->colorspace == CMYKColorspace)
- pixel.black+=span.x*s->black;
- if (scale_image->matte != MagickFalse)
- pixel.alpha+=span.x*s->alpha;
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ pixel[i]+=span.x*scanline[(x-1)*GetPixelChannels(image)+i];
}
- if ((next_column == MagickFalse) &&
- ((ssize_t) (t-scale_scanline) < (ssize_t) scale_image->columns))
+ if( IfMagickFalse(next_column) &&
+ ((ssize_t) n < (ssize_t) scale_image->columns))
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
- t->red=pixel.red;
- t->green=pixel.green;
- t->blue=pixel.blue;
- if (scale_image->colorspace == CMYKColorspace)
- t->black=pixel.black;
- if (scale_image->matte != MagickFalse)
- t->alpha=pixel.alpha;
+ channel=GetPixelChannelMapChannel(image,i);
+ scale_scanline[n*MaxPixelChannels+channel]=pixel[i];
}
/*
Transfer scanline to scaled image.
*/
- t=scale_scanline;
for (x=0; x < (ssize_t) scale_image->columns; x++)
{
- if (scale_image->matte != MagickFalse)
- alpha=QuantumScale*s->alpha;
- alpha=1.0/(fabs(alpha) <= MagickEpsilon ? 1.0 : alpha);
- SetPixelRed(scale_image,ClampToQuantum(alpha*t->red),q);
- SetPixelGreen(scale_image,ClampToQuantum(alpha*t->green),q);
- SetPixelBlue(scale_image,ClampToQuantum(alpha*t->blue),q);
- if (scale_image->colorspace == CMYKColorspace)
- SetPixelBlack(scale_image,ClampToQuantum(alpha*t->black),q);
- if (scale_image->matte != MagickFalse)
- SetPixelAlpha(scale_image,ClampToQuantum(t->alpha),q);
- t++;
- q+=GetPixelComponents(scale_image);
+ if (GetPixelMask(scale_image,q) != 0)
+ {
+ q+=GetPixelChannels(scale_image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(scale_image); i++)
+ {
+ channel=GetPixelChannelMapChannel(scale_image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ scale_traits=GetPixelChannelMapTraits(scale_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (scale_traits == UndefinedPixelTrait))
+ continue;
+ if ((traits & BlendPixelTrait) == 0)
+ {
+ 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);
+ SetPixelChannel(scale_image,channel,ClampToQuantum(gamma*
+ 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=(PixelInfo *) RelinquishMagickMemory(y_vector);
- scale_scanline=(PixelInfo *) RelinquishMagickMemory(scale_scanline);
+ y_vector=(MagickRealType *) RelinquishMagickMemory(y_vector);
+ scale_scanline=(MagickRealType *) RelinquishMagickMemory(scale_scanline);
if (scale_image->rows != image->rows)
- scanline=(PixelInfo *) RelinquishMagickMemory(scanline);
- x_vector=(PixelInfo *) RelinquishMagickMemory(x_vector);
+ scanline=(MagickRealType *) RelinquishMagickMemory(scanline);
+ x_vector=(MagickRealType *) RelinquishMagickMemory(x_vector);
scale_image->type=image->type;
return(scale_image);
}
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;
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)
- (void) SetImageAlphaChannel(thumbnail_image,OpaqueAlphaChannel);
+ if( IfMagickFalse(thumbnail_image->matte) )
+ (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);
}