]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/threshold.c
(no commit message)
[imagemagick] / MagickCore / threshold.c
index 4aa006d3275f6766ec7dac85736ad26a699dbec6..1e5e3c125e67da2c754e3209dfab4dd4be9f6399 100644 (file)
@@ -17,7 +17,7 @@
 %                                 October 1996                                %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
@@ -48,6 +48,7 @@
 #include "MagickCore/color-private.h"
 #include "MagickCore/colormap.h"
 #include "MagickCore/colorspace.h"
+#include "MagickCore/colorspace-private.h"
 #include "MagickCore/configure.h"
 #include "MagickCore/constitute.h"
 #include "MagickCore/decorate.h"
 #include "MagickCore/string-private.h"
 #include "MagickCore/thread-private.h"
 #include "MagickCore/threshold.h"
+#include "MagickCore/token.h"
 #include "MagickCore/transform.h"
 #include "MagickCore/xml-tree.h"
+#include "MagickCore/xml-tree-private.h"
 \f
 /*
   Define declarations.
@@ -107,6 +110,12 @@ struct _ThresholdMap
     *levels;
 };
 \f
+/*
+  Forward declarations.
+*/
+static ThresholdMap
+  *GetThresholdMapFile(const char *,const char *,const char *,ExceptionInfo *);
+\f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                             %
@@ -181,9 +190,9 @@ MagickExport Image *AdaptiveThresholdImage(const Image *image,
     exception);
   if (threshold_image == (Image *) NULL)
     return((Image *) NULL);
-  if (SetImageStorageClass(threshold_image,DirectClass) == MagickFalse)
+  status=SetImageStorageClass(threshold_image,DirectClass,exception);
+  if (status == MagickFalse)
     {
-      InheritException(exception,&threshold_image->exception);
       threshold_image=DestroyImage(threshold_image);
       return((Image *) NULL);
     }
@@ -193,10 +202,11 @@ MagickExport Image *AdaptiveThresholdImage(const Image *image,
   status=MagickTrue;
   progress=0;
   number_pixels=(MagickSizeType) width*height;
-  image_view=AcquireCacheView(image);
-  threshold_view=AcquireCacheView(threshold_image);
+  image_view=AcquireVirtualCacheView(image,exception);
+  threshold_view=AcquireAuthenticCacheView(threshold_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++)
   {
@@ -209,10 +219,6 @@ MagickExport Image *AdaptiveThresholdImage(const Image *image,
     register ssize_t
       x;
 
-    size_t
-      channels,
-      threshold_channels;
-
     ssize_t
       center;
 
@@ -227,17 +233,16 @@ MagickExport Image *AdaptiveThresholdImage(const Image *image,
         status=MagickFalse;
         continue;
       }
-    channels=GetPixelChannels(image);
-    threshold_channels=GetPixelChannels(threshold_image);
-    center=channels*(image->columns+width)*(height/2L)+channels*(width/2);
+    center=(ssize_t) GetPixelChannels(image)*(image->columns+width)*(height/2L)+
+      GetPixelChannels(image)*(width/2);
     for (x=0; x < (ssize_t) image->columns; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) channels; i++)
+      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
-        MagickRealType
+        double
           mean,
           pixel;
 
@@ -257,14 +262,14 @@ MagickExport Image *AdaptiveThresholdImage(const Image *image,
         ssize_t
           v;
 
-        traits=GetPixelChannelMapTraits(image,i);
-        if (traits == UndefinedPixelTrait)
-          continue;
         channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
         threshold_traits=GetPixelChannelMapTraits(threshold_image,channel);
-        if (threshold_traits == UndefinedPixelTrait)
+        if ((traits == UndefinedPixelTrait) ||
+            (threshold_traits == UndefinedPixelTrait))
           continue;
-        if ((threshold_traits & CopyPixelTrait) != 0)
+        if (((threshold_traits & CopyPixelTrait) != 0) ||
+            (GetPixelMask(image,p) != 0))
           {
             SetPixelChannel(threshold_image,channel,p[center+i],q);
             continue;
@@ -276,16 +281,16 @@ MagickExport Image *AdaptiveThresholdImage(const Image *image,
           for (u=0; u < (ssize_t) width; u++)
           {
             pixel+=pixels[i];
-            pixels+=channels;
+            pixels+=GetPixelChannels(image);
           }
-          pixels+=image->columns*channels;
+          pixels+=image->columns*GetPixelChannels(image);
         }
-        mean=pixel/number_pixels+bias;
-        SetPixelChannel(threshold_image,channel,(Quantum) (((MagickRealType)
-          p[center+i] <= mean) ? 0 : QuantumRange),q);
+        mean=(double) (pixel/number_pixels+bias);
+        SetPixelChannel(threshold_image,channel,(Quantum) ((double)
+          p[center+i] <= mean ? 0 : QuantumRange),q);
       }
-      p+=channels;
-      q+=threshold_channels;
+      p+=GetPixelChannels(image);
+      q+=GetPixelChannels(threshold_image);
     }
     if (SyncCacheViewAuthenticPixels(threshold_view,exception) == MagickFalse)
       status=MagickFalse;
@@ -295,7 +300,7 @@ MagickExport Image *AdaptiveThresholdImage(const Image *image,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_AdaptiveThresholdImage)
+        #pragma omp critical (MagickCore_AdaptiveThresholdImage)
 #endif
         proceed=SetImageProgress(image,AdaptiveThresholdImageTag,progress++,
           image->rows);
@@ -337,7 +342,8 @@ MagickExport Image *AdaptiveThresholdImage(const Image *image,
 %
 %  The format of the BilevelImage method is:
 %
-%      MagickBooleanType BilevelImage(Image *image,const double threshold)
+%      MagickBooleanType BilevelImage(Image *image,const double threshold,
+%        ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
@@ -345,21 +351,20 @@ MagickExport Image *AdaptiveThresholdImage(const Image *image,
 %
 %    o threshold: define the threshold values.
 %
+%    o exception: return any errors or warnings in this structure.
+%
 %  Aside: You can get the same results as operator using LevelImages()
 %  with the 'threshold' value for both the black_point and the white_point.
 %
 */
-MagickExport MagickBooleanType BilevelImage(Image *image,
-  const double threshold)
+MagickExport MagickBooleanType BilevelImage(Image *image,const double threshold,
+  ExceptionInfo *exception)
 {
 #define ThresholdImageTag  "Threshold/Image"
 
   CacheView
     *image_view;
 
-  ExceptionInfo
-    *exception;
-
   MagickBooleanType
     status;
 
@@ -373,17 +378,17 @@ MagickExport MagickBooleanType BilevelImage(Image *image,
   assert(image->signature == MagickSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
+  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
     return(MagickFalse);
   /*
     Bilevel threshold image.
   */
   status=MagickTrue;
   progress=0;
-  exception=(&image->exception);
-  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++)
   {
@@ -396,50 +401,43 @@ MagickExport MagickBooleanType BilevelImage(Image *image,
     if (status == MagickFalse)
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
-    if (q == (const Quantum *) NULL)
+    if (q == (Quantum *) NULL)
       {
         status=MagickFalse;
         continue;
       }
-    if (image->sync != MagickFalse)
-      {
-        for (x=0; x < (ssize_t) image->columns; x++)
+    for (x=0; x < (ssize_t) image->columns; x++)
+    {
+      double
+        pixel;
+
+      register ssize_t
+        i;
+
+      if (GetPixelMask(image,q) != 0)
         {
-          SetPixelRed(image,(Quantum) ((MagickRealType)
-            GetPixelIntensity(image,q) <= threshold ? 0 : QuantumRange),q);
-          SetPixelGreen(image,GetPixelRed(image,q),q);
-          SetPixelBlue(image,GetPixelRed(image,q),q);
           q+=GetPixelChannels(image);
+          continue;
         }
-      }
-    else
-      for (x=0; x < (ssize_t) image->columns; x++)
+      pixel=GetPixelIntensity(image,q);
+      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
-        if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
-          SetPixelRed(image,(Quantum) ((MagickRealType)
-            GetPixelRed(image,q) <= threshold ? 0 : QuantumRange),q);
-        if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
-          SetPixelGreen(image,(Quantum) ((MagickRealType)
-            GetPixelGreen(image,q) <= threshold ? 0 : QuantumRange),q);
-        if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
-          SetPixelBlue(image,(Quantum) ((MagickRealType)
-            GetPixelBlue(image,q) <= threshold ? 0 : QuantumRange),q);
-        if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
-            (image->colorspace == CMYKColorspace))
-          SetPixelBlack(image,(Quantum) ((MagickRealType)
-            GetPixelBlack(image,q) <= threshold ? 0 : QuantumRange),q);
-        if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
-          {
-            if (image->matte == MagickFalse)
-              SetPixelAlpha(image,(Quantum) ((MagickRealType)
-                GetPixelAlpha(image,q) <= threshold ? 0 : QuantumRange),q);
-            else
-              SetPixelAlpha(image,(Quantum) ((MagickRealType)
-                GetPixelAlpha(image,q) >= threshold ? OpaqueAlpha :
-                TransparentAlpha),q);
-          }
-        q+=GetPixelChannels(image);
+        PixelChannel
+          channel;
+
+        PixelTrait
+          traits;
+
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
+        if ((traits & UpdatePixelTrait) == 0)
+          continue;
+        if (image->channel_mask != DefaultChannels)
+          pixel=(double) q[i];
+        q[i]=(Quantum) (pixel <= threshold ? 0 : QuantumRange);
       }
+      q+=GetPixelChannels(image);
+    }
     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
@@ -448,7 +446,7 @@ MagickExport MagickBooleanType BilevelImage(Image *image,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_BilevelImage)
+        #pragma omp critical (MagickCore_BilevelImage)
 #endif
         proceed=SetImageProgress(image,ThresholdImageTag,progress++,
           image->rows);
@@ -484,7 +482,7 @@ MagickExport MagickBooleanType BilevelImage(Image *image,
 %
 %    o image: the image.
 %
-%    o threshold: Define the threshold value.
+%    o threshold: define the threshold value.
 %
 %    o exception: return any errors or warnings in this structure.
 %
@@ -521,39 +519,47 @@ MagickExport MagickBooleanType BlackThresholdImage(Image *image,
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (thresholds == (const char *) NULL)
     return(MagickTrue);
-  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
+  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
     return(MagickFalse);
+  if (IsGrayColorspace(image->colorspace) != MagickFalse)
+    (void) TransformImageColorspace(image,RGBColorspace,exception);
   GetPixelInfo(image,&threshold);
   flags=ParseGeometry(thresholds,&geometry_info);
   threshold.red=geometry_info.rho;
-  threshold.green=geometry_info.sigma;
-  if ((flags & SigmaValue) == 0)
-    threshold.green=threshold.red;
-  threshold.blue=geometry_info.xi;
-  if ((flags & XiValue) == 0)
-    threshold.blue=threshold.red;
-  threshold.alpha=geometry_info.psi;
-  if ((flags & PsiValue) == 0)
-    threshold.alpha=threshold.red;
-  threshold.black=geometry_info.chi;
-  if ((flags & ChiValue) == 0)
-    threshold.black=threshold.red;
+  threshold.green=geometry_info.rho;
+  threshold.blue=geometry_info.rho;
+  threshold.black=geometry_info.rho;
+  threshold.alpha=100.0;
+  if ((flags & SigmaValue) != 0)
+    threshold.green=geometry_info.sigma;
+  if ((flags & XiValue) != 0)
+    threshold.blue=geometry_info.xi;
+  if ((flags & PsiValue) != 0)
+    threshold.alpha=geometry_info.psi;
+  if (threshold.colorspace == CMYKColorspace)
+    {
+      if ((flags & PsiValue) != 0)
+        threshold.black=geometry_info.psi;
+      if ((flags & ChiValue) != 0)
+        threshold.alpha=geometry_info.chi;
+    }
   if ((flags & PercentValue) != 0)
     {
       threshold.red*=(QuantumRange/100.0);
       threshold.green*=(QuantumRange/100.0);
       threshold.blue*=(QuantumRange/100.0);
-      threshold.alpha*=(QuantumRange/100.0);
       threshold.black*=(QuantumRange/100.0);
+      threshold.alpha*=(QuantumRange/100.0);
     }
   /*
-    Black threshold image.
+    White threshold 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++)
   {
@@ -566,43 +572,42 @@ MagickExport MagickBooleanType BlackThresholdImage(Image *image,
     if (status == MagickFalse)
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
-    if (q == (const Quantum *) NULL)
+    if (q == (Quantum *) NULL)
       {
         status=MagickFalse;
         continue;
       }
     for (x=0; x < (ssize_t) image->columns; x++)
     {
-      if (image->sync != MagickFalse)
-        {
-          if (GetPixelIntensity(image,q) < GetPixelInfoIntensity(&threshold))
-            {
-              SetPixelRed(image,0,q);
-              SetPixelGreen(image,0,q);
-              SetPixelBlue(image,0,q);
-              if (image->colorspace == CMYKColorspace)
-                SetPixelBlack(image,0,q);
-            }
-        }
-      else
+      double
+        pixel;
+
+      register ssize_t
+        i;
+
+      if (GetPixelMask(image,q) != 0)
         {
-          if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
-              ((MagickRealType) GetPixelRed(image,q) < threshold.red))
-            SetPixelRed(image,0,q);
-          if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
-              ((MagickRealType) GetPixelGreen(image,q) < threshold.green))
-            SetPixelGreen(image,0,q);
-          if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
-              ((MagickRealType) GetPixelBlue(image,q) < threshold.blue))
-            SetPixelBlue(image,0,q);
-          if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
-              (image->colorspace == CMYKColorspace) &&
-              ((MagickRealType) GetPixelBlack(image,q) < threshold.black))
-            SetPixelBlack(image,0,q);
-          if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-              ((MagickRealType) GetPixelAlpha(image,q) < threshold.alpha))
-            SetPixelAlpha(image,0,q);
+          q+=GetPixelChannels(image);
+          continue;
         }
+      pixel=GetPixelIntensity(image,q);
+      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+      {
+        PixelChannel
+          channel;
+
+        PixelTrait
+          traits;
+
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
+        if ((traits & UpdatePixelTrait) == 0)
+          continue;
+        if (image->channel_mask != DefaultChannels)
+          pixel=(double) q[i];
+        if (pixel <= GetPixelInfoChannel(&threshold,channel))
+          q[i]=0;
+      }
       q+=GetPixelChannels(image);
     }
     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
@@ -613,7 +618,7 @@ MagickExport MagickBooleanType BlackThresholdImage(Image *image,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_BlackThresholdImage)
+        #pragma omp critical (MagickCore_BlackThresholdImage)
 #endif
         proceed=SetImageProgress(image,ThresholdImageTag,progress++,
           image->rows);
@@ -640,37 +645,35 @@ MagickExport MagickBooleanType BlackThresholdImage(Image *image,
 %
 %  The format of the ClampImage method is:
 %
-%      MagickBooleanType ClampImage(Image *image)
+%      MagickBooleanType ClampImage(Image *image,ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
 %    o image: the image.
 %
+%    o exception: return any errors or warnings in this structure.
+%
 */
 
 static inline Quantum ClampToUnsignedQuantum(const Quantum quantum)
 {
-#if defined(MAGICKCORE_HDRI_SUPPORT)
   if (quantum <= 0)
     return(0);
   if (quantum >= QuantumRange)
     return(QuantumRange);
   return(quantum);
-#else
-  return(quantum);
-#endif
 }
 
-MagickExport MagickBooleanType ClampImage(Image *image)
+MagickExport MagickBooleanType ClampImage(Image *image,ExceptionInfo *exception)
 {
+#if !defined(MAGICKCORE_HDRI_SUPPORT)
+  return(MagickTrue);
+#else
 #define ClampImageTag  "Clamp/Image"
 
   CacheView
     *image_view;
 
-  ExceptionInfo
-    *exception;
-
   MagickBooleanType
     status;
 
@@ -689,29 +692,29 @@ MagickExport MagickBooleanType ClampImage(Image *image)
       register ssize_t
         i;
 
-      register PixelPacket
+      register PixelInfo
         *restrict q;
 
       q=image->colormap;
       for (i=0; i < (ssize_t) image->colors; i++)
       {
-        q->red=ClampToUnsignedQuantum(q->red);
-        q->green=ClampToUnsignedQuantum(q->green);
-        q->blue=ClampToUnsignedQuantum(q->blue);
-        q->alpha=ClampToUnsignedQuantum(q->alpha);
+        q->red=(double) ClampToUnsignedQuantum(ClampToQuantum(q->red));
+        q->green=(double) ClampToUnsignedQuantum(ClampToQuantum(q->green));
+        q->blue=(double) ClampToUnsignedQuantum(ClampToQuantum(q->blue));
+        q->alpha=(double) ClampToUnsignedQuantum(ClampToQuantum(q->alpha));
         q++;
       }
-      return(SyncImage(image));
+      return(SyncImage(image,exception));
     }
   /*
     Clamp image.
   */
   status=MagickTrue;
   progress=0;
-  exception=(&image->exception);
-  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++)
   {
@@ -724,24 +727,35 @@ MagickExport MagickBooleanType ClampImage(Image *image)
     if (status == MagickFalse)
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
-    if (q == (const Quantum *) NULL)
+    if (q == (Quantum *) NULL)
       {
         status=MagickFalse;
         continue;
       }
     for (x=0; x < (ssize_t) image->columns; x++)
     {
-      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
-        SetPixelRed(image,ClampToUnsignedQuantum(GetPixelRed(image,q)),q);
-      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
-        SetPixelGreen(image,ClampToUnsignedQuantum(GetPixelGreen(image,q)),q);
-      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
-        SetPixelBlue(image,ClampToUnsignedQuantum(GetPixelBlue(image,q)),q);
-      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
-          (image->colorspace == CMYKColorspace))
-        SetPixelBlack(image,ClampToUnsignedQuantum(GetPixelBlack(image,q)),q);
-      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
-        SetPixelAlpha(image,ClampToUnsignedQuantum(GetPixelAlpha(image,q)),q);
+      register ssize_t
+        i;
+
+      if (GetPixelMask(image,q) != 0)
+        {
+          q+=GetPixelChannels(image);
+          continue;
+        }
+      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+      {
+        PixelChannel
+          channel;
+
+        PixelTrait
+          traits;
+
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
+        if (traits == UndefinedPixelTrait)
+          continue;
+        q[i]=ClampToUnsignedQuantum(q[i]);
+      }
       q+=GetPixelChannels(image);
     }
     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
@@ -752,16 +766,16 @@ MagickExport MagickBooleanType ClampImage(Image *image)
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_ClampImage)
+        #pragma omp critical (MagickCore_ClampImage)
 #endif
-        proceed=SetImageProgress(image,ClampImageTag,progress++,
-          image->rows);
+        proceed=SetImageProgress(image,ClampImageTag,progress++,image->rows);
         if (proceed == MagickFalse)
           status=MagickFalse;
       }
   }
   image_view=DestroyCacheView(image_view);
   return(status);
+#endif
 }
 \f
 /*
@@ -804,6 +818,54 @@ MagickExport ThresholdMap *DestroyThresholdMap(ThresholdMap *map)
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%  G e t T h r e s h o l d M a p                                              %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  GetThresholdMap() loads and searches one or more threshold map files for the
+%  map matching the given name or alias.
+%
+%  The format of the GetThresholdMap method is:
+%
+%      ThresholdMap *GetThresholdMap(const char *map_id,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows.
+%
+%    o map_id:  ID of the map to look for.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport ThresholdMap *GetThresholdMap(const char *map_id,
+  ExceptionInfo *exception)
+{
+  const StringInfo
+    *option;
+
+  LinkedListInfo
+    *options;
+
+  ThresholdMap
+    *map;
+
+  map=(ThresholdMap *)NULL;
+  options=GetConfigureOptions(ThresholdsFilename,exception);
+  while ((option=(const StringInfo *) GetNextValueInLinkedList(options)) !=
+         (const StringInfo *) NULL && (map == (ThresholdMap *) NULL))
+    map=GetThresholdMapFile((const char *) GetStringInfoDatum(option),
+      GetStringInfoPath(option),map_id,exception);
+  options=DestroyConfigureOptions(options);
+  return(map);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 +  G e t T h r e s h o l d M a p F i l e                                      %
 %                                                                             %
 %                                                                             %
@@ -829,224 +891,178 @@ MagickExport ThresholdMap *DestroyThresholdMap(ThresholdMap *map)
 %    o exception: return any errors or warnings in this structure.
 %
 */
-MagickExport ThresholdMap *GetThresholdMapFile(const char *xml,
+static ThresholdMap *GetThresholdMapFile(const char *xml,
   const char *filename,const char *map_id,ExceptionInfo *exception)
 {
+  char
+    *p;
+
   const char
-    *attr,
+    *attribute,
     *content;
 
   double
     value;
 
+  register ssize_t
+    i;
+
   ThresholdMap
-     *map;
+    *map;
 
   XMLTreeInfo
-     *description,
-     *levels,
-     *threshold,
-     *thresholds;
+    *description,
+    *levels,
+    *threshold,
+    *thresholds;
 
-  map = (ThresholdMap *)NULL;
   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
     "Loading threshold map file \"%s\" ...",filename);
+  map=(ThresholdMap *) NULL;
   thresholds=NewXMLTree(xml,exception);
-  if ( thresholds == (XMLTreeInfo *)NULL )
+  if (thresholds == (XMLTreeInfo *) NULL)
     return(map);
-
-  for( threshold = GetXMLTreeChild(thresholds,"threshold");
-       threshold != (XMLTreeInfo *)NULL;
-       threshold = GetNextXMLTreeTag(threshold) ) {
-    attr = GetXMLTreeAttribute(threshold, "map");
-    if ( (attr != (char *)NULL) && (LocaleCompare(map_id,attr) == 0) )
+  for (threshold=GetXMLTreeChild(thresholds,"threshold");
+       threshold != (XMLTreeInfo *) NULL;
+       threshold=GetNextXMLTreeTag(threshold))
+  {
+    attribute=GetXMLTreeAttribute(threshold,"map");
+    if ((attribute != (char *) NULL) && (LocaleCompare(map_id,attribute) == 0))
       break;
-    attr = GetXMLTreeAttribute(threshold, "alias");
-    if ( (attr != (char *)NULL) && (LocaleCompare(map_id,attr) == 0) )
+    attribute=GetXMLTreeAttribute(threshold,"alias");
+    if ((attribute != (char *) NULL) && (LocaleCompare(map_id,attribute) == 0))
       break;
   }
-  if ( threshold == (XMLTreeInfo *)NULL ) {
-    return(map);
-  }
-  description = GetXMLTreeChild(threshold,"description");
-  if ( description == (XMLTreeInfo *)NULL ) {
-    (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-      "XmlMissingElement", "<description>, map \"%s\"", map_id);
-    thresholds = DestroyXMLTree(thresholds);
+  if (threshold == (XMLTreeInfo *) NULL)
     return(map);
-  }
-  levels = GetXMLTreeChild(threshold,"levels");
-  if ( levels == (XMLTreeInfo *)NULL ) {
-    (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-      "XmlMissingElement", "<levels>, map \"%s\"", map_id);
-    thresholds = DestroyXMLTree(thresholds);
-    return(map);
-  }
-
-  /* The map has been found -- Allocate a Threshold Map to return */
-  map = (ThresholdMap *)AcquireMagickMemory(sizeof(ThresholdMap));
-  if ( map == (ThresholdMap *)NULL )
+  description=GetXMLTreeChild(threshold,"description");
+  if (description == (XMLTreeInfo *) NULL)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+        "XmlMissingElement", "<description>, map \"%s\"",map_id);
+      thresholds=DestroyXMLTree(thresholds);
+      return(map);
+    }
+  levels=GetXMLTreeChild(threshold,"levels");
+  if (levels == (XMLTreeInfo *) NULL)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+        "XmlMissingElement", "<levels>, map \"%s\"", map_id);
+      thresholds=DestroyXMLTree(thresholds);
+      return(map);
+    }
+  map=(ThresholdMap *) AcquireMagickMemory(sizeof(ThresholdMap));
+  if (map == (ThresholdMap *) NULL)
     ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireThresholdMap");
-  map->map_id = (char *)NULL;
-  map->description = (char *)NULL;
-  map->levels = (ssize_t *) NULL;
-
-  /* Assign Basic Attributes */
-  attr = GetXMLTreeAttribute(threshold, "map");
-  if ( attr != (char *)NULL )
-    map->map_id = ConstantString(attr);
-
-  content = GetXMLTreeContent(description);
-  if ( content != (char *)NULL )
-    map->description = ConstantString(content);
-
-  attr = GetXMLTreeAttribute(levels, "width");
-  if ( attr == (char *)NULL ) {
-    (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-      "XmlMissingAttribute", "<levels width>, map \"%s\"", map_id);
-    thresholds = DestroyXMLTree(thresholds);
-    map = DestroyThresholdMap(map);
-    return(map);
-  }
-  map->width = StringToUnsignedLong(attr);
-  if ( map->width == 0 ) {
-    (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-     "XmlInvalidAttribute", "<levels width>, map \"%s\"", map_id);
-    thresholds = DestroyXMLTree(thresholds);
-    map = DestroyThresholdMap(map);
-    return(map);
-  }
-
-  attr = GetXMLTreeAttribute(levels, "height");
-  if ( attr == (char *)NULL ) {
-    (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-      "XmlMissingAttribute", "<levels height>, map \"%s\"", map_id);
-    thresholds = DestroyXMLTree(thresholds);
-    map = DestroyThresholdMap(map);
-    return(map);
-  }
-  map->height = StringToUnsignedLong(attr);
-  if ( map->height == 0 ) {
-    (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-      "XmlInvalidAttribute", "<levels height>, map \"%s\"", map_id);
-    thresholds = DestroyXMLTree(thresholds);
-    map = DestroyThresholdMap(map);
-    return(map);
-  }
-
-  attr = GetXMLTreeAttribute(levels, "divisor");
-  if ( attr == (char *)NULL ) {
-    (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-      "XmlMissingAttribute", "<levels divisor>, map \"%s\"", map_id);
-    thresholds = DestroyXMLTree(thresholds);
-    map = DestroyThresholdMap(map);
-    return(map);
-  }
-  map->divisor = (ssize_t) StringToLong(attr);
-  if ( map->divisor < 2 ) {
-    (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-      "XmlInvalidAttribute", "<levels divisor>, map \"%s\"", map_id);
-    thresholds = DestroyXMLTree(thresholds);
-    map = DestroyThresholdMap(map);
-    return(map);
-  }
-
-  /* Allocate theshold levels array */
-  content = GetXMLTreeContent(levels);
-  if ( content == (char *)NULL ) {
-    (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-      "XmlMissingContent", "<levels>, map \"%s\"", map_id);
-    thresholds = DestroyXMLTree(thresholds);
-    map = DestroyThresholdMap(map);
-    return(map);
-  }
+  map->map_id=(char *) NULL;
+  map->description=(char *) NULL;
+  map->levels=(ssize_t *) NULL;
+  attribute=GetXMLTreeAttribute(threshold,"map");
+  if (attribute != (char *) NULL)
+    map->map_id=ConstantString(attribute);
+  content=GetXMLTreeContent(description);
+  if (content != (char *) NULL)
+    map->description=ConstantString(content);
+  attribute=GetXMLTreeAttribute(levels,"width");
+  if (attribute == (char *) NULL)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+        "XmlMissingAttribute", "<levels width>, map \"%s\"",map_id);
+      thresholds=DestroyXMLTree(thresholds);
+      map=DestroyThresholdMap(map);
+      return(map);
+    }
+  map->width=StringToUnsignedLong(attribute);
+  if (map->width == 0)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+       "XmlInvalidAttribute", "<levels width>, map \"%s\"",map_id);
+      thresholds=DestroyXMLTree(thresholds);
+      map=DestroyThresholdMap(map);
+      return(map);
+    }
+  attribute=GetXMLTreeAttribute(levels,"height");
+  if (attribute == (char *) NULL)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+        "XmlMissingAttribute", "<levels height>, map \"%s\"",map_id);
+      thresholds=DestroyXMLTree(thresholds);
+      map=DestroyThresholdMap(map);
+      return(map);
+    }
+  map->height=StringToUnsignedLong(attribute);
+  if (map->height == 0)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+        "XmlInvalidAttribute", "<levels height>, map \"%s\"",map_id);
+      thresholds=DestroyXMLTree(thresholds);
+      map=DestroyThresholdMap(map);
+      return(map);
+    }
+  attribute=GetXMLTreeAttribute(levels,"divisor");
+  if (attribute == (char *) NULL)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+        "XmlMissingAttribute", "<levels divisor>, map \"%s\"",map_id);
+      thresholds=DestroyXMLTree(thresholds);
+      map=DestroyThresholdMap(map);
+      return(map);
+    }
+  map->divisor=(ssize_t) StringToLong(attribute);
+  if (map->divisor < 2)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+        "XmlInvalidAttribute", "<levels divisor>, map \"%s\"",map_id);
+      thresholds=DestroyXMLTree(thresholds);
+      map=DestroyThresholdMap(map);
+      return(map);
+    }
+  content=GetXMLTreeContent(levels);
+  if (content == (char *) NULL)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+        "XmlMissingContent", "<levels>, map \"%s\"",map_id);
+      thresholds=DestroyXMLTree(thresholds);
+      map=DestroyThresholdMap(map);
+      return(map);
+    }
   map->levels=(ssize_t *) AcquireQuantumMemory((size_t) map->width,map->height*
     sizeof(*map->levels));
-  if ( map->levels == (ssize_t *)NULL )
+  if (map->levels == (ssize_t *) NULL)
     ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireThresholdMap");
-  { /* parse levels into integer array */
-    ssize_t i;
-    char *p;
-    for( i=0; i< (ssize_t) (map->width*map->height); i++) {
-      map->levels[i] = (ssize_t)strtol(content, &p, 10);
-      if ( p == content ) {
+  for (i=0; i < (ssize_t) (map->width*map->height); i++)
+  {
+    map->levels[i]=(ssize_t) strtol(content,&p,10);
+    if (p == content)
+      {
         (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-          "XmlInvalidContent", "<level> too few values, map \"%s\"", map_id);
-        thresholds = DestroyXMLTree(thresholds);
-        map = DestroyThresholdMap(map);
+          "XmlInvalidContent", "<level> too few values, map \"%s\"",map_id);
+        thresholds=DestroyXMLTree(thresholds);
+        map=DestroyThresholdMap(map);
         return(map);
       }
-      if ( map->levels[i] < 0 || map->levels[i] > map->divisor ) {
+    if ((map->levels[i] < 0) || (map->levels[i] > map->divisor))
+      {
         (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
           "XmlInvalidContent", "<level> %.20g out of range, map \"%s\"",
           (double) map->levels[i],map_id);
-        thresholds = DestroyXMLTree(thresholds);
-        map = DestroyThresholdMap(map);
+        thresholds=DestroyXMLTree(thresholds);
+        map=DestroyThresholdMap(map);
         return(map);
       }
-      content = p;
-    }
-    value=(double) strtol(content,&p,10);
-    (void) value;
-    if (p != content)
-      {
-        (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-          "XmlInvalidContent", "<level> too many values, map \"%s\"", map_id);
-       thresholds=DestroyXMLTree(thresholds);
-       map=DestroyThresholdMap(map);
-       return(map);
-     }
+    content=p;
   }
-
-  thresholds = DestroyXMLTree(thresholds);
-  return(map);
-}
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%  G e t T h r e s h o l d M a p                                              %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  GetThresholdMap() load and search one or more threshold map files for the
-%  a map matching the given name or aliase.
-%
-%  The format of the GetThresholdMap method is:
-%
-%      ThresholdMap *GetThresholdMap(const char *map_id,
-%         ExceptionInfo *exception)
-%
-%  A description of each parameter follows.
-%
-%    o map_id:  ID of the map to look for.
-%
-%    o exception: return any errors or warnings in this structure.
-%
-*/
-MagickExport ThresholdMap *GetThresholdMap(const char *map_id,
-  ExceptionInfo *exception)
-{
-  const StringInfo
-    *option;
-
-  LinkedListInfo
-    *options;
-
-  ThresholdMap
-    *map;
-
-  map=(ThresholdMap *)NULL;
-  options=GetConfigureOptions(ThresholdsFilename,exception);
-  while (( option=(const StringInfo *) GetNextValueInLinkedList(options) )
-          != (const StringInfo *) NULL && map == (ThresholdMap *)NULL )
-    map=GetThresholdMapFile((const char *) GetStringInfoDatum(option),
-      GetStringInfoPath(option),map_id,exception);
-  options=DestroyConfigureOptions(options);
+  value=(double) strtol(content,&p,10);
+  (void) value;
+  if (p != content)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+        "XmlInvalidContent", "<level> too many values, map \"%s\"",map_id);
+     thresholds=DestroyXMLTree(thresholds);
+     map=DestroyThresholdMap(map);
+     return(map);
+   }
+  thresholds=DestroyXMLTree(thresholds);
   return(map);
 }
 \f
@@ -1083,49 +1099,55 @@ MagickExport ThresholdMap *GetThresholdMap(const char *map_id,
 MagickBooleanType ListThresholdMapFile(FILE *file,const char *xml,
   const char *filename,ExceptionInfo *exception)
 {
-  XMLTreeInfo *thresholds,*threshold,*description;
-  const char *map,*alias,*content;
+  const char
+    *alias,
+    *content,
+    *map;
+
+  XMLTreeInfo
+    *description,
+    *threshold,
+    *thresholds;
 
   assert( xml != (char *)NULL );
   assert( file != (FILE *)NULL );
-
   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
     "Loading threshold map file \"%s\" ...",filename);
   thresholds=NewXMLTree(xml,exception);
   if ( thresholds == (XMLTreeInfo *)NULL )
     return(MagickFalse);
-
   (void) FormatLocaleFile(file,"%-16s %-12s %s\n","Map","Alias","Description");
   (void) FormatLocaleFile(file,
     "----------------------------------------------------\n");
-
-  for( threshold = GetXMLTreeChild(thresholds,"threshold");
-       threshold != (XMLTreeInfo *)NULL;
-       threshold = GetNextXMLTreeTag(threshold) )
+  threshold=GetXMLTreeChild(thresholds,"threshold");
+  for ( ; threshold != (XMLTreeInfo *) NULL;
+          threshold=GetNextXMLTreeTag(threshold))
   {
-    map = GetXMLTreeAttribute(threshold, "map");
-    if (map == (char *) NULL) {
-      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-        "XmlMissingAttribute", "<map>");
-      thresholds=DestroyXMLTree(thresholds);
-      return(MagickFalse);
-    }
-    alias = GetXMLTreeAttribute(threshold, "alias");
-    /* alias is optional, no if test needed */
+    map=GetXMLTreeAttribute(threshold,"map");
+    if (map == (char *) NULL)
+      {
+        (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+          "XmlMissingAttribute", "<map>");
+        thresholds=DestroyXMLTree(thresholds);
+        return(MagickFalse);
+      }
+    alias=GetXMLTreeAttribute(threshold,"alias");
     description=GetXMLTreeChild(threshold,"description");
-    if ( description == (XMLTreeInfo *)NULL ) {
-      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-        "XmlMissingElement", "<description>, map \"%s\"", map);
-      thresholds=DestroyXMLTree(thresholds);
-      return(MagickFalse);
-    }
+    if (description == (XMLTreeInfo *) NULL)
+      {
+        (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+          "XmlMissingElement", "<description>, map \"%s\"",map);
+        thresholds=DestroyXMLTree(thresholds);
+        return(MagickFalse);
+      }
     content=GetXMLTreeContent(description);
