Initial porting of new interpolations and resize spline, from IMv6 to IMv7
Not quite finished with spline, blend, and background
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;