% MagickCore Image Resize Methods %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% July 1992 %
% %
% %
-% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2014 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/blob.h"
#include "MagickCore/cache.h"
#include "MagickCore/cache-view.h"
+#include "MagickCore/channel.h"
#include "MagickCore/color.h"
#include "MagickCore/color-private.h"
#include "MagickCore/draw.h"
#include "MagickCore/image-private.h"
#include "MagickCore/list.h"
#include "MagickCore/memory_.h"
+#include "MagickCore/memory-private.h"
#include "MagickCore/magick.h"
#include "MagickCore/pixel-accessor.h"
#include "MagickCore/property.h"
#include "MagickCore/monitor.h"
#include "MagickCore/monitor-private.h"
+#include "MagickCore/nt-base-private.h"
#include "MagickCore/option.h"
#include "MagickCore/pixel.h"
#include "MagickCore/pixel-private.h"
blur, /* x-scale (blur-sharpen) */
coefficient[7]; /* cubic coefficents for BC-cubic filters */
+ ResizeWeightingFunctionType
+ filterWeightingType,
+ windowWeightingType;
+
size_t
signature;
};
%
% The individual filter functions have this format...
%
-% static MagickRealtype *FilterName(const double x,
-% const double support)
+% static MagickRealtype *FilterName(const double x,const double support)
%
% A description of each parameter follows:
%
return((double)cos((double) (MagickPI2*x)));
}
-static double CubicBC(const double x,
- const ResizeFilter *resize_filter)
+static double CubicBC(const double x,const ResizeFilter *resize_filter)
{
/*
Cubic Filters using B,C determined values:
return(0.0);
}
-static double Gaussian(const double x,
- const ResizeFilter *resize_filter)
+static double Gaussian(const double x,const ResizeFilter *resize_filter)
{
/*
Gaussian with a sigma = 1/2 (or as user specified)
return(exp((double)(-resize_filter->coefficient[1]*x*x)));
}
-static double Hanning(const double x,
+static double Hann(const double x,
const ResizeFilter *magick_unused(resize_filter))
{
/*
return(BesselOrderOne(MagickPI*x)/x);
}
-static double Kaiser(const double x,
- const ResizeFilter *resize_filter)
+static double Kaiser(const double x,const ResizeFilter *resize_filter)
{
/*
Kaiser Windowing Function (bessel windowing)
but without it the filters has a large value at x=0 making it
difficult to compare the function with other windowing functions.
*/
- return(resize_filter->coefficient[1]*
- I0(resize_filter->coefficient[0]*sqrt((double) (1.0-x*x))));
+ return(resize_filter->coefficient[1]*I0(resize_filter->coefficient[0]*
+ sqrt((double) (1.0-x*x))));
}
-static double Lagrange(const double x,
- const ResizeFilter *resize_filter)
+static double Lagrange(const double x,const ResizeFilter *resize_filter)
{
double
value;
return(0.0);
}
-static double Welsh(const double x,
+static double Welch(const double x,
const ResizeFilter *magick_unused(resize_filter))
{
/*
- Welsh parabolic windowing filter.
+ Welch parabolic windowing filter.
*/
if (x < 1.0)
return(1.0-x*x);
% Gaussian Sinc Jinc (Bessel)
%
% Windowed Sinc/Jinc Filters
-% Blackman Hanning Hamming
-% Kaiser Lanczos
+% Blackman Bohman Lanczos
+% Hann Hamming Cosine
+% Kaiser Welch Parzen
+% Bartlett
%
% Special Purpose Filters
% Cubic SincFast LanczosSharp Lanczos2 Lanczos2Sharp
%
% FIR filters are used as is, and are limited to that filters support window
% (unless over-ridden). 'Gaussian' while classed as an IIR filter, is also
-% simply clipped by its support size (currently 1.5 or approximatally 3*sigma
+% simply clipped by its support size (currently 1.5 or approximately 3*sigma
% as recommended by many references)
%
% The special a 'cylindrical' filter flag will promote the default 4-lobed
%
% These artifact "defines" are not recommended for production use without
% expert knowledge of resampling, filtering, and the effects they have on the
-% resulting resampled (resize ro distorted) image.
+% resulting resampled (resized or distorted) image.
%
% They can be used to override any and all filter default, and it is
% recommended you make good use of "filter:verbose" to make sure that the
% "filter:window" Select this windowing function for the filter. While any
% filter could be used as a windowing function, using the 'first lobe' of
% that filter over the whole support window, using a non-windowing
-% function is not advisible. If no weighting filter function is specifed
+% function is not advisible. If no weighting filter function is specified
% a 'SincFast' filter is used.
%
% "filter:lobes" Number of lobes to use for the Sinc/Jinc filter. This a
% causes the windowing (or self-windowing Lagrange filter) to act is if
% the support window it much much larger than what is actually supplied
% to the calling operator. The filter however is still clipped to the
-% real support size given, by the support range suppiled to the caller.
+% real support size given, by the support range supplied to the caller.
% If unset this will equal the normal filter support size.
%
% "filter:blur" Scale the filter and support window by this amount. A value
-% > 1 will generally result in a more burred image with more ringing
+% of > 1 will generally result in a more blurred image with more ringing
% effects, while a value <1 will sharpen the resulting image with more
% aliasing effects.
%
{ BoxFilter, BoxFilter }, /* Box averaging filter */
{ TriangleFilter, BoxFilter }, /* Linear interpolation filter */
{ HermiteFilter, BoxFilter }, /* Hermite interpolation filter */
- { SincFastFilter, HanningFilter }, /* Hanning -- cosine-sinc */
- { SincFastFilter, HammingFilter }, /* Hamming -- '' variation */
+ { SincFastFilter, HannFilter }, /* Hann -- cosine-sinc */
+ { SincFastFilter, HammingFilter }, /* Hamming -- '' variation */
{ SincFastFilter, BlackmanFilter }, /* Blackman -- 2*cosine-sinc */
{ GaussianFilter, BoxFilter }, /* Gaussian blur filter */
{ QuadraticFilter, BoxFilter }, /* Quadratic Gaussian approx */
{ SincFilter, BoxFilter }, /* Raw 4-lobed Sinc function */
{ SincFastFilter, BoxFilter }, /* Raw fast sinc ("Pade"-type) */
{ SincFastFilter, KaiserFilter }, /* Kaiser -- square root-sinc */
- { SincFastFilter, WelshFilter }, /* Welsh -- parabolic-sinc */
+ { LanczosFilter, WelchFilter }, /* Welch -- parabolic (3 lobe) */
{ SincFastFilter, CubicFilter }, /* Parzen -- cubic-sinc */
{ SincFastFilter, BohmanFilter }, /* Bohman -- 2*cosine-sinc */
{ SincFastFilter, TriangleFilter }, /* Bartlett -- triangle-sinc */
{ Lanczos2SharpFilter, Lanczos2SharpFilter },
{ RobidouxFilter, BoxFilter }, /* Cubic Keys tuned for EWA */
{ RobidouxSharpFilter, BoxFilter }, /* Sharper Cubic Keys for EWA */
- { SincFastFilter, CosineFilter }, /* low level cosine window */
+ { LanczosFilter, CosineFilter }, /* Cosine window (3 lobes) */
{ SplineFilter, BoxFilter }, /* Spline Cubic Filter */
+ { LanczosRadiusFilter, LanczosFilter }, /* Lanczos with integer radius */
};
/*
Table mapping the filter/window from the above table to an actual function.
B,C; /* BC-spline coefficients, ignored if not a CubicBC filter. */
} const filters[SentinelFilter] =
{
- /* .--- support window
- | .--- first crossing (if used as a Windowing function)
+ /* .--- support window (if used as a Weighting Function)
+ | .--- first crossing (if used as a Windowing Function)
| | .--- B value for Cubic Function
| | | .---- C value for Cubic Function
| | | | */
{ Box, 0.5, 0.5, 0.0, 0.0 }, /* Box */
{ Triangle, 1.0, 1.0, 0.0, 0.0 }, /* Triangle */
{ CubicBC, 1.0, 1.0, 0.0, 0.0 }, /* Hermite (cubic B=C=0) */
- { Hanning, 1.0, 1.0, 0.0, 0.0 }, /* Hanning, cosine window */
+ { Hann, 1.0, 1.0, 0.0, 0.0 }, /* Hann, cosine window */
{ Hamming, 1.0, 1.0, 0.0, 0.0 }, /* Hamming, '' variation */
{ Blackman, 1.0, 1.0, 0.0, 0.0 }, /* Blackman, 2*cosine window */
{ Gaussian, 2.0, 1.5, 0.0, 0.0 }, /* Gaussian */
{ Sinc, 4.0, 1.0, 0.0, 0.0 }, /* Raw 4-lobed Sinc */
{ SincFast, 4.0, 1.0, 0.0, 0.0 }, /* Raw fast sinc ("Pade"-type) */
{ Kaiser, 1.0, 1.0, 0.0, 0.0 }, /* Kaiser (square root window) */
- { Welsh, 1.0, 1.0, 0.0, 0.0 }, /* Welsh (parabolic window) */
+ { Welch, 1.0, 1.0, 0.0, 0.0 }, /* Welch (parabolic window) */
{ CubicBC, 2.0, 2.0, 1.0, 0.0 }, /* Parzen (B-Spline window) */
{ Bohman, 1.0, 1.0, 0.0, 0.0 }, /* Bohman, 2*Cosine window */
{ Triangle, 1.0, 1.0, 0.0, 0.0 }, /* Bartlett (triangle window) */
{ Lagrange, 2.0, 1.0, 0.0, 0.0 }, /* Lagrange sinc approximation */
{ SincFast, 3.0, 1.0, 0.0, 0.0 }, /* Lanczos, 3-lobed Sinc-Sinc */
- { SincFast, 3.0, 1.0, 0.0, 0.0 }, /* lanczos, Sharpened */
+ { SincFast, 3.0, 1.0, 0.0, 0.0 }, /* Lanczos, Sharpened */
{ SincFast, 2.0, 1.0, 0.0, 0.0 }, /* Lanczos, 2-lobed */
{ SincFast, 2.0, 1.0, 0.0, 0.0 }, /* Lanczos2, sharpened */
/* Robidoux: Keys cubic close to Lanczos2D sharpened */
0.2620145123990142, 0.3689927438004929 },
{ Cosine, 1.0, 1.0, 0.0, 0.0 }, /* Low level cosine window */
{ CubicBC, 2.0, 2.0, 1.0, 0.0 }, /* Cubic B-Spline (B=1,C=0) */
+ { SincFast, 3.0, 1.0, 0.0, 0.0 }, /* Lanczos, Interger Radius */
};
/*
The known zero crossings of the Jinc() or more accurately the Jinc(x*PI)
*/
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
- if( IfMagickTrue(image->debug) )
+ if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(UndefinedFilter < filter && filter < SentinelFilter);
assert(exception != (ExceptionInfo *) NULL);
window_type=mapping[filter].window;
resize_filter->blur=1.0;
/* Promote 1D Windowed Sinc Filters to a 2D Windowed Jinc filters */
- if( IfMagickTrue(cylindrical) && (filter_type == SincFastFilter) &&
+ if ( IfMagickTrue(cylindrical) && (filter_type == SincFastFilter) &&
(filter != SincFastFilter))
filter_type=JincFilter; /* 1D Windowed Sinc => 2D Windowed Jinc filters */
case LanczosSharpFilter:
case Lanczos2Filter:
case Lanczos2SharpFilter:
+ case LanczosRadiusFilter:
resize_filter->filter=filters[JincFilter].function;
resize_filter->window=filters[JincFilter].function;
resize_filter->scale=filters[JincFilter].scale;
case Lanczos2SharpFilter:
resize_filter->blur *= 0.9549963639785485;
break;
+ /* case LanczosRadius: blur adjust is done after lobes */
default:
break;
}
value=StringToDouble(artifact,(char **) NULL);
/* Define coefficents for Gaussian */
resize_filter->coefficient[0]=value; /* note sigma too */
- resize_filter->coefficient[1]=MagickEpsilonReciprocal(2.0*value*value); /* sigma scaling */
- resize_filter->coefficient[2]=MagickEpsilonReciprocal(Magick2PI*value*value);
+ resize_filter->coefficient[1]=PerceptibleReciprocal(2.0*value*value); /* sigma scaling */
+ resize_filter->coefficient[2]=PerceptibleReciprocal(Magick2PI*value*value);
/* normalization - not actually needed or used! */
if ( value > 0.5 )
- resize_filter->support *= value/0.5; /* increase support */
+ resize_filter->support *= 2*value; /* increase support linearly */
}
/* User Kaiser Alpha Override - no support change */
value=StringToDouble(artifact,(char **) NULL)*MagickPI;
/* Define coefficents for Kaiser Windowing Function */
resize_filter->coefficient[0]=value; /* alpha */
- resize_filter->coefficient[1]=MagickEpsilonReciprocal(I0(value)); /* normalization */
+ resize_filter->coefficient[1]=PerceptibleReciprocal(I0(value));
+ /* normalization */
}
- /* Blur Override */
- artifact=GetImageArtifact(image,"filter:blur");
- if (artifact != (const char *) NULL)
- resize_filter->blur*=StringToDouble(artifact,(char **) NULL);
- if (resize_filter->blur < MagickEpsilon)
- resize_filter->blur=(double) MagickEpsilon;
-
/* Support Overrides */
artifact=GetImageArtifact(image,"filter:lobes");
if (artifact != (const char *) NULL)
lobes=1;
resize_filter->support=(double) lobes;
}
- /* Convert a Jinc function lobes value to a real support value */
if (resize_filter->filter == Jinc)
{
+ /*
+ Convert a Jinc function lobes value to a real support value.
+ */
if (resize_filter->support > 16)
resize_filter->support=jinc_zeros[15]; /* largest entry in table */
else
- resize_filter->support=jinc_zeros[((long)resize_filter->support)-1];
+ resize_filter->support=jinc_zeros[((long) resize_filter->support)-1];
+ /*
+ Blur this filter so support is a integer value (lobes dependant).
+ */
+ if (filter_type == LanczosRadiusFilter)
+ resize_filter->blur*=floor(resize_filter->support)/
+ resize_filter->support;
}
- /* expert override of the support setting */
+ /*
+ Expert blur override.
+ */
+ artifact=GetImageArtifact(image,"filter:blur");
+ if (artifact != (const char *) NULL)
+ resize_filter->blur*=StringToDouble(artifact,(char **) NULL);
+ if (resize_filter->blur < MagickEpsilon)
+ resize_filter->blur=(double) MagickEpsilon;
+ /*
+ Expert override of the support setting.
+ */
artifact=GetImageArtifact(image,"filter:support");
if (artifact != (const 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
- override)
+ Scale windowing function separately to the support 'clipping' window
+ that calling operator is planning to actually use. (Expert override)
*/
resize_filter->window_support=resize_filter->support; /* default */
artifact=GetImageArtifact(image,"filter:win-support");
if (artifact != (const char *) NULL)
resize_filter->window_support=fabs(StringToDouble(artifact,(char **) NULL));
/*
- Adjust window function scaling to match windowing support for
- weighting function. This avoids a division on every filter call.
+ Adjust window function scaling to match windowing support for weighting
+ function. This avoids a division on every filter call.
*/
resize_filter->scale/=resize_filter->window_support;
-
/*
* Set Cubic Spline B,C values, calculate Cubic coefficients.
*/
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;
+ const double
+ twoB = B+B;
+
+ /*
+ Convert B,C values into Cubic Coefficents. See CubicBC().
+ */
resize_filter->coefficient[0]=1.0-(1.0/3.0)*B;
resize_filter->coefficient[1]=-3.0+twoB+C;
resize_filter->coefficient[2]=2.0-1.5*B-C;
x;
/*
- Set the weighting function properly when the weighting
- function may not exactly match the filter of the same name.
- EG: a Point filter is really uses a Box weighting function
- with a different support than is typically used.
+ Set the weighting function properly when the weighting function
+ may not exactly match the filter of the same name. EG: a Point
+ filter is really uses a Box weighting function with a different
+ support than is typically used.
*/
if (resize_filter->filter == Box) filter_type=BoxFilter;
if (resize_filter->filter == Sinc) filter_type=SincFilter;
Report Filter Details.
*/
support=GetResizeFilterSupport(resize_filter); /* practical_support */
- (void) FormatLocaleFile(stdout,"# Resize Filter (for graphing)\n#\n");
+ (void) FormatLocaleFile(stdout,
+ "# Resampling 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,"# window-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 || window_type == GaussianFilter )
+ GetMagickPrecision(),(double)resize_filter->blur);
+ if ((filter_type == GaussianFilter) || (window_type == GaussianFilter))
(void) FormatLocaleFile(stdout,"# gaussian-sigma = %.*g\n",
- GetMagickPrecision(), (double)resize_filter->coefficient[0]);
+ GetMagickPrecision(),(double)resize_filter->coefficient[0]);
if ( filter_type == KaiserFilter || window_type == KaiserFilter )
(void) FormatLocaleFile(stdout,"# kaiser-beta = %.*g\n",
- GetMagickPrecision(),
- (double)resize_filter->coefficient[0]);
+ GetMagickPrecision(),(double)resize_filter->coefficient[0]);
(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.
+ Output values of resulting filter graph -- for graphing filter result.
*/
for (x=0.0; x <= support; x+=0.01f)
- (void) FormatLocaleFile(stdout,"%5.2lf\t%.*g\n",x,GetMagickPrecision(),
- (double) GetResizeFilterWeight(resize_filter,x));
- /* A final value so gnuplot can graph the 'stop' properly. */
+ (void) FormatLocaleFile(stdout,"%5.2lf\t%.*g\n",x,
+ GetMagickPrecision(),(double)
+ GetResizeFilterWeight(resize_filter,x));
+ /*
+ A final value so gnuplot can graph the 'stop' properly.
+ */
(void) FormatLocaleFile(stdout,"%5.2lf\t%.*g\n",support,
GetMagickPrecision(),0.0);
}
MagickExport Image *AdaptiveResizeImage(const Image *image,
const size_t columns,const size_t rows,ExceptionInfo *exception)
{
- return(InterpolativeResizeImage(image,columns,rows,MeshInterpolatePixel,
- exception));
+ Image
+ *resize_image;
+
+ resize_image=InterpolativeResizeImage(image,columns,rows,MeshInterpolatePixel,
+ exception);
+ return(resize_image);
}
\f
/*
% o filter: Image filter to use.
%
*/
+
+MagickPrivate double *GetResizeFilterCoefficient(
+ const ResizeFilter *resize_filter)
+{
+ assert(resize_filter != (ResizeFilter *) NULL);
+ assert(resize_filter->signature == MagickSignature);
+ return((double *) resize_filter->coefficient);
+}
+
+MagickPrivate double GetResizeFilterBlur(
+ const ResizeFilter *resize_filter)
+{
+ assert(resize_filter != (ResizeFilter *) NULL);
+ assert(resize_filter->signature == MagickSignature);
+ return(resize_filter->blur);
+}
+
+MagickPrivate double GetResizeFilterScale(
+ const ResizeFilter *resize_filter)
+{
+ assert(resize_filter != (ResizeFilter *) NULL);
+ assert(resize_filter->signature == MagickSignature);
+ return(resize_filter->scale);
+}
+
+MagickPrivate double GetResizeFilterWindowSupport(
+ const ResizeFilter *resize_filter)
+{
+ assert(resize_filter != (ResizeFilter *) NULL);
+ assert(resize_filter->signature == MagickSignature);
+ return(resize_filter->window_support);
+}
+
+MagickPrivate ResizeWeightingFunctionType GetResizeFilterWeightingType(
+ const ResizeFilter *resize_filter)
+{
+ assert(resize_filter != (ResizeFilter *) NULL);
+ assert(resize_filter->signature == MagickSignature);
+ return(resize_filter->filterWeightingType);
+}
+
+MagickPrivate ResizeWeightingFunctionType GetResizeFilterWindowWeightingType(
+ const ResizeFilter *resize_filter)
+{
+ assert(resize_filter != (ResizeFilter *) NULL);
+ assert(resize_filter->signature == MagickSignature);
+ return(resize_filter->windowWeightingType);
+}
+
MagickPrivate double GetResizeFilterSupport(
const ResizeFilter *resize_filter)
{
% o x: the point.
%
*/
-MagickPrivate double GetResizeFilterWeight(
- const ResizeFilter *resize_filter,const double x)
+MagickPrivate double GetResizeFilterWeight(const ResizeFilter *resize_filter,
+ const double x)
{
double
scale,
*/
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
- if( IfMagickTrue(image->debug) )
+ if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
resize_image=CloneImage(image,columns,rows,MagickTrue,exception);
if (resize_image == (Image *) NULL)
return((Image *) NULL);
- if( IfMagickFalse(SetImageStorageClass(resize_image,DirectClass,exception)) )
+ if (SetImageStorageClass(resize_image,DirectClass,exception) == MagickFalse)
{
resize_image=DestroyImage(resize_image);
return((Image *) NULL);
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) \
- dynamic_number_threads(image,image->columns,image->rows,1)
+ #pragma omp parallel for schedule(static,4) shared(progress,status) \
+ magick_threads(image,resize_image,resize_image->rows,1)
#endif
for (y=0; y < (ssize_t) resize_image->rows; y++)
{
register ssize_t
x;
- if( IfMagickFalse(status) )
+ if (status == MagickFalse)
continue;
q=QueueCacheViewAuthenticPixels(resize_view,0,y,resize_image->columns,1,
exception);
register ssize_t
i;
- if (GetPixelMask(resize_image,q) != 0)
+ if (GetPixelReadMask(resize_image,q) == 0)
{
q+=GetPixelChannels(resize_image);
continue;
resize_traits,
traits;
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
- resize_traits=GetPixelChannelMapTraits(resize_image,channel);
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ resize_traits=GetPixelChannelTraits(resize_image,channel);
if ((traits == UndefinedPixelTrait) ||
(resize_traits == UndefinedPixelTrait))
continue;
}
q+=GetPixelChannels(resize_image);
}
- if( IfMagickFalse(SyncCacheViewAuthenticPixels(resize_view,exception)) )
- continue;
+ if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
+ status=MagickFalse;
if (image->progress_monitor != (MagickProgressMonitor) NULL)
{
MagickBooleanType
#endif
proceed=SetImageProgress(image,InterpolativeResizeImageTag,progress++,
image->rows);
- if( IfMagickFalse(proceed) )
+ if (proceed == MagickFalse)
status=MagickFalse;
}
}
resize_view=DestroyCacheView(resize_view);
image_view=DestroyCacheView(image_view);
- if( IfMagickFalse(status) )
+ if (status == MagickFalse)
resize_image=DestroyImage(resize_image);
return(resize_image);
}
MagickBooleanType
status;
+ MemoryInfo
+ *pixel_info;
+
register gfloat
*q;
*/
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
- if( IfMagickTrue(image->debug) )
+ if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
/*
Honor liquid resize size limitations.
*/
- for (width=image->columns; columns >= (2*width-1); width*=2);
- for (height=image->rows; rows >= (2*height-1); height*=2);
+ 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,exception);
if (resize_image == (Image *) NULL)
return((Image *) NULL);
resize_image=DestroyImage(resize_image);
return(rescale_image);
}
- pixels=(gfloat *) AcquireQuantumMemory(image->columns,image->rows*
+ pixel_info=AcquireVirtualMemory(image->columns,image->rows*
GetPixelChannels(image)*sizeof(*pixels));
- if (pixels == (gfloat *) NULL)
+ if (pixel_info == (MemoryInfo *) NULL)
return((Image *) NULL);
+ pixels=(gfloat *) GetVirtualMemoryBlob(pixel_info);
status=MagickTrue;
q=pixels;
image_view=AcquireVirtualCacheView(image,exception);
register ssize_t
x;
- if( IfMagickFalse(status) )
+ if (status == MagickFalse)
continue;
p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
if (p == (const Quantum *) NULL)
}
}
image_view=DestroyCacheView(image_view);
- carver=lqr_carver_new_ext(pixels,image->columns,image->rows,
- GetPixelChannels(image),LQR_COLDEPTH_32F);
+ carver=lqr_carver_new_ext(pixels,(int) image->columns,(int) image->rows,
+ (int) GetPixelChannels(image),LQR_COLDEPTH_32F);
if (carver == (LqrCarver *) NULL)
{
- pixels=(gfloat *) RelinquishMagickMemory(pixels);
+ pixel_info=RelinquishVirtualMemory(pixel_info);
ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
}
+ lqr_carver_set_preserve_input_image(carver);
lqr_status=lqr_carver_init(carver,(int) delta_x,rigidity);
- lqr_status=lqr_carver_resize(carver,columns,rows);
+ lqr_status=lqr_carver_resize(carver,(int) columns,(int) rows);
(void) lqr_status;
rescale_image=CloneImage(image,lqr_carver_get_width(carver),
lqr_carver_get_height(carver),MagickTrue,exception);
if (rescale_image == (Image *) NULL)
{
- pixels=(gfloat *) RelinquishMagickMemory(pixels);
+ pixel_info=RelinquishVirtualMemory(pixel_info);
return((Image *) NULL);
}
- if( IfMagickFalse(SetImageStorageClass(rescale_image,DirectClass,exception)) )
+ if (SetImageStorageClass(rescale_image,DirectClass,exception) == MagickFalse)
{
- pixels=(gfloat *) RelinquishMagickMemory(pixels);
+ pixel_info=RelinquishVirtualMemory(pixel_info);
rescale_image=DestroyImage(rescale_image);
return((Image *) NULL);
}
rescale_traits,
traits;
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
- rescale_traits=GetPixelChannelMapTraits(rescale_image,channel);
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ rescale_traits=GetPixelChannelTraits(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)) )
+ if (SyncCacheViewAuthenticPixels(rescale_view,exception) == MagickFalse)
break;
}
rescale_view=DestroyCacheView(rescale_view);
+ pixel_info=RelinquishVirtualMemory(pixel_info);
lqr_carver_destroy(carver);
return(rescale_image);
}
{
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
- if( IfMagickTrue(image->debug) )
+ if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% MagnifyImage() is a convenience method that scales an image proportionally
-% to twice its size.
+% MagnifyImage() doubles the size of the image with a pixel art scaling
+% algorithm.
%
% The format of the MagnifyImage method is:
%
*/
MagickExport Image *MagnifyImage(const Image *image,ExceptionInfo *exception)
{
+#define MagnifyImageTag "Magnify/Image"
+
+ CacheView
+ *image_view,
+ *magnify_view;
+
Image
*magnify_image;
- assert(image != (Image *) NULL);
+ MagickBooleanType
+ status;
+
+ MagickOffsetType
+ progress;
+
+ ssize_t
+ y;
+
+ /*
+ Initialize magnified image attributes.
+ */
+ assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
- if( IfMagickTrue(image->debug) )
+ if (image->debug != MagickFalse)
(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,SplineFilter,
+ magnify_image=CloneImage(image,2*image->columns,2*image->rows,MagickTrue,
exception);
+ if (magnify_image == (Image *) NULL)
+ return((Image *) NULL);
+ /*
+ Magnify image.
+ */
+ status=MagickTrue;
+ progress=0;
+ image_view=AcquireVirtualCacheView(image,exception);
+ magnify_view=AcquireAuthenticCacheView(magnify_image,exception);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(static,4) shared(progress,status) \
+ magick_threads(image,magnify_image,image->rows,1)
+#endif
+ for (y=0; y < (ssize_t) image->rows; y++)
+ {
+ register Quantum
+ *restrict q;
+
+ register ssize_t
+ x;
+
+ if (status == MagickFalse)
+ continue;
+ q=QueueCacheViewAuthenticPixels(magnify_view,0,2*y,magnify_image->columns,2,
+ exception);
+ if (q == (Quantum *) NULL)
+ {
+ status=MagickFalse;
+ continue;
+ }
+ /*
+ Magnify this row of pixels.
+ */
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
+ MagickRealType
+ intensity[9];
+
+ register const Quantum
+ *restrict p;
+
+ register Quantum
+ *restrict r;
+
+ register ssize_t
+ i;
+
+ size_t
+ channels;
+
+ p=GetCacheViewVirtualPixels(image_view,x-1,y-1,3,3,exception);
+ if (p == (const Quantum *) NULL)
+ {
+ status=MagickFalse;
+ continue;
+ }
+ channels=GetPixelChannels(image);
+ for (i=0; i < 9; i++)
+ intensity[i]=GetPixelIntensity(image,p+i*channels);
+ r=q;
+ if ((fabs(intensity[1]-intensity[7]) < MagickEpsilon) ||
+ (fabs(intensity[3]-intensity[5]) < MagickEpsilon))
+ {
+ /*
+ Clone center pixel.
+ */
+ for (i=0; i < (ssize_t) channels; i++)
+ r[i]=p[4*channels+i];
+ r+=GetPixelChannels(magnify_image);
+ for (i=0; i < (ssize_t) channels; i++)
+ r[i]=p[4*channels+i];
+ r+=(magnify_image->columns-1)*GetPixelChannels(magnify_image);
+ for (i=0; i < (ssize_t) channels; i++)
+ r[i]=p[4*channels+i];
+ r+=GetPixelChannels(magnify_image);
+ for (i=0; i < (ssize_t) channels; i++)
+ r[i]=p[4*channels+i];
+ }
+ else
+ {
+ /*
+ Selectively clone pixel.
+ */
+ if (fabs(intensity[1]-intensity[3]) < MagickEpsilon)
+ for (i=0; i < (ssize_t) channels; i++)
+ r[i]=p[3*channels+i];
+ else
+ for (i=0; i < (ssize_t) channels; i++)
+ r[i]=p[4*channels+i];
+ r+=GetPixelChannels(magnify_image);
+ if (fabs(intensity[1]-intensity[5]) < MagickEpsilon)
+ for (i=0; i < (ssize_t) channels; i++)
+ r[i]=p[5*channels+i];
+ else
+ for (i=0; i < (ssize_t) channels; i++)
+ r[i]=p[4*channels+i];
+ r+=(magnify_image->columns-1)*GetPixelChannels(magnify_image);
+ if (fabs(intensity[3]-intensity[7]) < MagickEpsilon)
+ for (i=0; i < (ssize_t) channels; i++)
+ r[i]=p[3*channels+i];
+ else
+ for (i=0; i < (ssize_t) channels; i++)
+ r[i]=p[4*channels+i];
+ r+=GetPixelChannels(magnify_image);
+ if (fabs(intensity[5]-intensity[7]) < MagickEpsilon)
+ for (i=0; i < (ssize_t) channels; i++)
+ r[i]=p[5*channels+i];
+ else
+ for (i=0; i < (ssize_t) channels; i++)
+ r[i]=p[4*channels+i];
+ }
+ q+=2*GetPixelChannels(magnify_image);
+ }
+ if (SyncCacheViewAuthenticPixels(magnify_view,exception) == MagickFalse)
+ status=MagickFalse;
+ if (image->progress_monitor != (MagickProgressMonitor) NULL)
+ {
+ MagickBooleanType
+ proceed;
+
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp critical (MagickCore_MagnifyImage)
+#endif
+ proceed=SetImageProgress(image,MagnifyImageTag,progress++,image->rows);
+ if (proceed == MagickFalse)
+ status=MagickFalse;
+ }
+ }
+ magnify_view=DestroyCacheView(magnify_view);
+ image_view=DestroyCacheView(image_view);
+ if (status == MagickFalse)
+ magnify_image=DestroyImage(magnify_image);
return(magnify_image);
}
\f
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if( IfMagickTrue(image->debug) )
+ if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
*/
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
- if( IfMagickTrue(image->debug) )
+ if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
%
% The format of the ResizeImage method is:
%
-% Image *ResizeImage(Image *image,const size_t columns,
-% const size_t rows,const FilterTypes filter,const double blur,
-% ExceptionInfo *exception)
+% Image *ResizeImage(Image *image,const size_t columns,const size_t rows,
+% const FilterTypes filter,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
%
% o filter: Image filter to use.
%
-% o blur: the blur factor where > 1 is blurry, < 1 is sharp. Typically set
-% this to 1.0.
-%
% o exception: return any errors or warnings in this structure.
%
*/
(void) ResetMagickMemory(contribution,0,number_threads*sizeof(*contribution));
for (i=0; i < (ssize_t) number_threads; i++)
{
- contribution[i]=(ContributionInfo *) AcquireAlignedMemory(count,
- sizeof(**contribution));
+ contribution[i]=(ContributionInfo *) MagickAssumeAligned(
+ AcquireAlignedMemory(count,sizeof(**contribution)));
if (contribution[i] == (ContributionInfo *) NULL)
return(DestroyContributionThreadSet(contribution));
}
scale=MagickMax(1.0/x_factor+MagickEpsilon,1.0);
support=scale*GetResizeFilterSupport(resize_filter);
storage_class=support > 0.5 ? DirectClass : image->storage_class;
- if( IfMagickFalse(SetImageStorageClass(resize_image,storage_class,exception)) )
+ if (SetImageStorageClass(resize_image,storage_class,exception) == MagickFalse)
return(MagickFalse);
if (support < 0.5)
{
if (contributions == (ContributionInfo **) NULL)
{
(void) ThrowMagickException(exception,GetMagickModule(),
- ResourceLimitError,"MemoryAllocationFailed","'%s'",image->filename);
+ ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
return(MagickFalse);
}
status=MagickTrue;
- scale=MagickEpsilonReciprocal(scale);
+ scale=PerceptibleReciprocal(scale);
image_view=AcquireVirtualCacheView(image,exception);
resize_view=AcquireAuthenticCacheView(resize_image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(static,4) shared(status) \
- dynamic_number_threads(image,image->columns,image->rows,1)
+ magick_threads(image,resize_image,resize_image->columns,1)
#endif
for (x=0; x < (ssize_t) resize_image->columns; x++)
{
+ const int
+ id = GetOpenMPThreadId();
+
double
bisect,
density;
start,
stop;
- if( IfMagickFalse(status) )
+ if (status == MagickFalse)
continue;
bisect=(double) (x+0.5)/x_factor+MagickEpsilon;
start=(ssize_t) MagickMax(bisect-support+0.5,0.0);
stop=(ssize_t) MagickMin(bisect+support+0.5,(double) image->columns);
density=0.0;
- contribution=contributions[GetOpenMPThreadId()];
+ contribution=contributions[id];
for (n=0; n < (stop-start); n++)
{
contribution[n].pixel=start+n;
/*
Normalize.
*/
- density=MagickEpsilonReciprocal(density);
+ density=PerceptibleReciprocal(density);
for (i=0; i < n; i++)
contribution[i].weight*=density;
}
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++)
{
double
ssize_t
k;
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
- resize_traits=GetPixelChannelMapTraits(resize_image,channel);
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ resize_traits=GetPixelChannelTraits(resize_image,channel);
if ((traits == UndefinedPixelTrait) ||
(resize_traits == UndefinedPixelTrait))
continue;
- if ((resize_traits & CopyPixelTrait) != 0)
+ if (((resize_traits & CopyPixelTrait) != 0) ||
+ (GetPixelReadMask(resize_image,q) == 0))
{
j=(ssize_t) (MagickMin(MagickMax(bisect,(double) start),(double)
stop-1.0)+0.5);
pixel+=alpha*p[k*GetPixelChannels(image)+i];
gamma+=alpha;
}
- gamma=MagickEpsilonReciprocal(gamma);
+ gamma=PerceptibleReciprocal(gamma);
SetPixelChannel(resize_image,channel,ClampToQuantum(gamma*pixel),q);
}
q+=GetPixelChannels(resize_image);
}
- if( IfMagickFalse(SyncCacheViewAuthenticPixels(resize_view,exception)) )
+ if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
status=MagickFalse;
if (image->progress_monitor != (MagickProgressMonitor) NULL)
{
#pragma omp critical (MagickCore_HorizontalFilter)
#endif
proceed=SetImageProgress(image,ResizeImageTag,(*offset)++,span);
- if( IfMagickFalse(proceed) )
+ if (proceed == MagickFalse)
status=MagickFalse;
}
}
ContributionInfo
**restrict contributions;
- MagickBooleanType
- status;
-
- PixelInfo
- zero;
-
double
scale,
support;
+ MagickBooleanType
+ status;
+
ssize_t
y;
scale=MagickMax(1.0/y_factor+MagickEpsilon,1.0);
support=scale*GetResizeFilterSupport(resize_filter);
storage_class=support > 0.5 ? DirectClass : image->storage_class;
- if( IfMagickFalse(SetImageStorageClass(resize_image,storage_class,exception)) )
+ if (SetImageStorageClass(resize_image,storage_class,exception) == MagickFalse)
return(MagickFalse);
if (support < 0.5)
{
if (contributions == (ContributionInfo **) NULL)
{
(void) ThrowMagickException(exception,GetMagickModule(),
- ResourceLimitError,"MemoryAllocationFailed","'%s'",image->filename);
+ ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
return(MagickFalse);
}
status=MagickTrue;
- scale=MagickEpsilonReciprocal(scale);
- (void) ResetMagickMemory(&zero,0,sizeof(zero));
+ scale=PerceptibleReciprocal(scale);
image_view=AcquireVirtualCacheView(image,exception);
resize_view=AcquireAuthenticCacheView(resize_image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(static,4) shared(status) \
- dynamic_number_threads(image,image->columns,image->rows,1)
+ magick_threads(image,resize_image,resize_image->rows,1)
#endif
for (y=0; y < (ssize_t) resize_image->rows; y++)
{
+ const int
+ id = GetOpenMPThreadId();
+
double
bisect,
density;
start,
stop;
- if( IfMagickFalse(status) )
+ if (status == MagickFalse)
continue;
bisect=(double) (y+0.5)/y_factor+MagickEpsilon;
start=(ssize_t) MagickMax(bisect-support+0.5,0.0);
stop=(ssize_t) MagickMin(bisect+support+0.5,(double) image->rows);
density=0.0;
- contribution=contributions[GetOpenMPThreadId()];
+ contribution=contributions[id];
for (n=0; n < (stop-start); n++)
{
contribution[n].pixel=start+n;
/*
Normalize.
*/
- density=MagickEpsilonReciprocal(density);
+ density=PerceptibleReciprocal(density);
for (i=0; i < n; i++)
contribution[i].weight*=density;
}
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++)
{
double
ssize_t
k;
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
- resize_traits=GetPixelChannelMapTraits(resize_image,channel);
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ resize_traits=GetPixelChannelTraits(resize_image,channel);
if ((traits == UndefinedPixelTrait) ||
(resize_traits == UndefinedPixelTrait))
continue;
- if ((resize_traits & CopyPixelTrait) != 0)
+ if (((resize_traits & CopyPixelTrait) != 0) ||
+ (GetPixelReadMask(resize_image,q) == 0))
{
j=(ssize_t) (MagickMin(MagickMax(bisect,(double) start),(double)
stop-1.0)+0.5);
pixel+=alpha*p[k*GetPixelChannels(image)+i];
gamma+=alpha;
}
- gamma=MagickEpsilonReciprocal(gamma);
+ gamma=PerceptibleReciprocal(gamma);
SetPixelChannel(resize_image,channel,ClampToQuantum(gamma*pixel),q);
}
q+=GetPixelChannels(resize_image);
}
- if( IfMagickFalse(SyncCacheViewAuthenticPixels(resize_view,exception)) )
+ if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
status=MagickFalse;
if (image->progress_monitor != (MagickProgressMonitor) NULL)
{
#pragma omp critical (MagickCore_VerticalFilter)
#endif
proceed=SetImageProgress(image,ResizeImageTag,(*offset)++,span);
- if( IfMagickFalse(proceed) )
+ if (proceed == MagickFalse)
status=MagickFalse;
}
}
MagickExport Image *ResizeImage(const Image *image,const size_t columns,
const size_t rows,const FilterTypes filter,ExceptionInfo *exception)
{
-#define WorkLoadFactor 0.265
+ double
+ x_factor,
+ y_factor;
FilterTypes
filter_type;
MagickOffsetType
offset;
- double
- x_factor,
- y_factor;
-
MagickSizeType
span;
*/
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if( IfMagickTrue(image->debug) )
+ if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
*/
x_factor=(double) columns/(double) image->columns;
y_factor=(double) rows/(double) image->rows;
- if ((x_factor*y_factor) > WorkLoadFactor)
+ if (x_factor > y_factor)
filter_image=CloneImage(image,columns,image->rows,MagickTrue,exception);
else
filter_image=CloneImage(image,image->columns,rows,MagickTrue,exception);
filter_type=PointFilter;
else
if ((image->storage_class == PseudoClass) ||
- IfMagickTrue(image->matte) ||
+ (image->alpha_trait == BlendPixelTrait) ||
((x_factor*y_factor) > 1.0))
filter_type=MitchellFilter;
resize_filter=AcquireResizeFilter(image,filter_type,MagickFalse,exception);
Resize image.
*/
offset=0;
- if ((x_factor*y_factor) > WorkLoadFactor)
+ if (x_factor > y_factor)
{
span=(MagickSizeType) (filter_image->columns+rows);
status=HorizontalFilter(resize_filter,image,filter_image,x_factor,span,
*/
filter_image=DestroyImage(filter_image);
resize_filter=DestroyResizeFilter(resize_filter);
- if( IfMagickFalse(status) )
+ if (status == MagickFalse)
{
resize_image=DestroyImage(resize_image);
return((Image *) NULL);
*x_offset,
y;
+ PointInfo
+ sample_offset;
+
/*
Initialize sampled image attributes.
*/
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
- if( IfMagickTrue(image->debug) )
+ if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
sample_image=CloneImage(image,columns,rows,MagickTrue,exception);
if (sample_image == (Image *) NULL)
return((Image *) NULL);
+ /*
+ Set the sampling offset, default is in the mid-point of sample regions.
+ */
+ sample_offset.x=sample_offset.y=0.5-MagickEpsilon;
+ {
+ const char
+ *value;
+
+ value=GetImageArtifact(image,"sample:offset");
+ if (value != (char *) NULL)
+ {
+ GeometryInfo
+ geometry_info;
+
+ MagickStatusType
+ flags;
+
+ (void) ParseGeometry(value,&geometry_info);
+ flags=ParseGeometry(value,&geometry_info);
+ sample_offset.x=sample_offset.y=geometry_info.rho/100.0-MagickEpsilon;
+ if ((flags & SigmaValue) != 0)
+ sample_offset.y=geometry_info.sigma/100.0-MagickEpsilon;
+ }
+ }
/*
Allocate scan line buffer and column offset buffers.
*/
ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
}
for (x=0; x < (ssize_t) sample_image->columns; x++)
- x_offset[x]=(ssize_t) (((double) x+0.5)*image->columns/
+ x_offset[x]=(ssize_t) ((((double) x+sample_offset.x)*image->columns)/
sample_image->columns);
/*
Sample each row.
image_view=AcquireVirtualCacheView(image,exception);
sample_view=AcquireAuthenticCacheView(sample_image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(static) shared(progress,status) \
- dynamic_number_threads(image,image->columns,image->rows,1)
+ #pragma omp parallel for schedule(static,4) shared(status) \
+ magick_threads(image,sample_image,1,1)
#endif
for (y=0; y < (ssize_t) sample_image->rows; y++)
{
ssize_t
y_offset;
- if( IfMagickFalse(status) )
+ if (status == MagickFalse)
continue;
- y_offset=(ssize_t) (((double) y+0.5)*image->rows/
+ y_offset=(ssize_t) ((((double) y+sample_offset.y)*image->rows)/
sample_image->rows);
p=GetCacheViewVirtualPixels(image_view,0,y_offset,image->columns,1,
exception);
register ssize_t
i;
- if (GetPixelMask(sample_image,q) != 0)
+ if (GetPixelReadMask(sample_image,q) == 0)
{
q+=GetPixelChannels(sample_image);
continue;
sample_traits,
traits;
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
- sample_traits=GetPixelChannelMapTraits(sample_image,channel);
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ sample_traits=GetPixelChannelTraits(sample_image,channel);
if ((traits == UndefinedPixelTrait) ||
(sample_traits == UndefinedPixelTrait))
continue;
}
q+=GetPixelChannels(sample_image);
}
- if( IfMagickFalse(SyncCacheViewAuthenticPixels(sample_view,exception)) )
+ if (SyncCacheViewAuthenticPixels(sample_view,exception) == MagickFalse)
status=MagickFalse;
if (image->progress_monitor != (MagickProgressMonitor) NULL)
{
#pragma omp critical (MagickCore_SampleImage)
#endif
proceed=SetImageProgress(image,SampleImageTag,progress++,image->rows);
- if( IfMagickFalse(proceed) )
+ if (proceed == MagickFalse)
status=MagickFalse;
}
}
sample_view=DestroyCacheView(sample_view);
x_offset=(ssize_t *) RelinquishMagickMemory(x_offset);
sample_image->type=image->type;
+ if (status == MagickFalse)
+ sample_image=DestroyImage(sample_image);
return(sample_image);
}
\f
*image_view,
*scale_view;
- Image
- *scale_image;
-
- MagickBooleanType
- next_column,
- next_row,
- proceed;
-
double
alpha,
gamma,
*x_vector,
*y_vector;
+ Image
+ *scale_image;
+
+ MagickBooleanType
+ next_column,
+ next_row,
+ proceed,
+ status;
+
PixelChannel
channel;
*/
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
- if( IfMagickTrue(image->debug) )
+ if (image->debug != MagickFalse)
(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( IfMagickFalse(SetImageStorageClass(scale_image,DirectClass,exception)) )
+ if (SetImageStorageClass(scale_image,DirectClass,exception) == MagickFalse)
{
scale_image=DestroyImage(scale_image);
return((Image *) NULL);
for (i=0; i < (ssize_t) (GetPixelChannels(image)*image->columns); i++)
y_vector[i]=0.0;
n=0;
+ status=MagickTrue;
image_view=AcquireVirtualCacheView(image,exception);
scale_view=AcquireAuthenticCacheView(scale_image,exception);
for (y=0; y < (ssize_t) scale_image->rows; y++)
register ssize_t
x;
+ if (status == MagickFalse)
+ break;
q=QueueCacheViewAuthenticPixels(scale_view,0,y,scale_image->columns,1,
exception);
if (q == (Quantum *) NULL)
- break;
+ {
+ status=MagickFalse;
+ break;
+ }
alpha=1.0;
if (scale_image->rows == image->rows)
{
p=GetCacheViewVirtualPixels(image_view,0,n++,image->columns,1,
exception);
if (p == (const Quantum *) NULL)
- break;
+ {
+ status=MagickFalse;
+ break;
+ }
for (x=0; x < (ssize_t) image->columns; x++)
{
- if (GetPixelMask(image,p) != 0)
+ if (GetPixelReadMask(image,p) == 0)
{
p+=GetPixelChannels(image);
continue;
PixelTrait
traits;
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
if ((traits & BlendPixelTrait) == 0)
{
x_vector[x*GetPixelChannels(image)+i]=(double) p[i];
*/
while (scale.y < span.y)
{
- if( IfMagickTrue(next_row) && (number_rows < (ssize_t) image->rows))
+ if ((next_row != MagickFalse) &&
+ (number_rows < (ssize_t) image->rows))
{
/*
Read a new scanline.
p=GetCacheViewVirtualPixels(image_view,0,n++,image->columns,1,
exception);
if (p == (const Quantum *) NULL)
- break;
+ {
+ status=MagickFalse;
+ break;
+ }
for (x=0; x < (ssize_t) image->columns; x++)
{
- if (GetPixelMask(image,p) != 0)
+ if (GetPixelReadMask(image,p) == 0)
{
p+=GetPixelChannels(image);
continue;
PixelTrait
traits;
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
if ((traits & BlendPixelTrait) == 0)
{
x_vector[x*GetPixelChannels(image)+i]=(double)
scale.y=(double) scale_image->rows/(double) image->rows;
next_row=MagickTrue;
}
- if( IfMagickTrue(next_row) && (number_rows < (ssize_t) image->rows))
+ if ((next_row != MagickFalse) && (number_rows < (ssize_t) image->rows))
{
/*
Read a new scanline.
p=GetCacheViewVirtualPixels(image_view,0,n++,image->columns,1,
exception);
if (p == (const Quantum *) NULL)
- break;
+ {
+ status=MagickFalse;
+ break;
+ }
for (x=0; x < (ssize_t) image->columns; x++)
{
- if (GetPixelMask(image,p) != 0)
+ if (GetPixelReadMask(image,p) == 0)
{
p+=GetPixelChannels(image);
continue;
PixelTrait
traits;
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
if ((traits & BlendPixelTrait) == 0)
{
x_vector[x*GetPixelChannels(image)+i]=(double) p[i];
*/
for (x=0; x < (ssize_t) scale_image->columns; x++)
{
- if (GetPixelMask(scale_image,q) != 0)
+ if (GetPixelReadMask(scale_image,q) == 0)
{
q+=GetPixelChannels(scale_image);
continue;
ssize_t
offset;
- channel=GetPixelChannelMapChannel(scale_image,i);
- traits=GetPixelChannelMapTraits(image,channel);
- scale_traits=GetPixelChannelMapTraits(scale_image,channel);
+ channel=GetPixelChannelChannel(scale_image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ scale_traits=GetPixelChannelTraits(scale_image,channel);
if ((traits == UndefinedPixelTrait) ||
(scale_traits == UndefinedPixelTrait))
continue;
- offset=GetPixelChannelMapOffset(image,channel);
+ offset=GetPixelChannelOffset(image,channel);
if ((traits & BlendPixelTrait) == 0)
{
SetPixelChannel(scale_image,channel,ClampToQuantum(
continue;
}
alpha=QuantumScale*scanline[x*GetPixelChannels(image)+
- GetPixelChannelMapChannel(image,AlphaPixelChannel)];
- gamma=MagickEpsilonReciprocal(alpha);
+ GetPixelChannelChannel(image,AlphaPixelChannel)];
+ gamma=PerceptibleReciprocal(alpha);
SetPixelChannel(scale_image,channel,ClampToQuantum(gamma*scanline[
x*GetPixelChannels(image)+offset]),q);
}
scale.x=(double) scale_image->columns/(double) image->columns;
while (scale.x >= span.x)
{
- if( IfMagickTrue(next_column) )
+ if (next_column != MagickFalse)
{
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
pixel[i]=0.0;
PixelTrait
traits;
- channel=GetPixelChannelMapChannel(image,i);
- traits=GetPixelChannelMapTraits(image,channel);
+ channel=GetPixelChannelChannel(image,i);
+ traits=GetPixelChannelTraits(image,channel);
if (traits == UndefinedPixelTrait)
continue;
pixel[i]+=span.x*scanline[x*GetPixelChannels(image)+i];
}
if (scale.x > 0)
{
- if( IfMagickTrue(next_column) )
+ if (next_column != MagickFalse)
{
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
pixel[i]=0.0;
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
pixel[i]+=span.x*scanline[(x-1)*GetPixelChannels(image)+i];
}
- if( IfMagickFalse(next_column) &&
+ if ((next_column == MagickFalse) &&
((ssize_t) n < (ssize_t) scale_image->columns))
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
- channel=GetPixelChannelMapChannel(image,i);
+ channel=GetPixelChannelChannel(image,i);
scale_scanline[n*MaxPixelChannels+channel]=pixel[i];
}
/*
*/
for (x=0; x < (ssize_t) scale_image->columns; x++)
{
- if (GetPixelMask(scale_image,q) != 0)
+ if (GetPixelReadMask(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);
+ channel=GetPixelChannelChannel(scale_image,i);
+ traits=GetPixelChannelTraits(image,channel);
+ scale_traits=GetPixelChannelTraits(scale_image,channel);
if ((traits == UndefinedPixelTrait) ||
(scale_traits == UndefinedPixelTrait))
continue;
scale_scanline[x*MaxPixelChannels+channel]),q);
continue;
}
- SetPixelChannel(scale_image,channel,ClampToQuantum(
- scale_scanline[x*MaxPixelChannels+channel]),q);
+ SetPixelChannel(scale_image,channel,ClampToQuantum(scale_scanline[
+ x*MaxPixelChannels+channel]),q);
}
q+=GetPixelChannels(scale_image);
}
}
- if( IfMagickFalse(SyncCacheViewAuthenticPixels(scale_view,exception)) )
- break;
+ if (SyncCacheViewAuthenticPixels(scale_view,exception) == MagickFalse)
+ {
+ status=MagickFalse;
+ break;
+ }
proceed=SetImageProgress(image,ScaleImageTag,(MagickOffsetType) y,
image->rows);
- if( IfMagickFalse(proceed) )
- break;
+ if (proceed == MagickFalse)
+ {
+ status=MagickFalse;
+ break;
+ }
}
scale_view=DestroyCacheView(scale_view);
image_view=DestroyCacheView(image_view);
scanline=(double *) RelinquishMagickMemory(scanline);
x_vector=(double *) RelinquishMagickMemory(x_vector);
scale_image->type=image->type;
+ if (status == MagickFalse)
+ scale_image=DestroyImage(scale_image);
return(scale_image);
}
\f
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if( IfMagickTrue(image->debug) )
+ if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
if (thumbnail_image == (Image *) NULL)
return(thumbnail_image);
(void) ParseAbsoluteGeometry("0x0+0+0",&thumbnail_image->page);
- if( IfMagickFalse(thumbnail_image->matte) )
+ if (thumbnail_image->alpha_trait != BlendPixelTrait)
(void) SetImageAlphaChannel(thumbnail_image,OpaqueAlphaChannel,exception);
thumbnail_image->depth=8;
thumbnail_image->interlace=NoInterlace;
image->magick_filename);
(void) SetImageProperty(thumbnail_image,"Thumb::URI",value,exception);
(void) CopyMagickString(value,image->magick_filename,MaxTextExtent);
- if( IfMagickTrue(GetPathAttributes(image->filename,&attributes)) )
+ if ( IfMagickTrue(GetPathAttributes(image->filename,&attributes)) )
{
(void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
attributes.st_mtime);