Initial porting of new interpolations and resize spline, from IMv6 to IMv7
Not quite finished with spline, blend, and background
diff --git a/MagickCore/option.c b/MagickCore/option.c
index 47022e5..e5f1293 100644
--- a/MagickCore/option.c
+++ b/MagickCore/option.c
@@ -1036,6 +1036,7 @@
{ "RobidouxSharp", RobidouxSharpFilter, UndefinedOptionFlag, MagickFalse },
{ "Sinc", SincFilter, UndefinedOptionFlag, MagickFalse },
{ "SincFast", SincFastFilter, UndefinedOptionFlag, MagickFalse },
+ { "Spline", SplineFilter, UndefinedOptionFlag, MagickFalse },
{ "Triangle", TriangleFilter, UndefinedOptionFlag, MagickFalse },
{ "Welsh", WelshFilter, UndefinedOptionFlag, MagickFalse },
{ (char *) NULL, UndefinedFilter, UndefinedOptionFlag, MagickFalse }
@@ -1090,14 +1091,19 @@
{
{ "Undefined", UndefinedInterpolatePixel, UndefinedOptionFlag, MagickTrue },
{ "Average", AverageInterpolatePixel, UndefinedOptionFlag, MagickFalse },
- { "Bicubic", BicubicInterpolatePixel, UndefinedOptionFlag, MagickFalse },
+ { "Average4", AverageInterpolatePixel, UndefinedOptionFlag, MagickFalse },
+ { "Average9", Average9InterpolatePixel, UndefinedOptionFlag, MagickFalse },
+ { "Average16", Average16InterpolatePixel, UndefinedOptionFlag, MagickFalse },
+ { "Background", BackgroundInterpolatePixel, UndefinedOptionFlag, MagickFalse },
{ "Bilinear", BilinearInterpolatePixel, UndefinedOptionFlag, MagickFalse },
- { "filter", FilterInterpolatePixel, UndefinedOptionFlag, MagickFalse },
+ { "Blend", BlendInterpolatePixel, UndefinedOptionFlag, MagickFalse },
+ { "Catrom", CatromInterpolatePixel, UndefinedOptionFlag, MagickFalse },
{ "Integer", IntegerInterpolatePixel, UndefinedOptionFlag, MagickFalse },
{ "Mesh", MeshInterpolatePixel, UndefinedOptionFlag, MagickFalse },
- { "Nearest", NearestNeighborInterpolatePixel, UndefinedOptionFlag, MagickFalse },
- { "NearestNeighbor", NearestNeighborInterpolatePixel, UndefinedOptionFlag, MagickFalse },
+ { "Nearest", NearestInterpolatePixel, UndefinedOptionFlag, MagickFalse },
+ { "NearestNeighbor", NearestInterpolatePixel, UndefinedOptionFlag, MagickTrue },
{ "Spline", SplineInterpolatePixel, UndefinedOptionFlag, MagickFalse },
+/* { "Filter", FilterInterpolatePixel, UndefinedOptionFlag, MagickFalse }, */
{ (char *) NULL, UndefinedInterpolatePixel, UndefinedOptionFlag, MagickFalse }
},
KernelOptions[] =
diff --git a/MagickCore/pixel.c b/MagickCore/pixel.c
index 996cd1b..2fa2b04 100644
--- a/MagickCore/pixel.c
+++ b/MagickCore/pixel.c
@@ -4013,6 +4013,8 @@
% floating point coordinate and the pixels surrounding that coordinate. No
% pixel area resampling, or scaling of the result is performed.
%
+% Interpolation is restricted to just the specified channel.
+%
% The format of the InterpolatePixelChannel method is:
%
% MagickBooleanType InterpolatePixelChannel(const Image *image,
@@ -4045,7 +4047,7 @@
return(y);
}
-static inline MagickRealType CubicWeightingFunction(const MagickRealType x)
+static inline MagickRealType SplineWeightingFunction(const MagickRealType x)
{
MagickRealType
alpha,
@@ -4068,12 +4070,14 @@
return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
}
+/*
static inline ssize_t NearestNeighbor(const MagickRealType x)
{
if (x >= 0.0)
return((ssize_t) (x+0.5));
return((ssize_t) (x-0.5));
}
+*/
MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
const CacheView *image_view,const PixelChannel channel,
@@ -4094,13 +4098,16 @@
register const Quantum
*p;
- register ssize_t
+ register size_t
i;
ssize_t
x_offset,
y_offset;
+ PixelInterpolateMethod
+ interpolate;
+
assert(image != (Image *) NULL);
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
@@ -4110,38 +4117,97 @@
traits=GetPixelChannelMapTraits(image,channel);
x_offset=(ssize_t) floor(x);
y_offset=(ssize_t) floor(y);
- switch (method == UndefinedInterpolatePixel ? image->interpolate : method)
+ interpolate = method;
+ if ( interpolate == UndefinedInterpolatePixel )
+ interpolate = image->interpolate;
+ switch (interpolate)
{
- case AverageInterpolatePixel:
+ case AverageInterpolatePixel: /* nearest 4 neighbours */
+ case Average9InterpolatePixel: /* nearest 9 neighbours */
+ case Average16InterpolatePixel: /* nearest 16 neighbours */
{
- p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
+ size_t
+ count=2; /* size of the area to average - default nearest 4 */
+
+ if (interpolate == Average9InterpolatePixel)
+ {
+ count=3;
+ x_offset=(ssize_t) (floor(x+0.5)-1);
+ y_offset=(ssize_t) (floor(y+0.5)-1);
+ }
+ else if (interpolate == Average16InterpolatePixel)
+ {
+ count=4;
+ x_offset--;
+ y_offset--;
+ }
+ p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,count,count,
exception);
if (p == (const Quantum *) NULL)
{
status=MagickFalse;
break;
}
+
+ count*=count; /* Number of pixels to Average */
if ((traits & BlendPixelTrait) == 0)
- for (i=0; i < 16; i++)
+ for (i=0; i < count; i++)
{
alpha[i]=1.0;
pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
}
else
- for (i=0; i < 16; i++)
+ for (i=0; i < count; i++)
{
alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
GetPixelChannels(image));
pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
}
- for (i=0; i < 16; i++)
+ for (i=0; i < count; i++)
{
- gamma=MagickEpsilonReciprocal(alpha[i]);
- *pixel+=gamma*0.0625*pixels[i];
+ gamma=MagickEpsilonReciprocal(alpha[i])/count;
+ *pixel+=gamma*pixels[i];
}
break;
}
- case BicubicInterpolatePixel:
+ case BilinearInterpolatePixel:
+ default:
+ {
+ PointInfo
+ delta,
+ epsilon;
+
+ p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
+ if (p == (const Quantum *) NULL)
+ {
+ status=MagickFalse;
+ break;
+ }
+ if ((traits & BlendPixelTrait) == 0)
+ for (i=0; i < 4; i++)
+ {
+ alpha[i]=1.0;
+ pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
+ }
+ else
+ for (i=0; i < 4; i++)
+ {
+ alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
+ GetPixelChannels(image));
+ pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
+ }
+ delta.x=x-x_offset;
+ delta.y=y-y_offset;
+ epsilon.x=1.0-delta.x;
+ epsilon.y=1.0-delta.y;
+ gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
+ (epsilon.x*alpha[2]+delta.x*alpha[3])));
+ gamma=MagickEpsilonReciprocal(gamma);
+ *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
+ (epsilon.x*pixels[2]+delta.x*pixels[3]));
+ break;
+ }
+ case CatromInterpolatePixel:
{
MagickRealType
beta[4],
@@ -4211,43 +4277,8 @@
cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
break;
}
- case BilinearInterpolatePixel:
- default:
- {
- PointInfo
- delta,
- epsilon;
-
- p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
- if (p == (const Quantum *) NULL)
- {
- status=MagickFalse;
- break;
- }
- if ((traits & BlendPixelTrait) == 0)
- for (i=0; i < 4; i++)
- {
- alpha[i]=1.0;
- pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
- }
- else
- for (i=0; i < 4; i++)
- {
- alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
- GetPixelChannels(image));
- pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
- }
- delta.x=x-x_offset;
- delta.y=y-y_offset;
- epsilon.x=1.0-delta.x;
- epsilon.y=1.0-delta.y;
- gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
- (epsilon.x*alpha[2]+delta.x*alpha[3])));
- gamma=MagickEpsilonReciprocal(gamma);
- *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
- (epsilon.x*pixels[2]+delta.x*pixels[3]));
- break;
- }
+#if 0
+ /* depreciated useless and very slow interpolator */
case FilterInterpolatePixel:
{
CacheView
@@ -4284,6 +4315,7 @@
filter_image=DestroyImage(filter_image);
break;
}
+#endif
case IntegerInterpolatePixel:
{
p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
@@ -4295,10 +4327,11 @@
*pixel=(double) GetPixelChannel(image,channel,p);
break;
}
- case NearestNeighborInterpolatePixel:
+ case NearestInterpolatePixel:
{
- p=GetCacheViewVirtualPixels(image_view,NearestNeighbor(x),
- NearestNeighbor(y),1,1,exception);
+ x_offset=(ssize_t) floor(x+0.5);
+ y_offset=(ssize_t) floor(y+0.5);
+ p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
if (p == (const Quantum *) NULL)
{
status=MagickFalse;
@@ -4434,10 +4467,10 @@
n=0;
for (i=(-1); i < 3L; i++)
{
- dy=CubicWeightingFunction((MagickRealType) i-delta.y);
+ dy=SplineWeightingFunction((MagickRealType) i-delta.y);
for (j=(-1); j < 3L; j++)
{
- dx=CubicWeightingFunction(delta.x-(MagickRealType) j);
+ dx=SplineWeightingFunction(delta.x-(MagickRealType) j);
gamma=MagickEpsilonReciprocal(alpha[n]);
*pixel+=gamma*dx*dy*pixels[n];
n++;
@@ -4464,6 +4497,9 @@
% floating point coordinate and the pixels surrounding that coordinate. No
% pixel area resampling, or scaling of the result is performed.
%
+% Interpolation is restricted to just the current channel setting of the
+% destination image into which the color is to be stored
+%
% The format of the InterpolatePixelChannels method is:
%
% MagickBooleanType InterpolatePixelChannels(const Image *source,
@@ -4477,7 +4513,7 @@
%
% o source_view: the source view.
%
-% o destination: the destination image.
+% o destination: the destination image, for the interpolated color
%
% o method: the pixel color interpolation method.
%
@@ -4511,13 +4547,16 @@
register const Quantum
*p;
- register ssize_t
+ register size_t
i;
ssize_t
x_offset,
y_offset;
+ PixelInterpolateMethod
+ interpolate;
+
assert(source != (Image *) NULL);
assert(source != (Image *) NULL);
assert(source->signature == MagickSignature);
@@ -4525,23 +4564,44 @@
status=MagickTrue;
x_offset=(ssize_t) floor(x);
y_offset=(ssize_t) floor(y);
- switch (method == UndefinedInterpolatePixel ? source->interpolate : method)
+ interpolate = method;
+ if ( interpolate == UndefinedInterpolatePixel )
+ interpolate = source->interpolate;
+ switch (interpolate)
{
- case AverageInterpolatePixel:
+ case AverageInterpolatePixel: /* nearest 4 neighbours */
+ case Average9InterpolatePixel: /* nearest 9 neighbours */
+ case Average16InterpolatePixel: /* nearest 16 neighbours */
{
- p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
+ size_t
+ count=2; /* size of the area to average - default nearest 4 */
+
+ if (interpolate == Average9InterpolatePixel)
+ {
+ count=3;
+ x_offset=(ssize_t) (floor(x+0.5)-1);
+ y_offset=(ssize_t) (floor(y+0.5)-1);
+ }
+ else if (interpolate == Average16InterpolatePixel)
+ {
+ count=4;
+ x_offset--;
+ y_offset--;
+ }
+ p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,count,count,
exception);
if (p == (const Quantum *) NULL)
{
status=MagickFalse;
break;
}
- for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
+ count*=count; /* Number of pixels to Average */
+ for (i=0; i < GetPixelChannels(source); i++)
{
double
sum;
- register ssize_t
+ register size_t
j;
channel=GetPixelChannelMapChannel(source,i);
@@ -4550,29 +4610,88 @@
if ((traits == UndefinedPixelTrait) ||
(destination_traits == UndefinedPixelTrait))
continue;
- for (j=0; j < 16; j++)
+ for (j=0; j < count; j++)
pixels[j]=(MagickRealType) p[j*GetPixelChannels(source)+i];
sum=0.0;
if ((traits & BlendPixelTrait) == 0)
{
- for (j=0; j < 16; j++)
- sum+=0.0625*pixels[j];
+ for (j=0; j < count; j++)
+ sum+=pixels[j];
+ sum/=count;
SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
continue;
}
- for (j=0; j < 16; j++)
+ for (j=0; j < count; j++)
{
alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
GetPixelChannels(source));
pixels[j]*=alpha[j];
gamma=MagickEpsilonReciprocal(alpha[j]);
- sum+=gamma*0.0625*pixels[j];
+ sum+=gamma*pixels[j];
}
+ sum/=count;
SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
}
break;
}
- case BicubicInterpolatePixel:
+ case BilinearInterpolatePixel:
+ default:
+ {
+ p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
+ if (p == (const Quantum *) NULL)
+ {
+ status=MagickFalse;
+ break;
+ }
+ for (i=0; i < GetPixelChannels(source); i++)
+ {
+ PointInfo
+ delta,
+ epsilon;
+
+ channel=GetPixelChannelMapChannel(source,i);
+ traits=GetPixelChannelMapTraits(source,channel);
+ destination_traits=GetPixelChannelMapTraits(destination,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (destination_traits == UndefinedPixelTrait))
+ continue;
+ delta.x=x-x_offset;
+ delta.y=y-y_offset;
+ epsilon.x=1.0-delta.x;
+ epsilon.y=1.0-delta.y;
+ pixels[0]=(MagickRealType) p[i];
+ pixels[1]=(MagickRealType) p[GetPixelChannels(source)+i];
+ pixels[2]=(MagickRealType) p[2*GetPixelChannels(source)+i];
+ pixels[3]=(MagickRealType) p[3*GetPixelChannels(source)+i];
+ if ((traits & BlendPixelTrait) == 0)
+ {
+ gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
+ gamma=MagickEpsilonReciprocal(gamma);
+ SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
+ (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*
+ pixels[2]+delta.x*pixels[3]))),pixel);
+ continue;
+ }
+ alpha[0]=QuantumScale*GetPixelAlpha(source,p);
+ alpha[1]=QuantumScale*GetPixelAlpha(source,p+GetPixelChannels(source));
+ alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
+ GetPixelChannels(source));
+ alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
+ GetPixelChannels(source));
+ pixels[0]*=alpha[0];
+ pixels[1]*=alpha[1];
+ pixels[2]*=alpha[2];
+ pixels[3]*=alpha[3];
+ gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
+ (epsilon.x*alpha[2]+delta.x*alpha[3])));
+ gamma=MagickEpsilonReciprocal(gamma);
+ SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
+ (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*pixels[2]+
+ delta.x*pixels[3]))),pixel);
+ }
+ break;
+ }
+ case CatromInterpolatePixel:
{
MagickRealType
beta[4],
@@ -4594,7 +4713,7 @@
status=MagickFalse;
break;
}
- for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
+ for (i=0; i < GetPixelChannels(source); i++)
{
register ssize_t
j;
@@ -4655,66 +4774,11 @@
}
break;
}
- case BilinearInterpolatePixel:
- default:
- {
- p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
- if (p == (const Quantum *) NULL)
- {
- status=MagickFalse;
- break;
- }
- for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
- {
- PointInfo
- delta,
- epsilon;
-
- channel=GetPixelChannelMapChannel(source,i);
- traits=GetPixelChannelMapTraits(source,channel);
- destination_traits=GetPixelChannelMapTraits(destination,channel);
- if ((traits == UndefinedPixelTrait) ||
- (destination_traits == UndefinedPixelTrait))
- continue;
- delta.x=x-x_offset;
- delta.y=y-y_offset;
- epsilon.x=1.0-delta.x;
- epsilon.y=1.0-delta.y;
- pixels[0]=(MagickRealType) p[i];
- pixels[1]=(MagickRealType) p[GetPixelChannels(source)+i];
- pixels[2]=(MagickRealType) p[2*GetPixelChannels(source)+i];
- pixels[3]=(MagickRealType) p[3*GetPixelChannels(source)+i];
- if ((traits & BlendPixelTrait) == 0)
- {
- gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
- gamma=MagickEpsilonReciprocal(gamma);
- SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
- (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*
- pixels[2]+delta.x*pixels[3]))),pixel);
- continue;
- }
- alpha[0]=QuantumScale*GetPixelAlpha(source,p);
- alpha[1]=QuantumScale*GetPixelAlpha(source,p+GetPixelChannels(source));
- alpha[2]=QuantumScale*GetPixelAlpha(source,p+2*
- GetPixelChannels(source));
- alpha[3]=QuantumScale*GetPixelAlpha(source,p+3*
- GetPixelChannels(source));
- pixels[0]*=alpha[0];
- pixels[1]*=alpha[1];
- pixels[2]*=alpha[2];
- pixels[3]*=alpha[3];
- gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
- (epsilon.x*alpha[2]+delta.x*alpha[3])));
- gamma=MagickEpsilonReciprocal(gamma);
- SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
- (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*pixels[2]+
- delta.x*pixels[3]))),pixel);
- }
- break;
- }
+#if 0
+ /* depreciated useless and very slow interpolator */
case FilterInterpolatePixel:
{
- for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
+ for (i=0; i < GetPixelChannels(source); i++)
{
CacheView
*filter_view;
@@ -4759,6 +4823,7 @@
}
break;
}
+#endif
case IntegerInterpolatePixel:
{
p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
@@ -4767,7 +4832,7 @@
status=MagickFalse;
break;
}
- for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
+ for (i=0; i < GetPixelChannels(source); i++)
{
channel=GetPixelChannelMapChannel(source,i);
traits=GetPixelChannelMapTraits(source,channel);
@@ -4779,16 +4844,17 @@
}
break;
}
- case NearestNeighborInterpolatePixel:
+ case NearestInterpolatePixel:
{
- p=GetCacheViewVirtualPixels(source_view,NearestNeighbor(x),
- NearestNeighbor(y),1,1,exception);
+ x_offset=(ssize_t) floor(x+0.5);
+ y_offset=(ssize_t) floor(y+0.5);
+ p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
if (p == (const Quantum *) NULL)
{
status=MagickFalse;
break;
}
- for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
+ for (i=0; i < GetPixelChannels(source); i++)
{
channel=GetPixelChannelMapChannel(source,i);
traits=GetPixelChannelMapTraits(source,channel);
@@ -4808,7 +4874,7 @@
status=MagickFalse;
break;
}
- for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
+ for (i=0; i < GetPixelChannels(source); i++)
{
PointInfo
delta,
@@ -4843,11 +4909,13 @@
}
delta.x=x-x_offset;
delta.y=y-y_offset;
- luminance.x=GetPixelLuminance(source,p)-(double)
- GetPixelLuminance(source,p+3*GetPixelChannels(source));
- luminance.y=GetPixelLuminance(source,p+GetPixelChannels(source))-
- (double) GetPixelLuminance(source,p+2*GetPixelChannels(source));
- if (fabs(luminance.x) < fabs(luminance.y))
+ luminance.x=fabs((double)(
+ GetPixelLuminance(source,p)
+ -GetPixelLuminance(source,p+3*GetPixelChannels(source))));
+ luminance.y=fabs((double)(
+ GetPixelLuminance(source,p+GetPixelChannels(source))
+ -GetPixelLuminance(source,p+2*GetPixelChannels(source))));
+ if (luminance.x < luminance.y)
{
/*
Diagonal 0-3 NW-SE.
@@ -4915,7 +4983,7 @@
status=MagickFalse;
break;
}
- for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
+ for (i=0; i < GetPixelChannels(source); i++)
{
double
sum;
@@ -4959,10 +5027,10 @@
n=0;
for (j=(-1); j < 3L; j++)
{
- dy=CubicWeightingFunction((MagickRealType) j-delta.y);
+ dy=SplineWeightingFunction((MagickRealType) j-delta.y);
for (k=(-1); k < 3L; k++)
{
- dx=CubicWeightingFunction(delta.x-(MagickRealType) k);
+ dx=SplineWeightingFunction(delta.x-(MagickRealType) k);
gamma=MagickEpsilonReciprocal(alpha[n]);
sum+=gamma*dx*dy*pixels[n];
n++;
@@ -4991,6 +5059,8 @@
% floating point coordinate and the pixels surrounding that coordinate. No
% pixel area resampling, or scaling of the result is performed.
%
+% Interpolation is restricted to just RGBKA channels.
+%
% The format of the InterpolatePixelInfo method is:
%
% MagickBooleanType InterpolatePixelInfo(const Image *image,
@@ -5056,70 +5126,173 @@
register const Quantum
*p;
- register ssize_t
+ register size_t
i;
ssize_t
x_offset,
y_offset;
+ PixelInterpolateMethod
+ interpolate;
+
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(image_view != (CacheView *) NULL);
status=MagickTrue;
x_offset=(ssize_t) floor(x);
y_offset=(ssize_t) floor(y);
- switch (method == UndefinedInterpolatePixel ? image->interpolate : method)
+ interpolate = method;
+ if ( interpolate == UndefinedInterpolatePixel )
+ interpolate = image->interpolate;
+ switch (interpolate)
{
- case AverageInterpolatePixel:
+ case AverageInterpolatePixel: /* nearest 4 neighbours */
+ case Average9InterpolatePixel: /* nearest 9 neighbours */
+ case Average16InterpolatePixel: /* nearest 16 neighbours */
{
- p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
+ size_t
+ count=2; /* size of the area to average - default nearest 4 */
+
+ if (interpolate == Average9InterpolatePixel)
+ {
+ count=3;
+ x_offset=(ssize_t) (floor(x+0.5)-1);
+ y_offset=(ssize_t) (floor(y+0.5)-1);
+ }
+ else if (interpolate == Average16InterpolatePixel)
+ {
+ count=4;
+ x_offset--;
+ y_offset--;
+ }
+ p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,count,count,
exception);
if (p == (const Quantum *) NULL)
{
status=MagickFalse;
break;
}
- AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
- AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
- AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
- AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
- AlphaBlendPixelInfo(image,p+4*GetPixelChannels(image),pixels+4,alpha+4);
- AlphaBlendPixelInfo(image,p+5*GetPixelChannels(image),pixels+5,alpha+5);
- AlphaBlendPixelInfo(image,p+6*GetPixelChannels(image),pixels+6,alpha+6);
- AlphaBlendPixelInfo(image,p+7*GetPixelChannels(image),pixels+7,alpha+7);
- AlphaBlendPixelInfo(image,p+8*GetPixelChannels(image),pixels+8,alpha+8);
- AlphaBlendPixelInfo(image,p+9*GetPixelChannels(image),pixels+9,alpha+9);
- AlphaBlendPixelInfo(image,p+10*GetPixelChannels(image),pixels+10,alpha+
- 10);
- AlphaBlendPixelInfo(image,p+11*GetPixelChannels(image),pixels+11,alpha+
- 11);
- AlphaBlendPixelInfo(image,p+12*GetPixelChannels(image),pixels+12,alpha+
- 12);
- AlphaBlendPixelInfo(image,p+13*GetPixelChannels(image),pixels+13,alpha+
- 13);
- AlphaBlendPixelInfo(image,p+14*GetPixelChannels(image),pixels+14,alpha+
- 14);
- AlphaBlendPixelInfo(image,p+15*GetPixelChannels(image),pixels+15,alpha+
- 15);
pixel->red=0.0;
pixel->green=0.0;
pixel->blue=0.0;
pixel->black=0.0;
pixel->alpha=0.0;
- for (i=0; i < 16L; i++)
+ count*=count; /* number of pixels - square of size */
+ for (i=0; i < count; i++)
{
- gamma=MagickEpsilonReciprocal(alpha[i]);
- pixel->red+=gamma*0.0625*pixels[i].red;
- pixel->green+=gamma*0.0625*pixels[i].green;
- pixel->blue+=gamma*0.0625*pixels[i].blue;
- if (image->colorspace == CMYKColorspace)
- pixel->black+=gamma*0.0625*pixels[i].black;
- pixel->alpha+=0.0625*pixels[i].alpha;
+ AlphaBlendPixelInfo(image,p,pixels,alpha);
+ gamma=MagickEpsilonReciprocal(alpha[0]);
+ pixel->red += gamma*pixels[0].red;
+ pixel->green += gamma*pixels[0].green;
+ pixel->blue += gamma*pixels[0].blue;
+ pixel->black += gamma*pixels[0].black;
+ pixel->alpha += pixels[0].alpha;
+ p += GetPixelChannels(image);
}
+ gamma=1.0/count; /* average weighting of each pixel in area */
+ pixel->red *= gamma;
+ pixel->green *= gamma;
+ pixel->blue *= gamma;
+ pixel->black *= gamma;
+ pixel->alpha *= gamma;
break;
}
- case BicubicInterpolatePixel:
+ case BackgroundInterpolatePixel:
+ {
+ *pixel = image->background_color; /* Copy PixelInfo Structure */
+ break;
+ }
+ case BilinearInterpolatePixel:
+ default:
+ {
+ PointInfo
+ delta,
+ epsilon;
+
+ p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
+ if (p == (const Quantum *) NULL)
+ {
+ status=MagickFalse;
+ break;
+ }
+ for (i=0; i < 4L; i++)
+ AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
+ delta.x=x-x_offset;
+ delta.y=y-y_offset;
+ epsilon.x=1.0-delta.x;
+ epsilon.y=1.0-delta.y;
+ gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
+ (epsilon.x*alpha[2]+delta.x*alpha[3])));
+ gamma=MagickEpsilonReciprocal(gamma);
+ pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
+ pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
+ pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
+ pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x*
+ pixels[3].green));
+ pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x*
+ pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x*
+ pixels[3].blue));
+ if (image->colorspace == CMYKColorspace)
+ pixel->black=gamma*(epsilon.y*(epsilon.x*pixels[0].black+delta.x*
+ pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
+ pixels[3].black));
+ gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
+ gamma=MagickEpsilonReciprocal(gamma);
+ pixel->alpha=(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
+ pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
+ pixels[3].alpha));
+ break;
+ }
+ case BlendInterpolatePixel:
+ {
+ p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
+ if (p == (const Quantum *) NULL)
+ {
+ status=MagickFalse;
+ break;
+ }
+ for (i=0; i < 4L; i++)
+ AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
+ gamma=1.0; /* number of pixels blended together */
+ for (i=0; i <= 1L; i++) {
+ if ( y-y_offset >= 0.75 ) {
+ alpha[i] = alpha[i+2];
+ pixels[i] = pixels[i+2];
+ }
+ else if ( y-y_offset > 0.25 ) {
+ gamma = 2.0; /* each y pixels have been blended */
+ alpha[i] += alpha[i+2]; /* add up alpha weights */
+ pixels[i].red += pixels[i+2].red;
+ pixels[i].green += pixels[i+2].green;
+ pixels[i].blue += pixels[i+2].blue;
+ pixels[i].black += pixels[i+2].black;
+ pixels[i].alpha += pixels[i+2].alpha;
+ }
+ }
+ if ( x-x_offset >= 0.75 ) {
+ alpha[0] = alpha[1];
+ pixels[0] = pixels[1];
+ }
+ else if ( x-x_offset > 0.25 ) {
+ gamma *= 2.0; /* double number of pixels blended */
+ alpha[0] += alpha[1]; /* add up alpha weights */
+ pixels[0].red += pixels[1].red;
+ pixels[0].green += pixels[1].green;
+ pixels[0].blue += pixels[1].blue;
+ pixels[0].black += pixels[1].black;
+ pixels[0].alpha += pixels[1].alpha;
+ }
+ gamma = 1.0/gamma;
+ alpha[0]=MagickEpsilonReciprocal(alpha[0]);
+ pixel->red = alpha[0]*pixels[0].red;
+ pixel->green = alpha[0]*pixels[0].green; /* divide by sum of alpha */
+ pixel->blue = alpha[0]*pixels[0].blue;
+ pixel->black = alpha[0]*pixels[0].black;
+ pixel->alpha = gamma*pixels[0].alpha; /* divide by number of pixels */
+ break;
+ }
+ case CatromInterpolatePixel:
{
MagickRealType
beta[4],
@@ -5129,7 +5302,6 @@
PointInfo
delta;
-
/*
Refactoring of the Catmull-Rom computation by Nicolas Robidoux with 55
flops = 28* + 10- + 17+. Originally implemented for the VIPS (Virtual
@@ -5142,28 +5314,8 @@
status=MagickFalse;
break;
}
- AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
- AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
- AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
- AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
- AlphaBlendPixelInfo(image,p+4*GetPixelChannels(image),pixels+4,alpha+4);
- AlphaBlendPixelInfo(image,p+5*GetPixelChannels(image),pixels+5,alpha+5);
- AlphaBlendPixelInfo(image,p+6*GetPixelChannels(image),pixels+6,alpha+6);
- AlphaBlendPixelInfo(image,p+7*GetPixelChannels(image),pixels+7,alpha+7);
- AlphaBlendPixelInfo(image,p+8*GetPixelChannels(image),pixels+8,alpha+8);
- AlphaBlendPixelInfo(image,p+9*GetPixelChannels(image),pixels+9,alpha+9);
- AlphaBlendPixelInfo(image,p+10*GetPixelChannels(image),pixels+10,alpha+
- 10);
- AlphaBlendPixelInfo(image,p+11*GetPixelChannels(image),pixels+11,alpha+
- 11);
- AlphaBlendPixelInfo(image,p+12*GetPixelChannels(image),pixels+12,alpha+
- 12);
- AlphaBlendPixelInfo(image,p+13*GetPixelChannels(image),pixels+13,alpha+
- 13);
- AlphaBlendPixelInfo(image,p+14*GetPixelChannels(image),pixels+14,alpha+
- 14);
- AlphaBlendPixelInfo(image,p+15*GetPixelChannels(image),pixels+15,alpha+
- 15);
+ for (i=0; i < 16L; i++)
+ AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
delta.x=x-x_offset;
delta.y=y-y_offset;
beta[0]=1.0-delta.x;
@@ -5228,49 +5380,8 @@
pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
break;
}
- case BilinearInterpolatePixel:
- default:
- {
- PointInfo
- delta,
- epsilon;
-
- p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
- if (p == (const Quantum *) NULL)
- {
- status=MagickFalse;
- break;
- }
- AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
- AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
- AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
- AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
- delta.x=x-x_offset;
- delta.y=y-y_offset;
- epsilon.x=1.0-delta.x;
- epsilon.y=1.0-delta.y;
- gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
- (epsilon.x*alpha[2]+delta.x*alpha[3])));
- gamma=MagickEpsilonReciprocal(gamma);
- pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
- pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
- pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
- pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x*
- pixels[3].green));
- pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x*
- pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x*
- pixels[3].blue));
- if (image->colorspace == CMYKColorspace)
- pixel->black=gamma*(epsilon.y*(epsilon.x*pixels[0].black+delta.x*
- pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
- pixels[3].black));
- gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
- gamma=MagickEpsilonReciprocal(gamma);
- pixel->alpha=(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
- pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
- pixels[3].alpha));
- break;
- }
+#if 0
+ /* depreciated useless and very slow interpolator */
case FilterInterpolatePixel:
{
CacheView
@@ -5305,6 +5416,7 @@
filter_image=DestroyImage(filter_image);
break;
}
+#endif
case IntegerInterpolatePixel:
{
p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
@@ -5436,10 +5548,11 @@
}
break;
}
- case NearestNeighborInterpolatePixel:
+ case NearestInterpolatePixel:
{
- p=GetCacheViewVirtualPixels(image_view,NearestNeighbor(x),
- NearestNeighbor(y),1,1,exception);
+ x_offset=(ssize_t) floor(x+0.5);
+ y_offset=(ssize_t) floor(y+0.5);
+ p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
if (p == (const Quantum *) NULL)
{
status=MagickFalse;
@@ -5468,28 +5581,8 @@
status=MagickFalse;
break;
}
- AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
- AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
- AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
- AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
- AlphaBlendPixelInfo(image,p+4*GetPixelChannels(image),pixels+4,alpha+4);
- AlphaBlendPixelInfo(image,p+5*GetPixelChannels(image),pixels+5,alpha+5);
- AlphaBlendPixelInfo(image,p+6*GetPixelChannels(image),pixels+6,alpha+6);
- AlphaBlendPixelInfo(image,p+7*GetPixelChannels(image),pixels+7,alpha+7);
- AlphaBlendPixelInfo(image,p+8*GetPixelChannels(image),pixels+8,alpha+8);
- AlphaBlendPixelInfo(image,p+9*GetPixelChannels(image),pixels+9,alpha+9);
- AlphaBlendPixelInfo(image,p+10*GetPixelChannels(image),pixels+10,alpha+
- 10);
- AlphaBlendPixelInfo(image,p+11*GetPixelChannels(image),pixels+11,alpha+
- 11);
- AlphaBlendPixelInfo(image,p+12*GetPixelChannels(image),pixels+12,alpha+
- 12);
- AlphaBlendPixelInfo(image,p+13*GetPixelChannels(image),pixels+13,alpha+
- 13);
- AlphaBlendPixelInfo(image,p+14*GetPixelChannels(image),pixels+14,alpha+
- 14);
- AlphaBlendPixelInfo(image,p+15*GetPixelChannels(image),pixels+15,alpha+
- 15);
+ for (i=0; i < 16L; i++)
+ AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
pixel->red=0.0;
pixel->green=0.0;
pixel->blue=0.0;
@@ -5500,10 +5593,10 @@
n=0;
for (i=(-1); i < 3L; i++)
{
- dy=CubicWeightingFunction((MagickRealType) i-delta.y);
+ dy=SplineWeightingFunction((MagickRealType) i-delta.y);
for (j=(-1); j < 3L; j++)
{
- dx=CubicWeightingFunction(delta.x-(MagickRealType) j);
+ dx=SplineWeightingFunction(delta.x-(MagickRealType) j);
gamma=MagickEpsilonReciprocal(alpha[n]);
pixel->red+=gamma*dx*dy*pixels[n].red;
pixel->green+=gamma*dx*dy*pixels[n].green;
diff --git a/MagickCore/pixel.h b/MagickCore/pixel.h
index 691c96a..e646a7b 100644
--- a/MagickCore/pixel.h
+++ b/MagickCore/pixel.h
@@ -61,14 +61,18 @@
typedef enum
{
UndefinedInterpolatePixel,
- AverageInterpolatePixel,
- BicubicInterpolatePixel,
- BilinearInterpolatePixel,
- FilterInterpolatePixel,
- IntegerInterpolatePixel,
- MeshInterpolatePixel,
- NearestNeighborInterpolatePixel,
- SplineInterpolatePixel
+ AverageInterpolatePixel, /* Average 4 nearest neighbours */
+ Average9InterpolatePixel, /* Average 9 nearest neighbours */
+ Average16InterpolatePixel, /* Average 16 nearest neighbours */
+ BackgroundInterpolatePixel, /* Just return background color */
+ BilinearInterpolatePixel, /* Triangular filter interpolation */
+ BlendInterpolatePixel, /* blend of nearest 1, 2 or 4 pixels */
+ CatromInterpolatePixel, /* Catmull-Rom interpolation */
+ IntegerInterpolatePixel, /* Integer (floor) interpolation */
+ MeshInterpolatePixel, /* Triangular Mesh interpolation */
+ NearestInterpolatePixel, /* Nearest Neighbour Only */
+ SplineInterpolatePixel, /* Cubic Spline (blurred) interpolation */
+ /* FilterInterpolatePixel, ** Use resize filter - (very slow) */
} PixelInterpolateMethod;
typedef enum
diff --git a/MagickCore/resample.h b/MagickCore/resample.h
index 7701612..89316bf 100644
--- a/MagickCore/resample.h
+++ b/MagickCore/resample.h
@@ -26,7 +26,7 @@
/*
WARNING: The order of this table must also match the order of a table
- located in AcquireResizeFilter() or "resize.c" otherwise the users filter
+ located in AcquireResizeFilter() in "resize.c" otherwise the users filter
will not match the actual filter that is setup.
*/
typedef enum
@@ -60,6 +60,7 @@
RobidouxFilter,
RobidouxSharpFilter,
CosineFilter,
+ SplineFilter,
SentinelFilter /* a count of all the filters, not a real filter */
} FilterTypes;
diff --git a/MagickCore/resize.c b/MagickCore/resize.c
index fe71d2a..aa6fc1d 100644
--- a/MagickCore/resize.c
+++ b/MagickCore/resize.c
@@ -91,7 +91,7 @@
window_support, /* window support, usally equal to support (expert only) */
scale, /* dimension scaling to fit window support (usally 1.0) */
blur, /* x-scale (blur-sharpen) */
- coefficient[7]; /* cubic coefficents for BC-cubic spline filters */
+ coefficient[7]; /* cubic coefficents for BC-cubic filters */
size_t
signature;
@@ -197,8 +197,8 @@
Cubic Filters using B,C determined values:
Mitchell-Netravali B = 1/3 C = 1/3 "Balanced" cubic spline filter
Catmull-Rom B = 0 C = 1/2 Interpolatory and exact on linears
- Cubic B-Spline B = 1 C = 0 Spline approximation of Gaussian
- Hermite B = 0 C = 0 Spline with small support (= 1)
+ Spline B = 1 C = 0 B-Spline Gaussian approximation
+ Hermite B = 0 C = 0 B-Spline interpolator
See paper by Mitchell and Netravali, Reconstruction Filters in Computer
Graphics Computer Graphics, Volume 22, Number 4, August 1988
@@ -520,7 +520,7 @@
%
% FIR (Finite impulse Response) Filters
% Box Triangle Quadratic
-% Cubic Hermite Catrom
+% Spline Hermite Catrom
% Mitchell
%
% IIR (Infinite impulse Response) Filters
@@ -530,8 +530,8 @@
% Blackman Hanning Hamming
% Kaiser Lanczos
%
-% Special purpose Filters
-% SincFast LanczosSharp Lanczos2 Lanczos2Sharp
+% Special Purpose Filters
+% Cubic SincFast LanczosSharp Lanczos2 Lanczos2Sharp
% Robidoux RobidouxSharp
%
% The users "-filter" selection is used to lookup the default 'expert'
@@ -651,7 +651,7 @@
% using it for Distort.
%
% "filter:b"
-% "filter:c" Override the preset B,C values for a Cubic type of filter.
+% "filter:c" Override the preset B,C values for a Cubic filter.
% If only one of these are given it is assumes to be a 'Keys' type of
% filter such that B+2C=1, where Keys 'alpha' value = C.
%
@@ -737,7 +737,7 @@
{ SincFastFilter, BlackmanFilter }, /* Blackman -- 2*cosine-sinc */
{ GaussianFilter, BoxFilter }, /* Gaussian blur filter */
{ QuadraticFilter, BoxFilter }, /* Quadratic Gaussian approx */
- { CubicFilter, BoxFilter }, /* Cubic B-Spline */
+ { CubicFilter, BoxFilter }, /* General Cubic Filter, Spline */
{ CatromFilter, BoxFilter }, /* Cubic-Keys interpolator */
{ MitchellFilter, BoxFilter }, /* 'Ideal' Cubic-Keys filter */
{ JincFilter, BoxFilter }, /* Raw 3-lobed Jinc function */
@@ -756,6 +756,7 @@
{ RobidouxFilter, BoxFilter }, /* Cubic Keys tuned for EWA */
{ RobidouxSharpFilter, BoxFilter }, /* Sharper Cubic Keys for EWA */
{ SincFastFilter, CosineFilter }, /* low level cosine window */
+ { SplineFilter, BoxFilter }, /* Spline Cubic Filter */
};
/*
Table mapping the filter/window from the above table to an actual function.
@@ -793,7 +794,7 @@
{ Blackman, 1.0, 1.0, 0.0, 0.0 }, /* Blackman, 2*cosine window */
{ Gaussian, 2.0, 1.5, 0.0, 0.0 }, /* Gaussian */
{ Quadratic, 1.5, 1.5, 0.0, 0.0 }, /* Quadratic gaussian */
- { CubicBC, 2.0, 2.0, 1.0, 0.0 }, /* Cubic B-Spline (B=1,C=0) */
+ { CubicBC, 2.0, 2.0, 1.0, 0.0 }, /* General Cubic Filter */
{ CubicBC, 2.0, 1.0, 0.0, 0.5 }, /* Catmull-Rom (B=0,C=1/2) */
{ CubicBC, 2.0, 8.0/7.0, 1./3., 1./3. }, /* Mitchell (B=C=1/3) */
{ Jinc, 3.0, 1.2196698912665045, 0.0, 0.0 }, /* Raw 3-lobed Jinc */
@@ -815,7 +816,8 @@
/* RobidouxSharp: Sharper version of Robidoux */
{ CubicBC, 2.0, 1.105822933719019,
0.2620145123990142, 0.3689927438004929 },
- { Cosine, 1.0, 1.0, 0.0, 0.0 } /* Low level cosine window */
+ { Cosine, 1.0, 1.0, 0.0, 0.0 }, /* Low level cosine window */
+ { CubicBC, 2.0, 2.0, 1.0, 0.0 }, /* Cubic B-Spline (B=1,C=0) */
};
/*
The known zero crossings of the Jinc() or more accurately the Jinc(x*PI)
@@ -1182,7 +1184,7 @@
% 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:
%
@@ -1198,12 +1200,8 @@
MagickExport Image *AdaptiveResizeImage(const Image *image,
const size_t columns,const size_t rows,ExceptionInfo *exception)
{
- Image
- *resize_image;
-
- resize_image=InterpolativeResizeImage(image,columns,rows,MeshInterpolatePixel,
- exception);
- return(resize_image);
+ return(InterpolativeResizeImage(image,columns,rows,MeshInterpolatePixel,
+ exception));
}
/*
@@ -1951,7 +1949,7 @@
(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,
+ magnify_image=ResizeImage(image,2*image->columns,2*image->rows,SplineFilter,
exception);
return(magnify_image);
}
@@ -1992,7 +1990,7 @@
(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,
+ minify_image=ResizeImage(image,image->columns/2,image->rows/2,SplineFilter,
exception);
return(minify_image);
}