-    if ( content == (char *)NULL ) {
-      (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-        "XmlMissingContent", "<description>, map \"%s\"", map);
-      thresholds=DestroyXMLTree(thresholds);
-      return(MagickFalse);
-    }
+    if (content == (char *) NULL)
+      {
+        (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+          "XmlMissingContent", "<description>, map \"%s\"", map);
+        thresholds=DestroyXMLTree(thresholds);
+        return(MagickFalse);
+      }
     (void) FormatLocaleFile(file,"%-16s %-12s %s\n",map,alias ? alias : "",
       content);
   }
@@ -1171,14 +1193,13 @@ MagickExport MagickBooleanType ListThresholdMaps(FILE *file,
     status;
 
   status=MagickFalse;
-  if ( file == (FILE *)NULL )
-    file = stdout;
+  if (file == (FILE *) NULL)
+    file=stdout;
   options=GetConfigureOptions(ThresholdsFilename,exception);
-
   (void) FormatLocaleFile(file,
     "\n   Threshold Maps for Ordered Dither Operations\n");
-  while ( ( option=(const StringInfo *) GetNextValueInLinkedList(options) )
-          != (const StringInfo *) NULL)
+  while ((option=(const StringInfo *) GetNextValueInLinkedList(options)) !=
+         (const StringInfo *) NULL)
   {
     (void) FormatLocaleFile(file,"\nPATH: %s\n\n",GetStringInfoPath(option));
     status|=ListThresholdMapFile(file,(const char *) GetStringInfoDatum(option),
@@ -1243,8 +1264,11 @@ MagickExport MagickBooleanType OrderedPosterizeImage(Image *image,
   CacheView
     *image_view;
 
-  LongPixelPacket
-    levels;
+  char
+    token[MaxTextExtent];
+
+  const char
+    *p;
 
   MagickBooleanType
     status;
@@ -1252,6 +1276,12 @@ MagickExport MagickBooleanType OrderedPosterizeImage(Image *image,
   MagickOffsetType
     progress;
 
+  double
+    levels[CompositePixelChannel];
+
+  register ssize_t
+    i;
+
   ssize_t
     y;
 
@@ -1266,218 +1296,124 @@ MagickExport MagickBooleanType OrderedPosterizeImage(Image *image,
   assert(exception->signature == MagickSignature);
   if (threshold_map == (const char *) NULL)
     return(MagickTrue);
+  p=(char *) threshold_map;
+  while (((isspace((int) ((unsigned char) *p)) != 0) || (*p == ',')) &&
+         (*p != '\0'))
+    p++;
+  threshold_map=p;
+  while (((isspace((int) ((unsigned char) *p)) == 0) && (*p != ',')) &&
+         (*p != '\0'))
   {
-    char
-      token[MaxTextExtent];
-
-    register const char
-      *p;
-
-    p=(char *)threshold_map;
-    while (((isspace((int) ((unsigned char) *p)) != 0) || (*p == ',')) &&
-                    (*p != '\0'))
-      p++;
-    threshold_map=p;
-    while (((isspace((int) ((unsigned char) *p)) == 0) && (*p != ',')) &&
-                    (*p != '\0')) {
-      if ((p-threshold_map) >= (MaxTextExtent-1))
-        break;
-      token[p-threshold_map] = *p;
-      p++;
-    }
-    token[p-threshold_map] = '\0';
-    map = GetThresholdMap(token, exception);
-    if ( map == (ThresholdMap *)NULL ) {
+    if ((p-threshold_map) >= (MaxTextExtent-1))
+      break;
+    token[p-threshold_map]=(*p);
+    p++;
+  }
+  token[p-threshold_map]='\0';
+  map=GetThresholdMap(token,exception);
+  if (map == (ThresholdMap *) NULL)
+    {
       (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
         "InvalidArgument","%s : '%s'","ordered-dither",threshold_map);
       return(MagickFalse);
     }
-  }
-  /* Set channel levels from extra comma separated arguments
-     Default to 2, the single value given, or individual channel values
-  */
-#if 1
-  { /* parse directly as a comma separated list of integers */
-    char *p;
-
-    p = strchr((char *) threshold_map,',');
-    levels.red=0;
-    levels.green=0;
-    levels.blue=0;
-    levels.black=0;
-    levels.alpha=0;
-    if ( p != (char *)NULL && isdigit((int) ((unsigned char) *(++p))) )
-      levels.black = (unsigned int) strtoul(p, &p, 10);
-    else
-      levels.black = 2;
-
-    if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
-      levels.red=levels.black;
-    if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
-      levels.green=levels.black;
-    if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
-      levels.blue=levels.black;
-    if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
-        (image->colorspace == CMYKColorspace))
-      levels.black=levels.black;
-    if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-        (image->matte != MagickFalse))
-      levels.alpha=levels.black;
-
-    /* if more than a single number, each channel has a separate value */
-    if ( p != (char *) NULL && *p == ',' ) {
-      p=strchr((char *) threshold_map,',');
-      p++;
-      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
-        levels.red = (unsigned int) strtoul(p, &p, 10),   (void)(*p == ',' && p++);
-      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
-        levels.green = (unsigned int) strtoul(p, &p, 10), (void)(*p == ',' && p++);
-      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
-        levels.blue = (unsigned int) strtoul(p, &p, 10),  (void)(*p == ',' && p++);
-      if ((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0 &&
-          (image->colorspace == CMYKColorspace))
-        levels.black=(unsigned int) strtoul(p, &p, 10), (void)(*p == ',' && p++);
-      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
-        levels.alpha = (unsigned int) strtoul(p, &p, 10), (void)(*p == ',' && p++);
+  for (i=0; i < MaxPixelChannels; i++)
+    levels[i]=2.0;
+  p=strchr((char *) threshold_map,',');
+  if ((p != (char *) NULL) && (isdigit((int) ((unsigned char) *(++p))) != 0))
+    for (i=0; (*p != '\0') && (i < MaxPixelChannels); i++)
+    {
+      GetMagickToken(p,&p,token);
+      if (*token == ',')
+        GetMagickToken(p,&p,token);
+      levels[i]=StringToDouble(token,(char **) NULL);
     }
-  }
-#else
-  /* Parse level values as a geometry */
-  /* This difficult!
-   * How to map   GeometryInfo structure elements into
-   * LongPixelPacket structure elements, but according to channel?
-   * Note the channels list may skip elements!!!!
-   * EG  -channel BA  -ordered-dither map,2,3
-   * will need to map  g.rho -> l.blue, and g.sigma -> l.alpha
-   * A simpler way is needed, probably converting geometry to a temporary
-   * array, then using channel to advance the index into ssize_t pixel packet.
-   */
-#endif
-
-#if 0
-printf("DEBUG levels  r=%u g=%u b=%u a=%u i=%u\n",
-     levels.red, levels.green, levels.blue, levels.alpha, levels.index);
+  for (i=0; i < MaxPixelChannels; i++)
+    if (fabs(levels[i]) >= 1)
+      levels[i]-=1.0;
+  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
+    return(MagickFalse);
+  status=MagickTrue;
+  progress=0;
+  image_view=AcquireAuthenticCacheView(image,exception);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+  #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++)
+  {
+    register ssize_t
+      x;
 
-  { /* Do the posterized ordered dithering of the image */
-    ssize_t
-      d;
-
-    /* d = number of psuedo-level divisions added between color levels */
-    d = map->divisor-1;
-
-    /* reduce levels to levels - 1 */
-    levels.red     = levels.red     ? levels.red-1     : 0;
-    levels.green   = levels.green   ? levels.green-1   : 0;
-    levels.blue    = levels.blue    ? levels.blue-1    : 0;
-    levels.black   = levels.black   ? levels.black-1   : 0;
-    levels.alpha = levels.alpha ? levels.alpha-1 : 0;
+    register Quantum
+      *restrict q;
 
-    if (SetImageStorageClass(image,DirectClass) == MagickFalse)
+    if (status == MagickFalse)
+      continue;
+    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
+    if (q == (Quantum *) NULL)
       {
-        InheritException(exception,&image->exception);
-        return(MagickFalse);
+        status=MagickFalse;
+        continue;
       }
-    status=MagickTrue;
-    progress=0;
-    image_view=AcquireCacheView(image);
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
-#endif
-    for (y=0; y < (ssize_t) image->rows; y++)
+    for (x=0; x < (ssize_t) image->columns; x++)
     {
       register ssize_t
-        x;
+        i;
 
-      register Quantum
-        *restrict q;
+      ssize_t
+        n;
 
-      if (status == MagickFalse)
-        continue;
-      q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
-      if (q == (const Quantum *) NULL)
+      n=0;
+      if (GetPixelMask(image,q) != 0)
         {
-          status=MagickFalse;
+          q+=GetPixelChannels(image);
           continue;
         }
-      for (x=0; x < (ssize_t) image->columns; x++)
+      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
-        register ssize_t
-          threshold,
-          t,
-          l;
-
-        /*
-          Figure out the dither threshold for this pixel
-          This must be a integer from 1 to map->divisor-1
-        */
-        threshold = map->levels[(x%map->width) +map->width*(y%map->height)];
-
-        /* Dither each channel in the image as appropriate
-          Notes on the integer Math...
-              total number of divisions = (levels-1)*(divisor-1)+1)
-              t1 = this colors psuedo_level =
-                      q->red * total_divisions / (QuantumRange+1)
-              l = posterization level       0..levels
-              t = dither threshold level    0..divisor-1  NB: 0 only on last
-              Each color_level is of size   QuantumRange / (levels-1)
-              NB: All input levels and divisor are already had 1 subtracted
-              Opacity is inverted so 'off' represents transparent.
-        */
-        if (levels.red != 0) {
-          t = (ssize_t) (QuantumScale*GetPixelRed(image,q)*(levels.red*d+1));
-          l = t/d;  t = t-l*d;
-          SetPixelRed(image,RoundToQuantum((MagickRealType)
-            ((l+(t >= threshold))*(MagickRealType) QuantumRange/levels.red)),q);
-        }
-        if (levels.green != 0) {
-          t = (ssize_t) (QuantumScale*GetPixelGreen(image,q)*
-            (levels.green*d+1));
-          l = t/d;  t = t-l*d;
-          SetPixelGreen(image,RoundToQuantum((MagickRealType)
-            ((l+(t >= threshold))*(MagickRealType) QuantumRange/levels.green)),q);
-        }
-        if (levels.blue != 0) {
-          t = (ssize_t) (QuantumScale*GetPixelBlue(image,q)*
-            (levels.blue*d+1));
-          l = t/d;  t = t-l*d;
-          SetPixelBlue(image,RoundToQuantum((MagickRealType)
-            ((l+(t >= threshold))*(MagickRealType) QuantumRange/levels.blue)),q);
-        }
-        if (levels.alpha != 0) {
-          t = (ssize_t) ((1.0-QuantumScale*GetPixelAlpha(image,q))*
-            (levels.alpha*d+1));
-          l = t/d;  t = t-l*d;
-          SetPixelAlpha(image,RoundToQuantum((MagickRealType)
-            ((1.0-l-(t >= threshold))*(MagickRealType) QuantumRange/
-            levels.alpha)),q);
-        }
-        if (levels.black != 0) {
-          t = (ssize_t) (QuantumScale*GetPixelBlack(image,q)*
-            (levels.black*d+1));
-          l = t/d;  t = t-l*d;
-          SetPixelBlack(image,RoundToQuantum((MagickRealType)
-            ((l+(t>=threshold))*(MagickRealType) QuantumRange/levels.black)),q);
-        }
-        q+=GetPixelChannels(image);
+        PixelChannel
+          channel;
+
+        PixelTrait
+          traits;
+
+        ssize_t
+          level,
+          threshold;
+
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
+        if ((traits & UpdatePixelTrait) == 0)
+          continue;
+        if (fabs(levels[n++]) < MagickEpsilon)
+          continue;
+        threshold=(ssize_t) (QuantumScale*q[i]*(levels[n]*(map->divisor-1)+1));
+        level=threshold/(map->divisor-1);
+        threshold-=level*(map->divisor-1);
+        q[i]=ClampToQuantum((double) (level+(threshold >=
+          map->levels[(x % map->width)+map->width*(y % map->height)]))*
+          QuantumRange/levels[n]);
+        n++;
       }
-      if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
-        status=MagickFalse;
-      if (image->progress_monitor != (MagickProgressMonitor) NULL)
-        {
-          MagickBooleanType
-            proceed;
+      q+=GetPixelChannels(image);
+    }
+    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+      status=MagickFalse;
+    if (image->progress_monitor != (MagickProgressMonitor) NULL)
+      {
+        MagickBooleanType
+          proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_OrderedPosterizeImage)
+        #pragma omp critical (MagickCore_OrderedPosterizeImage)
 #endif
-          proceed=SetImageProgress(image,DitherImageTag,progress++,image->rows);
-          if (proceed == MagickFalse)
-            status=MagickFalse;
-        }
-    }
-    image_view=DestroyCacheView(image_view);
+        proceed=SetImageProgress(image,DitherImageTag,progress++,image->rows);
+        if (proceed == MagickFalse)
+          status=MagickFalse;
+      }
   }
+  image_view=DestroyCacheView(image_view);
   map=DestroyThresholdMap(map);
   return(MagickTrue);
 }
@@ -1536,7 +1472,7 @@ MagickExport MagickBooleanType RandomThresholdImage(Image *image,
   PixelInfo
     threshold;
 
-  MagickRealType
+  double
     min_threshold,
     max_threshold;
 
@@ -1546,6 +1482,9 @@ MagickExport MagickBooleanType RandomThresholdImage(Image *image,
   ssize_t
     y;
 
+  unsigned long
+    key;
+
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
   if (image->debug != MagickFalse)
@@ -1554,9 +1493,11 @@ MagickExport MagickBooleanType RandomThresholdImage(Image *image,
   assert(exception->signature == MagickSignature);
   if (thresholds == (const char *) NULL)
     return(MagickTrue);
+  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
+    return(MagickFalse);
   GetPixelInfo(image,&threshold);
   min_threshold=0.0;
-  max_threshold=(MagickRealType) QuantumRange;
+  max_threshold=(double) QuantumRange;
   flags=ParseGeometry(thresholds,&geometry_info);
   min_threshold=geometry_info.rho;
   max_threshold=geometry_info.sigma;
@@ -1564,99 +1505,20 @@ MagickExport MagickBooleanType RandomThresholdImage(Image *image,
     max_threshold=min_threshold;
   if (strchr(thresholds,'%') != (char *) NULL)
     {
-      max_threshold*=(MagickRealType) (0.01*QuantumRange);
-      min_threshold*=(MagickRealType) (0.01*QuantumRange);
+      max_threshold*=(double) (0.01*QuantumRange);
+      min_threshold*=(double) (0.01*QuantumRange);
     }
   /*
     Random threshold image.
   */
   status=MagickTrue;
   progress=0;
-  if (image->sync != MagickFalse)
-    {
-      if (AcquireImageColormap(image,2) == MagickFalse)
-        ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
-          image->filename);
-      random_info=AcquireRandomInfoThreadSet();
-      image_view=AcquireCacheView(image);
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
-#endif
-      for (y=0; y < (ssize_t) image->rows; y++)
-      {
-        const int
-          id = GetOpenMPThreadId();
-
-        MagickBooleanType
-          sync;
-
-        register ssize_t
-          x;
-
-        register Quantum
-          *restrict q;
-
-        if (status == MagickFalse)
-          continue;
-        q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
-          exception);
-        if (q == (const Quantum *) NULL)
-          {
-            status=MagickFalse;
-            continue;
-          }
-        for (x=0; x < (ssize_t) image->columns; x++)
-        {
-          MagickRealType
-            intensity;
-
-          Quantum
-            index;
-
-          intensity=(MagickRealType) GetPixelIntensity(image,q);
-          if (intensity < min_threshold)
-            threshold.black=min_threshold;
-          else
-            if (intensity > max_threshold)
-              threshold.black=max_threshold;
-            else
-              threshold.black=(MagickRealType)(QuantumRange*
-                GetPseudoRandomValue(random_info[id]));
-          index=(Quantum) (intensity <= threshold.black ? 0 : 1);
-          SetPixelIndex(image,index,q);
-          SetPixelPacket(image,image->colormap+(ssize_t) index,q);
-          q+=GetPixelChannels(image);
-        }
-        sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
-          status=MagickFalse;
-        if (image->progress_monitor != (MagickProgressMonitor) NULL)
-          {
-            MagickBooleanType
-              proceed;
-
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_RandomThresholdImage)
-#endif
-            proceed=SetImageProgress(image,ThresholdImageTag,progress++,
-              image->rows);
-            if (proceed == MagickFalse)
-              status=MagickFalse;
-          }
-      }
-      image_view=DestroyCacheView(image_view);
-      random_info=DestroyRandomInfoThreadSet(random_info);
-      return(status);
-    }
-  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
-    {
-      InheritException(exception,&image->exception);
-      return(MagickFalse);
-    }
   random_info=AcquireRandomInfoThreadSet();
-  image_view=AcquireCacheView(image);
+  key=GetRandomSecretKey(random_info[0]);
+  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,key == ~0UL)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -1672,85 +1534,46 @@ MagickExport MagickBooleanType RandomThresholdImage(Image *image,
     if (status == MagickFalse)
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
-    if (q == (const Quantum *) NULL)
+    if (q == (Quantum *) NULL)
       {
         status=MagickFalse;
         continue;
       }
     for (x=0; x < (ssize_t) image->columns; x++)
     {
-      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
-        {
-          if ((MagickRealType) GetPixelRed(image,q) < min_threshold)
-            threshold.red=min_threshold;
-          else
-            if ((MagickRealType) GetPixelRed(image,q) > max_threshold)
-              threshold.red=max_threshold;
-            else
-              threshold.red=(MagickRealType) (QuantumRange*
-                GetPseudoRandomValue(random_info[id]));
-        }
-      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
-        {
-          if ((MagickRealType) GetPixelGreen(image,q) < min_threshold)
-            threshold.green=min_threshold;
-          else
-            if ((MagickRealType) GetPixelGreen(image,q) > max_threshold)
-              threshold.green=max_threshold;
-            else
-              threshold.green=(MagickRealType) (QuantumRange*
-                GetPseudoRandomValue(random_info[id]));
-        }
-      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
-        {
-          if ((MagickRealType) GetPixelBlue(image,q) < min_threshold)
-            threshold.blue=min_threshold;
-          else
-            if ((MagickRealType) GetPixelBlue(image,q) > max_threshold)
-              threshold.blue=max_threshold;
-            else
-              threshold.blue=(MagickRealType) (QuantumRange*
-                GetPseudoRandomValue(random_info[id]));
-        }
-      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
-          (image->colorspace == CMYKColorspace))
+      register ssize_t
+        i;
+
+      if (GetPixelMask(image,q) != 0)
         {
-          if ((MagickRealType) GetPixelBlack(image,q) < min_threshold)
-            threshold.black=min_threshold;
-          else
-            if ((MagickRealType) GetPixelBlack(image,q) > max_threshold)
-              threshold.black=max_threshold;
-            else
-              threshold.black=(MagickRealType) (QuantumRange*
-                GetPseudoRandomValue(random_info[id]));
+          q+=GetPixelChannels(image);
+          continue;
         }
-      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
-        {
-          if ((MagickRealType) GetPixelAlpha(image,q) < min_threshold)
-            threshold.alpha=min_threshold;
+      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+      {
+        double
+          threshold;
+
+        PixelChannel
+          channel;
+
+        PixelTrait
+          traits;
+
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
+        if ((traits & UpdatePixelTrait) == 0)
+          continue;
+        if ((double) q[i] < min_threshold)
+          threshold=min_threshold;
+        else
+          if ((double) q[i] > max_threshold)
+            threshold=max_threshold;
           else
-            if ((MagickRealType) GetPixelAlpha(image,q) > max_threshold)
-              threshold.alpha=max_threshold;
-            else
-              threshold.alpha=(MagickRealType) (QuantumRange*
-                GetPseudoRandomValue(random_info[id]));
-        }
-      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
-        SetPixelRed(image,(Quantum) ((MagickRealType)
-          GetPixelRed(image,q) <= threshold.red ? 0 : QuantumRange),q);
-      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
-        SetPixelGreen(image,(Quantum) ((MagickRealType)
-          GetPixelGreen(image,q) <= threshold.green ? 0 : QuantumRange),q);
-      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
-        SetPixelBlue(image,(Quantum) ((MagickRealType)
-          GetPixelBlue(image,q) <= threshold.blue ? 0 : QuantumRange),q);
-      if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
-          (image->colorspace == CMYKColorspace))
-        SetPixelBlack(image,(Quantum) ((MagickRealType)
-          GetPixelBlack(image,q) <= threshold.black ? 0 : QuantumRange),q);
-      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
-        SetPixelAlpha(image,(Quantum) ((MagickRealType)
-          GetPixelAlpha(image,q) <= threshold.alpha ? 0 : QuantumRange),q);
+            threshold=(double) (QuantumRange*
+              GetPseudoRandomValue(random_info[id]));
+        q[i]=(double) q[i] <= threshold ? 0 : QuantumRange;
+      }
       q+=GetPixelChannels(image);
     }
     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
@@ -1761,7 +1584,7 @@ MagickExport MagickBooleanType RandomThresholdImage(Image *image,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_RandomThresholdImage)
+        #pragma omp critical (MagickCore_RandomThresholdImage)
 #endif
         proceed=SetImageProgress(image,ThresholdImageTag,progress++,
           image->rows);
@@ -1817,12 +1640,12 @@ MagickExport MagickBooleanType WhiteThresholdImage(Image *image,
   MagickBooleanType
     status;
 
-  PixelInfo
-    threshold;
-
   MagickOffsetType
     progress;
 
+  PixelInfo
+    threshold;
+
   MagickStatusType
     flags;
 
@@ -1835,39 +1658,47 @@ MagickExport MagickBooleanType WhiteThresholdImage(Image *image,
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (thresholds == (const char *) NULL)
     return(MagickTrue);
-  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
+  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
     return(MagickFalse);
-  flags=ParseGeometry(thresholds,&geometry_info);
+  if (IsGrayColorspace(image->colorspace) != MagickFalse)
+    (void) TransformImageColorspace(image,RGBColorspace,exception);
   GetPixelInfo(image,&threshold);
+  flags=ParseGeometry(thresholds,&geometry_info);
   threshold.red=geometry_info.rho;
-  threshold.green=geometry_info.sigma;
-  if ((flags & SigmaValue) == 0)
-    threshold.green=threshold.red;
-  threshold.blue=geometry_info.xi;
-  if ((flags & XiValue) == 0)
-    threshold.blue=threshold.red;
-  threshold.alpha=geometry_info.psi;
-  if ((flags & PsiValue) == 0)
-    threshold.alpha=threshold.red;
-  threshold.black=geometry_info.chi;
-  if ((flags & ChiValue) == 0)
-    threshold.black=threshold.red;
+  threshold.green=geometry_info.rho;
+  threshold.blue=geometry_info.rho;
+  threshold.black=geometry_info.rho;
+  threshold.alpha=100.0;
+  if ((flags & SigmaValue) != 0)
+    threshold.green=geometry_info.sigma;
+  if ((flags & XiValue) != 0)
+    threshold.blue=geometry_info.xi;
+  if ((flags & PsiValue) != 0)
+    threshold.alpha=geometry_info.psi;
+  if (threshold.colorspace == CMYKColorspace)
+    {
+      if ((flags & PsiValue) != 0)
+        threshold.black=geometry_info.psi;
+      if ((flags & ChiValue) != 0)
+        threshold.alpha=geometry_info.chi;
+    }
   if ((flags & PercentValue) != 0)
     {
       threshold.red*=(QuantumRange/100.0);
       threshold.green*=(QuantumRange/100.0);
       threshold.blue*=(QuantumRange/100.0);
-      threshold.alpha*=(QuantumRange/100.0);
       threshold.black*=(QuantumRange/100.0);
+      threshold.alpha*=(QuantumRange/100.0);
     }
   /*
     White threshold 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++)
   {
@@ -1880,43 +1711,42 @@ MagickExport MagickBooleanType WhiteThresholdImage(Image *image,
     if (status == MagickFalse)
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
-    if (q == (const Quantum *) NULL)
+    if (q == (Quantum *) NULL)
       {
         status=MagickFalse;
         continue;
       }
     for (x=0; x < (ssize_t) image->columns; x++)
     {
-      if (image->sync != MagickFalse)
-        {
-          if (GetPixelIntensity(image,q) > GetPixelInfoIntensity(&threshold))
-            {
-              SetPixelRed(image,QuantumRange,q);
-              SetPixelGreen(image,QuantumRange,q);
-              SetPixelBlue(image,QuantumRange,q);
-              if (image->colorspace == CMYKColorspace)
-                SetPixelBlack(image,QuantumRange,q);
-            }
-        }
-      else
+      double
+        pixel;
+
+      register ssize_t
+        i;
+
+      if (GetPixelMask(image,q) != 0)
         {
-          if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
-              ((MagickRealType) GetPixelRed(image,q) > threshold.red))
-            SetPixelRed(image,QuantumRange,q);
-          if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
-              ((MagickRealType) GetPixelGreen(image,q) > threshold.green))
-            SetPixelGreen(image,QuantumRange,q);
-          if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
-              ((MagickRealType) GetPixelBlue(image,q) > threshold.blue))
-            SetPixelBlue(image,QuantumRange,q);
-          if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
-              (image->colorspace == CMYKColorspace) &&
-              ((MagickRealType) GetPixelBlack(image,q)) > threshold.black)
-            SetPixelBlack(image,QuantumRange,q);
-          if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-              ((MagickRealType) GetPixelAlpha(image,q) > threshold.alpha))
-            SetPixelAlpha(image,QuantumRange,q);
+          q+=GetPixelChannels(image);
+          continue;
         }
+      pixel=GetPixelIntensity(image,q);
+      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+      {
+        PixelChannel
+          channel;
+
+        PixelTrait
+          traits;
+
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
+        if ((traits & UpdatePixelTrait) == 0)
+          continue;
+        if (image->channel_mask != DefaultChannels)
+          pixel=(double) q[i];
+        if (pixel > GetPixelInfoChannel(&threshold,channel))
+          q[i]=QuantumRange;
+      }
       q+=GetPixelChannels(image);
     }
     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
@@ -1927,7 +1757,7 @@ MagickExport MagickBooleanType WhiteThresholdImage(Image *image,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_WhiteThresholdImage)
+        #pragma omp critical (MagickCore_WhiteThresholdImage)
 #endif
         proceed=SetImageProgress(image,ThresholdImageTag,progress++,
           image->rows);