]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/enhance.c
(no commit message)
[imagemagick] / MagickCore / enhance.c
index b3d66dbe0b9a49708fa0bf0f5e8618b1cc3cc4d2..19108a48ce2445d8b3b16367b8630c2c930a4cf6 100644 (file)
 %                    MagickCore Image Enhancement Methods                     %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                                 July 1992                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2014 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  %
 */
 #include "MagickCore/studio.h"
 #include "MagickCore/artifact.h"
+#include "MagickCore/attribute.h"
 #include "MagickCore/cache.h"
 #include "MagickCore/cache-view.h"
+#include "MagickCore/channel.h"
 #include "MagickCore/color.h"
 #include "MagickCore/color-private.h"
 #include "MagickCore/colorspace.h"
@@ -147,7 +149,7 @@ MagickExport MagickBooleanType AutoGammaImage(Image *image,
     gamma=log(mean*QuantumScale)/log_mean;
     status&=LevelImage(image,0.0,(double) QuantumRange,gamma,exception);
     (void) SetImageChannelMask(image,channel_mask);
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       break;
   }
   return(status != 0 ? MagickTrue : MagickFalse);
@@ -234,7 +236,7 @@ MagickExport MagickBooleanType BrightnessContrastImage(Image *image,
   */
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   alpha=contrast;
   slope=tan((double) (MagickPI*(alpha/100.0+1.0)/4.0));
@@ -318,14 +320,15 @@ MagickExport MagickBooleanType ClutImage(Image *image,const Image *clut_image,
 
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(clut_image != (Image *) NULL);
   assert(clut_image->signature == MagickSignature);
-  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
+  if( IfMagickFalse(SetImageStorageClass(image,DirectClass,exception)) )
     return(MagickFalse);
-  if (IsGrayColorspace(image->colorspace) != MagickFalse)
-    (void) TransformImageColorspace(image,RGBColorspace,exception);
+  if( IfMagickTrue(IsGrayColorspace(image->colorspace)) &&
+      IfMagickFalse(IsGrayColorspace(clut_image->colorspace)))
+    (void) SetImageColorspace(image,sRGBColorspace,exception);
   clut_map=(PixelInfo *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*clut_map));
   if (clut_map == (PixelInfo *) NULL)
     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
@@ -361,7 +364,7 @@ MagickExport MagickBooleanType ClutImage(Image *image,const Image *clut_image,
     register ssize_t
       x;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
     if (q == (Quantum *) NULL)
@@ -372,7 +375,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 (GetPixelReadMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
@@ -391,7 +394,7 @@ MagickExport MagickBooleanType ClutImage(Image *image,const Image *clut_image,
       SetPixelInfoPixel(image,&pixel,q);
       q+=GetPixelChannels(image);
     }
-    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -402,7 +405,7 @@ MagickExport MagickBooleanType ClutImage(Image *image,const Image *clut_image,
         #pragma omp critical (MagickCore_ClutImage)
 #endif
         proceed=SetImageProgress(image,ClutImageTag,progress++,image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
@@ -522,7 +525,7 @@ MagickExport MagickBooleanType ColorDecisionListImage(Image *image,
   */
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (color_correction_collection == (const char *) NULL)
     return(MagickFalse);
@@ -667,7 +670,7 @@ MagickExport MagickBooleanType ColorDecisionListImage(Image *image,
         }
     }
   ccc=DestroyXMLTree(ccc);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     {
       (void) LogMagickEvent(TransformEvent,GetMagickModule(),
         "  Color Correction Collection:");
@@ -747,7 +750,7 @@ MagickExport MagickBooleanType ColorDecisionListImage(Image *image,
     register ssize_t
       x;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
     if (q == (Quantum *) NULL)
@@ -757,8 +760,8 @@ MagickExport MagickBooleanType ColorDecisionListImage(Image *image,
       }
     for (x=0; x < (ssize_t) image->columns; x++)
     {
-      luma=0.21267f*GetPixelRed(image,q)+0.71526*GetPixelGreen(image,q)+0.07217f*
-        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*
@@ -767,7 +770,7 @@ MagickExport MagickBooleanType ColorDecisionListImage(Image *image,
         (cdl_map[ScaleQuantumToMap(GetPixelBlue(image,q))].blue-luma)),q);
       q+=GetPixelChannels(image);
     }
-    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -779,7 +782,7 @@ MagickExport MagickBooleanType ColorDecisionListImage(Image *image,
 #endif
         proceed=SetImageProgress(image,ColorDecisionListCorrectImageTag,
           progress++,image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
@@ -870,9 +873,9 @@ MagickExport MagickBooleanType ContrastImage(Image *image,
 
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  sign=sharpen != MagickFalse ? 1 : -1;
+  sign=IfMagickTrue(sharpen) ? 1 : -1;
   if (image->storage_class == PseudoClass)
     {
       /*
@@ -885,10 +888,13 @@ MagickExport MagickBooleanType ContrastImage(Image *image,
           green,
           red;
 
+        red=0.0;
+        green=0.0;
+        blue=0.0;
         Contrast(sign,&red,&green,&blue);
         image->colormap[i].red=(MagickRealType) red;
-        image->colormap[i].red=(MagickRealType) red;
-        image->colormap[i].red=(MagickRealType) red;
+        image->colormap[i].green=(MagickRealType) green;
+        image->colormap[i].blue=(MagickRealType) blue;
       }
     }
   /*
@@ -914,7 +920,7 @@ MagickExport MagickBooleanType ContrastImage(Image *image,
     register ssize_t
       x;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
     if (q == (Quantum *) NULL)
@@ -933,7 +939,7 @@ MagickExport MagickBooleanType ContrastImage(Image *image,
       SetPixelBlue(image,ClampToQuantum(blue),q);
       q+=GetPixelChannels(image);
     }
-    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -944,7 +950,7 @@ MagickExport MagickBooleanType ContrastImage(Image *image,
         #pragma omp critical (MagickCore_ContrastImage)
 #endif
         proceed=SetImageProgress(image,ContrastImageTag,progress++,image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
@@ -1024,7 +1030,7 @@ MagickExport MagickBooleanType ContrastStretchImage(Image *image,
   */
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   black=(double *) AcquireQuantumMemory(GetPixelChannels(image),sizeof(*black));
   white=(double *) AcquireQuantumMemory(GetPixelChannels(image),sizeof(*white));
@@ -1049,6 +1055,8 @@ MagickExport MagickBooleanType ContrastStretchImage(Image *image,
   /*
     Form histogram.
   */
+  if( IfMagickTrue(IsImageGray(image,exception)) )
+    (void) SetImageColorspace(image,GRAYColorspace,exception);
   status=MagickTrue;
   (void) ResetMagickMemory(histogram,0,(MaxMap+1)*GetPixelChannels(image)*
     sizeof(*histogram));
@@ -1061,7 +1069,7 @@ MagickExport MagickBooleanType ContrastStretchImage(Image *image,
     register ssize_t
       x;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
     if (p == (const Quantum *) NULL)
@@ -1138,13 +1146,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)
@@ -1205,7 +1211,7 @@ MagickExport MagickBooleanType ContrastStretchImage(Image *image,
     register ssize_t
       x;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
     if (q == (Quantum *) NULL)
@@ -1218,7 +1224,7 @@ MagickExport MagickBooleanType ContrastStretchImage(Image *image,
       register ssize_t
         i;
 
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelReadMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
@@ -1234,7 +1240,7 @@ MagickExport MagickBooleanType ContrastStretchImage(Image *image,
       }
       q+=GetPixelChannels(image);
     }
-    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -1246,7 +1252,7 @@ MagickExport MagickBooleanType ContrastStretchImage(Image *image,
 #endif
         proceed=SetImageProgress(image,ContrastStretchImageTag,progress++,
           image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
@@ -1318,7 +1324,7 @@ MagickExport Image *EnhanceImage(const Image *image,ExceptionInfo *exception)
   */
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
@@ -1326,7 +1332,7 @@ MagickExport Image *EnhanceImage(const Image *image,ExceptionInfo *exception)
     exception);
   if (enhance_image == (Image *) NULL)
     return((Image *) NULL);
-  if (SetImageStorageClass(enhance_image,DirectClass,exception) == MagickFalse)
+  if( IfMagickFalse(SetImageStorageClass(enhance_image,DirectClass,exception)) )
     {
       enhance_image=DestroyImage(enhance_image);
       return((Image *) NULL);
@@ -1356,7 +1362,7 @@ MagickExport Image *EnhanceImage(const Image *image,ExceptionInfo *exception)
     ssize_t
       center;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     p=GetCacheViewVirtualPixels(image_view,-2,y-2,image->columns+4,5,exception);
     q=QueueCacheViewAuthenticPixels(enhance_view,0,y,enhance_image->columns,1,
@@ -1372,8 +1378,9 @@ MagickExport Image *EnhanceImage(const Image *image,ExceptionInfo *exception)
       register ssize_t
         i;
 
-      if (GetPixelMask(image,p) != 0)
+      if (GetPixelReadMask(image,p) == 0)
         {
+          SetPixelBackgoundColor(enhance_image,q);
           p+=GetPixelChannels(image);
           q+=GetPixelChannels(enhance_image);
           continue;
@@ -1425,7 +1432,7 @@ MagickExport Image *EnhanceImage(const Image *image,ExceptionInfo *exception)
       p+=GetPixelChannels(image);
       q+=GetPixelChannels(enhance_image);
     }
-    if (SyncCacheViewAuthenticPixels(enhance_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(enhance_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -1436,13 +1443,13 @@ MagickExport Image *EnhanceImage(const Image *image,ExceptionInfo *exception)
         #pragma omp critical (MagickCore_EnhanceImage)
 #endif
         proceed=SetImageProgress(image,EnhanceImageTag,progress++,image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
   enhance_view=DestroyCacheView(enhance_view);
   image_view=DestroyCacheView(image_view);
-  if (status == MagickFalse)
+  if( IfMagickFalse(status) )
     enhance_image=DestroyImage(enhance_image);
   return(enhance_image);
 }
@@ -1486,11 +1493,11 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
     progress;
 
   double
-    black[CompositePixelChannel],
+    black[CompositePixelChannel+1],
     *equalize_map,
     *histogram,
     *map,
-    white[CompositePixelChannel];
+    white[CompositePixelChannel+1];
 
   register ssize_t
     i;
@@ -1506,14 +1513,14 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
   */
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   equalize_map=(double *) AcquireQuantumMemory(MaxMap+1UL,
     GetPixelChannels(image)*sizeof(*equalize_map));
-  histogram=(double *) AcquireQuantumMemory(MaxMap+1UL,
-    GetPixelChannels(image)*sizeof(*histogram));
-  map=(double *) AcquireQuantumMemory(MaxMap+1UL,
-    GetPixelChannels(image)*sizeof(*map));
+  histogram=(double *) AcquireQuantumMemory(MaxMap+1UL,GetPixelChannels(image)*
+    sizeof(*histogram));
+  map=(double *) AcquireQuantumMemory(MaxMap+1UL,GetPixelChannels(image)*
+    sizeof(*map));
   if ((equalize_map == (double *) NULL) || (histogram == (double *) NULL) ||
       (map == (double *) NULL))
     {
@@ -1541,7 +1548,7 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
     register ssize_t
       x;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
     if (p == (const Quantum *) NULL)
@@ -1581,6 +1588,8 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
   }
   (void) ResetMagickMemory(equalize_map,0,(MaxMap+1)*GetPixelChannels(image)*
     sizeof(*equalize_map));
+  (void) ResetMagickMemory(black,0,sizeof(*black));
+  (void) ResetMagickMemory(white,0,sizeof(*white));
   number_channels=GetPixelChannels(image);
   for (i=0; i < (ssize_t) number_channels; i++)
   {
@@ -1660,7 +1669,7 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
     register ssize_t
       x;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
     if (q == (Quantum *) NULL)
@@ -1673,7 +1682,7 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
       register ssize_t
         i;
 
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelReadMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
@@ -1689,7 +1698,7 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
       }
       q+=GetPixelChannels(image);
     }
-    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -1700,7 +1709,7 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
         #pragma omp critical (MagickCore_EqualizeImage)
 #endif
         proceed=SetImageProgress(image,EqualizeImageTag,progress++,image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
@@ -1743,6 +1752,12 @@ MagickExport MagickBooleanType EqualizeImage(Image *image,
 %    o gamma: the image gamma.
 %
 */
+
+static inline double gamma_pow(const double value,const double gamma)
+{
+  return(value < 0.0 ? value : pow(value,gamma));
+}
+
 MagickExport MagickBooleanType GammaImage(Image *image,const double gamma,
   ExceptionInfo *exception)
 {
@@ -1771,7 +1786,7 @@ MagickExport MagickBooleanType GammaImage(Image *image,const double gamma,
   */
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (gamma == 1.0)
     return(MagickTrue);
@@ -1790,18 +1805,33 @@ MagickExport MagickBooleanType GammaImage(Image *image,const double gamma,
       /*
         Gamma-correct colormap.
       */
+#if !defined(MAGICKCORE_HDRI_SUPPORT)
       if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
-        image->colormap[i].red=(double) gamma_map[
-          ScaleQuantumToMap(ClampToQuantum(image->colormap[i].red))];
+        image->colormap[i].red=(double) gamma_map[ScaleQuantumToMap(
+          ClampToQuantum(image->colormap[i].red))];
       if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
-        image->colormap[i].green=(double) gamma_map[
-          ScaleQuantumToMap(ClampToQuantum(image->colormap[i].green))];
+        image->colormap[i].green=(double) gamma_map[ScaleQuantumToMap(
+          ClampToQuantum(image->colormap[i].green))];
       if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
-        image->colormap[i].blue=(double) gamma_map[
-          ScaleQuantumToMap(ClampToQuantum(image->colormap[i].blue))];
+        image->colormap[i].blue=(double) gamma_map[ScaleQuantumToMap(
+          ClampToQuantum(image->colormap[i].blue))];
       if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
-        image->colormap[i].alpha=(double) gamma_map[
-          ScaleQuantumToMap(ClampToQuantum(image->colormap[i].alpha))];
+        image->colormap[i].alpha=(double) gamma_map[ScaleQuantumToMap(
+          ClampToQuantum(image->colormap[i].alpha))];
+#else
+      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+        image->colormap[i].red=QuantumRange*gamma_pow(QuantumScale*
+          image->colormap[i].red,1.0/gamma);
+      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+        image->colormap[i].green=QuantumRange*gamma_pow(QuantumScale*
+          image->colormap[i].green,1.0/gamma);
+      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+        image->colormap[i].blue=QuantumRange*gamma_pow(QuantumScale*
+          image->colormap[i].blue,1.0/gamma);
+      if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
+        image->colormap[i].alpha=QuantumRange*gamma_pow(QuantumScale*
+          image->colormap[i].alpha,1.0/gamma);
+#endif
     }
   /*
     Gamma-correct image.
@@ -1821,7 +1851,7 @@ MagickExport MagickBooleanType GammaImage(Image *image,const double gamma,
     register ssize_t
       x;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
     if (q == (Quantum *) NULL)
@@ -1834,7 +1864,7 @@ MagickExport MagickBooleanType GammaImage(Image *image,const double gamma,
       register ssize_t
         i;
 
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelReadMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
@@ -1845,11 +1875,15 @@ MagickExport MagickBooleanType GammaImage(Image *image,const double gamma,
         PixelTrait traits=GetPixelChannelTraits(image,channel);
         if ((traits & UpdatePixelTrait) == 0)
           continue;
+#if !defined(MAGICKCORE_HDRI_SUPPORT)
         q[i]=gamma_map[ScaleQuantumToMap(q[i])];
+#else
+        q[i]=QuantumRange*gamma_pow(QuantumScale*q[i],1.0/gamma);
+#endif
       }
       q+=GetPixelChannels(image);
     }
-    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -1861,7 +1895,7 @@ MagickExport MagickBooleanType GammaImage(Image *image,const double gamma,
 #endif
         proceed=SetImageProgress(image,GammaCorrectImageTag,progress++,
           image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
@@ -1877,6 +1911,222 @@ 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 method,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( IfMagickTrue(image->debug) )
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  if (image->storage_class == PseudoClass)
+    {
+      if( IfMagickFalse(SyncImage(image,exception)) )
+        return(MagickFalse);
+      if( IfMagickFalse(SetImageStorageClass(image,DirectClass,exception)) )
+        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( IfMagickFalse(status) )
+      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 (GetPixelReadMask(image,q) == 0)
+        {
+          q+=GetPixelChannels(image);
+          continue;
+        }
+      red=(MagickRealType) GetPixelRed(image,q);
+      green=(MagickRealType) GetPixelGreen(image,q);
+      blue=(MagickRealType) GetPixelBlue(image,q);
+      intensity=0.0;
+      switch (method)
+      {
+        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)+
+            MagickMax(MagickMax(red,green),blue))/2.0;
+          break;
+        }
+        case MSPixelIntensityMethod:
+        {
+          intensity=(MagickRealType) (((double) red*red+green*green+
+            blue*blue)/3.0);
+          break;
+        }
+        case Rec601LumaPixelIntensityMethod:
+        {
+          if (image->colorspace == RGBColorspace)
+            {
+              red=EncodePixelGamma(red);
+              green=EncodePixelGamma(green);
+              blue=EncodePixelGamma(blue);
+            }
+          intensity=0.298839*red+0.586811*green+0.114350*blue;
+          break;
+        }
+        case Rec601LuminancePixelIntensityMethod:
+        {
+          if (image->colorspace == sRGBColorspace)
+            {
+              red=DecodePixelGamma(red);
+              green=DecodePixelGamma(green);
+              blue=DecodePixelGamma(blue);
+            }
+          intensity=0.298839*red+0.586811*green+0.114350*blue;
+          break;
+        }
+        case Rec709LumaPixelIntensityMethod:
+        default:
+        {
+          if (image->colorspace == RGBColorspace)
+            {
+              red=EncodePixelGamma(red);
+              green=EncodePixelGamma(green);
+              blue=EncodePixelGamma(blue);
+            }
+          intensity=0.212656*red+0.715158*green+0.072186*blue;
+          break;
+        }
+        case Rec709LuminancePixelIntensityMethod:
+        {
+          if (image->colorspace == sRGBColorspace)
+            {
+              red=DecodePixelGamma(red);
+              green=DecodePixelGamma(green);
+              blue=DecodePixelGamma(blue);
+            }
+          intensity=0.212656*red+0.715158*green+0.072186*blue;
+          break;
+        }
+        case RMSPixelIntensityMethod:
+        {
+          intensity=(MagickRealType) (sqrt((double) red*red+green*green+
+            blue*blue)/sqrt(3.0));
+          break;
+        }
+      }
+      SetPixelGray(image,ClampToQuantum(intensity),q);
+      q+=GetPixelChannels(image);
+    }
+    if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)))
+      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( IfMagickFalse(proceed) )
+          status=MagickFalse;
+      }
+  }
+  image_view=DestroyCacheView(image_view);
+  image->intensity=method;
+  image->type=GrayscaleType;
+  return(SetImageColorspace(image,GRAYColorspace,exception));
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %     H a l d C l u t I m a g e                                               %
 %                                                                             %
 %                                                                             %
@@ -1903,14 +2153,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)
 {
@@ -1950,14 +2192,12 @@ MagickExport MagickBooleanType HaldClutImage(Image *image,
 
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(hald_image != (Image *) NULL);
   assert(hald_image->signature == MagickSignature);
-  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
+  if( IfMagickFalse(SetImageStorageClass(image,DirectClass,exception)) )
     return(MagickFalse);
-  if (IsGrayColorspace(image->colorspace) != MagickFalse)
-    (void) TransformImageColorspace(image,RGBColorspace,exception);
   if (image->alpha_trait != BlendPixelTrait)
     (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
   /*
@@ -1965,7 +2205,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;
@@ -1985,7 +2226,7 @@ MagickExport MagickBooleanType HaldClutImage(Image *image,
     register ssize_t
       x;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
     if (q == (Quantum *) NULL)
@@ -2049,7 +2290,7 @@ MagickExport MagickBooleanType HaldClutImage(Image *image,
         SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
       q+=GetPixelChannels(image);
     }
-    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -2060,7 +2301,7 @@ MagickExport MagickBooleanType HaldClutImage(Image *image,
         #pragma omp critical (MagickCore_HaldClutImage)
 #endif
         proceed=SetImageProgress(image,HaldClutImageTag,progress++,image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
@@ -2121,8 +2362,8 @@ static inline double LevelPixel(const double black_point,
     scale;
 
   scale=(white_point != black_point) ? 1.0/(white_point-black_point) : 1.0;
-  level_pixel=(double) QuantumRange*pow(scale*((double) pixel-
-    black_point),1.0/gamma);
+  level_pixel=QuantumRange*gamma_pow(scale*((double) pixel-black_point),
+    1.0/gamma);
   return(level_pixel);
 }
 
@@ -2151,7 +2392,7 @@ MagickExport MagickBooleanType LevelImage(Image *image,const double black_point,
   */
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (image->storage_class == PseudoClass)
     for (i=0; i < (ssize_t) image->colors; i++)
@@ -2190,7 +2431,7 @@ MagickExport MagickBooleanType LevelImage(Image *image,const double black_point,
     register ssize_t
       x;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
     if (q == (Quantum *) NULL)
@@ -2203,7 +2444,7 @@ MagickExport MagickBooleanType LevelImage(Image *image,const double black_point,
       register ssize_t
         i;
 
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelReadMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
@@ -2219,7 +2460,7 @@ MagickExport MagickBooleanType LevelImage(Image *image,const double black_point,
       }
       q+=GetPixelChannels(image);
     }
-    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -2230,11 +2471,12 @@ MagickExport MagickBooleanType LevelImage(Image *image,const double black_point,
         #pragma omp critical (MagickCore_LevelImage)
 #endif
         proceed=SetImageProgress(image,LevelImageTag,progress++,image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
   image_view=DestroyCacheView(image_view);
+  (void) ClampImage(image,exception);
   return(status);
 }
 \f
@@ -2285,8 +2527,8 @@ MagickExport MagickBooleanType LevelizeImage(Image *image,
   ExceptionInfo *exception)
 {
 #define LevelizeImageTag  "Levelize/Image"
-#define LevelizeValue(x) (ClampToQuantum((pow((double) (QuantumScale*(x)), \
-  1.0/gamma))*(white_point-black_point)+black_point))
+#define LevelizeValue(x) ClampToQuantum(((MagickRealType) gamma_pow((double) \
+  (QuantumScale*(x)),gamma))*(white_point-black_point)+black_point)
 
   CacheView
     *image_view;
@@ -2308,10 +2550,8 @@ MagickExport MagickBooleanType LevelizeImage(Image *image,
   */
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  if (IsGrayColorspace(image->colorspace) != MagickFalse)
-    (void) SetImageColorspace(image,RGBColorspace,exception);
   if (image->storage_class == PseudoClass)
     for (i=0; i < (ssize_t) image->colors; i++)
     {
@@ -2319,14 +2559,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);
@@ -2349,7 +2587,7 @@ MagickExport MagickBooleanType LevelizeImage(Image *image,
     register ssize_t
       x;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
     if (q == (Quantum *) NULL)
@@ -2362,7 +2600,7 @@ MagickExport MagickBooleanType LevelizeImage(Image *image,
       register ssize_t
         i;
 
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelReadMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
@@ -2377,7 +2615,7 @@ MagickExport MagickBooleanType LevelizeImage(Image *image,
       }
       q+=GetPixelChannels(image);
     }
-    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -2388,7 +2626,7 @@ MagickExport MagickBooleanType LevelizeImage(Image *image,
         #pragma omp critical (MagickCore_LevelizeImage)
 #endif
         proceed=SetImageProgress(image,LevelizeImageTag,progress++,image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
@@ -2452,29 +2690,33 @@ MagickExport MagickBooleanType LevelImageColors(Image *image,
   */
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  if( IfMagickTrue(IsGrayColorspace(image->colorspace)) &&
+      (IfMagickFalse(IsGrayColorspace(black_color->colorspace)) ||
+       IfMagickFalse(IsGrayColorspace(white_color->colorspace))))
+    (void) SetImageColorspace(image,sRGBColorspace,exception);
   status=MagickFalse;
-  if (invert == MagickFalse)
+  if( IfMagickFalse(invert) )
     {
       if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         {
           channel_mask=SetImageChannelMask(image,RedChannel);
-          status|=LevelImage(image,black_color->red,white_color->red,1.0,
+          status&=LevelImage(image,black_color->red,white_color->red,1.0,
             exception);
           (void) SetImageChannelMask(image,channel_mask);
         }
       if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         {
           channel_mask=SetImageChannelMask(image,GreenChannel);
-          status|=LevelImage(image,black_color->green,white_color->green,1.0,
+          status&=LevelImage(image,black_color->green,white_color->green,1.0,
             exception);
           (void) SetImageChannelMask(image,channel_mask);
         }
       if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         {
           channel_mask=SetImageChannelMask(image,BlueChannel);
-          status|=LevelImage(image,black_color->blue,white_color->blue,1.0,
+          status&=LevelImage(image,black_color->blue,white_color->blue,1.0,
             exception);
           (void) SetImageChannelMask(image,channel_mask);
         }
@@ -2482,7 +2724,7 @@ MagickExport MagickBooleanType LevelImageColors(Image *image,
           (image->colorspace == CMYKColorspace))
         {
           channel_mask=SetImageChannelMask(image,BlackChannel);
-          status|=LevelImage(image,black_color->black,white_color->black,1.0,
+          status&=LevelImage(image,black_color->black,white_color->black,1.0,
             exception);
           (void) SetImageChannelMask(image,channel_mask);
         }
@@ -2490,7 +2732,7 @@ MagickExport MagickBooleanType LevelImageColors(Image *image,
           (image->alpha_trait == BlendPixelTrait))
         {
           channel_mask=SetImageChannelMask(image,AlphaChannel);
-          status|=LevelImage(image,black_color->alpha,white_color->alpha,1.0,
+          status&=LevelImage(image,black_color->alpha,white_color->alpha,1.0,
             exception);
           (void) SetImageChannelMask(image,channel_mask);
         }
@@ -2500,21 +2742,21 @@ MagickExport MagickBooleanType LevelImageColors(Image *image,
       if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
         {
           channel_mask=SetImageChannelMask(image,RedChannel);
-          status|=LevelizeImage(image,black_color->red,white_color->red,1.0,
+          status&=LevelizeImage(image,black_color->red,white_color->red,1.0,
             exception);
           (void) SetImageChannelMask(image,channel_mask);
         }
       if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
         {
           channel_mask=SetImageChannelMask(image,GreenChannel);
-          status|=LevelizeImage(image,black_color->green,white_color->green,1.0,
+          status&=LevelizeImage(image,black_color->green,white_color->green,1.0,
             exception);
           (void) SetImageChannelMask(image,channel_mask);
         }
       if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
         {
           channel_mask=SetImageChannelMask(image,BlueChannel);
-          status|=LevelizeImage(image,black_color->blue,white_color->blue,1.0,
+          status&=LevelizeImage(image,black_color->blue,white_color->blue,1.0,
             exception);
           (void) SetImageChannelMask(image,channel_mask);
         }
@@ -2522,7 +2764,7 @@ MagickExport MagickBooleanType LevelImageColors(Image *image,
           (image->colorspace == CMYKColorspace))
         {
           channel_mask=SetImageChannelMask(image,BlackChannel);
-          status|=LevelizeImage(image,black_color->black,white_color->black,1.0,
+          status&=LevelizeImage(image,black_color->black,white_color->black,1.0,
             exception);
           (void) SetImageChannelMask(image,channel_mask);
         }
@@ -2530,12 +2772,12 @@ MagickExport MagickBooleanType LevelImageColors(Image *image,
           (image->alpha_trait == BlendPixelTrait))
         {
           channel_mask=SetImageChannelMask(image,AlphaChannel);
-          status|=LevelizeImage(image,black_color->alpha,white_color->alpha,1.0,
+          status&=LevelizeImage(image,black_color->alpha,white_color->alpha,1.0,
             exception);
           (void) SetImageChannelMask(image,channel_mask);
         }
     }
-  return(status == 0 ? MagickFalse : MagickTrue);
+  return(status != 0 ? MagickTrue : MagickFalse);
 }
 \f
 /*
@@ -2702,6 +2944,29 @@ static inline void ModulateHCL(const double percent_hue,
   ConvertHCLToRGB(hue,chroma,luma,red,green,blue);
 }
 
+static inline void ModulateHCLp(const double percent_hue,
+  const double percent_chroma,const double percent_luma,double *red,
+  double *green,double *blue)
+{
+  double
+    hue,
+    luma,
+    chroma;
+
+  /*
+    Increase or decrease color luma, chroma, or hue.
+  */
+  ConvertRGBToHCLp(*red,*green,*blue,&hue,&chroma,&luma);
+  hue+=0.5*(0.01*percent_hue-1.0);
+  while (hue < 0.0)
+    hue+=1.0;
+  while (hue > 1.0)
+    hue-=1.0;
+  chroma*=0.01*percent_chroma;
+  luma*=0.01*percent_luma;
+  ConvertHCLpToRGB(hue,chroma,luma,red,green,blue);
+}
+
 static inline void ModulateHSB(const double percent_hue,
   const double percent_saturation,const double percent_brightness,double *red,
   double *green,double *blue)
@@ -2725,6 +2990,29 @@ static inline void ModulateHSB(const double percent_hue,
   ConvertHSBToRGB(hue,saturation,brightness,red,green,blue);
 }
 
+static inline void ModulateHSI(const double percent_hue,
+  const double percent_saturation,const double percent_intensity,double *red,
+  double *green,double *blue)
+{
+  double
+    intensity,
+    hue,
+    saturation;
+
+  /*
+    Increase or decrease color intensity, saturation, or hue.
+  */
+  ConvertRGBToHSI(*red,*green,*blue,&hue,&saturation,&intensity);
+  hue+=0.5*(0.01*percent_hue-1.0);
+  while (hue < 0.0)
+    hue+=1.0;
+  while (hue > 1.0)
+    hue-=1.0;
+  saturation*=0.01*percent_saturation;
+  intensity*=0.01*percent_intensity;
+  ConvertHSIToRGB(hue,saturation,intensity,red,green,blue);
+}
+
 static inline void ModulateHSL(const double percent_hue,
   const double percent_saturation,const double percent_lightness,double *red,
   double *green,double *blue)
@@ -2741,13 +3029,36 @@ static inline void ModulateHSL(const double percent_hue,
   hue+=0.5*(0.01*percent_hue-1.0);
   while (hue < 0.0)
     hue+=1.0;
-  while (hue > 1.0)
+  while (hue >= 1.0)
     hue-=1.0;
   saturation*=0.01*percent_saturation;
   lightness*=0.01*percent_lightness;
   ConvertHSLToRGB(hue,saturation,lightness,red,green,blue);
 }
 
+static inline void ModulateHSV(const double percent_hue,
+  const double percent_saturation,const double percent_value,double *red,
+  double *green,double *blue)
+{
+  double
+    hue,
+    saturation,
+    value;
+
+  /*
+    Increase or decrease color value, saturation, or hue.
+  */
+  ConvertRGBToHSV(*red,*green,*blue,&hue,&saturation,&value);
+  hue+=0.5*(0.01*percent_hue-1.0);
+  while (hue < 0.0)
+    hue+=1.0;
+  while (hue >= 1.0)
+    hue-=1.0;
+  saturation*=0.01*percent_saturation;
+  value*=0.01*percent_value;
+  ConvertHSVToRGB(hue,saturation,value,red,green,blue);
+}
+
 static inline void ModulateHWB(const double percent_hue,
   const double percent_whiteness,const double percent_blackness,double *red,
   double *green,double *blue)
@@ -2764,13 +3075,59 @@ static inline void ModulateHWB(const double percent_hue,
   hue+=0.5*(0.01*percent_hue-1.0);
   while (hue < 0.0)
     hue+=1.0;
-  while (hue > 1.0)
+  while (hue >= 1.0)
     hue-=1.0;
   blackness*=0.01*percent_blackness;
   whiteness*=0.01*percent_whiteness;
   ConvertHWBToRGB(hue,whiteness,blackness,red,green,blue);
 }
 
+static inline void ModulateLCHab(const double percent_luma,
+  const double percent_chroma,const double percent_hue,double *red,
+  double *green,double *blue)
+{
+  double
+    hue,
+    luma,
+    chroma;
+
+  /*
+    Increase or decrease color luma, chroma, or hue.
+  */
+  ConvertRGBToLCHab(*red,*green,*blue,&luma,&chroma,&hue);
+  luma*=0.01*percent_luma;
+  chroma*=0.01*percent_chroma;
+  hue+=0.5*(0.01*percent_hue-1.0);
+  while (hue < 0.0)
+    hue+=1.0;
+  while (hue >= 1.0)
+    hue-=1.0;
+  ConvertLCHabToRGB(luma,chroma,hue,red,green,blue);
+}
+
+static inline void ModulateLCHuv(const double percent_luma,
+  const double percent_chroma,const double percent_hue,double *red,
+  double *green,double *blue)
+{
+  double
+    hue,
+    luma,
+    chroma;
+
+  /*
+    Increase or decrease color luma, chroma, or hue.
+  */
+  ConvertRGBToLCHuv(*red,*green,*blue,&luma,&chroma,&hue);
+  luma*=0.01*percent_luma;
+  chroma*=0.01*percent_chroma;
+  hue+=0.5*(0.01*percent_hue-1.0);
+  while (hue < 0.0)
+    hue+=1.0;
+  while (hue >= 1.0)
+    hue-=1.0;
+  ConvertLCHuvToRGB(luma,chroma,hue,red,green,blue);
+}
+
 MagickExport MagickBooleanType ModulateImage(Image *image,const char *modulate,
   ExceptionInfo *exception)
 {
@@ -2813,12 +3170,12 @@ MagickExport MagickBooleanType ModulateImage(Image *image,const char *modulate,
   */
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (modulate == (char *) NULL)
     return(MagickFalse);
-  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
-    (void) TransformImageColorspace(image,sRGBColorspace,exception);
+  if( IfMagickFalse(IssRGBCompatibleColorspace(image->colorspace)) )
+    (void) SetImageColorspace(image,sRGBColorspace,exception);
   flags=ParseGeometry(modulate,&geometry_info);
   percent_brightness=geometry_info.rho;
   percent_saturation=geometry_info.sigma;
@@ -2841,11 +3198,11 @@ MagickExport MagickBooleanType ModulateImage(Image *image,const char *modulate,
         red;
 
       /*
-        Modulate colormap.
+        Modulate image colormap.
       */
-      red=image->colormap[i].red;
-      green=image->colormap[i].green;
-      blue=image->colormap[i].blue;
+      red=(double) image->colormap[i].red;
+      green=(double) image->colormap[i].green;
+      blue=(double) image->colormap[i].blue;
       switch (colorspace)
       {
         case HCLColorspace:
@@ -2854,12 +3211,24 @@ MagickExport MagickBooleanType ModulateImage(Image *image,const char *modulate,
             &red,&green,&blue);
           break;
         }
+        case HCLpColorspace:
+        {
+          ModulateHCLp(percent_hue,percent_saturation,percent_brightness,
+            &red,&green,&blue);
+          break;
+        }
         case HSBColorspace:
         {
           ModulateHSB(percent_hue,percent_saturation,percent_brightness,
             &red,&green,&blue);
           break;
         }
+        case HSIColorspace:
+        {
+          ModulateHSI(percent_hue,percent_saturation,percent_brightness,
+            &red,&green,&blue);
+          break;
+        }
         case HSLColorspace:
         default:
         {
@@ -2867,13 +3236,35 @@ MagickExport MagickBooleanType ModulateImage(Image *image,const char *modulate,
             &red,&green,&blue);
           break;
         }
+        case HSVColorspace:
+        {
+          ModulateHSV(percent_hue,percent_saturation,percent_brightness,
+            &red,&green,&blue);
+          break;
+        }
         case HWBColorspace:
         {
           ModulateHWB(percent_hue,percent_saturation,percent_brightness,
             &red,&green,&blue);
           break;
         }
+        case LCHColorspace:
+        case LCHabColorspace:
+        {
+          ModulateLCHab(percent_brightness,percent_saturation,percent_hue,
+            &red,&green,&blue);
+          break;
+        }
+        case LCHuvColorspace:
+        {
+          ModulateLCHuv(percent_brightness,percent_saturation,percent_hue,
+            &red,&green,&blue);
+          break;
+        }
       }
+      image->colormap[i].red=red;
+      image->colormap[i].green=green;
+      image->colormap[i].blue=blue;
     }
   /*
     Modulate image.
@@ -2893,7 +3284,7 @@ MagickExport MagickBooleanType ModulateImage(Image *image,const char *modulate,
     register ssize_t
       x;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
     if (q == (Quantum *) NULL)
@@ -2919,6 +3310,12 @@ MagickExport MagickBooleanType ModulateImage(Image *image,const char *modulate,
             &red,&green,&blue);
           break;
         }
+        case HCLpColorspace:
+        {
+          ModulateHCLp(percent_hue,percent_saturation,percent_brightness,
+            &red,&green,&blue);
+          break;
+        }
         case HSBColorspace:
         {
           ModulateHSB(percent_hue,percent_saturation,percent_brightness,
@@ -2932,19 +3329,38 @@ MagickExport MagickBooleanType ModulateImage(Image *image,const char *modulate,
             &red,&green,&blue);
           break;
         }
+        case HSVColorspace:
+        {
+          ModulateHSV(percent_hue,percent_saturation,percent_brightness,
+            &red,&green,&blue);
+          break;
+        }
         case HWBColorspace:
         {
           ModulateHWB(percent_hue,percent_saturation,percent_brightness,
             &red,&green,&blue);
           break;
         }
+        case LCHabColorspace:
+        {
+          ModulateLCHab(percent_brightness,percent_saturation,percent_hue,
+            &red,&green,&blue);
+          break;
+        }
+        case LCHColorspace:
+        case LCHuvColorspace:
+        {
+          ModulateLCHuv(percent_brightness,percent_saturation,percent_hue,
+            &red,&green,&blue);
+          break;
+        }
       }
       SetPixelRed(image,ClampToQuantum(red),q);
       SetPixelGreen(image,ClampToQuantum(green),q);
       SetPixelBlue(image,ClampToQuantum(blue),q);
       q+=GetPixelChannels(image);
     }
-    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -2955,7 +3371,7 @@ MagickExport MagickBooleanType ModulateImage(Image *image,const char *modulate,
         #pragma omp critical (MagickCore_ModulateImage)
 #endif
         proceed=SetImageProgress(image,ModulateImageTag,progress++,image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
@@ -3013,7 +3429,7 @@ MagickExport MagickBooleanType NegateImage(Image *image,
 
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (image->storage_class == PseudoClass)
     for (i=0; i < (ssize_t) image->colors; i++)
@@ -3021,7 +3437,7 @@ MagickExport MagickBooleanType NegateImage(Image *image,
       /*
         Negate colormap.
       */
-      if (grayscale != MagickFalse)
+      if( IfMagickTrue(grayscale) )
         if ((image->colormap[i].red != image->colormap[i].green) ||
             (image->colormap[i].green != image->colormap[i].blue))
           continue;
@@ -3038,7 +3454,7 @@ MagickExport MagickBooleanType NegateImage(Image *image,
   status=MagickTrue;
   progress=0;
   image_view=AcquireAuthenticCacheView(image,exception);
-  if (grayscale != MagickFalse)
+  if( IfMagickTrue(grayscale) )
     {
       for (y=0; y < (ssize_t) image->rows; y++)
       {
@@ -3051,7 +3467,7 @@ MagickExport MagickBooleanType NegateImage(Image *image,
         register ssize_t
           x;
 
-        if (status == MagickFalse)
+        if( IfMagickFalse(status) )
           continue;
         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
           exception);
@@ -3065,8 +3481,8 @@ MagickExport MagickBooleanType NegateImage(Image *image,
           register ssize_t
             i;
 
-          if ((GetPixelMask(image,q) != 0) ||
-              (IsPixelGray(image,q) != MagickFalse))
+          if ((GetPixelReadMask(image,q) == 0) ||
+              IfMagickTrue(IsPixelGray(image,q)))
             {
               q+=GetPixelChannels(image);
               continue;
@@ -3082,7 +3498,7 @@ MagickExport MagickBooleanType NegateImage(Image *image,
           q+=GetPixelChannels(image);
         }
         sync=SyncCacheViewAuthenticPixels(image_view,exception);
-        if (sync == MagickFalse)
+        if( IfMagickFalse(sync) )
           status=MagickFalse;
         if (image->progress_monitor != (MagickProgressMonitor) NULL)
           {
@@ -3094,7 +3510,7 @@ MagickExport MagickBooleanType NegateImage(Image *image,
 #endif
             proceed=SetImageProgress(image,NegateImageTag,progress++,
               image->rows);
-            if (proceed == MagickFalse)
+            if( IfMagickFalse(proceed) )
               status=MagickFalse;
           }
       }
@@ -3116,7 +3532,7 @@ MagickExport MagickBooleanType NegateImage(Image *image,
     register ssize_t
       x;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
     if (q == (Quantum *) NULL)
@@ -3129,7 +3545,7 @@ MagickExport MagickBooleanType NegateImage(Image *image,
       register ssize_t
         i;
 
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelReadMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
@@ -3144,7 +3560,7 @@ MagickExport MagickBooleanType NegateImage(Image *image,
       }
       q+=GetPixelChannels(image);
     }
-    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -3155,7 +3571,7 @@ MagickExport MagickBooleanType NegateImage(Image *image,
         #pragma omp critical (MagickCore_NegateImage)
 #endif
         proceed=SetImageProgress(image,NegateImageTag,progress++,image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
@@ -3353,7 +3769,7 @@ MagickExport MagickBooleanType SigmoidalContrastImage(Image *image,
   */
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   /*
     Side effect: may clamp values unless contrast<MagickEpsilon, in which
@@ -3369,29 +3785,37 @@ MagickExport MagickBooleanType SigmoidalContrastImage(Image *image,
       register ssize_t
         i;
 
-      if (sharpen != MagickFalse)
+      if( IfMagickTrue(sharpen) )
         for (i=0; i < (ssize_t) image->colors; i++)
         {
           if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
-            image->colormap[i].red=ScaledSig(image->colormap[i].red);
+            image->colormap[i].red=(MagickRealType) ScaledSig(
+              image->colormap[i].red);
           if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
-            image->colormap[i].green=ScaledSig(image->colormap[i].green);
+            image->colormap[i].green=(MagickRealType) ScaledSig(
+              image->colormap[i].green);
           if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
-            image->colormap[i].blue=ScaledSig(image->colormap[i].blue);
+            image->colormap[i].blue=(MagickRealType) ScaledSig(
+              image->colormap[i].blue);
           if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
-            image->colormap[i].alpha=ScaledSig(image->colormap[i].alpha);
+            image->colormap[i].alpha=(MagickRealType) ScaledSig(
+              image->colormap[i].alpha);
         }
       else
         for (i=0; i < (ssize_t) image->colors; i++)
         {
           if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
-            image->colormap[i].red=InverseScaledSig(image->colormap[i].red);
+            image->colormap[i].red=(MagickRealType) InverseScaledSig(
+              image->colormap[i].red);
           if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
-            image->colormap[i].green=InverseScaledSig(image->colormap[i].green);
+            image->colormap[i].green=(MagickRealType) InverseScaledSig(
+              image->colormap[i].green);
           if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
-            image->colormap[i].blue=InverseScaledSig(image->colormap[i].blue);
+            image->colormap[i].blue=(MagickRealType) InverseScaledSig(
+              image->colormap[i].blue);
           if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
-            image->colormap[i].alpha=InverseScaledSig(image->colormap[i].alpha);
+            image->colormap[i].alpha=(MagickRealType) InverseScaledSig(
+              image->colormap[i].alpha);
         }
     }
   /*
@@ -3412,7 +3836,7 @@ MagickExport MagickBooleanType SigmoidalContrastImage(Image *image,
     register ssize_t
       x;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
     if (q == (Quantum *) NULL)
@@ -3425,7 +3849,7 @@ MagickExport MagickBooleanType SigmoidalContrastImage(Image *image,
       register ssize_t
         i;
 
-      if (GetPixelMask(image,q) != 0)
+      if (GetPixelReadMask(image,q) == 0)
         {
           q+=GetPixelChannels(image);
           continue;
@@ -3436,14 +3860,14 @@ MagickExport MagickBooleanType SigmoidalContrastImage(Image *image,
         PixelTrait traits=GetPixelChannelTraits(image,channel);
         if ((traits & UpdatePixelTrait) == 0)
           continue;
-        if (sharpen != MagickFalse)
+        if( IfMagickTrue(sharpen) )
           q[i]=ScaledSig(q[i]);
         else
           q[i]=InverseScaledSig(q[i]);
       }
       q+=GetPixelChannels(image);
     }
-    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -3455,7 +3879,7 @@ MagickExport MagickBooleanType SigmoidalContrastImage(Image *image,
 #endif
         proceed=SetImageProgress(image,SigmoidalContrastImageTag,progress++,
           image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }