]> granicus.if.org Git - imagemagick/commitdiff
(no commit message)
authorcristy <urban-warrior@git.imagemagick.org>
Sun, 31 Jul 2011 00:51:45 +0000 (00:51 +0000)
committercristy <urban-warrior@git.imagemagick.org>
Sun, 31 Jul 2011 00:51:45 +0000 (00:51 +0000)
MagickCore/pixel.c
MagickCore/resize.c

index 32d700bc24744a608c92e514af280093e53b795b..304a5dd6b40e14fa3a677ecc0a66001f5f57d0bc 100644 (file)
@@ -3573,10 +3573,9 @@ MagickExport MagickBooleanType ImportImagePixels(Image *image,
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  InterpolatePixelChannel() applies bi-linear or tri-linear interpolation
-%  between a floating point coordinate and the pixels surrounding that
-%  coordinate.  No pixel area resampling, or scaling of the result is
-%  performed.
+%  InterpolatePixelChannel() applies a pixel interpolation method between a
+%  floating point coordinate and the pixels surrounding that coordinate.  No
+%  pixel area resampling, or scaling of the result is performed.
 %
 %  The format of the InterpolatePixelChannel method is:
 %
@@ -3603,12 +3602,43 @@ MagickExport MagickBooleanType ImportImagePixels(Image *image,
 %
 */
 
+static inline double MagickMax(const MagickRealType x,const MagickRealType y)
+{
+  if (x > y)
+    return(x);
+  return(y);
+}
+
+static inline MagickRealType CubicWeightingFunction(const MagickRealType x)
+{
+  MagickRealType
+    alpha,
+    gamma;
+
+  alpha=MagickMax(x+2.0,0.0);
+  gamma=1.0*alpha*alpha*alpha;
+  alpha=MagickMax(x+1.0,0.0);
+  gamma-=4.0*alpha*alpha*alpha;
+  alpha=MagickMax(x+0.0,0.0);
+  gamma+=6.0*alpha*alpha*alpha;
+  alpha=MagickMax(x-1.0,0.0);
+  gamma-=4.0*alpha*alpha*alpha;
+  return(gamma/6.0);
+}
+
 static inline double MeshInterpolate(const PointInfo *delta,const double p,
   const double x,const double y)
 {
   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,
   const InterpolatePixelMethod method,const double x,const double y,
@@ -3619,14 +3649,12 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
 
   MagickRealType
     alpha[16],
-    gamma;
+    gamma,
+    pixels[16];
 
   PixelTrait
     traits;
 
-  Quantum
-    pixels[16];
-
   register const Quantum
     *p;
 
@@ -3642,20 +3670,99 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
   assert(image->signature == MagickSignature);
   assert(image_view != (CacheView *) NULL);
   status=MagickTrue;
-  *pixel=0;
+  *pixel=0.0;
   traits=GetPixelChannelMapTraits(image,channel);
-  if (traits == UndefinedPixelTrait)
-    return(MagickTrue);
   x_offset=(ssize_t) floor(x);
   y_offset=(ssize_t) floor(y);
   switch (method == UndefinedInterpolatePixel ? image->interpolate : method)
   {
-    case MeshInterpolatePixel:
+    case AverageInterpolatePixel:
+    {
+      p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
+        exception);
+      if (p == (const Quantum *) NULL)
+        {
+          status=MagickFalse;
+          break;
+        }
+      if (((traits & BlendPixelTrait) == 0) ||
+          (GetPixelAlphaTraits(image) == UndefinedPixelTrait) ||
+          (image->matte == MagickFalse))
+        for (i=0; i < 16; i++)
+        {
+          alpha[i]=1.0;
+          pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
+        }
+      else
+        for (i=0; i < 16; 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++)
+      {
+        gamma=1.0/(fabs((double) alpha[i]) <= MagickEpsilon ? 1.0 : alpha[i]);
+        *pixel+=gamma*0.0625*pixels[i];
+      }
+      break;
+    }
+    case BicubicInterpolatePixel:
+    {
+      MagickRealType
+        u[4],
+        v[4];
+
+      PointInfo
+        delta;
+
+      p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
+        exception);
+      if (p == (const Quantum *) NULL)
+        {
+          status=MagickFalse;
+          break;
+        }
+      if (((traits & BlendPixelTrait) == 0) ||
+          (GetPixelAlphaTraits(image) == UndefinedPixelTrait) ||
+          (image->matte == MagickFalse))
+        for (i=0; i < 16; i++)
+        {
+          alpha[i]=1.0;
+          pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
+        }
+      else
+        for (i=0; i < 16; 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;
+      for (i=0; i < 4; i++)
+      {
+        u[0]=(pixels[4*i+3]-pixels[4*i+2])-(pixels[4*i+0]-pixels[4*i+1]);
+        u[1]=(pixels[4*i+0]-pixels[4*i+1])-u[0];
+        u[2]=pixels[4*i+2]-pixels[4*i+0];
+        u[3]=pixels[4*i+1];
+        v[i]=(delta.x*delta.x*delta.x*u[0])+(delta.x*delta.x*u[1])+(delta.x*
+          u[2])+u[3];
+      }
+      u[0]=(v[3]-v[2])-(v[0]-v[1]);
+      u[1]=(v[0]-v[1])-u[0];
+      u[2]=v[2]-v[0];
+      u[3]=v[1];
+      *pixel=(delta.y*delta.y*delta.y*u[0])+(delta.y*delta.y*u[1])+(delta.y*
+        u[2])+u[3];
+      break;
+    }
+    case BilinearInterpolatePixel:
     default:
     {
       PointInfo
         delta,
-        luminance;
+        epsilon;
 
       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
       if (p == (const Quantum *) NULL)
@@ -3663,19 +3770,111 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
           status=MagickFalse;
           break;
         }
+      if (((traits & BlendPixelTrait) == 0) ||
+          (GetPixelAlphaTraits(image) == UndefinedPixelTrait) ||
+          (image->matte == MagickFalse))
+        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;
-      luminance.x=GetPixelLuminance(image,p+0*GetPixelChannels(image))-(double)
-        GetPixelLuminance(image,p+3*GetPixelChannels(image));
-      luminance.y=GetPixelLuminance(image,p+1*GetPixelChannels(image))-(double)
-        GetPixelLuminance(image,p+2*GetPixelChannels(image));
+      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=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : 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 FilterInterpolatePixel:
+    {
+      CacheView
+        *filter_view;
+
+      Image
+        *excerpt_image,
+        *filter_image;
+
+      RectangleInfo
+        geometry;
+
+      geometry.width=4L;
+      geometry.height=4L;
+      geometry.x=x_offset-1;
+      geometry.y=y_offset-1;
+      excerpt_image=ExcerptImage(image,&geometry,exception);
+      if (excerpt_image == (Image *) NULL)
+        {
+          status=MagickFalse;
+          break;
+        }
+      filter_image=ResizeImage(excerpt_image,1,1,image->filter,image->blur,
+        exception);
+      excerpt_image=DestroyImage(excerpt_image);
+      if (filter_image == (Image *) NULL)
+        break;
+      filter_view=AcquireCacheView(filter_image);
+      p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
+      if (p == (const Quantum *) NULL)
+        status=MagickFalse;
+      else
+        *pixel=(double) p[channel];
+      filter_view=DestroyCacheView(filter_view);
+      filter_image=DestroyImage(filter_image);
+      break;
+    }
+    case IntegerInterpolatePixel:
+    {
+      p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
+      if (p == (const Quantum *) NULL)
+        {
+          status=MagickFalse;
+          break;
+        }
+      *pixel=(double) p[channel];
+      break;
+    }
+    case NearestNeighborInterpolatePixel:
+    {
+      p=GetCacheViewVirtualPixels(image_view,NearestNeighbor(x),
+        NearestNeighbor(y),1,1,exception);
+      if (p == (const Quantum *) NULL)
+        {
+          status=MagickFalse;
+          break;
+        }
+      *pixel=(double) p[channel];
+      break;
+    }
+    case MeshInterpolatePixel:
+    {
+      PointInfo
+        delta,
+        luminance;
+
+      p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
+      if (p == (const Quantum *) NULL)
+        {
+          status=MagickFalse;
+          break;
+        }
       if (((traits & BlendPixelTrait) == 0) ||
           (GetPixelAlphaTraits(image) == UndefinedPixelTrait) ||
           (image->matte == MagickFalse))
         for (i=0; i < 4; i++)
         {
           alpha[i]=1.0;
-          pixels[i]=p[i*GetPixelChannels(image)+channel];
+          pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
         }
       else
         for (i=0; i < 4; i++)
@@ -3684,6 +3883,12 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
             GetPixelChannels(image));
           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
         }
+      delta.x=x-x_offset;
+      delta.y=y-y_offset;
+      luminance.x=GetPixelLuminance(image,p)-(double)
+        GetPixelLuminance(image,p+3*GetPixelChannels(image));
+      luminance.y=GetPixelLuminance(image,p+1*GetPixelChannels(image))-(double)
+        GetPixelLuminance(image,p+2*GetPixelChannels(image));
       if (fabs(luminance.x) < fabs(luminance.y))
         {
           /*
@@ -3742,6 +3947,57 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
         }
       break;
     }
+    case SplineInterpolatePixel:
+    {
+      MagickRealType
+        dx,
+        dy;
+
+      PointInfo
+        delta;
+
+      ssize_t
+        j,
+        n;
+
+      p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
+        exception);
+      if (p == (const Quantum *) NULL)
+        {
+          status=MagickFalse;
+          break;
+        }
+      if (((traits & BlendPixelTrait) == 0) ||
+          (GetPixelAlphaTraits(image) == UndefinedPixelTrait) ||
+          (image->matte == MagickFalse))
+        for (i=0; i < 16; i++)
+        {
+          alpha[i]=1.0;
+          pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
+        }
+      else
+        for (i=0; i < 16; 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;
+      n=0;
+      for (i=(-1); i < 3L; i++)
+      {
+        dy=CubicWeightingFunction((MagickRealType) i-delta.y);
+        for (j=(-1); j < 3L; j++)
+        {
+          dx=CubicWeightingFunction(delta.x-(MagickRealType) j);
+          gamma=1.0/(fabs((double) alpha[n]) <= MagickEpsilon ? 1.0 : alpha[n]);
+          *pixel+=gamma*dx*dy*pixels[n];
+          n++;
+        }
+      }
+      break;
+    }
   }
   return(status);
 }
@@ -3757,10 +4013,9 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  InterpolatePixelInfo() applies bi-linear or tri-linear interpolation
-%  between a floating point coordinate and the pixels surrounding that
-%  coordinate.  No pixel area resampling, or scaling of the result is
-%  performed.
+%  InterpolatePixelInfo() applies a pixel interpolation method between a
+%  floating point coordinate and the pixels surrounding that coordinate.  No
+%  pixel area resampling, or scaling of the result is performed.
 %
 %  The format of the InterpolatePixelInfo method is:
 %
@@ -3851,37 +4106,6 @@ static void BicubicInterpolate(const PixelInfo *pixels,const double dx,
     }
 }
 
-static inline double MagickMax(const MagickRealType x,const MagickRealType y)
-{
-  if (x > y)
-    return(x);
-  return(y);
-}
-
-static inline MagickRealType CubicWeightingFunction(const MagickRealType x)
-{
-  MagickRealType
-    alpha,
-    gamma;
-
-  alpha=MagickMax(x+2.0,0.0);
-  gamma=1.0*alpha*alpha*alpha;
-  alpha=MagickMax(x+1.0,0.0);
-  gamma-=4.0*alpha*alpha*alpha;
-  alpha=MagickMax(x+0.0,0.0);
-  gamma+=6.0*alpha*alpha*alpha;
-  alpha=MagickMax(x-1.0,0.0);
-  gamma-=4.0*alpha*alpha*alpha;
-  return(gamma/6.0);
-}
-
-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 InterpolatePixelInfo(const Image *image,
   const CacheView *image_view,const InterpolatePixelMethod method,
   const double x,const double y,PixelInfo *pixel,ExceptionInfo *exception)
@@ -4042,6 +4266,8 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
         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=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : 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));
@@ -4107,7 +4333,7 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
         }
       delta.x=x-x_offset;
       delta.y=y-y_offset;
-      luminance.x=GetPixelLuminance(image,p+0*GetPixelChannels(image))-(double)
+      luminance.x=GetPixelLuminance(image,p)-(double)
         GetPixelLuminance(image,p+3*GetPixelChannels(image));
       luminance.y=GetPixelLuminance(image,p+1*GetPixelChannels(image))-(double)
         GetPixelLuminance(image,p+2*GetPixelChannels(image));
index 157a51cfc63d811c98a98d434fb37774a3494a1c..da094a8290a43c948ea6621c3a65f7f10f0c4cae 100644 (file)
@@ -1227,7 +1227,7 @@ MagickExport Image *AdaptiveResizeImage(const Image *image,
     offset.y=((MagickRealType) (y+0.5)*image->rows/resize_image->rows);
     for (x=0; x < (ssize_t) resize_image->columns; x++)
     {
-      register PixelChannel
+      register ssize_t
         i;
 
       offset.x=((MagickRealType) (x+0.5)*image->columns/resize_image->columns);