]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/quantize.c
(no commit message)
[imagemagick] / MagickCore / quantize.c
index 1d6e97f182ccc717bddc2543ff760359f179ac1e..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,10 +516,8 @@ 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))
-      (void) TransformImageColorspace((Image *) image,RGBColorspace,exception);
+    if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+      (void) TransformImageColorspace((Image *) image,sRGBColorspace,exception);
   if (AcquireImageColormap(image,cube_info->colors,exception) == MagickFalse)
     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
       image->filename);
@@ -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(dynamic,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;
@@ -620,11 +619,15 @@ static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info,
               SetPixelIndex(image,(Quantum) index,q);
             if (cube.quantize_info->measure_error == MagickFalse)
               {
-                SetPixelRed(image,image->colormap[index].red,q);
-                SetPixelGreen(image,image->colormap[index].green,q);
-                SetPixelBlue(image,image->colormap[index].blue,q);
+                SetPixelRed(image,ClampToQuantum(
+                  image->colormap[index].red),q);
+                SetPixelGreen(image,ClampToQuantum(
+                  image->colormap[index].green),q);
+                SetPixelBlue(image,ClampToQuantum(
+                  image->colormap[index].blue),q);
                 if (cube.associate_alpha != MagickFalse)
-                  SetPixelAlpha(image,image->colormap[index].alpha,q);
+                  SetPixelAlpha(image,ClampToQuantum(
+                    image->colormap[index].alpha),q);
               }
             q+=GetPixelChannels(image);
           }
@@ -652,7 +655,7 @@ static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info,
   if ((cube_info->quantize_info->number_colors == 2) &&
       (cube_info->quantize_info->colorspace == GRAYColorspace))
     {
-      Quantum
+      double
         intensity;
 
       register PixelInfo
@@ -667,8 +670,8 @@ static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info,
       q=image->colormap;
       for (i=0; i < (ssize_t) image->colors; i++)
       {
-        intensity=(Quantum) ((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;
@@ -678,7 +681,7 @@ static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info,
   (void) SyncImage(image,exception);
   if ((cube_info->quantize_info->colorspace != UndefinedColorspace) &&
       (cube_info->quantize_info->colorspace != CMYKColorspace))
-    (void) TransformImageColorspace((Image *) image,RGBColorspace,exception);
+    (void) TransformImageColorspace((Image *) image,sRGBColorspace,exception);
   return(MagickTrue);
 }
 \f
@@ -748,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) &&
@@ -768,7 +772,7 @@ static MagickBooleanType ClassifyImageColors(CubeInfo *cube_info,
   MagickBooleanType
     proceed;
 
-  MagickRealType
+  double
     bisect;
 
   NodeInfo
@@ -798,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))
-      (void) TransformImageColorspace((Image *) image,RGBColorspace,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;
+    if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+      (void) TransformImageColorspace((Image *) image,sRGBColorspace,exception);
+  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
@@ -843,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++)
@@ -862,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++;
@@ -938,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++)
@@ -996,7 +998,7 @@ static MagickBooleanType ClassifyImageColors(CubeInfo *cube_info,
   image_view=DestroyCacheView(image_view);
   if ((cube_info->quantize_info->colorspace != UndefinedColorspace) &&
       (cube_info->quantize_info->colorspace != CMYKColorspace))
-    (void) TransformImageColorspace((Image *) image,RGBColorspace,exception);
+    (void) TransformImageColorspace((Image *) image,sRGBColorspace,exception);
   return(MagickTrue);
 }
 \f
@@ -1039,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;
@@ -1093,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;
@@ -1116,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;
@@ -1237,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
@@ -1247,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=ClampToQuantum((MagickRealType)
-            (alpha*QuantumRange*node_info->total_color.red));
-          q->green=ClampToQuantum((MagickRealType)
-            (alpha*QuantumRange*node_info->total_color.green));
-          q->blue=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*(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=ClampToQuantum(opacity);
+          q->alpha=(double) ClampToQuantum(opacity);
           if (q->alpha == OpaqueAlpha)
             {
-              q->red=ClampToQuantum((MagickRealType)
-                (alpha*QuantumRange*node_info->total_color.red));
-              q->green=ClampToQuantum((MagickRealType)
-                (alpha*QuantumRange*node_info->total_color.green));
-              q->blue=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=ClampToQuantum((MagickRealType)
-                (alpha*gamma*QuantumRange*node_info->total_color.red));
-              q->green=ClampToQuantum((MagickRealType)
-                (alpha*gamma*QuantumRange*node_info->total_color.green));
-              q->blue=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;
@@ -1416,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);
@@ -1434,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)
@@ -1495,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
@@ -1580,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)
         {
@@ -1609,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;
@@ -1622,11 +1623,11 @@ static MagickBooleanType FloydSteinbergDither(Image *image,CubeInfo *cube_info,
         SetPixelIndex(image,(Quantum) index,q);
       if (cube.quantize_info->measure_error == MagickFalse)
         {
-          SetPixelRed(image,image->colormap[index].red,q);
-          SetPixelGreen(image,image->colormap[index].green,q);
-          SetPixelBlue(image,image->colormap[index].blue,q);
+          SetPixelRed(image,ClampToQuantum(image->colormap[index].red),q);
+          SetPixelGreen(image,ClampToQuantum(image->colormap[index].green),q);
+          SetPixelBlue(image,ClampToQuantum(image->colormap[index].blue),q);
           if (cube.associate_alpha != MagickFalse)
-            SetPixelAlpha(image,image->colormap[index].alpha,q);
+            SetPixelAlpha(image,ClampToQuantum(image->colormap[index].alpha),q);
         }
       if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
         status=MagickFalse;
@@ -1836,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)
         {
@@ -1866,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;
@@ -1879,11 +1880,11 @@ static MagickBooleanType RiemersmaDither(Image *image,CacheView *image_view,
         SetPixelIndex(image,(Quantum) index,q);
       if (cube_info->quantize_info->measure_error == MagickFalse)
         {
-          SetPixelRed(image,image->colormap[index].red,q);
-          SetPixelGreen(image,image->colormap[index].green,q);
-          SetPixelBlue(image,image->colormap[index].blue,q);
+          SetPixelRed(image,ClampToQuantum(image->colormap[index].red),q);
+          SetPixelGreen(image,ClampToQuantum(image->colormap[index].green),q);
+          SetPixelBlue(image,ClampToQuantum(image->colormap[index].blue),q);
           if (cube_info->associate_alpha != MagickFalse)
-            SetPixelAlpha(image,image->colormap[index].alpha,q);
+            SetPixelAlpha(image,ClampToQuantum(image->colormap[index].alpha),q);
         }
       if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
         return(MagickFalse);
@@ -1958,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);
@@ -2006,7 +2007,7 @@ static CubeInfo *GetCubeInfo(const QuantizeInfo *quantize_info,
   CubeInfo
     *cube_info;
 
-  MagickRealType
+  double
     sum,
     weight;
 
@@ -2037,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.
@@ -2058,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));
   }
   /*
@@ -2189,7 +2190,7 @@ MagickExport MagickBooleanType GetImageQuantizeError(Image *image,
   CacheView
     *image_view;
 
-  MagickRealType
+  double
     alpha,
     area,
     beta,
@@ -2218,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
@@ -2233,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);
@@ -2295,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;
@@ -2319,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:
 %
@@ -2328,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.
@@ -2346,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( \
@@ -2376,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(dynamic,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++)
     {
@@ -2384,22 +2385,27 @@ MagickExport MagickBooleanType PosterizeImage(Image *image,const size_t levels,
         Posterize colormap.
       */
       if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
