]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/quantize.c
(no commit message)
[imagemagick] / MagickCore / quantize.c
index 6069c3c284fe1e6564896ad4366879ebc5de9ca3..f98e8aaa29cfcf865a340045243ef7d5cdbe5551 100644 (file)
 #include "MagickCore/monitor-private.h"
 #include "MagickCore/option.h"
 #include "MagickCore/pixel-accessor.h"
+#include "MagickCore/pixel-private.h"
 #include "MagickCore/quantize.h"
 #include "MagickCore/quantum.h"
 #include "MagickCore/quantum-private.h"
+#include "MagickCore/resource_.h"
 #include "MagickCore/string_.h"
 #include "MagickCore/thread-private.h"
 \f
 */
 typedef struct _RealPixelInfo
 {
-  MagickRealType
+  double
     red,
     green,
     blue,
@@ -237,7 +239,7 @@ typedef struct _NodeInfo
   RealPixelInfo
     total_color;
 
-  MagickRealType
+  double
     quantize_error;
 
   size_t
@@ -273,7 +275,7 @@ typedef struct _CubeInfo
   RealPixelInfo
     target;
 
-  MagickRealType
+  double
     distance,
     pruning_threshold,
     next_threshold;
@@ -295,7 +297,7 @@ typedef struct _CubeInfo
   RealPixelInfo
     error[ErrorQueueLength];
 
-  MagickRealType
+  double
     weights[ErrorQueueLength];
 
   QuantizeInfo
@@ -379,7 +381,8 @@ MagickExport QuantizeInfo *AcquireQuantizeInfo(const ImageInfo *image_info)
       const char
         *option;
 
-      quantize_info->dither=image_info->dither;
+      quantize_info->dither_method=image_info->dither == MagickFalse ?
+        NoDitherMethod : RiemersmaDitherMethod;
       option=GetImageOption(image_info,"dither");
       if (option != (const char *) NULL)
         quantize_info->dither_method=(DitherMethod) ParseCommandOption(
@@ -432,54 +435,54 @@ MagickExport QuantizeInfo *AcquireQuantizeInfo(const ImageInfo *image_info)
 static inline void AssociateAlphaPixel(const Image *image,
   const CubeInfo *cube_info,const Quantum *pixel,RealPixelInfo *alpha_pixel)
 {
-  MagickRealType
+  double
     alpha;
 
   if ((cube_info->associate_alpha == MagickFalse) ||
       (GetPixelAlpha(image,pixel)== OpaqueAlpha))
     {
-      alpha_pixel->red=(MagickRealType) GetPixelRed(image,pixel);
-      alpha_pixel->green=(MagickRealType) GetPixelGreen(image,pixel);
-      alpha_pixel->blue=(MagickRealType) GetPixelBlue(image,pixel);
-      alpha_pixel->alpha=(MagickRealType) GetPixelAlpha(image,pixel);
+      alpha_pixel->red=(double) GetPixelRed(image,pixel);
+      alpha_pixel->green=(double) GetPixelGreen(image,pixel);
+      alpha_pixel->blue=(double) GetPixelBlue(image,pixel);
+      alpha_pixel->alpha=(double) GetPixelAlpha(image,pixel);
       return;
     }
-  alpha=(MagickRealType) (QuantumScale*GetPixelAlpha(image,pixel));
+  alpha=(double) (QuantumScale*GetPixelAlpha(image,pixel));
   alpha_pixel->red=alpha*GetPixelRed(image,pixel);
   alpha_pixel->green=alpha*GetPixelGreen(image,pixel);
   alpha_pixel->blue=alpha*GetPixelBlue(image,pixel);
-  alpha_pixel->alpha=(MagickRealType) GetPixelAlpha(image,pixel);
+  alpha_pixel->alpha=(double) GetPixelAlpha(image,pixel);
 }
 
 static inline void AssociateAlphaPixelInfo(const Image *image,
   const CubeInfo *cube_info,const PixelInfo *pixel,
   RealPixelInfo *alpha_pixel)
 {
-  MagickRealType
+  double
     alpha;
 
   if ((cube_info->associate_alpha == MagickFalse) ||
       (pixel->alpha == OpaqueAlpha))
     {
-      alpha_pixel->red=(MagickRealType) pixel->red;
-      alpha_pixel->green=(MagickRealType) pixel->green;
-      alpha_pixel->blue=(MagickRealType) pixel->blue;
-      alpha_pixel->alpha=(MagickRealType) pixel->alpha;
+      alpha_pixel->red=(double) pixel->red;
+      alpha_pixel->green=(double) pixel->green;
+      alpha_pixel->blue=(double) pixel->blue;
+      alpha_pixel->alpha=(double) pixel->alpha;
       return;
     }
-  alpha=(MagickRealType) (QuantumScale*pixel->alpha);
+  alpha=(double) (QuantumScale*pixel->alpha);
   alpha_pixel->red=alpha*pixel->red;
   alpha_pixel->green=alpha*pixel->green;
   alpha_pixel->blue=alpha*pixel->blue;
-  alpha_pixel->alpha=(MagickRealType) pixel->alpha;
+  alpha_pixel->alpha=(double) pixel->alpha;
 }
 
-static inline Quantum ClampToUnsignedQuantum(const MagickRealType value)
+static inline Quantum ClampToUnsignedQuantum(const double value)
 {
   if (value <= 0.0)
     return((Quantum) 0);
   if (value >= QuantumRange)
-    return((Quantum) QuantumRange);
+    return(QuantumRange);
   return((Quantum) (value+0.5));
 }
 
@@ -513,9 +516,7 @@ static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info,
     (void) TransformImageColorspace((Image *) image,
       cube_info->quantize_info->colorspace,exception);
   else
-    if ((image->colorspace != GRAYColorspace) &&
-        (IsRGBColorspace(image->colorspace) == MagickFalse) &&
-        (image->colorspace != CMYColorspace))
+    if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
       (void) TransformImageColorspace((Image *) image,sRGBColorspace,exception);
   if (AcquireImageColormap(image,cube_info->colors,exception) == MagickFalse)
     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
@@ -527,7 +528,7 @@ static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info,
   /*
     Create a reduced color image.
   */
-  if ((cube_info->quantize_info->dither != MagickFalse) &&
+  if ((cube_info->quantize_info->dither_method != NoDitherMethod) &&
       (cube_info->quantize_info->dither_method != NoDitherMethod))
     (void) DitherImage(image,cube_info,exception);
   else
@@ -535,16 +536,14 @@ static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info,
       CacheView
         *image_view;
 
-      ExceptionInfo
-        *exception;
-
       MagickBooleanType
         status;
 
       status=MagickTrue;
-      image_view=AcquireCacheView(image);
+      image_view=AcquireAuthenticCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) shared(status)
+      #pragma omp parallel for schedule(static,4) shared(status) \
+        dynamic_number_threads(image,image->columns,image->rows,1)
 #endif
       for (y=0; y < (ssize_t) image->rows; y++)
       {
@@ -610,7 +609,7 @@ static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info,
             Find closest color among siblings and their children.
           */
           cube.target=pixel;
-          cube.distance=(MagickRealType) (4.0*(QuantumRange+1.0)*
+          cube.distance=(double) (4.0*(QuantumRange+1.0)*
             (QuantumRange+1.0)+1.0);
           ClosestColor(image,&cube,node_info->parent);
           index=cube.color_number;
@@ -671,8 +670,8 @@ static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info,
       q=image->colormap;
       for (i=0; i < (ssize_t) image->colors; i++)
       {
-        intensity=(double) ((MagickRealType) GetPixelInfoIntensity(q) <
-          ((MagickRealType) QuantumRange/2.0) ? 0 : QuantumRange);
+        intensity=(double) ((double) GetPixelInfoIntensity(q) <
+          ((double) QuantumRange/2.0) ? 0 : QuantumRange);
         q->red=intensity;
         q->green=intensity;
         q->blue=intensity;
@@ -752,7 +751,8 @@ static inline void SetAssociatedAlpha(const Image *image,CubeInfo *cube_info)
   MagickBooleanType
     associate_alpha;
 
-  associate_alpha=image->matte;
+  associate_alpha=image->alpha_trait == BlendPixelTrait ? MagickTrue :
+    MagickFalse;
   if (cube_info->quantize_info->colorspace == TransparentColorspace)
     associate_alpha=MagickFalse;
   if ((cube_info->quantize_info->number_colors == 2) &&
@@ -772,7 +772,7 @@ static MagickBooleanType ClassifyImageColors(CubeInfo *cube_info,
   MagickBooleanType
     proceed;
 
-  MagickRealType
+  double
     bisect;
 
   NodeInfo
@@ -802,16 +802,14 @@ static MagickBooleanType ClassifyImageColors(CubeInfo *cube_info,
     (void) TransformImageColorspace((Image *) image,
       cube_info->quantize_info->colorspace,exception);
   else
-    if ((image->colorspace != GRAYColorspace) &&
-        (image->colorspace != CMYColorspace) &&
-        (IsRGBColorspace(image->colorspace) == MagickFalse))
+    if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
       (void) TransformImageColorspace((Image *) image,sRGBColorspace,exception);
-  midpoint.red=(MagickRealType) QuantumRange/2.0;
-  midpoint.green=(MagickRealType) QuantumRange/2.0;
-  midpoint.blue=(MagickRealType) QuantumRange/2.0;
-  midpoint.alpha=(MagickRealType) QuantumRange/2.0;
+  midpoint.red=(double) QuantumRange/2.0;
+  midpoint.green=(double) QuantumRange/2.0;
+  midpoint.blue=(double) QuantumRange/2.0;
+  midpoint.alpha=(double) QuantumRange/2.0;
   error.alpha=0.0;
-  image_view=AcquireCacheView(image);
+  image_view=AcquireVirtualCacheView(image,exception);
   for (y=0; y < (ssize_t) image->rows; y++)
   {
     register const Quantum
@@ -847,7 +845,7 @@ static MagickBooleanType ClassifyImageColors(CubeInfo *cube_info,
       }
       AssociateAlphaPixel(image,cube_info,p,&pixel);
       index=MaxTreeDepth-1;
-      bisect=((MagickRealType) QuantumRange+1.0)/2.0;
+      bisect=((double) QuantumRange+1.0)/2.0;
       mid=midpoint;
       node_info=cube_info->root;
       for (level=1; level <= MaxTreeDepth; level++)
@@ -866,7 +864,7 @@ static MagickBooleanType ClassifyImageColors(CubeInfo *cube_info,
             node_info->child[id]=GetNodeInfo(cube_info,id,level,node_info);
             if (node_info->child[id] == (NodeInfo *) NULL)
               (void) ThrowMagickException(exception,GetMagickModule(),
-                ResourceLimitError,"MemoryAllocationFailed","`%s'",
+                ResourceLimitError,"MemoryAllocationFailed","'%s'",
                 image->filename);
             if (level == MaxTreeDepth)
               cube_info->colors++;
@@ -942,7 +940,7 @@ static MagickBooleanType ClassifyImageColors(CubeInfo *cube_info,
       }
       AssociateAlphaPixel(image,cube_info,p,&pixel);
       index=MaxTreeDepth-1;
-      bisect=((MagickRealType) QuantumRange+1.0)/2.0;
+      bisect=((double) QuantumRange+1.0)/2.0;
       mid=midpoint;
       node_info=cube_info->root;
       for (level=1; level <= cube_info->depth; level++)
@@ -1043,7 +1041,6 @@ MagickExport QuantizeInfo *CloneQuantizeInfo(const QuantizeInfo *quantize_info)
     return(clone_info);
   clone_info->number_colors=quantize_info->number_colors;
   clone_info->tree_depth=quantize_info->tree_depth;
-  clone_info->dither=quantize_info->dither;
   clone_info->dither_method=quantize_info->dither_method;
   clone_info->colorspace=quantize_info->colorspace;
   clone_info->measure_error=quantize_info->measure_error;
@@ -1097,10 +1094,10 @@ static void ClosestColor(const Image *image,CubeInfo *cube_info,
       ClosestColor(image,cube_info,node_info->child[i]);
   if (node_info->number_unique != 0)
     {
-      MagickRealType
+      double
         pixel;
 
-      register MagickRealType
+      register double
         alpha,
         beta,
         distance;
@@ -1120,8 +1117,8 @@ static void ClosestColor(const Image *image,CubeInfo *cube_info,
       beta=1.0;
       if (cube_info->associate_alpha != MagickFalse)
         {
-          alpha=(MagickRealType) (QuantumScale*p->alpha);
-          beta=(MagickRealType) (QuantumScale*q->alpha);
+          alpha=(double) (QuantumScale*p->alpha);
+          beta=(double) (QuantumScale*q->alpha);
         }
       pixel=alpha*p->red-beta*q->red;
       distance=pixel*pixel;
@@ -1241,7 +1238,7 @@ static size_t DefineImageColormap(Image *image,CubeInfo *cube_info,
       (void) DefineImageColormap(image,cube_info,node_info->child[i]);
   if (node_info->number_unique != 0)
     {
-      register MagickRealType
+      register double
         alpha;
 
       register PixelInfo
@@ -1251,48 +1248,48 @@ static size_t DefineImageColormap(Image *image,CubeInfo *cube_info,
         Colormap entry is defined by the mean color in this cube.
       */
       q=image->colormap+image->colors;
-      alpha=(MagickRealType) ((MagickOffsetType) node_info->number_unique);
-      alpha=1.0/(fabs(alpha) <= MagickEpsilon ? 1.0 : alpha);
+      alpha=(double) ((MagickOffsetType) node_info->number_unique);
+      alpha=MagickEpsilonReciprocal(alpha);
       if (cube_info->associate_alpha == MagickFalse)
         {
-          q->red=(double) ClampToQuantum((MagickRealType)
-            (alpha*QuantumRange*node_info->total_color.red));
-          q->green=(double) ClampToQuantum((MagickRealType)
-            (alpha*QuantumRange*node_info->total_color.green));
-          q->blue=(double) ClampToQuantum((MagickRealType)
-            (alpha*(double) QuantumRange*node_info->total_color.blue));
+          q->red=(double) ClampToQuantum(alpha*QuantumRange*
+            node_info->total_color.red);
+          q->green=(double) ClampToQuantum(alpha*QuantumRange*
+            node_info->total_color.green);
+          q->blue=(double) ClampToQuantum(alpha*(double) QuantumRange*
+            node_info->total_color.blue);
           q->alpha=OpaqueAlpha;
         }
       else
         {
-          MagickRealType
+          double
             opacity;
 
-          opacity=(MagickRealType) (alpha*QuantumRange*
+          opacity=(double) (alpha*QuantumRange*
             node_info->total_color.alpha);
           q->alpha=(double) ClampToQuantum(opacity);
           if (q->alpha == OpaqueAlpha)
             {
-              q->red=(double) ClampToQuantum((MagickRealType)
-                (alpha*QuantumRange*node_info->total_color.red));
-              q->green=(double) ClampToQuantum((MagickRealType)
-                (alpha*QuantumRange*node_info->total_color.green));
-              q->blue=(double) ClampToQuantum((MagickRealType)
-                (alpha*QuantumRange*node_info->total_color.blue));
+              q->red=(double) ClampToQuantum(alpha*QuantumRange*
+                node_info->total_color.red);
+              q->green=(double) ClampToQuantum(alpha*QuantumRange*
+                node_info->total_color.green);
+              q->blue=(double) ClampToQuantum(alpha*QuantumRange*
+                node_info->total_color.blue);
             }
           else
             {
-              MagickRealType
+              double
                 gamma;
 
-              gamma=(MagickRealType) (QuantumScale*q->alpha);
-              gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
-              q->red=(double) ClampToQuantum((MagickRealType)
-                (alpha*gamma*QuantumRange*node_info->total_color.red));
-              q->green=(double) ClampToQuantum((MagickRealType)
-                (alpha*gamma*QuantumRange*node_info->total_color.green));
-              q->blue=(double) ClampToQuantum((MagickRealType)
-                (alpha*gamma*QuantumRange*node_info->total_color.blue));
+              gamma=(double) (QuantumScale*q->alpha);
+              gamma=MagickEpsilonReciprocal(gamma);
+              q->red=(double) ClampToQuantum(alpha*gamma*QuantumRange*
+                node_info->total_color.red);
+              q->green=(double) ClampToQuantum(alpha*gamma*QuantumRange*
+                node_info->total_color.green);
+              q->blue=(double) ClampToQuantum(alpha*gamma*QuantumRange*
+                node_info->total_color.blue);
               if (node_info->number_unique > cube_info->transparent_pixels)
                 {
                   cube_info->transparent_pixels=node_info->number_unique;
@@ -1420,7 +1417,7 @@ static RealPixelInfo **DestroyPixelThreadSet(RealPixelInfo **pixels)
     i;
 
   assert(pixels != (RealPixelInfo **) NULL);
-  for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
+  for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
     if (pixels[i] != (RealPixelInfo *) NULL)
       pixels[i]=(RealPixelInfo *) RelinquishMagickMemory(pixels[i]);
   pixels=(RealPixelInfo **) RelinquishMagickMemory(pixels);
@@ -1438,7 +1435,7 @@ static RealPixelInfo **AcquirePixelThreadSet(const size_t count)
   size_t
     number_threads;
 
-  number_threads=GetOpenMPMaximumThreads();
+  number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
   pixels=(RealPixelInfo **) AcquireQuantumMemory(number_threads,
     sizeof(*pixels));
   if (pixels == (RealPixelInfo **) NULL)
@@ -1499,7 +1496,7 @@ static MagickBooleanType FloydSteinbergDither(Image *image,CubeInfo *cube_info,
   if (pixels == (RealPixelInfo **) NULL)
     return(MagickFalse);
   status=MagickTrue;
-  image_view=AcquireCacheView(image);
+  image_view=AcquireAuthenticCacheView(image,exception);
   for (y=0; y < (ssize_t) image->rows; y++)
   {
     const int
@@ -1584,11 +1581,11 @@ static MagickBooleanType FloydSteinbergDither(Image *image,CubeInfo *cube_info,
                 pixel.alpha+=3*previous[u-v].alpha/16;
             }
         }
-      pixel.red=(MagickRealType) ClampToUnsignedQuantum(pixel.red);
-      pixel.green=(MagickRealType) ClampToUnsignedQuantum(pixel.green);
-      pixel.blue=(MagickRealType) ClampToUnsignedQuantum(pixel.blue);
+      pixel.red=(double) ClampToUnsignedQuantum(pixel.red);
+      pixel.green=(double) ClampToUnsignedQuantum(pixel.green);
+      pixel.blue=(double) ClampToUnsignedQuantum(pixel.blue);
       if (cube.associate_alpha != MagickFalse)
-        pixel.alpha=(MagickRealType) ClampToUnsignedQuantum(pixel.alpha);
+        pixel.alpha=(double) ClampToUnsignedQuantum(pixel.alpha);
       i=CacheOffset(&cube,&pixel);
       if (cube.cache[i] < 0)
         {
@@ -1613,7 +1610,7 @@ static MagickBooleanType FloydSteinbergDither(Image *image,CubeInfo *cube_info,
             Find closest color among siblings and their children.
           */
           cube.target=pixel;
-          cube.distance=(MagickRealType) (4.0*(QuantumRange+1.0)*(QuantumRange+
+          cube.distance=(double) (4.0*(QuantumRange+1.0)*(QuantumRange+
             1.0)+1.0);
           ClosestColor(image,&cube,node_info->parent);
           cube.cache[i]=(ssize_t) cube.color_number;
@@ -1840,11 +1837,11 @@ static MagickBooleanType RiemersmaDither(Image *image,CacheView *image_view,
         if (cube_info->associate_alpha != MagickFalse)
           pixel.alpha+=p->weights[i]*p->error[i].alpha;
       }
-      pixel.red=(MagickRealType) ClampToUnsignedQuantum(pixel.red);
-      pixel.green=(MagickRealType) ClampToUnsignedQuantum(pixel.green);
-      pixel.blue=(MagickRealType) ClampToUnsignedQuantum(pixel.blue);
+      pixel.red=(double) ClampToUnsignedQuantum(pixel.red);
+      pixel.green=(double) ClampToUnsignedQuantum(pixel.green);
+      pixel.blue=(double) ClampToUnsignedQuantum(pixel.blue);
       if (cube_info->associate_alpha != MagickFalse)
-        pixel.alpha=(MagickRealType) ClampToUnsignedQuantum(pixel.alpha);
+        pixel.alpha=(double) ClampToUnsignedQuantum(pixel.alpha);
       i=CacheOffset(cube_info,&pixel);
       if (p->cache[i] < 0)
         {
@@ -1870,7 +1867,7 @@ static MagickBooleanType RiemersmaDither(Image *image,CacheView *image_view,
             Find closest color among siblings and their children.
           */
           p->target=pixel;
-          p->distance=(MagickRealType) (4.0*(QuantumRange+1.0)*((MagickRealType)
+          p->distance=(double) (4.0*(QuantumRange+1.0)*((double)
             QuantumRange+1.0)+1.0);
           ClosestColor(image,p,node_info->parent);
           p->cache[i]=(ssize_t) p->color_number;
@@ -1962,7 +1959,7 @@ static MagickBooleanType DitherImage(Image *image,CubeInfo *cube_info,
     depth++;
   cube_info->offset=0;
   cube_info->span=(MagickSizeType) image->columns*image->rows;
-  image_view=AcquireCacheView(image);
+  image_view=AcquireAuthenticCacheView(image,exception);
   if (depth > 1)
     Riemersma(image,image_view,cube_info,depth-1,NorthGravity,exception);
   status=RiemersmaDither(image,image_view,cube_info,ForgetGravity,exception);
@@ -2010,7 +2007,7 @@ static CubeInfo *GetCubeInfo(const QuantizeInfo *quantize_info,
   CubeInfo
     *cube_info;
 
-  MagickRealType
+  double
     sum,
     weight;
 
@@ -2041,7 +2038,7 @@ static CubeInfo *GetCubeInfo(const QuantizeInfo *quantize_info,
     return((CubeInfo *) NULL);
   cube_info->root->parent=cube_info->root;
   cube_info->quantize_info=CloneQuantizeInfo(quantize_info);
-  if (cube_info->quantize_info->dither == MagickFalse)
+  if (cube_info->quantize_info->dither_method == NoDitherMethod)
     return(cube_info);
   /*
     Initialize dither resources.
@@ -2062,7 +2059,7 @@ static CubeInfo *GetCubeInfo(const QuantizeInfo *quantize_info,
   weight=1.0;
   for (i=0; i < ErrorQueueLength; i++)
   {
-    cube_info->weights[ErrorQueueLength-i-1]=1.0/weight;
+    cube_info->weights[ErrorQueueLength-i-1]=MagickEpsilonReciprocal(weight);
     weight*=exp(log(((double) QuantumRange+1.0))/(ErrorQueueLength-1.0));
   }
   /*
@@ -2193,7 +2190,7 @@ MagickExport MagickBooleanType GetImageQuantizeError(Image *image,
   CacheView
     *image_view;
 
-  MagickRealType
+  double
     alpha,
     area,
     beta,
@@ -2222,7 +2219,7 @@ MagickExport MagickBooleanType GetImageQuantizeError(Image *image,
   maximum_error=0.0;
   mean_error_per_pixel=0.0;
   mean_error=0.0;
-  image_view=AcquireCacheView(image);
+  image_view=AcquireVirtualCacheView(image,exception);
   for (y=0; y < (ssize_t) image->rows; y++)
   {
     register const Quantum
@@ -2237,10 +2234,10 @@ MagickExport MagickBooleanType GetImageQuantizeError(Image *image,
     for (x=0; x < (ssize_t) image->columns; x++)
     {
       index=1UL*GetPixelIndex(image,p);
-      if (image->matte != MagickFalse)
+      if (image->alpha_trait == BlendPixelTrait)
         {
-          alpha=(MagickRealType) (QuantumScale*GetPixelAlpha(image,p));
-          beta=(MagickRealType) (QuantumScale*image->colormap[index].alpha);
+          alpha=(double) (QuantumScale*GetPixelAlpha(image,p));
+          beta=(double) (QuantumScale*image->colormap[index].alpha);
         }
       distance=fabs(alpha*GetPixelRed(image,p)-beta*
         image->colormap[index].red);
@@ -2299,7 +2296,6 @@ MagickExport void GetQuantizeInfo(QuantizeInfo *quantize_info)
   assert(quantize_info != (QuantizeInfo *) NULL);
   (void) ResetMagickMemory(quantize_info,0,sizeof(*quantize_info));
   quantize_info->number_colors=256;
-  quantize_info->dither=MagickTrue;
   quantize_info->dither_method=RiemersmaDitherMethod;
   quantize_info->colorspace=UndefinedColorspace;
   quantize_info->measure_error=MagickFalse;
@@ -2323,7 +2319,7 @@ MagickExport void GetQuantizeInfo(QuantizeInfo *quantize_info)
 %  The format of the PosterizeImage method is:
 %
 %      MagickBooleanType PosterizeImage(Image *image,const size_t levels,
-%        const MagickBooleanType dither,ExceptionInfo *exception)
+%        const DitherMethod dither_method,ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
@@ -2332,14 +2328,14 @@ MagickExport void GetQuantizeInfo(QuantizeInfo *quantize_info)
 %    o levels: Number of color levels allowed in each channel.  Very low values
 %      (2, 3, or 4) have the most visible effect.
 %
-%    o dither: Set this integer value to something other than zero to dither
-%      the mapped image.
+%    o dither_method: choose from UndefinedDitherMethod, NoDitherMethod,
+%      RiemersmaDitherMethod, FloydSteinbergDitherMethod.
 %
 %    o exception: return any errors or warnings in this structure.
 %
 */
 
-static inline ssize_t MagickRound(MagickRealType x)
+static inline ssize_t MagickRound(double x)
 {
   /*
     Round the fraction to nearest integer.
@@ -2350,7 +2346,7 @@ static inline ssize_t MagickRound(MagickRealType x)
 }
 
 MagickExport MagickBooleanType PosterizeImage(Image *image,const size_t levels,
-  const MagickBooleanType dither,ExceptionInfo *exception)
+  const DitherMethod dither_method,ExceptionInfo *exception)
 {
 #define PosterizeImageTag  "Posterize/Image"
 #define PosterizePixel(pixel) (Quantum) (QuantumRange*(MagickRound( \
@@ -2380,7 +2376,8 @@ MagickExport MagickBooleanType PosterizeImage(Image *image,const size_t levels,
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (image->storage_class == PseudoClass)
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-    #pragma omp parallel for schedule(static,4) shared(progress,status)
+    #pragma omp parallel for schedule(static,4) shared(progress,status) \
+      dynamic_number_threads(image,image->columns,1,1)
 #endif
     for (i=0; i < (ssize_t) image->colors; i++)
     {
@@ -2405,9 +2402,10 @@ MagickExport MagickBooleanType PosterizeImage(Image *image,const size_t levels,
   */
   status=MagickTrue;
   progress=0;
-  image_view=AcquireCacheView(image);
+  image_view=AcquireAuthenticCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(static,4) shared(progress,status)
+  #pragma omp parallel for schedule(static,4) shared(progress,status) \
+    dynamic_number_threads(image,image->columns,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -2437,7 +2435,7 @@ MagickExport MagickBooleanType PosterizeImage(Image *image,const size_t levels,
           (image->colorspace == CMYKColorspace))
         SetPixelBlack(image,PosterizePixel(GetPixelBlack(image,q)),q);
       if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-          (image->matte == MagickTrue))
+          (image->alpha_trait == BlendPixelTrait))
         SetPixelAlpha(image,PosterizePixel(GetPixelAlpha(image,q)),q);
       q+=GetPixelChannels(image);
     }
@@ -2461,7 +2459,7 @@ MagickExport MagickBooleanType PosterizeImage(Image *image,const size_t levels,
   quantize_info=AcquireQuantizeInfo((ImageInfo *) NULL);
   quantize_info->number_colors=(size_t) MagickMin((ssize_t) levels*levels*
     levels,MaxColormapSize+1);
-  quantize_info->dither=dither;
+  quantize_info->dither_method=dither_method;
   quantize_info->tree_depth=MaxTreeDepth;
   status=QuantizeImage(quantize_info,image,exception);
   quantize_info=DestroyQuantizeInfo(quantize_info);
@@ -2680,7 +2678,7 @@ static MagickBooleanType DirectToColormapImage(Image *image,
   if (image->colors != number_colors)
     return(MagickFalse);
   i=0;
-  image_view=AcquireCacheView(image);
+  image_view=AcquireAuthenticCacheView(image,exception);
   for (y=0; y < (ssize_t) image->rows; y++)
   {
     MagickBooleanType
@@ -2740,11 +2738,13 @@ MagickExport MagickBooleanType QuantizeImage(const QuantizeInfo *quantize_info,
     maximum_colors=MaxColormapSize;
   if (maximum_colors > MaxColormapSize)
     maximum_colors=MaxColormapSize;
-  if ((image->columns*image->rows) <= maximum_colors)
-    (void) DirectToColormapImage(image,exception);
-  if ((IsImageGray(image,exception) != MagickFalse) &&
-      (image->matte == MagickFalse))
-    (void) SetGrayscaleImage(image,exception);
+  if (image->alpha_trait != BlendPixelTrait)
+    {
+      if ((image->columns*image->rows) <= maximum_colors)
+        (void) DirectToColormapImage(image,exception);
+      if (IsImageGray(image,exception) != MagickFalse)
+        (void) SetGrayscaleImage(image,exception);
+    }
   if ((image->storage_class == PseudoClass) &&
       (image->colors <= maximum_colors))
     return(MagickTrue);
@@ -2760,9 +2760,9 @@ MagickExport MagickBooleanType QuantizeImage(const QuantizeInfo *quantize_info,
       colors=maximum_colors;
       for (depth=1; colors != 0; depth++)
         colors>>=2;
-      if ((quantize_info->dither != MagickFalse) && (depth > 2))
+      if ((quantize_info->dither_method != NoDitherMethod) && (depth > 2))
         depth--;
-      if ((image->matte != MagickFalse) && (depth > 5))
+      if ((image->alpha_trait == BlendPixelTrait) && (depth > 5))
         depth--;
     }
   /*
@@ -2871,7 +2871,7 @@ MagickExport MagickBooleanType QuantizeImages(const QuantizeInfo *quantize_info,
       colors=maximum_colors;
       for (depth=1; colors != 0; depth++)
         colors>>=2;
-      if (quantize_info->dither != MagickFalse)
+      if (quantize_info->dither_method != NoDitherMethod)
         depth--;
     }
   /*
@@ -2881,7 +2881,7 @@ MagickExport MagickBooleanType QuantizeImages(const QuantizeInfo *quantize_info,
   if (cube_info == (CubeInfo *) NULL)
     {
       (void) ThrowMagickException(exception,GetMagickModule(),
-        ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
+        ResourceLimitError,"MemoryAllocationFailed","'%s'",images->filename);
       return(MagickFalse);
     }
   number_images=GetImageListLength(images);
@@ -3254,8 +3254,8 @@ static int IntensityCompare(const void *x,const void *y)
 
   color_1=(PixelInfo *) x;
   color_2=(PixelInfo *) y;
-  intensity=GetPixelInfoIntensity(color_1)-(ssize_t)
-    GetPixelInfoIntensity(color_2);
+  intensity=(ssize_t) (GetPixelInfoIntensity(color_1)-(ssize_t)
+    GetPixelInfoIntensity(color_2));
   return((int) intensity);
 }
 
@@ -3301,9 +3301,10 @@ static MagickBooleanType SetGrayscaleImage(Image *image,
           image->filename);
       image->colors=0;
       status=MagickTrue;
-      image_view=AcquireCacheView(image);
+      image_view=AcquireAuthenticCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) shared(status)
+      #pragma omp parallel for schedule(static,4) shared(status) \
+        dynamic_number_threads(image,image->columns,image->rows,1)
 #endif
       for (y=0; y < (ssize_t) image->rows; y++)
       {
@@ -3331,7 +3332,7 @@ static MagickBooleanType SetGrayscaleImage(Image *image,
           if (colormap_index[intensity] < 0)
             {
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-    #pragma omp critical (MagickCore_SetGrayscaleImage)
+              #pragma omp critical (MagickCore_SetGrayscaleImage)
 #endif
               if (colormap_index[intensity] < 0)
                 {
@@ -3345,8 +3346,7 @@ static MagickBooleanType SetGrayscaleImage(Image *image,
                   image->colors++;
                }
             }
-          SetPixelIndex(image,(Quantum) 
-            colormap_index[intensity],q);
+          SetPixelIndex(image,(Quantum) colormap_index[intensity],q);
           q+=GetPixelChannels(image);
         }
         if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
@@ -3378,9 +3378,10 @@ static MagickBooleanType SetGrayscaleImage(Image *image,
   image->colormap=(PixelInfo *) RelinquishMagickMemory(image->colormap);
   image->colormap=colormap;
   status=MagickTrue;
-  image_view=AcquireCacheView(image);
+  image_view=AcquireAuthenticCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(static,4) shared(status)
+  #pragma omp parallel for schedule(static,4) shared(status) \
+    dynamic_number_threads(image,image->columns,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {