]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/pixel.c
(no commit message)
[imagemagick] / MagickCore / pixel.c
index 8381500b95931392a548b6e242af0123bb29fa76..a30d4facea50a1282fe801c7edeab1c33574c5bb 100644 (file)
@@ -2006,7 +2006,7 @@ MagickExport void GetPixelInfo(const Image *image,PixelInfo *pixel)
 {
   pixel->storage_class=DirectClass;
   pixel->colorspace=sRGBColorspace;
-  pixel->matte=MagickFalse;
+  pixel->alpha_trait=UndefinedPixelTrait;
   pixel->fuzz=0.0;
   pixel->depth=MAGICKCORE_QUANTUM_DEPTH;
   pixel->red=0.0;
@@ -2019,7 +2019,7 @@ MagickExport void GetPixelInfo(const Image *image,PixelInfo *pixel)
     return;
   pixel->storage_class=image->storage_class;
   pixel->colorspace=image->colorspace;
-  pixel->matte=image->matte;
+  pixel->alpha_trait=image->alpha_trait;
   pixel->depth=image->depth;
   pixel->fuzz=image->fuzz;
 }
@@ -3736,7 +3736,7 @@ MagickExport MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
       case 'A':
       {
         quantum_map[i]=AlphaQuantum;
-        image->matte=MagickTrue;
+        image->alpha_trait=BlendPixelTrait;
         break;
       }
       case 'B':
@@ -3783,7 +3783,7 @@ MagickExport MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
       case 'o':
       {
         quantum_map[i]=OpacityQuantum;
-        image->matte=MagickTrue;
+        image->alpha_trait=BlendPixelTrait;
         break;
       }
       case 'P':
@@ -3910,7 +3910,7 @@ MagickExport void InitializePixelChannelMap(Image *image)
   (void) ResetMagickMemory(image->channel_map,0,MaxPixelChannels*
     sizeof(*image->channel_map));
   trait=UpdatePixelTrait;
-  if (image->matte != MagickFalse)
+  if (image->alpha_trait == BlendPixelTrait)
     trait=(PixelTrait) (trait | BlendPixelTrait);
   n=0;
   if (image->colorspace == GRAYColorspace)
@@ -3927,7 +3927,7 @@ MagickExport void InitializePixelChannelMap(Image *image)
     }
   if (image->colorspace == CMYKColorspace)
     SetPixelChannelAttributes(image,BlackPixelChannel,trait,n++);
-  if (image->matte != MagickFalse)
+  if (image->alpha_trait != UndefinedPixelTrait)
     SetPixelChannelAttributes(image,AlphaPixelChannel,CopyPixelTrait,n++);
   if (image->storage_class == PseudoClass)
     SetPixelChannelAttributes(image,IndexPixelChannel,CopyPixelTrait,n++);
@@ -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
@@ -4988,7 +5096,7 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
 static inline void AlphaBlendPixelInfo(const Image *image,
   const Quantum *pixel,PixelInfo *pixel_info,double *alpha)
 {
-  if (image->matte == MagickFalse)
+  if (image->alpha_trait != BlendPixelTrait)
     {
       *alpha=1.0;
       pixel_info->red=(double) GetPixelRed(image,pixel);
@@ -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;
@@ -5544,7 +5652,7 @@ MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
     destination->fuzz,(double) MagickSQ1_2);
   scale=1.0;
   distance=0.0;
-  if (source->matte != MagickFalse)
+  if (source->alpha_trait == BlendPixelTrait)
     {
       /*
         Transparencies are involved - set alpha distance
@@ -5663,13 +5771,13 @@ MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
       (double) MagickSQ1_2);
   scale=1.0;
   distance=0.0;
-  if ((p->matte != MagickFalse) || (q->matte != MagickFalse))
+  if ((p->alpha_trait == BlendPixelTrait) || (q->alpha_trait == BlendPixelTrait))
     {
       /*
         Transparencies are involved - set alpha distance.
       */
-      pixel=(p->matte != MagickFalse ? p->alpha : OpaqueAlpha)-
-        (q->matte != MagickFalse ? q->alpha : OpaqueAlpha);
+      pixel=(p->alpha_trait == BlendPixelTrait ? p->alpha : OpaqueAlpha)-
+        (q->alpha_trait == BlendPixelTrait ? q->alpha : OpaqueAlpha);
       distance=pixel*pixel;
       if (distance > fuzz)
         return(MagickFalse);
@@ -5677,9 +5785,9 @@ MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
         Generate a alpha scaling factor to generate a 4D cone on colorspace.
         If one color is transparent, distance has no color component.
       */
-      if (p->matte != MagickFalse)
+      if (p->alpha_trait == BlendPixelTrait)
         scale=(QuantumScale*p->alpha);
-      if (q->matte != MagickFalse)
+      if (q->alpha_trait == BlendPixelTrait)
         scale*=(QuantumScale*q->alpha);
       if (scale <= MagickEpsilon )
         return(MagickTrue);
@@ -5773,8 +5881,8 @@ MagickExport void SetPixelChannelMask(Image *image,
     channel=GetPixelChannelChannel(image,i);
     SetPixelChannelTraits(image,channel,
       GetChannelBit(channel_mask,channel) == 0 ? CopyPixelTrait :
-      image->matte == MagickFalse || (channel == AlphaPixelChannel) ?
-      UpdatePixelTrait : (PixelTrait) (UpdatePixelTrait | BlendPixelTrait));
+      image->alpha_trait != BlendPixelTrait || (channel == AlphaPixelChannel) ?
+      UpdatePixelTrait : (PixelTrait) (UpdatePixelTrait | image->alpha_trait));
   }
   if (image->storage_class == PseudoClass)
     SetPixelChannelTraits(image,IndexPixelChannel,CopyPixelTrait);