-        image->colormap[i].red=PosterizePixel(image->colormap[i].red);
+        image->colormap[i].red=(double)
+          PosterizePixel(image->colormap[i].red);
       if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
-        image->colormap[i].green=PosterizePixel(image->colormap[i].green);
+        image->colormap[i].green=(double)
+          PosterizePixel(image->colormap[i].green);
       if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
-        image->colormap[i].blue=PosterizePixel(image->colormap[i].blue);
+        image->colormap[i].blue=(double)
+          PosterizePixel(image->colormap[i].blue);
       if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
-        image->colormap[i].alpha=PosterizePixel(image->colormap[i].alpha);
+        image->colormap[i].alpha=(double)
+          PosterizePixel(image->colormap[i].alpha);
     }
   /*
     Posterize image.
   */
   status=MagickTrue;
   progress=0;
-  image_view=AcquireCacheView(image);
+  image_view=AcquireAuthenticCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(dynamic,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++)
   {
@@ -2429,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);
     }
@@ -2453,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);
@@ -2672,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
@@ -2689,10 +2695,10 @@ static MagickBooleanType DirectToColormapImage(Image *image,
       break;
     for (x=0; x < (ssize_t) image->columns; x++)
     {
-      image->colormap[i].red=GetPixelRed(image,q);
-      image->colormap[i].green=GetPixelGreen(image,q);
-      image->colormap[i].blue=GetPixelBlue(image,q);
-      image->colormap[i].alpha=GetPixelAlpha(image,q);
+      image->colormap[i].red=(double) GetPixelRed(image,q);
+      image->colormap[i].green=(double) GetPixelGreen(image,q);
+      image->colormap[i].blue=(double) GetPixelBlue(image,q);
+      image->colormap[i].alpha=(double) GetPixelAlpha(image,q);
       SetPixelIndex(image,(Quantum) i,q);
       i++;
       q+=GetPixelChannels(image);
@@ -2732,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);
@@ -2752,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--;
     }
   /*
@@ -2863,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--;
     }
   /*
@@ -2873,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);
@@ -3069,8 +3077,8 @@ static void ReduceImageColors(const Image *image,CubeInfo *cube_info)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  RemapImage() replaces the colors of an image with the closest color from
-%  a reference image.
+%  RemapImage() replaces the colors of an image with a dither of the colors
+%  provided.
 %
 %  The format of the RemapImage method is:
 %
@@ -3246,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);
 }
 
@@ -3293,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(dynamic,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++)
       {
@@ -3323,19 +3332,21 @@ 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)
                 {
                   colormap_index[intensity]=(ssize_t) image->colors;
-                  image->colormap[image->colors].red=GetPixelRed(image,q);
-                  image->colormap[image->colors].green=GetPixelGreen(image,q);
-                  image->colormap[image->colors].blue=GetPixelBlue(image,q);
+                  image->colormap[image->colors].red=(double)
+                    GetPixelRed(image,q);
+                  image->colormap[image->colors].green=(double)
+                    GetPixelGreen(image,q);
+                  image->colormap[image->colors].blue=(double)
+                    GetPixelBlue(image,q);
                   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)
@@ -3344,7 +3355,7 @@ static MagickBooleanType SetGrayscaleImage(Image *image,
       image_view=DestroyCacheView(image_view);
     }
   for (i=0; i < (ssize_t) image->colors; i++)
-    image->colormap[i].alpha=(unsigned short) i;
+    image->colormap[i].alpha=(double) i;
   qsort((void *) image->colormap,image->colors,sizeof(PixelInfo),
     IntensityCompare);
   colormap=(PixelInfo *) AcquireQuantumMemory(image->colors,
@@ -3367,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(dynamic,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++)
   {