]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/enhance.c
(no commit message)
[imagemagick] / MagickCore / enhance.c
index 2b42da1cd5aad8784ab0f9c67dc02d598bd3d1d3..950bd39e1c9b2706168d338ac86151bd79a5ee99 100644 (file)
@@ -17,7 +17,7 @@
 %                                 July 1992                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2013 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  %
@@ -42,6 +42,7 @@
 */
 #include "MagickCore/studio.h"
 #include "MagickCore/artifact.h"
+#include "MagickCore/attribute.h"
 #include "MagickCore/cache.h"
 #include "MagickCore/cache-view.h"
 #include "MagickCore/color.h"
@@ -138,14 +139,8 @@ MagickExport MagickBooleanType AutoGammaImage(Image *image,
     ChannelType
       channel_mask;
 
-    PixelChannel
-      channel;
-
-    PixelTrait
-      traits;
-
-    channel=GetPixelChannelChannel(image,i);
-    traits=GetPixelChannelTraits(image,channel);
+    PixelChannel channel=GetPixelChannelChannel(image,i);
+    PixelTrait traits=GetPixelChannelTraits(image,channel);
     if ((traits & UpdatePixelTrait) == 0)
       continue;
     channel_mask=SetImageChannelMask(image,(ChannelType) (1 << i));
@@ -330,8 +325,6 @@ MagickExport MagickBooleanType ClutImage(Image *image,const Image *clut_image,
   assert(clut_image->signature == MagickSignature);
   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
     return(MagickFalse);
-  if (IsGrayColorspace(image->colorspace) != MagickFalse)
-    (void) TransformImageColorspace(image,RGBColorspace,exception);
   clut_map=(PixelInfo *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*clut_map));
   if (clut_map == (PixelInfo *) NULL)
     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
@@ -354,7 +347,7 @@ MagickExport MagickBooleanType ClutImage(Image *image,const Image *clut_image,
   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)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -378,7 +371,7 @@ MagickExport MagickBooleanType ClutImage(Image *image,const Image *clut_image,
     GetPixelInfo(image,&pixel);
     for (x=0; x < (ssize_t) image->columns; x++)
     {
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
@@ -723,8 +716,8 @@ MagickExport MagickBooleanType ColorDecisionListImage(Image *image,
       double
         luma;
 
-      luma=0.21267*image->colormap[i].red+0.71526*image->colormap[i].green+
-        0.07217*image->colormap[i].blue;
+      luma=0.21267f*image->colormap[i].red+0.71526*image->colormap[i].green+
+        0.07217f*image->colormap[i].blue;
       image->colormap[i].red=luma+color_correction.saturation*cdl_map[
         ScaleQuantumToMap(ClampToQuantum(image->colormap[i].red))].red-luma;
       image->colormap[i].green=luma+color_correction.saturation*cdl_map[
@@ -740,7 +733,7 @@ MagickExport MagickBooleanType ColorDecisionListImage(Image *image,
   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)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -763,8 +756,8 @@ MagickExport MagickBooleanType ColorDecisionListImage(Image *image,
       }
     for (x=0; x < (ssize_t) image->columns; x++)
     {
-      luma=0.21267*GetPixelRed(image,q)+0.71526*GetPixelGreen(image,q)+0.07217*
-        GetPixelBlue(image,q);
+      luma=0.21267f*GetPixelRed(image,q)+0.71526*GetPixelGreen(image,q)+
+        0.07217f*GetPixelBlue(image,q);
       SetPixelRed(image,ClampToQuantum(luma+color_correction.saturation*
         (cdl_map[ScaleQuantumToMap(GetPixelRed(image,q))].red-luma)),q);
       SetPixelGreen(image,ClampToQuantum(luma+color_correction.saturation*
@@ -885,8 +878,17 @@ MagickExport MagickBooleanType ContrastImage(Image *image,
         Contrast enhance colormap.
       */
       for (i=0; i < (ssize_t) image->colors; i++)
-        Contrast(sign,&image->colormap[i].red,&image->colormap[i].green,
-          &image->colormap[i].blue);
+      {
+        double
+          blue,
+          green,
+          red;
+
+        Contrast(sign,&red,&green,&blue);
+        image->colormap[i].red=(MagickRealType) red;
+        image->colormap[i].red=(MagickRealType) red;
+        image->colormap[i].red=(MagickRealType) red;
+      }
     }
   /*
     Contrast enhance image.
@@ -896,7 +898,7 @@ MagickExport MagickBooleanType ContrastImage(Image *image,
   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)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -1046,6 +1048,8 @@ MagickExport MagickBooleanType ContrastStretchImage(Image *image,
   /*
     Form histogram.
   */
+  if (IsImageGray(image,exception) != MagickFalse)
+    (void) SetImageColorspace(image,GRAYColorspace,exception);
   status=MagickTrue;
   (void) ResetMagickMemory(histogram,0,(MaxMap+1)*GetPixelChannels(image)*
     sizeof(*histogram));
@@ -1135,13 +1139,11 @@ MagickExport MagickBooleanType ContrastStretchImage(Image *image,
         stretch_map[GetPixelChannels(image)*j+i]=0.0;
       else
         if (j > (ssize_t) white[i])
-          stretch_map[GetPixelChannels(image)*j+i]=(double)
-            QuantumRange;
+          stretch_map[GetPixelChannels(image)*j+i]=(double) QuantumRange;
         else
           if (black[i] != white[i])
-            stretch_map[GetPixelChannels(image)*j+i]=(double)
-              ScaleMapToQuantum((double) (MaxMap*(j-black[i])/
-              (white[i]-black[i])));
+            stretch_map[GetPixelChannels(image)*j+i]=(double) ScaleMapToQuantum(
+              (double) (MaxMap*(j-black[i])/(white[i]-black[i])));
     }
   }
   if (image->storage_class == PseudoClass)
@@ -1192,7 +1194,7 @@ MagickExport MagickBooleanType ContrastStretchImage(Image *image,
   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)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -1215,21 +1217,15 @@ MagickExport MagickBooleanType ContrastStretchImage(Image *image,
       register ssize_t
         i;
 
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
         }
       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
-        PixelChannel
-          channel;
-
-        PixelTrait
-          traits;
-
-        channel=GetPixelChannelChannel(image,i);
-        traits=GetPixelChannelTraits(image,channel);
+        PixelChannel channel=GetPixelChannelChannel(image,i);
+        PixelTrait traits=GetPixelChannelTraits(image,channel);
         if (((traits & UpdatePixelTrait) == 0) || (black[i] == white[i]))
           continue;
         q[i]=ClampToQuantum(stretch_map[GetPixelChannels(image)*
@@ -1289,12 +1285,10 @@ MagickExport Image *EnhanceImage(const Image *image,ExceptionInfo *exception)
 {
 #define EnhancePixel(weight) \
   mean=((double) r[i]+GetPixelChannel(enhance_image,channel,q))/2.0; \
-  distance=(double) r[i]-(double) GetPixelChannel( \
-    enhance_image,channel,q); \
-  distance_squared=QuantumScale*(2.0*((double) QuantumRange+1.0)+ \
-    mean)*distance*distance; \
-  if (distance_squared < ((double) QuantumRange*(double) \
-      QuantumRange/25.0f)) \
+  distance=(double) r[i]-(double) GetPixelChannel(enhance_image,channel,q); \
+  distance_squared=QuantumScale*(2.0*((double) QuantumRange+1.0)+mean)* \
+    distance*distance; \
+  if (distance_squared < ((double) QuantumRange*(double) QuantumRange/25.0f)) \
     { \
       aggregate+=(weight)*r[i]; \
       total_weight+=(weight); \
@@ -1345,7 +1339,7 @@ MagickExport Image *EnhanceImage(const Image *image,ExceptionInfo *exception)
   enhance_view=AcquireAuthenticCacheView(enhance_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)
+    magick_threads(image,enhance_image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -1377,7 +1371,7 @@ MagickExport Image *EnhanceImage(const Image *image,ExceptionInfo *exception)
       register ssize_t
         i;
 
-      if (GetPixelMask(image,p) != 0)
+      if (GetPixelMask(image,p) == 0)
         {
           p+=GetPixelChannels(image);
           q+=GetPixelChannels(enhance_image);
@@ -1392,19 +1386,12 @@ MagickExport Image *EnhanceImage(const Image *image,ExceptionInfo *exception)
           mean,
           total_weight;
 
-        PixelChannel
-          channel;
-
-        PixelTrait
-          enhance_traits,
-          traits;
-
         register const Quantum
           *restrict r;
 
-        channel=GetPixelChannelChannel(image,i);
-        traits=GetPixelChannelTraits(image,channel);
-        enhance_traits=GetPixelChannelTraits(enhance_image,channel);
+        PixelChannel channel=GetPixelChannelChannel(image,i);
+        PixelTrait traits=GetPixelChannelTraits(image,channel);
+        PixelTrait enhance_traits=GetPixelChannelTraits(enhance_image,channel);
         if ((traits == UndefinedPixelTrait) ||
             (enhance_traits == UndefinedPixelTrait))
           continue;
@@ -1454,6 +1441,8 @@ MagickExport Image *EnhanceImage(const Image *image,ExceptionInfo *exception)
   }
   enhance_view=DestroyCacheView(enhance_view);
   image_view=DestroyCacheView(image_view);
+  if (status == MagickFalse)
+    enhance_image=DestroyImage(enhance_image);
   return(enhance_image);
 }
 \f
@@ -1524,8 +1513,7 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
     GetPixelChannels(image)*sizeof(*histogram));
   map=(double *) AcquireQuantumMemory(MaxMap+1UL,
     GetPixelChannels(image)*sizeof(*map));
-  if ((equalize_map == (double *) NULL) ||
-      (histogram == (double *) NULL) ||
+  if ((equalize_map == (double *) NULL) || (histogram == (double *) NULL) ||
       (map == (double *) NULL))
     {
       if (map != (double *) NULL)
@@ -1610,9 +1598,6 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
   map=(double *) RelinquishMagickMemory(map);
   if (image->storage_class == PseudoClass)
     {
-      PixelChannel
-        channel;
-
       register ssize_t
         j;
 
@@ -1623,7 +1608,7 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
       {
         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
           {
-            channel=GetPixelChannelChannel(image,RedPixelChannel);
+            PixelChannel channel=GetPixelChannelChannel(image,RedPixelChannel);
             if (black[channel] != white[channel])
               image->colormap[j].red=equalize_map[GetPixelChannels(image)*
                 ScaleQuantumToMap(ClampToQuantum(image->colormap[j].red))]+
@@ -1631,7 +1616,8 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
           }
         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
           {
-            channel=GetPixelChannelChannel(image,GreenPixelChannel);
+            PixelChannel channel=GetPixelChannelChannel(image,
+              GreenPixelChannel);
             if (black[channel] != white[channel])
               image->colormap[j].green=equalize_map[GetPixelChannels(image)*
                 ScaleQuantumToMap(ClampToQuantum(image->colormap[j].green))]+
@@ -1639,7 +1625,7 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
           }
         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
           {
-            channel=GetPixelChannelChannel(image,BluePixelChannel);
+            PixelChannel channel=GetPixelChannelChannel(image,BluePixelChannel);
             if (black[channel] != white[channel])
               image->colormap[j].blue=equalize_map[GetPixelChannels(image)*
                 ScaleQuantumToMap(ClampToQuantum(image->colormap[j].blue))]+
@@ -1647,7 +1633,8 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
           }
         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
           {
-            channel=GetPixelChannelChannel(image,AlphaPixelChannel);
+            PixelChannel channel=GetPixelChannelChannel(image,
+              AlphaPixelChannel);
             if (black[channel] != white[channel])
               image->colormap[j].alpha=equalize_map[GetPixelChannels(image)*
                 ScaleQuantumToMap(ClampToQuantum(image->colormap[j].alpha))]+
@@ -1662,7 +1649,7 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
   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)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -1685,21 +1672,15 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
       register ssize_t
         i;
 
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
         }
       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
-        PixelChannel
-          channel;
-
-        PixelTrait
-          traits;
-
-        channel=GetPixelChannelChannel(image,i);
-        traits=GetPixelChannelTraits(image,channel);
+        PixelChannel channel=GetPixelChannelChannel(image,i);
+        PixelTrait traits=GetPixelChannelTraits(image,channel);
         if (((traits & UpdatePixelTrait) == 0) || (black[i] == white[i]))
           continue;
         q[i]=ClampToQuantum(equalize_map[GetPixelChannels(image)*
@@ -1829,7 +1810,7 @@ MagickExport MagickBooleanType GammaImage(Image *image,const double gamma,
   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)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -1852,21 +1833,15 @@ MagickExport MagickBooleanType GammaImage(Image *image,const double gamma,
       register ssize_t
         i;
 
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
         }
       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
-        PixelChannel
-          channel;
-
-        PixelTrait
-          traits;
-
-        channel=GetPixelChannelChannel(image,i);
-        traits=GetPixelChannelTraits(image,channel);
+        PixelChannel channel=GetPixelChannelChannel(image,i);
+        PixelTrait traits=GetPixelChannelTraits(image,channel);
         if ((traits & UpdatePixelTrait) == 0)
           continue;
         q[i]=gamma_map[ScaleQuantumToMap(q[i])];
@@ -1901,6 +1876,200 @@ MagickExport MagickBooleanType GammaImage(Image *image,const double gamma,
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%     G r a y s c a l e I m a g e                                             %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  GrayscaleImage() converts the image to grayscale.
+%
+%  The format of the GrayscaleImage method is:
+%
+%      MagickBooleanType GrayscaleImage(Image *image,
+%        const PixelIntensityMethod method ,ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+%    o method: the pixel intensity method.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+
+static inline MagickRealType MagickMax(const MagickRealType x,
+  const MagickRealType y)
+{
+  if (x > y)
+    return(x);
+  return(y);
+}
+
+static inline MagickRealType MagickMin(const MagickRealType x,
+  const MagickRealType y)
+{
+  if (x < y)
+    return(x);
+  return(y);
+}
+
+MagickExport MagickBooleanType GrayscaleImage(Image *image,
+  const PixelIntensityMethod grayscale,ExceptionInfo *exception)
+{
+#define GrayscaleImageTag  "Grayscale/Image"
+
+  CacheView
+    *image_view;
+
+  MagickBooleanType
+    status;
+
+  MagickOffsetType
+    progress;
+
+  ssize_t
+    y;
+
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickSignature);
+  if (image->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  if (image->storage_class == PseudoClass)
+    {
+      if (SyncImage(image,exception) == MagickFalse)
+        return(MagickFalse);
+      if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
+        return(MagickFalse);
+    }
+  /*
+    Grayscale image.
+  */
+  status=MagickTrue;
+  progress=0;
+  image_view=AcquireAuthenticCacheView(image,exception);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+  #pragma omp parallel for schedule(static,4) shared(progress,status) \
+    magick_threads(image,image,image->rows,1)
+#endif
+  for (y=0; y < (ssize_t) image->rows; y++)
+  {
+    register Quantum
+      *restrict q;
+
+    register ssize_t
+      x;
+
+    if (status == MagickFalse)
+      continue;
+    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
+    if (q == (Quantum *) NULL)
+      {
+        status=MagickFalse;
+        continue;
+      }
+    for (x=0; x < (ssize_t) image->columns; x++)
+    {
+      MagickRealType
+        blue,
+        green,
+        red,
+        intensity;
+
+      if (GetPixelMask(image,q) == 0)
+        {
+          q+=GetPixelChannels(image);
+          continue;
+        }
+      red=(MagickRealType) GetPixelRed(image,q);
+      green=(MagickRealType) GetPixelGreen(image,q);
+      blue=(MagickRealType) GetPixelBlue(image,q);
+      switch (image->intensity)
+      {
+        case AveragePixelIntensityMethod:
+        {
+          intensity=(red+green+blue)/3.0;
+          break;
+        }
+        case BrightnessPixelIntensityMethod:
+        {
+          intensity=MagickMax(MagickMax(red,green),blue);
+          break;
+        }
+        case LightnessPixelIntensityMethod:
+        {
+          intensity=MagickMin(MagickMin(red,green),blue);
+          break;
+        }
+        case Rec601LumaPixelIntensityMethod:
+        {
+          intensity=0.298839f*red+0.586811f*green+0.114350f*blue;
+          break;
+        }
+        case Rec601LuminancePixelIntensityMethod:
+        {
+          if (image->colorspace == sRGBColorspace)
+            {
+              red=DecodePixelGamma(red);
+              green=DecodePixelGamma(green);
+              blue=DecodePixelGamma(blue);
+            }
+          intensity=0.298839f*red+0.586811f*green+0.114350f*blue;
+          break;
+        }
+        case Rec709LumaPixelIntensityMethod:
+        default:
+        {
+          intensity=0.21260f*red+0.71520f*green+0.07220f*blue;
+          break;
+        }
+        case Rec709LuminancePixelIntensityMethod:
+        {
+          if (image->colorspace == sRGBColorspace)
+            {
+              red=DecodePixelGamma(red);
+              green=DecodePixelGamma(green);
+              blue=DecodePixelGamma(blue);
+            }
+          intensity=0.21260f*red+0.71520f*green+0.07220f*blue;
+          break;
+        }
+        case RMSPixelIntensityMethod:
+        {
+          intensity=(MagickRealType) sqrt((double) red*red+green*green+
+            blue*blue);
+          break;
+        }
+      }
+      SetPixelGray(image,ClampToQuantum(intensity),q);
+      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_GrayscaleImage)
+#endif
+        proceed=SetImageProgress(image,GrayscaleImageTag,progress++,
+           image->rows);
+        if (proceed == MagickFalse)
+          status=MagickFalse;
+      }
+  }
+  image_view=DestroyCacheView(image_view);
+  return(status);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %     H a l d C l u t I m a g e                                               %
 %                                                                             %
 %                                                                             %
@@ -1927,14 +2096,6 @@ MagickExport MagickBooleanType GammaImage(Image *image,const double gamma,
 %    o exception: return any errors or warnings in this structure.
 %
 */
-
-static inline size_t MagickMin(const size_t x,const size_t y)
-{
-  if (x < y)
-    return(x);
-  return(y);
-}
-
 MagickExport MagickBooleanType HaldClutImage(Image *image,
   const Image *hald_image,ExceptionInfo *exception)
 {
@@ -1981,7 +2142,7 @@ MagickExport MagickBooleanType HaldClutImage(Image *image,
   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
     return(MagickFalse);
   if (IsGrayColorspace(image->colorspace) != MagickFalse)
-    (void) TransformImageColorspace(image,RGBColorspace,exception);
+    (void) TransformImageColorspace(image,sRGBColorspace,exception);
   if (image->alpha_trait != BlendPixelTrait)
     (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
   /*
@@ -1989,7 +2150,8 @@ MagickExport MagickBooleanType HaldClutImage(Image *image,
   */
   status=MagickTrue;
   progress=0;
-  length=MagickMin(hald_image->columns,hald_image->rows);
+  length=(size_t) MagickMin((MagickRealType) hald_image->columns,
+    (MagickRealType) hald_image->rows);
   for (level=2; (level*level*level) < length; level++) ;
   level*=level;
   cube_size=level*level;
@@ -1999,7 +2161,7 @@ MagickExport MagickBooleanType HaldClutImage(Image *image,
   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)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -2204,7 +2366,7 @@ MagickExport MagickBooleanType LevelImage(Image *image,const double black_point,
   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)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -2227,21 +2389,15 @@ MagickExport MagickBooleanType LevelImage(Image *image,const double black_point,
       register ssize_t
         i;
 
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
         }
       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
-        PixelChannel
-          channel;
-
-        PixelTrait
-          traits;
-
-        channel=GetPixelChannelChannel(image,i);
-        traits=GetPixelChannelTraits(image,channel);
+        PixelChannel channel=GetPixelChannelChannel(image,i);
+        PixelTrait traits=GetPixelChannelTraits(image,channel);
         if ((traits & UpdatePixelTrait) == 0)
           continue;
         q[i]=ClampToQuantum(LevelPixel(black_point,white_point,gamma,
@@ -2265,8 +2421,6 @@ MagickExport MagickBooleanType LevelImage(Image *image,const double black_point,
       }
   }
   image_view=DestroyCacheView(image_view);
-  if (status != MagickFalse)
-    (void) ClampImage(image,exception);
   return(status);
 }
 \f
@@ -2343,7 +2497,7 @@ MagickExport MagickBooleanType LevelizeImage(Image *image,
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (IsGrayColorspace(image->colorspace) != MagickFalse)
-    (void) SetImageColorspace(image,RGBColorspace,exception);
+    (void) SetImageColorspace(image,sRGBColorspace,exception);
   if (image->storage_class == PseudoClass)
     for (i=0; i < (ssize_t) image->colors; i++)
     {
@@ -2351,14 +2505,12 @@ MagickExport MagickBooleanType LevelizeImage(Image *image,
         Level colormap.
       */
       if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
-        image->colormap[i].red=(double) LevelizeValue(
-          image->colormap[i].red);
+        image->colormap[i].red=(double) LevelizeValue(image->colormap[i].red);
       if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         image->colormap[i].green=(double) LevelizeValue(
           image->colormap[i].green);
       if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
-        image->colormap[i].blue=(double) LevelizeValue(
-          image->colormap[i].blue);
+        image->colormap[i].blue=(double) LevelizeValue(image->colormap[i].blue);
       if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
         image->colormap[i].alpha=(double) LevelizeValue(
           image->colormap[i].alpha);
@@ -2371,7 +2523,7 @@ MagickExport MagickBooleanType LevelizeImage(Image *image,
   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)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -2394,21 +2546,15 @@ MagickExport MagickBooleanType LevelizeImage(Image *image,
       register ssize_t
         i;
 
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
         }
       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
-        PixelChannel
-          channel;
-
-        PixelTrait
-          traits;
-
-        channel=GetPixelChannelChannel(image,i);
-        traits=GetPixelChannelTraits(image,channel);
+        PixelChannel channel=GetPixelChannelChannel(image,i);
+        PixelTrait traits=GetPixelChannelTraits(image,channel);
         if ((traits & UpdatePixelTrait) == 0)
           continue;
         q[i]=LevelizeValue(q[i]);
@@ -2615,13 +2761,13 @@ MagickExport MagickBooleanType LinearStretchImage(Image *image,
   CacheView
     *image_view;
 
-  MagickBooleanType
-    status;
-
   double
     *histogram,
     intensity;
 
+  MagickBooleanType
+    status;
+
   ssize_t
     black,
     white,
@@ -2632,8 +2778,7 @@ MagickExport MagickBooleanType LinearStretchImage(Image *image,
   */
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  histogram=(double *) AcquireQuantumMemory(MaxMap+1UL,
-    sizeof(*histogram));
+  histogram=(double *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*histogram));
   if (histogram == (double *) NULL)
     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
       image->filename);
@@ -2922,7 +3067,7 @@ MagickExport MagickBooleanType ModulateImage(Image *image,const char *modulate,
   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)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -3104,7 +3249,7 @@ MagickExport MagickBooleanType NegateImage(Image *image,
           register ssize_t
             i;
 
-          if ((GetPixelMask(image,q) != 0) ||
+          if ((GetPixelMask(image,q) == 0) ||
               (IsPixelGray(image,q) != MagickFalse))
             {
               q+=GetPixelChannels(image);
@@ -3112,14 +3257,8 @@ MagickExport MagickBooleanType NegateImage(Image *image,
             }
           for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
           {
-            PixelChannel
-              channel;
-
-            PixelTrait
-              traits;
-
-            channel=GetPixelChannelChannel(image,i);
-            traits=GetPixelChannelTraits(image,channel);
+            PixelChannel channel=GetPixelChannelChannel(image,i);
+            PixelTrait traits=GetPixelChannelTraits(image,channel);
             if ((traits & UpdatePixelTrait) == 0)
               continue;
             q[i]=QuantumRange-q[i];
@@ -3150,8 +3289,8 @@ MagickExport MagickBooleanType NegateImage(Image *image,
     Negate image.
   */
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(static) shared(progress,status) \
-    dynamic_number_threads(image,image->columns,image->rows,1)
+  #pragma omp parallel for schedule(static,4) shared(progress,status) \
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -3174,21 +3313,15 @@ MagickExport MagickBooleanType NegateImage(Image *image,
       register ssize_t
         i;
 
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
         }
       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
-        PixelChannel
-          channel;
-
-        PixelTrait
-          traits;
-
-        channel=GetPixelChannelChannel(image,i);
-        traits=GetPixelChannelTraits(image,channel);
+        PixelChannel channel=GetPixelChannelChannel(image,i);
+        PixelTrait traits=GetPixelChannelTraits(image,channel);
         if ((traits & UpdatePixelTrait) == 0)
           continue;
         q[i]=QuantumRange-q[i];
@@ -3293,30 +3426,36 @@ MagickExport MagickBooleanType NormalizeImage(Image *image,
 %
 */
 
-  /*
-    Sigmoidal function with inflexion point moved to b and "slope
-    constant" set to a.
-    The first version, based on the hyperbolic tangent tanh, when
-    combined with the scaling step, is an exact arithmetic clone of the
-    the sigmoid function based on the logistic curve. The equivalence is
-    based on the identity
+/*
+  ImageMagick 6 has a version of this function which uses LUTs.
+*/
+
+/*
+  Sigmoidal function Sigmoidal with inflexion point moved to b and "slope
+  constant" set to a.
+
+  The first version, based on the hyperbolic tangent tanh, when combined with
+  the scaling step, is an exact arithmetic clone of the the sigmoid function
+  based on the logistic curve. The equivalence is based on the identity
+
     1/(1+exp(-t)) = (1+tanh(t/2))/2
-    (http://de.wikipedia.org/wiki/Sigmoidfunktion) and the fact that the
-    scaled sigmoidal derivation is invariant under affine transformations
-    of the ordinate.
-    The tanh version is almost certainly more accurate and cheaper.
-    The 0.5 factor in its argument is to clone the legacy ImageMagick
-    behavior.  The reason for making the define depend on atanh even
-    though it only uses tanh has to do with the construction of the
-    inverse of the scaled sigmoidal.
-  */
+
+  (http://de.wikipedia.org/wiki/Sigmoidfunktion) and the fact that the
+  scaled sigmoidal derivation is invariant under affine transformations of
+  the ordinate.
+
+  The tanh version is almost certainly more accurate and cheaper.  The 0.5
+  factor in the argument is to clone the legacy ImageMagick behavior. The
+  reason for making the define depend on atanh even though it only uses tanh
+  has to do with the construction of the inverse of the scaled sigmoidal.
+*/
 #if defined(MAGICKCORE_HAVE_ATANH)
 #define Sigmoidal(a,b,x) ( tanh((0.5*(a))*((x)-(b))) )
 #else
 #define Sigmoidal(a,b,x) ( 1.0/(1.0+exp((a)*((b)-(x)))) )
 #endif
 /*
-  Scaled sigmoidal formula:
+  Scaled sigmoidal function:
 
     ( Sigmoidal(a,b,x) - Sigmoidal(a,b,0) ) /
     ( Sigmoidal(a,b,1) - Sigmoidal(a,b,0) )
@@ -3324,52 +3463,52 @@ MagickExport MagickBooleanType NormalizeImage(Image *image,
   See http://osdir.com/ml/video.image-magick.devel/2005-04/msg00006.html and
   http://www.cs.dartmouth.edu/farid/downloads/tutorials/fip.pdf.  The limit
   of ScaledSigmoidal as a->0 is the identity, but a=0 gives a division by
-  zero. This is fixed above by exiting immediately when contrast is small,
+  zero. This is fixed below by exiting immediately when contrast is small,
   leaving the image (or colormap) unmodified. This appears to be safe because
   the series expansion of the logistic sigmoidal function around x=b is
-  1/2-a*(b-x)/4+... so that the key denominator s(1)-s(0) is about a/4
-  (a/2 with tanh).
+
+  1/2-a*(b-x)/4+...
+
+  so that the key denominator s(1)-s(0) is about a/4 (a/2 with tanh).
 */
 #define ScaledSigmoidal(a,b,x) (                    \
   (Sigmoidal((a),(b),(x))-Sigmoidal((a),(b),0.0)) / \
   (Sigmoidal((a),(b),1.0)-Sigmoidal((a),(b),0.0)) )
 /*
-  Inverse of ScaledSigmoidal, used for +sigmoidal-contrast.  Because b may be
-  0 or 1, the argument of the hyperbolic tangent (resp. logistic sigmoidal)
-  may be outside of the interval (-1,1) (resp. (0,1)), even when creating a
-  LUT, hence the branching.  In addition, HDRI may have out of gamut values.
-  InverseScaledSigmoidal is not a two-side inverse of ScaledSigmoidal:
+  Inverse of ScaledSigmoidal, used for +sigmoidal-contrast.  Because b
+  may be 0 or 1, the argument of the hyperbolic tangent (resp. logistic
+  sigmoidal) may be outside of the interval (-1,1) (resp. (0,1)), even
+  when creating a LUT from in gamut values, hence the branching.  In
+  addition, HDRI may have out of gamut values.
+  InverseScaledSigmoidal is not a two-sided inverse of ScaledSigmoidal:
   It is only a right inverse. This is unavoidable.
 */
-#if defined(MAGICKCORE_HAVE_ATANH)
 static inline double InverseScaledSigmoidal(const double a,const double b,
   const double x)
 {
-  const double _argument =
-    (Sigmoidal((a),(b),1.0)-Sigmoidal((a),(b),0.0)) * (x) +
-    Sigmoidal((a),(b),0.0);
-
-  const double _clamped_argument =
-    ( _argument < -1+MagickEpsilon ? -1+MagickEpsilon :
-    ( _argument > 1-MagickEpsilon ? 1-MagickEpsilon : _argument ) );
-
-  return((b) + (2.0/(a)) * atanh(_clamped_argument));
-}
+  const double sig0=Sigmoidal(a,b,0.0);
+  const double sig1=Sigmoidal(a,b,1.0);
+  const double argument=(sig1-sig0)*x+sig0;
+  const double clamped=
+    (
+#if defined(MAGICKCORE_HAVE_ATANH)
+      argument < -1+MagickEpsilon
+      ?
+      -1+MagickEpsilon
+      :
+      ( argument > 1-MagickEpsilon ? 1-MagickEpsilon : argument )
+    );
+  return(b+(2.0/a)*atanh(clamped));
 #else
-static inline double InverseScaledSigmoidal(const double a,const double b,
-  const double x)
-{
-  const double _argument =
-    (Sigmoidal((a),(b),1.0)-Sigmoidal((a),(b),0.0)) * (x) +
-    Sigmoidal((a),(b),0.0);
-
-  const double _clamped_argument = 
-    ( _argument < MagickEpsilon ? MagickEpsilon :
-    ( _argument > 1-MagickEpsilon ? 1-MagickEpsilon : _argument ) );
-
-  return((b) + (-1.0/(a)) * log(1.0/_clamped_argument+-1.0));
-}
+      argument < MagickEpsilon
+      ?
+      MagickEpsilon
+      :
+      ( argument > 1-MagickEpsilon ? 1-MagickEpsilon : argument )
+    );
+  return(b-log(1.0/clamped-1.0)/a);
 #endif
+}
 
 MagickExport MagickBooleanType SigmoidalContrastImage(Image *image,
   const MagickBooleanType sharpen,const double contrast,const double midpoint,
@@ -3401,7 +3540,7 @@ MagickExport MagickBooleanType SigmoidalContrastImage(Image *image,
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   /*
-    Side effect: clamps values unless contrast<MagickEpsilon, in which
+    Side effect: may clamp values unless contrast<MagickEpsilon, in which
     case nothing is done.
   */
   if (contrast < MagickEpsilon)
@@ -3447,7 +3586,7 @@ MagickExport MagickBooleanType SigmoidalContrastImage(Image *image,
   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)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -3470,21 +3609,15 @@ MagickExport MagickBooleanType SigmoidalContrastImage(Image *image,
       register ssize_t
         i;
 
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
         }
       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
-        PixelChannel
-          channel;
-
-        PixelTrait
-          traits;
-
-        channel=GetPixelChannelChannel(image,i);
-        traits=GetPixelChannelTraits(image,channel);
+        PixelChannel channel=GetPixelChannelChannel(image,i);
+        PixelTrait traits=GetPixelChannelTraits(image,channel);
         if ((traits & UpdatePixelTrait) == 0)
           continue;
         if (sharpen != MagickFalse)