]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/pixel.c
(no commit message)
[imagemagick] / MagickCore / pixel.c
index a1856c49b914ef0b24a3625e02bc528cb9b41ad8..a30d4facea50a1282fe801c7edeab1c33574c5bb 100644 (file)
@@ -3992,38 +3992,39 @@ static inline double MagickMax(const double x,const double y)
   return(y);
 }
 
-static inline void CatromWeights(const double x,
-  double (*weights)[4])
+static inline void CatromWeights(const double x,double (*weights)[4])
 {
-  /*
-    Nicolas Robidoux' 10 flops (4* + 5- + 1+) refactoring of the
-    computation of the standard four 1D Catmull-Rom weights. The
-    sampling location is assumed between the second and third input
-    pixel locations, and x is the position relative to the second
-    input pixel location. Formulas originally derived for the VIPS
-    (Virtual Image Processing System) library.
-  */
   double
     alpha,
     beta,
     gamma;
 
+  /*
+    Nicolas Robidoux' 10 flops (4* + 5- + 1+) refactoring of the computation
+    of the standard four 1D Catmull-Rom weights. The sampling location is
+    assumed between the second and third input pixel locations, and x is the
+    position relative to the second input pixel location. Formulas originally
+    derived for the VIPS (Virtual Image Processing System) library.
+  */
   alpha=(double) 1.0-x;
   beta=(double) (-0.5)*x*alpha;
   (*weights)[0]=alpha*beta;
   (*weights)[3]=x*beta;
   /*
-    The following computation of the inner weights from the outer ones
-    works for all Keys cubics.
+    The following computation of the inner weights from the outer ones work
+    for all Keys cubics.
   */
   gamma=(*weights)[3]-(*weights)[0];
   (*weights)[1]=alpha-(*weights)[0]+gamma;
   (*weights)[2]=x-(*weights)[3]-gamma;
 }
 
-static inline void SplineWeights(const double x,
-  double (*weights)[4])
+static inline void SplineWeights(const double x,double (*weights)[4])
 {
+  double
+    alpha,
+    beta;
+
   /*
     Nicolas Robidoux' 12 flops (6* + 5- + 1+) refactoring of the
     computation of the standard four 1D cubic B-spline smoothing
@@ -4031,10 +4032,6 @@ static inline void SplineWeights(const double x,
     third input pixel locations, and x is the position relative to the
     second input pixel location.
   */
-  double
-    alpha,
-    beta;
-
   alpha=(double) 1.0-x;
   (*weights)[3]=(double) (1.0/6.0)*x*x*x;
   (*weights)[0]=(double) (1.0/6.0)*alpha*alpha*alpha;
@@ -4186,6 +4183,55 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
         (epsilon.x*pixels[2]+delta.x*pixels[3]));
       break;
     }
+    case BlendInterpolatePixel:
+    {
+      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];
+        }
+      gamma=1.0;    /* number of pixels blended together (its variable) */
+      for (i=0; i <= 1L; i++) {
+        if ( y-y_offset >= 0.75 ) { /* take right pixels */
+          alpha[i]  = alpha[i+2];
+          pixels[i] = pixels[i+2];
+        }
+        else if ( y-y_offset > 0.25 ) {
+          gamma = 2.0;              /* blend both pixels in row */
+          alpha[i]  += alpha[i+2];  /* add up alpha weights */
+          pixels[i] += pixels[i+2];
+        }
+      }
+      if ( x-x_offset >= 0.75 ) {   /* take bottom row blend */
+        alpha[0]  = alpha[1];
+        pixels[0] = pixels[1];
+      }
+      else if ( x-x_offset > 0.25 ) {
+        gamma *= 2.0;               /* blend both rows */
+        alpha[0]  += alpha[1];      /* add up alpha weights */
+        pixels[0] += pixels[1];
+      }
+      if (channel != AlphaPixelChannel)
+        gamma=MagickEpsilonReciprocal(alpha[0]); /* (color) 1/alpha_weights */
+      else
+        gamma=MagickEpsilonReciprocal(gamma); /* (alpha) 1/number_of_pixels */
+      *pixel=gamma*pixels[0];
+      break;
+    }
     case CatromInterpolatePixel:
     {
       double
@@ -4633,6 +4679,68 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
       }
       break;
     }
+    case BlendInterpolatePixel:
+    {
+      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++)
+      {
+        register ssize_t
+          j;
+
+        channel=GetPixelChannelChannel(source,i);
+        traits=GetPixelChannelTraits(source,channel);
+        destination_traits=GetPixelChannelTraits(destination,channel);
+        if ((traits == UndefinedPixelTrait) ||
+            (destination_traits == UndefinedPixelTrait))
+          continue;
+        if ((traits & BlendPixelTrait) == 0)
+          for (j=0; j < 4; j++)
+          {
+            alpha[j]=1.0;
+            pixels[j]=(MagickRealType) p[j*GetPixelChannels(source)+channel];
+          }
+        else
+          for (j=0; j < 4; j++)
+          {
+            alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
+              GetPixelChannels(source));
+            pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+channel];
+          }
+        gamma=1.0;    /* number of pixels blended together (its variable) */
+        for (j=0; j <= 1L; j++) {
+          if ( y-y_offset >= 0.75 ) { /* take right pixels */
+            alpha[j]  = alpha[j+2];
+            pixels[j] = pixels[j+2];
+          }
+          else if ( y-y_offset > 0.25 ) {
+            gamma = 2.0;              /* blend both pixels in row */
+            alpha[j]  += alpha[j+2];  /* add up alpha weights */
+            pixels[j] += pixels[j+2];
+          }
+        }
+        if ( x-x_offset >= 0.75 ) {   /* take bottom row blend */
+          alpha[0]  = alpha[1];
+          pixels[0] = pixels[1];
+        }
+        else if ( x-x_offset > 0.25 ) {
+          gamma *= 2.0;               /* blend both rows */
+          alpha[0]  += alpha[1];      /* add up alpha weights */
+          pixels[0] += pixels[1];
+        }
+        if ((traits & BlendPixelTrait) == 0)
+          gamma=MagickEpsilonReciprocal(alpha[0]); /* (color) 1/alpha_weights */
+        else
+          gamma=MagickEpsilonReciprocal(gamma); /* (alpha) 1/number_of_pixels */
+        SetPixelChannel(destination,channel,ClampToQuantum(gamma*pixels[0]),
+             pixel);
+      }
+      break;
+    }
     case CatromInterpolatePixel:
     {
       double
@@ -5155,14 +5263,14 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
         }
       for (i=0; i < 4L; i++)
         AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
-      gamma=1.0;       /* number of pixels blended together */
+      gamma=1.0;    /* number of pixels blended together (its variable) */
       for (i=0; i <= 1L; i++) {
-        if ( y-y_offset >= 0.75 ) {
+        if ( y-y_offset >= 0.75 ) {       /* take right pixels */
           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 */
+          gamma = 2.0;                    /* blend both pixels in row */
           alpha[i]        += alpha[i+2];  /* add up alpha weights */
           pixels[i].red   += pixels[i+2].red;
           pixels[i].green += pixels[i+2].green;
@@ -5176,8 +5284,8 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
         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 */
+        gamma *= 2.0;                     /* blend both rows */
+        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;