]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/color.c
(no commit message)
[imagemagick] / MagickCore / color.c
index 7402e510848aa599bbe0c49518c31d8855effbbd..d2fa27635b044eb424445f0e6a859998ba2b26a4 100644 (file)
 %                          MagickCore Color Methods                           %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                                 July 1992                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2011 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  %
@@ -69,6 +69,7 @@
 #include "MagickCore/utility.h"
 #include "MagickCore/utility-private.h"
 #include "MagickCore/xml-tree.h"
+#include "MagickCore/xml-tree-private.h"
 \f
 /*
   Define declarations.
@@ -109,7 +110,7 @@ static const ColorMapInfo
     { "cyan", 0, 255, 255, 1, SVGCompliance | X11Compliance | XPMCompliance },
     { "blue", 0, 0, 255, 1, SVGCompliance | X11Compliance | XPMCompliance },
     { "yellow", 255, 255, 0, 1, SVGCompliance | X11Compliance | XPMCompliance },
-    { "white", 255, 255, 255, 1, SVGCompliance | X11Compliance },
+    { "white", 255, 255, 255, 1, SVGCompliance | X11Compliance | XPMCompliance },
     { "AliceBlue", 240, 248, 255, 1, SVGCompliance | X11Compliance | XPMCompliance },
     { "AntiqueWhite", 250, 235, 215, 1, SVGCompliance | X11Compliance | XPMCompliance },
     { "AntiqueWhite1", 255, 239, 219, 1, X11Compliance },
@@ -785,20 +786,114 @@ static const ColorMapInfo
   Static declarations.
 */
 static LinkedListInfo
-  *color_list = (LinkedListInfo *) NULL;
+  *color_cache = (LinkedListInfo *) NULL;
 
 static SemaphoreInfo
   *color_semaphore = (SemaphoreInfo *) NULL;
-
-static volatile MagickBooleanType
-  instantiate_color = MagickFalse;
 \f
 /*
   Forward declarations.
 */
 static MagickBooleanType
-  InitializeColorList(ExceptionInfo *),
-  LoadColorLists(const char *,ExceptionInfo *);
+  IsColorCacheInstantiated(ExceptionInfo *),
+  LoadColorCache(LinkedListInfo *,const char *,const char *,const size_t,
+    ExceptionInfo *);
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%  A c q u i r e C o l o r C a c h e                                          %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  AcquireColorCache() caches one or more color configurations which provides a
+%  mapping between color attributes and a color name.
+%
+%  The format of the AcquireColorCache method is:
+%
+%      LinkedListInfo *AcquireColorCache(const char *filename,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o filename: the font file name.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+static LinkedListInfo *AcquireColorCache(const char *filename,
+  ExceptionInfo *exception)
+{
+  const StringInfo
+    *option;
+
+  LinkedListInfo
+    *color_cache,
+    *options;
+
+  MagickStatusType
+    status;
+
+  register ssize_t
+    i;
+
+  /*
+    Load external color map.
+  */
+  color_cache=NewLinkedList(0);
+  if (color_cache == (LinkedListInfo *) NULL)
+    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
+  status=MagickTrue;
+  options=GetConfigureOptions(filename,exception);
+  option=(const StringInfo *) GetNextValueInLinkedList(options);
+  while (option != (const StringInfo *) NULL)
+  {
+    status&=LoadColorCache(color_cache,(const char *)
+      GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
+    option=(const StringInfo *) GetNextValueInLinkedList(options);
+  }
+  options=DestroyConfigureOptions(options);
+  /*
+    Load built-in color map.
+  */
+  for (i=0; i < (ssize_t) (sizeof(ColorMap)/sizeof(*ColorMap)); i++)
+  {
+    ColorInfo
+      *color_info;
+
+    register const ColorMapInfo
+      *p;
+
+    p=ColorMap+i;
+    color_info=(ColorInfo *) AcquireMagickMemory(sizeof(*color_info));
+    if (color_info == (ColorInfo *) NULL)
+      {
+        (void) ThrowMagickException(exception,GetMagickModule(),
+          ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
+        continue;
+      }
+    (void) ResetMagickMemory(color_info,0,sizeof(*color_info));
+    color_info->path=(char *) "[built-in]";
+    color_info->name=(char *) p->name;
+    GetPixelInfo((Image *) NULL,&color_info->color);
+    color_info->color.red=(double) ScaleCharToQuantum(p->red);
+    color_info->color.green=(double) ScaleCharToQuantum(p->green);
+    color_info->color.blue=(double) ScaleCharToQuantum(p->blue);
+    color_info->color.alpha=(double) (QuantumRange*p->alpha);
+    color_info->compliance=(ComplianceType) p->compliance;
+    color_info->exempt=MagickTrue;
+    color_info->signature=MagickSignature;
+    status&=AppendValueToLinkedList(color_cache,color_info);
+    if (IfMagickFalse(status))
+      (void) ThrowMagickException(exception,GetMagickModule(),
+        ResourceLimitError,"MemoryAllocationFailed","`%s'",color_info->name);
+  }
+  return(color_cache);
+}
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -820,7 +915,8 @@ static MagickBooleanType
 */
 MagickPrivate MagickBooleanType ColorComponentGenesis(void)
 {
-  AcquireSemaphoreInfo(&color_semaphore);
+  if (color_semaphore == (SemaphoreInfo *) NULL)
+    color_semaphore=AcquireSemaphoreInfo();
   return(MagickTrue);
 }
 \f
@@ -849,7 +945,7 @@ static void *DestroyColorElement(void *color_info)
     *p;
 
   p=(ColorInfo *) color_info;
-  if (p->exempt  == MagickFalse)
+  if (IfMagickFalse(p->exempt))
     {
       if (p->path != (char *) NULL)
         p->path=DestroyString(p->path);
@@ -863,13 +959,12 @@ static void *DestroyColorElement(void *color_info)
 MagickPrivate void ColorComponentTerminus(void)
 {
   if (color_semaphore == (SemaphoreInfo *) NULL)
-    AcquireSemaphoreInfo(&color_semaphore);
+    ActivateSemaphoreInfo(&color_semaphore);
   LockSemaphoreInfo(color_semaphore);
-  if (color_list != (LinkedListInfo *) NULL)
-    color_list=DestroyLinkedList(color_list,DestroyColorElement);
-  instantiate_color=MagickFalse;
+  if (color_cache != (LinkedListInfo *) NULL)
+    color_cache=DestroyLinkedList(color_cache,DestroyColorElement);
   UnlockSemaphoreInfo(color_semaphore);
-  DestroySemaphoreInfo(&color_semaphore);
+  RelinquishSemaphoreInfo(&color_semaphore);
 }
 \f
 /*
@@ -913,19 +1008,14 @@ MagickExport const ColorInfo *GetColorCompliance(const char *name,
     *q;
 
   assert(exception != (ExceptionInfo *) NULL);
-  if ((color_list == (LinkedListInfo *) NULL) ||
-      (instantiate_color == MagickFalse))
-    if (InitializeColorList(exception) == MagickFalse)
-      return((const ColorInfo *) NULL);
-  if ((color_list == (LinkedListInfo *) NULL) ||
-      (IsLinkedListEmpty(color_list) != MagickFalse))
+  if (IfMagickFalse(IsColorCacheInstantiated(exception)))
     return((const ColorInfo *) NULL);
-  if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
-    return((const ColorInfo *) GetValueFromLinkedList(color_list,0));
   /*
     Strip names of whitespace.
   */
-  (void) CopyMagickString(colorname,name,MaxTextExtent);
+  *colorname='\0';
+  if (name != (const char *) NULL)
+    (void) CopyMagickString(colorname,name,MaxTextExtent);
   for (q=colorname; *q != '\0'; q++)
   {
     if (isspace((int) ((unsigned char) *q)) == 0)
@@ -937,21 +1027,26 @@ MagickExport const ColorInfo *GetColorCompliance(const char *name,
     Search for color tag.
   */
   LockSemaphoreInfo(color_semaphore);
-  ResetLinkedListIterator(color_list);
-  p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
+  ResetLinkedListIterator(color_cache);
+  p=(const ColorInfo *) GetNextValueInLinkedList(color_cache);
+  if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
+    {
+      UnlockSemaphoreInfo(color_semaphore);
+      return(p);
+    }
   while (p != (const ColorInfo *) NULL)
   {
     if (((p->compliance & compliance) != 0) &&
         (LocaleCompare(colorname,p->name) == 0))
       break;
-    p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
+    p=(const ColorInfo *) GetNextValueInLinkedList(color_cache);
   }
   if (p == (ColorInfo *) NULL)
     (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
       "UnrecognizedColor","`%s'",name);
   else
-    (void) InsertValueInLinkedList(color_list,0,
-      RemoveElementByValueFromLinkedList(color_list,p));
+    (void) InsertValueInLinkedList(color_cache,0,
+      RemoveElementByValueFromLinkedList(color_cache,p));
   UnlockSemaphoreInfo(color_semaphore);
   return(p);
 }
@@ -1027,7 +1122,7 @@ MagickExport void ConcatenateColorComponent(const PixelInfo *pixel,
   char
     text[MaxTextExtent];
 
-  MagickRealType
+  double
     color;
 
   color=0.0;
@@ -1061,6 +1156,12 @@ MagickExport void ConcatenateColorComponent(const PixelInfo *pixel,
     default:
       break;
   }
+  if (compliance == NoCompliance)
+    {
+      (void) FormatLocaleString(text,MaxTextExtent,"%.*g",GetMagickPrecision(),color);
+      (void) ConcatenateMagickString(tuple,text,MaxTextExtent);
+      return;
+    }
   if (compliance != SVGCompliance)
     {
       if (pixel->depth > 16)
@@ -1084,22 +1185,27 @@ MagickExport void ConcatenateColorComponent(const PixelInfo *pixel,
     }
   if (component == AlphaPixelChannel)
     {
-      (void) FormatLocaleString(text,MaxTextExtent,"%g",(double)
+      (void) FormatLocaleString(text,MaxTextExtent,"%.*g",GetMagickPrecision(),
         (QuantumScale*color));
       (void) ConcatenateMagickString(tuple,text,MaxTextExtent);
       return;
     }
-  if ((pixel->colorspace == HSLColorspace) ||
-      (pixel->colorspace == HSBColorspace))
+  if ((pixel->colorspace == HCLColorspace) ||
+      (pixel->colorspace == HCLpColorspace) ||
+      (pixel->colorspace == HSBColorspace) ||
+      (pixel->colorspace == HSIColorspace) ||
+      (pixel->colorspace == HSLColorspace) ||
+      (pixel->colorspace == HSVColorspace) ||
+      (pixel->colorspace == HWBColorspace))
     {
-      (void) FormatLocaleString(text,MaxTextExtent,"%g%%",(double)
+      (void) FormatLocaleString(text,MaxTextExtent,"%.*g%%",GetMagickPrecision(),
         (100.0*QuantumScale*color));
       (void) ConcatenateMagickString(tuple,text,MaxTextExtent);
       return;
     }
   if (pixel->depth > 8)
     {
-      (void) FormatLocaleString(text,MaxTextExtent,"%g%%",(double)
+      (void) FormatLocaleString(text,MaxTextExtent,"%.*g%%",GetMagickPrecision(),
         (100.0*QuantumScale*color));
       (void) ConcatenateMagickString(tuple,text,MaxTextExtent);
       return;
@@ -1181,21 +1287,21 @@ MagickExport const ColorInfo **GetColorInfoList(const char *pattern,
   if (p == (const ColorInfo *) NULL)
     return((const ColorInfo **) NULL);
   colors=(const ColorInfo **) AcquireQuantumMemory((size_t)
-    GetNumberOfElementsInLinkedList(color_list)+1UL,sizeof(*colors));
+    GetNumberOfElementsInLinkedList(color_cache)+1UL,sizeof(*colors));
   if (colors == (const ColorInfo **) NULL)
     return((const ColorInfo **) NULL);
   /*
     Generate color list.
   */
   LockSemaphoreInfo(color_semaphore);
-  ResetLinkedListIterator(color_list);
-  p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
+  ResetLinkedListIterator(color_cache);
+  p=(const ColorInfo *) GetNextValueInLinkedList(color_cache);
   for (i=0; p != (const ColorInfo *) NULL; )
   {
-    if ((p->stealth == MagickFalse) &&
-        (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
+    if (IsMagickFalse(p->stealth) &&
+        IsMagickTrue(GlobExpression(p->name,pattern,MagickFalse)))
       colors[i++]=p;
-    p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
+    p=(const ColorInfo *) GetNextValueInLinkedList(color_cache);
   }
   UnlockSemaphoreInfo(color_semaphore);
   qsort((void *) colors,(size_t) i,sizeof(*colors),ColorInfoCompare);
@@ -1274,21 +1380,21 @@ MagickExport char **GetColorList(const char *pattern,
   if (p == (const ColorInfo *) NULL)
     return((char **) NULL);
   colors=(char **) AcquireQuantumMemory((size_t)
-    GetNumberOfElementsInLinkedList(color_list)+1UL,sizeof(*colors));
+    GetNumberOfElementsInLinkedList(color_cache)+1UL,sizeof(*colors));
   if (colors == (char **) NULL)
     return((char **) NULL);
   /*
     Generate color list.
   */
   LockSemaphoreInfo(color_semaphore);
-  ResetLinkedListIterator(color_list);
-  p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
+  ResetLinkedListIterator(color_cache);
+  p=(const ColorInfo *) GetNextValueInLinkedList(color_cache);
   for (i=0; p != (const ColorInfo *) NULL; )
   {
-    if ((p->stealth == MagickFalse) &&
-        (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
+    if (IsMagickFalse(p->stealth) &&
+        IsMagickTrue(GlobExpression(p->name,pattern,MagickFalse)))
       colors[i++]=ConstantString(p->name);
-    p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
+    p=(const ColorInfo *) GetNextValueInLinkedList(color_cache);
   }
   UnlockSemaphoreInfo(color_semaphore);
   qsort((void *) colors,(size_t) i,sizeof(*colors),ColorCompare);
@@ -1327,38 +1433,38 @@ MagickExport char **GetColorList(const char *pattern,
 */
 
 static void ConcatentateHexColorComponent(const PixelInfo *pixel,
-  const ChannelType channel,char *tuple)
+  const PixelChannel channel,char *tuple)
 {
   char
     component[MaxTextExtent];
 
-  MagickRealType
+  double
     color;
 
   color=0.0;
   switch (channel)
   {
-    case RedChannel:
+    case RedPixelChannel:
     {
       color=pixel->red;
       break;
     }
-    case GreenChannel:
+    case GreenPixelChannel:
     {
       color=pixel->green;
       break;
     }
-    case BlueChannel:
+    case BluePixelChannel:
     {
       color=pixel->blue;
       break;
     }
-    case AlphaChannel:
+    case AlphaPixelChannel:
     {
       color=pixel->alpha;
       break;
     }
-    case BlackChannel:
+    case BlackPixelChannel:
     {
       color=pixel->black;
       break;
@@ -1404,19 +1510,20 @@ MagickExport void GetColorTuple(const PixelInfo *pixel,
   assert(tuple != (char *) NULL);
   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tuple);
   *tuple='\0';
-  if (hex != MagickFalse)
+  if (IfMagickTrue(hex))
     {
       /*
         Convert pixel to hex color.
       */
       (void) ConcatenateMagickString(tuple,"#",MaxTextExtent);
-      ConcatentateHexColorComponent(pixel,RedChannel,tuple);
-      ConcatentateHexColorComponent(pixel,GreenChannel,tuple);
-      ConcatentateHexColorComponent(pixel,BlueChannel,tuple);
+      ConcatentateHexColorComponent(pixel,RedPixelChannel,tuple);
+      ConcatentateHexColorComponent(pixel,GreenPixelChannel,tuple);
+      ConcatentateHexColorComponent(pixel,BluePixelChannel,tuple);
       if (pixel->colorspace == CMYKColorspace)
-        ConcatentateHexColorComponent(pixel,BlackChannel,tuple);
-      if ((pixel->matte != MagickFalse) && (pixel->alpha != OpaqueAlpha))
-        ConcatentateHexColorComponent(pixel,AlphaChannel,tuple);
+        ConcatentateHexColorComponent(pixel,BlackPixelChannel,tuple);
+      if ((pixel->alpha_trait == BlendPixelTrait) &&
+          (pixel->alpha != OpaqueAlpha))
+        ConcatentateHexColorComponent(pixel,AlphaPixelChannel,tuple);
       return;
     }
   /*
@@ -1425,7 +1532,7 @@ MagickExport void GetColorTuple(const PixelInfo *pixel,
   color=(*pixel);
   if (color.depth > 8)
     {
-#define SVGCompliant(component) ((MagickRealType) \
+#define SVGCompliant(component) ((double) \
    ScaleCharToQuantum(ScaleQuantumToChar(ClampToQuantum(component))))
 
       MagickStatusType
@@ -1434,37 +1541,42 @@ MagickExport void GetColorTuple(const PixelInfo *pixel,
       /*
         SVG requires color depths > 8 expressed as percentages.
       */
-      status=fabs(color.red-SVGCompliant(color.red)) < MagickEpsilon ?
-        MagickTrue : MagickFalse;
-      status&=fabs(color.green-SVGCompliant(color.green)) < MagickEpsilon ?
-        MagickTrue : MagickFalse;
-      status&=fabs(color.blue-SVGCompliant(color.blue)) < MagickEpsilon ?
-        MagickTrue : MagickFalse;
+      status=IsMagickTrue(fabs(color.red-SVGCompliant(color.red))
+           < MagickEpsilon);
+      status&=IsMagickTrue(fabs(color.green-SVGCompliant(color.green))
+           < MagickEpsilon);
+      status&=IsMagickTrue(fabs(color.blue-SVGCompliant(color.blue))
+           < MagickEpsilon);
       if (color.colorspace-CMYKColorspace)
-        status&=fabs(color.black-SVGCompliant(color.black)) < MagickEpsilon ?
-          MagickTrue : MagickFalse;
-      if (color.matte != MagickFalse)
-        status&=fabs(color.alpha-SVGCompliant(color.alpha)) < MagickEpsilon ?
-          MagickTrue : MagickFalse;
-      if (status != MagickFalse)
+        status&=IsMagickTrue(fabs(color.black-SVGCompliant(color.black))
+             < MagickEpsilon);
+      if (color.alpha_trait == BlendPixelTrait)
+        status&=IsMagickTrue(fabs(color.alpha-SVGCompliant(color.alpha))
+             < MagickEpsilon);
+      if (IfMagickTrue(status))
         color.depth=8;
     }
   (void) ConcatenateMagickString(tuple,CommandOptionToMnemonic(
     MagickColorspaceOptions,(ssize_t) color.colorspace),MaxTextExtent);
-  if (color.matte != MagickFalse)
+  if (color.alpha_trait == BlendPixelTrait)
     (void) ConcatenateMagickString(tuple,"a",MaxTextExtent);
   (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
-  ConcatenateColorComponent(&color,RedPixelChannel,SVGCompliance,tuple);
-  (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
-  ConcatenateColorComponent(&color,GreenPixelChannel,SVGCompliance,tuple);
-  (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
-  ConcatenateColorComponent(&color,BluePixelChannel,SVGCompliance,tuple);
+  if (color.colorspace == GRAYColorspace)
+    ConcatenateColorComponent(&color,GrayPixelChannel,SVGCompliance,tuple);
+  else
+    {
+      ConcatenateColorComponent(&color,RedPixelChannel,SVGCompliance,tuple);
+      (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
+      ConcatenateColorComponent(&color,GreenPixelChannel,SVGCompliance,tuple);
+      (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
+      ConcatenateColorComponent(&color,BluePixelChannel,SVGCompliance,tuple);
+    }
   if (color.colorspace == CMYKColorspace)
     {
       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
       ConcatenateColorComponent(&color,BlackPixelChannel,SVGCompliance,tuple);
     }
-  if (color.matte != MagickFalse)
+  if (color.alpha_trait == BlendPixelTrait)
     {
       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
       ConcatenateColorComponent(&color,AlphaPixelChannel,SVGCompliance,tuple);
@@ -1479,40 +1591,36 @@ MagickExport void GetColorTuple(const PixelInfo *pixel,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-+   I n i t i a l i z e C o l o r L i s t                                     %
++   I s C o l o r C a c h e I n s t a n t i a t e d                           %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  InitializeColorList() initializes the color list.
+%  IsColorCacheInstantiated() determines if the color list is instantiated.  If
+%  not, it instantiates the list and returns it.
 %
-%  The format of the InitializeColorList method is:
+%  The format of the IsColorInstantiated method is:
 %
-%      MagickBooleanType InitializeColorList(ExceptionInfo *exception)
+%      MagickBooleanType IsColorCacheInstantiated(ExceptionInfo *exception)
 %
 %  A description of each parameter follows.
 %
 %    o exception: return any errors or warnings in this structure.
 %
 */
-static MagickBooleanType InitializeColorList(ExceptionInfo *exception)
+static MagickBooleanType IsColorCacheInstantiated(ExceptionInfo *exception)
 {
-  if ((color_list == (LinkedListInfo *) NULL) &&
-      (instantiate_color == MagickFalse))
+  if (color_cache == (LinkedListInfo *) NULL)
     {
       if (color_semaphore == (SemaphoreInfo *) NULL)
-        AcquireSemaphoreInfo(&color_semaphore);
+        ActivateSemaphoreInfo(&color_semaphore);
       LockSemaphoreInfo(color_semaphore);
-      if ((color_list == (LinkedListInfo *) NULL) &&
-          (instantiate_color == MagickFalse))
-        {
-          (void) LoadColorLists(ColorFilename,exception);
-          instantiate_color=MagickTrue;
-        }
+      if (color_cache == (LinkedListInfo *) NULL)
+        color_cache=AcquireColorCache(ColorFilename,exception);
       UnlockSemaphoreInfo(color_semaphore);
     }
-  return(color_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
+  return(color_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
 }
 \f
 /*
@@ -1555,19 +1663,19 @@ static inline double MagickMax(const double x,const double y)
 MagickExport MagickBooleanType IsEquivalentAlpha(const Image *image,
   const PixelInfo *p,const PixelInfo *q)
 {
-  MagickRealType
+  double
     fuzz,
     pixel;
 
-  register MagickRealType
+  register double
     distance;
 
-  if (image->matte == MagickFalse)
+  if (image->alpha_trait != BlendPixelTrait)
     return(MagickTrue);
   if (p->alpha == q->alpha)
     return(MagickTrue);
   fuzz=MagickMax(image->fuzz,MagickSQ1_2)*MagickMax(image->fuzz,MagickSQ1_2);
-  pixel=(MagickRealType) p->alpha-(MagickRealType) q->alpha;
+  pixel=(double) p->alpha-(double) q->alpha;
   distance=pixel*pixel;
   if (distance > fuzz)
     return(MagickFalse);
@@ -1640,7 +1748,7 @@ MagickExport MagickBooleanType IsEquivalentImage(const 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(target_image != (Image *) NULL);
   assert(target_image->signature == MagickSignature);
@@ -1651,8 +1759,8 @@ MagickExport MagickBooleanType IsEquivalentImage(const Image *image,
   status=MagickTrue;
   GetPixelInfo(image,&pixel);
   GetPixelInfo(image,&target);
-  image_view=AcquireCacheView(image);
-  target_view=AcquireCacheView(target_image);
+  image_view=AcquireVirtualCacheView(image,exception);
+  target_view=AcquireVirtualCacheView(target_image,exception);
   for (y=(*y_offset); y < (ssize_t) image->rows; y++)
   {
     for (x=y == 0 ? *x_offset : 0; x < (ssize_t) image->columns; x++)
@@ -1662,10 +1770,14 @@ MagickExport MagickBooleanType IsEquivalentImage(const Image *image,
         for (i=0; i < (ssize_t) target_image->columns; i++)
         {
           p=GetCacheViewVirtualPixels(image_view,x+i,y+j,1,1,exception);
-          SetPixelInfo(image,p,&pixel);
+          if (p == (const Quantum *) NULL)
+            break;
+          GetPixelInfoPixel(image,p,&pixel);
           q=GetCacheViewVirtualPixels(target_view,i,j,1,1,exception);
-          SetPixelInfo(image,q,&target);
-          if (IsFuzzyEquivalencePixelInfo(&pixel,&target) == MagickFalse)
+          if (q == (const Quantum *) NULL)
+            break;
+          GetPixelInfoPixel(image,q,&target);
+          if (IfMagickFalse(IsFuzzyEquivalencePixelInfo(&pixel,&target)))
             break;
         }
         if (i < (ssize_t) target_image->columns)
@@ -1683,7 +1795,7 @@ MagickExport MagickBooleanType IsEquivalentImage(const Image *image,
 
         proceed=SetImageProgress(image,SearchImageText,(MagickOffsetType) y,
           image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
@@ -1691,9 +1803,9 @@ MagickExport MagickBooleanType IsEquivalentImage(const Image *image,
   image_view=DestroyCacheView(image_view);
   *x_offset=x;
   *y_offset=y;
-  if (status == MagickFalse)
+  if (IfMagickFalse(status))
     return(status);
-  return(y < (ssize_t) image->rows ? MagickTrue : MagickFalse);
+  return(IsMagickTrue(y < (ssize_t) image->rows));
 }
 \f
 /*
@@ -1751,7 +1863,7 @@ MagickExport MagickBooleanType ListColorInfo(FILE *file,
   path=(const char *) NULL;
   for (i=0; i < (ssize_t) number_colors; i++)
   {
-    if (color_info[i]->stealth != MagickFalse)
+    if (IfMagickTrue(color_info[i]->stealth))
       continue;
     if ((path == (const char *) NULL) ||
         (LocaleCompare(path,color_info[i]->path) != 0))
@@ -1793,13 +1905,14 @@ MagickExport MagickBooleanType ListColorInfo(FILE *file,
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  LoadColorList() loads the color configuration file which provides a mapping
+%  LoadColorCache() loads the color configurations which provides a mapping
 %  between color attributes and a color name.
 %
-%  The format of the LoadColorList method is:
+%  The format of the LoadColorCache method is:
 %
-%      MagickBooleanType LoadColorList(const char *xml,const char *filename,
-%        const size_t depth,ExceptionInfo *exception)
+%      MagickBooleanType LoadColorCache(LinkedListInfo *color_cache,
+%        const char *xml,const char *filename,const size_t depth,
+%        ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
@@ -1812,8 +1925,9 @@ MagickExport MagickBooleanType ListColorInfo(FILE *file,
 %    o exception: return any errors or warnings in this structure.
 %
 */
-static MagickBooleanType LoadColorList(const char *xml,const char *filename,
-  const size_t depth,ExceptionInfo *exception)
+static MagickBooleanType LoadColorCache(LinkedListInfo *color_cache,
+  const char *xml,const char *filename,const size_t depth,
+  ExceptionInfo *exception)
 {
   char
     keyword[MaxTextExtent],
@@ -1835,16 +1949,6 @@ static MagickBooleanType LoadColorList(const char *xml,const char *filename,
     "Loading color file \"%s\" ...",filename);
   if (xml == (char *) NULL)
     return(MagickFalse);
-  if (color_list == (LinkedListInfo *) NULL)
-    {
-      color_list=NewLinkedList(0);
-      if (color_list == (LinkedListInfo *) NULL)
-        {
-          ThrowFileException(exception,ResourceLimitError,
-            "MemoryAllocationFailed",filename);
-          return(MagickFalse);
-        }
-    }
   status=MagickTrue;
   color_info=(ColorInfo *) NULL;
   token=AcquireString(xml);
@@ -1906,10 +2010,11 @@ static MagickBooleanType LoadColorList(const char *xml,const char *filename,
                     (void) CopyMagickString(path,token,MaxTextExtent);
                   else
                     (void) ConcatenateMagickString(path,token,MaxTextExtent);
-                  xml=FileToString(path,~0,exception);
+                  xml=FileToXML(path,~0UL);
                   if (xml != (char *) NULL)
                     {
-                      status=LoadColorList(xml,path,depth+1,exception);
+                      status&=LoadColorCache(color_cache,xml,path,depth+1,
+                        exception);
                       xml=(char *) RelinquishMagickMemory(xml);
                     }
                 }
@@ -1935,12 +2040,13 @@ static MagickBooleanType LoadColorList(const char *xml,const char *filename,
       continue;
     if (LocaleCompare(keyword,"/>") == 0)
       {
-        status=AppendValueToLinkedList(color_list,color_info);
-        if (status == MagickFalse)
+        status=AppendValueToLinkedList(color_cache,color_info);
+        if (IfMagickFalse(status))
           (void) ThrowMagickException(exception,GetMagickModule(),
             ResourceLimitError,"MemoryAllocationFailed","`%s'",
             color_info->name);
         color_info=(ColorInfo *) NULL;
+        continue;
       }
     GetMagickToken(q,(const char **) NULL,token);
     if (*token != '=')
@@ -1954,8 +2060,8 @@ static MagickBooleanType LoadColorList(const char *xml,const char *filename,
       {
         if (LocaleCompare((char *) keyword,"color") == 0)
           {
-            (void) QueryColorCompliance(token,AllCompliance,
-              &color_info->color,exception);
+            (void) QueryColorCompliance(token,AllCompliance,&color_info->color,
+              exception);
             break;
           }
         if (LocaleCompare((char *) keyword,"compliance") == 0)
@@ -1964,11 +2070,11 @@ static MagickBooleanType LoadColorList(const char *xml,const char *filename,
               compliance;
 
             compliance=color_info->compliance;
-            if (GlobExpression(token,"*SVG*",MagickTrue) != MagickFalse)
+            if (IfMagickTrue(GlobExpression(token,"*SVG*",MagickTrue)))
               compliance|=SVGCompliance;
-            if (GlobExpression(token,"*X11*",MagickTrue) != MagickFalse)
+            if (IfMagickTrue(GlobExpression(token,"*X11*",MagickTrue)))
               compliance|=X11Compliance;
-            if (GlobExpression(token,"*XPM*",MagickTrue) != MagickFalse)
+            if (IfMagickTrue(GlobExpression(token,"*XPM*",MagickTrue)))
               compliance|=XPMCompliance;
             color_info->compliance=(ComplianceType) compliance;
             break;
@@ -1990,7 +2096,7 @@ static MagickBooleanType LoadColorList(const char *xml,const char *filename,
       {
         if (LocaleCompare((char *) keyword,"stealth") == 0)
           {
-            color_info->stealth=IsMagickTrue(token);
+            color_info->stealth=IsStringTrue(token);
             break;
           }
         break;
@@ -2008,116 +2114,14 @@ static MagickBooleanType LoadColorList(const char *xml,const char *filename,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%  L o a d C o l o r L i s t s                                                %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  LoadColorList() loads one or more color configuration file which provides a
-%  mapping between color attributes and a color name.
-%
-%  The format of the LoadColorLists method is:
-%
-%      MagickBooleanType LoadColorLists(const char *filename,
-%        ExceptionInfo *exception)
-%
-%  A description of each parameter follows:
-%
-%    o filename: the font file name.
-%
-%    o exception: return any errors or warnings in this structure.
-%
-*/
-static MagickBooleanType LoadColorLists(const char *filename,
-  ExceptionInfo *exception)
-{
-  const StringInfo
-    *option;
-
-  LinkedListInfo
-    *options;
-
-  MagickStatusType
-    status;
-
-  register ssize_t
-    i;
-
-  /*
-    Load built-in color map.
-  */
-  status=MagickFalse;
-  if (color_list == (LinkedListInfo *) NULL)
-    {
-      color_list=NewLinkedList(0);
-      if (color_list == (LinkedListInfo *) NULL)
-        {
-          ThrowFileException(exception,ResourceLimitError,
-            "MemoryAllocationFailed",filename);
-          return(MagickFalse);
-        }
-    }
-  for (i=0; i < (ssize_t) (sizeof(ColorMap)/sizeof(*ColorMap)); i++)
-  {
-    ColorInfo
-      *color_info;
-
-    register const ColorMapInfo
-      *p;
-
-    p=ColorMap+i;
-    color_info=(ColorInfo *) AcquireMagickMemory(sizeof(*color_info));
-    if (color_info == (ColorInfo *) NULL)
-      {
-        (void) ThrowMagickException(exception,GetMagickModule(),
-          ResourceLimitError,"MemoryAllocationFailed","`%s'",color_info->name);
-        continue;
-      }
-    (void) ResetMagickMemory(color_info,0,sizeof(*color_info));
-    color_info->path=(char *) "[built-in]";
-    color_info->name=(char *) p->name;
-    GetPixelInfo((Image *) NULL,&color_info->color);
-    color_info->color.red=(MagickRealType) ScaleCharToQuantum(p->red);
-    color_info->color.green=(MagickRealType) ScaleCharToQuantum(p->green);
-    color_info->color.blue=(MagickRealType) ScaleCharToQuantum(p->blue);
-    color_info->color.alpha=(MagickRealType) (QuantumRange*p->alpha);
-    color_info->compliance=(ComplianceType) p->compliance;
-    color_info->exempt=MagickTrue;
-    color_info->signature=MagickSignature;
-    status=AppendValueToLinkedList(color_list,color_info);
-    if (status == MagickFalse)
-      (void) ThrowMagickException(exception,GetMagickModule(),
-        ResourceLimitError,"MemoryAllocationFailed","`%s'",color_info->name);
-  }
-  /*
-    Load external color map.
-  */
-  options=GetConfigureOptions(filename,exception);
-  option=(const StringInfo *) GetNextValueInLinkedList(options);
-  while (option != (const StringInfo *) NULL)
-  {
-    status|=LoadColorList((const char *) GetStringInfoDatum(option),
-      GetStringInfoPath(option),0,exception);
-    option=(const StringInfo *) GetNextValueInLinkedList(options);
-  }
-  options=DestroyConfigureOptions(options);
-  return(status != 0 ? MagickTrue : MagickFalse);
-}
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
 +   Q u e r y C o l o r C o m p l i a n c e                                   %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  QueryColorCompliance() returns the red, green, blue, and alpha
-%  intensities for a given color name and standards compliance.
+%  QueryColorCompliance() returns the red, green, blue, and alpha intensities
+%  for a given color name and standards compliance.
 %
 %  The format of the QueryColorCompliance method is:
 %
@@ -2140,10 +2144,13 @@ static MagickBooleanType LoadColorLists(const char *filename,
 MagickExport MagickBooleanType QueryColorCompliance(const char *name,
   const ComplianceType compliance,PixelInfo *color,ExceptionInfo *exception)
 {
+  extern const char
+    BackgroundColor[];
+
   GeometryInfo
     geometry_info;
 
-  MagickRealType
+  double
     scale;
 
   MagickStatusType
@@ -2189,7 +2196,7 @@ MagickExport MagickBooleanType QueryColorCompliance(const char *name,
       */
       (void) ResetMagickMemory(&pixel,0,sizeof(pixel));
       name++;
-      for (n=0; isxdigit((int) ((unsigned char) name[n])) != MagickFalse; n++) ;
+      for (n=0; isxdigit((int) ((unsigned char) name[n])) != 0; n++) ;
       if ((n % 3) == 0)
         {
           do
@@ -2212,7 +2219,7 @@ MagickExport MagickBooleanType QueryColorCompliance(const char *name,
                   else
                     return(MagickFalse);
             }
-          } while (isxdigit((int) ((unsigned char) *name)) != MagickFalse);
+          } while (isxdigit((int) ((unsigned char) *name)) != 0);
           depth=4*(n/3);
         }
       else
@@ -2244,20 +2251,21 @@ MagickExport MagickBooleanType QueryColorCompliance(const char *name,
                   else
                     return(MagickFalse);
             }
-          } while (isxdigit((int) ((unsigned char) *name)) != MagickFalse);
+          } while (isxdigit((int) ((unsigned char) *name)) != 0);
           depth=4*(n/4);
         }
-      color->colorspace=RGBColorspace;
-      color->matte=MagickFalse;
+      color->colorspace=sRGBColorspace;
+      color->depth=depth;
+      color->alpha_trait=UndefinedPixelTrait;
       range=GetQuantumRange(depth);
-      color->red=(MagickRealType) ScaleAnyToQuantum(pixel.red,range);
-      color->green=(MagickRealType) ScaleAnyToQuantum(pixel.green,range);
-      color->blue=(MagickRealType) ScaleAnyToQuantum(pixel.blue,range);
-      color->alpha=(MagickRealType) OpaqueAlpha;
+      color->red=(double) ScaleAnyToQuantum(pixel.red,range);
+      color->green=(double) ScaleAnyToQuantum(pixel.green,range);
+      color->blue=(double) ScaleAnyToQuantum(pixel.blue,range);
+      color->alpha=(double) OpaqueAlpha;
       if ((n % 3) != 0)
         {
-          color->matte=MagickTrue;
-          color->alpha=(MagickRealType) ScaleAnyToQuantum(pixel.alpha,range);
+          color->alpha_trait=BlendPixelTrait;
+          color->alpha=(double) ScaleAnyToQuantum(pixel.alpha,range);
         }
       color->black=0.0;
       return(MagickTrue);
@@ -2267,6 +2275,9 @@ MagickExport MagickBooleanType QueryColorCompliance(const char *name,
       char
         colorspace[MaxTextExtent];
 
+      MagickBooleanType
+        icc_color;
+
       /*
         Parse color of the form rgb(100,255,0).
       */
@@ -2275,12 +2286,34 @@ MagickExport MagickBooleanType QueryColorCompliance(const char *name,
         if (colorspace[i] == '(')
           break;
       colorspace[i--]='\0';
+      scale=(double) ScaleCharToQuantum(1);
+      icc_color=MagickFalse;
+      if (LocaleNCompare(colorspace,"device-",7) == 0)
+        {
+          (void) CopyMagickString(colorspace,colorspace+7,MaxTextExtent);
+          scale=(double) QuantumRange;
+          icc_color=MagickTrue;
+        }
+      if (LocaleCompare(colorspace,"icc-color") == 0)
+        {
+          register ssize_t
+            j;
+
+          (void) CopyMagickString(colorspace,name+i+2,MaxTextExtent);
+          for (j=0; colorspace[j] != '\0'; j++)
+            if (colorspace[j] == ',')
+              break;
+          colorspace[j--]='\0';
+          i+=j+3;
+          scale=(double) QuantumRange;
+          icc_color=MagickTrue;
+        }
       LocaleLower(colorspace);
-      color->matte=MagickFalse;
+      color->alpha_trait=UndefinedPixelTrait;
       if ((i > 0) && (colorspace[i] == 'a'))
         {
           colorspace[i]='\0';
-          color->matte=MagickTrue;
+          color->alpha_trait=BlendPixelTrait;
         }
       type=ParseCommandOption(MagickColorspaceOptions,MagickFalse,colorspace);
       if (type < 0)
@@ -2290,72 +2323,117 @@ MagickExport MagickBooleanType QueryColorCompliance(const char *name,
           return(MagickFalse);
         }
       color->colorspace=(ColorspaceType) type;
-      SetGeometryInfo(&geometry_info);
-      flags=ParseGeometry(name+i+1,&geometry_info);
-      scale=(MagickRealType) ScaleCharToQuantum(1);
-      if ((flags & PercentValue) != 0)
-        scale=(MagickRealType) (QuantumRange/100.0);
-      if ((flags & RhoValue) != 0)
-        color->red=(MagickRealType) ClampToQuantum(scale*geometry_info.rho);
-      if ((flags & SigmaValue) != 0)
-        color->green=(MagickRealType) ClampToQuantum(scale*geometry_info.sigma);
-      if ((flags & XiValue) != 0)
-        color->blue=(MagickRealType) ClampToQuantum(scale*geometry_info.xi);
-      color->alpha=(MagickRealType) OpaqueAlpha;
-      if ((flags & PsiValue) != 0)
+      if (IfMagickFalse(icc_color) && (color->colorspace == RGBColorspace))
         {
-          if (color->colorspace == CMYKColorspace)
-            color->black=(MagickRealType) ClampToQuantum(scale*
-              geometry_info.psi);
-          else
-            if (color->matte != MagickFalse)
-              color->alpha=(MagickRealType) ClampToQuantum((MagickRealType)
-                QuantumRange*geometry_info.psi);
+          color->colorspace=sRGBColorspace;  /* as required by SVG standard */
+          color->depth=8;
         }
-      if (((flags & ChiValue) != 0) && (color->matte != MagickFalse))
-        color->alpha=(MagickRealType) ClampToQuantum((MagickRealType)
-          QuantumRange*geometry_info.chi);
-      if (LocaleCompare(colorspace,"gray") == 0)
+      SetGeometryInfo(&geometry_info);
+      flags=ParseGeometry(name+i+1,&geometry_info);
+      if (flags == 0)
         {
-          color->green=color->red;
-          color->blue=color->red;
-          if (((flags & SigmaValue) != 0) && (color->matte != MagickFalse))
-            color->alpha=(MagickRealType) ClampToQuantum((MagickRealType)
-              QuantumRange*geometry_info.sigma);
+          char
+            *colorname;
+
+          ColorspaceType
+            colorspace;
+
+          colorspace=color->colorspace;
+          colorname=AcquireString(name+i+1);
+          (void) SubstituteString(&colorname,")","");
+          (void) QueryColorCompliance(colorname,AllCompliance,color,exception);
+          colorname=DestroyString(colorname);
+          color->colorspace=colorspace;
         }
-      if ((LocaleCompare(colorspace,"HSB") == 0) ||
-          (LocaleCompare(colorspace,"HSL") == 0) ||
-          (LocaleCompare(colorspace,"HWB") == 0))
+      else
         {
-          PixelInfo
-            pixel;
-
-          scale=1.0/360.0;
           if ((flags & PercentValue) != 0)
-            scale=1.0/100.0;
-          geometry_info.rho*=360.0*scale;
-          scale=1.0/255.0;
-          if ((flags & PercentValue) != 0)
-            scale=1.0/100.0;
-          geometry_info.sigma*=scale;
-          geometry_info.xi*=scale;
-          if (LocaleCompare(colorspace,"HSB") == 0)
-            ConvertHSBToRGB(fmod(fmod(geometry_info.rho,360.0)+360.0,360.0)/
-              360.0,geometry_info.sigma,geometry_info.xi,&pixel.red,
-              &pixel.green,&pixel.blue);
-          else
-            if (LocaleCompare(colorspace,"HSL") == 0)
-              ConvertHSLToRGB(fmod(fmod(geometry_info.rho,360.0)+360.0,360.0)/
-                360.0,geometry_info.sigma,geometry_info.xi,&pixel.red,
-                &pixel.green,&pixel.blue);
-            else
-              ConvertHWBToRGB(fmod(fmod(geometry_info.rho,360.0)+360.0,360.0)/
-                360.0,geometry_info.sigma,geometry_info.xi,&pixel.red,
-                &pixel.green,&pixel.blue);
-          color->colorspace=RGBColorspace;
-          color->red=(MagickRealType) pixel.red;
-          color->green=(MagickRealType) pixel.green;
-          color->blue=(MagickRealType) pixel.blue;
+            scale=(double) (QuantumRange/100.0);
+          if ((flags & RhoValue) != 0)
+            color->red=(double) ClampToQuantum(scale*geometry_info.rho);
+          if ((flags & SigmaValue) != 0)
+            color->green=(double) ClampToQuantum(scale*
+              geometry_info.sigma);
+          if ((flags & XiValue) != 0)
+            color->blue=(double) ClampToQuantum(scale*geometry_info.xi);
+          color->alpha=(double) OpaqueAlpha;
+          if ((flags & PsiValue) != 0)
+            {
+              if (color->colorspace == CMYKColorspace)
+                color->black=(double) ClampToQuantum(scale*
+                  geometry_info.psi);
+              else
+                if (color->alpha_trait == BlendPixelTrait)
+                  color->alpha=(double) ClampToQuantum(QuantumRange*
+                    geometry_info.psi);
+            }
+          if (((flags & ChiValue) != 0) &&
+              (color->alpha_trait == BlendPixelTrait))
+            color->alpha=(double) ClampToQuantum(QuantumRange*
+              geometry_info.chi);
+          if (LocaleCompare(colorspace,"gray") == 0)
+            {
+              color->colorspace=GRAYColorspace;
+              color->green=color->red;
+              color->blue=color->red;
+              if (((flags & SigmaValue) != 0) &&
+                  (color->alpha_trait == BlendPixelTrait))
+                color->alpha=(double) ClampToQuantum(QuantumRange*
+                  geometry_info.sigma);
+            }
+          if ((LocaleCompare(colorspace,"HCL") == 0) ||
+              (LocaleCompare(colorspace,"HSB") == 0) ||
+              (LocaleCompare(colorspace,"HSL") == 0) ||
+              (LocaleCompare(colorspace,"HWB") == 0))
+            {
+              double
+                blue,
+                green,
+                red;
+
+              if (LocaleCompare(colorspace,"HCL") == 0)
+                color->colorspace=HCLColorspace;
+              else
+                if (LocaleCompare(colorspace,"HSB") == 0)
+                  color->colorspace=HSBColorspace;
+                else
+                  if (LocaleCompare(colorspace,"HSL") == 0)
+                    color->colorspace=HSLColorspace;
+                  else
+                    if (LocaleCompare(colorspace,"HWB") == 0)
+                      color->colorspace=HWBColorspace;
+              scale=1.0/360.0;
+              if ((flags & PercentValue) != 0)
+                scale=1.0/100.0;
+              geometry_info.rho*=360.0*scale;
+              scale=1.0/255.0;
+              if ((flags & PercentValue) != 0)
+                scale=1.0/100.0;
+              geometry_info.sigma*=scale;
+              geometry_info.xi*=scale;
+              if (LocaleCompare(colorspace,"HCL") == 0)
+                ConvertHCLToRGB(fmod(fmod(geometry_info.rho,360.0)+360.0,
+                  360.0)/360.0,geometry_info.sigma,geometry_info.xi,&red,
+                  &green,&blue);
+              else
+                if (LocaleCompare(colorspace,"HSB") == 0)
+                  ConvertHSBToRGB(fmod(fmod(geometry_info.rho,360.0)+360.0,
+                    360.0)/360.0,geometry_info.sigma,geometry_info.xi,&red,
+                    &green,&blue);
+                else
+                  if (LocaleCompare(colorspace,"HSL") == 0)
+                    ConvertHSLToRGB(fmod(fmod(geometry_info.rho,360.0)+360.0,
+                      360.0)/360.0,geometry_info.sigma,geometry_info.xi,&red,
+                      &green,&blue);
+                  else
+                    ConvertHWBToRGB(fmod(fmod(geometry_info.rho,360.0)+360.0,
+                      360.0)/360.0,geometry_info.sigma,geometry_info.xi,&red,
+                      &green,&blue);
+              color->colorspace=sRGBColorspace;
+              color->red=(MagickRealType) red;
+              color->green=(MagickRealType) green;
+              color->blue=(MagickRealType) blue;
+            }
         }
       return(MagickTrue);
     }
@@ -2365,12 +2443,14 @@ MagickExport MagickBooleanType QueryColorCompliance(const char *name,
   p=GetColorCompliance(name,compliance,exception);
   if (p == (const ColorInfo *) NULL)
     return(MagickFalse);
-  color->colorspace=RGBColorspace;
-  color->matte=p->color.alpha != OpaqueAlpha ? MagickTrue : MagickFalse;
-  color->red=(MagickRealType) p->color.red;
-  color->green=(MagickRealType) p->color.green;
-  color->blue=(MagickRealType) p->color.blue;
-  color->alpha=(MagickRealType) p->color.alpha;
+  color->colorspace=sRGBColorspace;
+  color->depth=8;
+  color->alpha_trait=p->color.alpha != OpaqueAlpha ? BlendPixelTrait :
+    UndefinedPixelTrait;
+  color->red=(double) p->color.red;
+  color->green=(double) p->color.green;
+  color->blue=(double) p->color.blue;
+  color->alpha=(double) p->color.alpha;
   color->black=0.0;
   return(MagickTrue);
 }
@@ -2391,6 +2471,9 @@ MagickExport MagickBooleanType QueryColorCompliance(const char *name,
 %  example an intensity of rgb:(0,0,0) returns black whereas rgb:(223,223,223)
 %  returns #dfdfdf.
 %
+%  UPDATE: the 'image' argument is no longer needed as all information should
+%  have been preset using GetPixelInfo().
+%
 %  The format of the QueryColorname method is:
 %
 %      MagickBooleanType QueryColorname(const Image *image,
@@ -2399,7 +2482,7 @@ MagickExport MagickBooleanType QueryColorCompliance(const char *name,
 %
 %  A description of each parameter follows.
 %
-%    o image: the image.
+%    o image: the image. (not used! - color gets settings from GetPixelInfo()
 %
 %    o color: the color intensities.
 %
@@ -2411,22 +2494,15 @@ MagickExport MagickBooleanType QueryColorCompliance(const char *name,
 %
 */
 
-static inline double MagickMin(const double x,const double y)
-{
-  if (x < y)
-    return(x);
-  return(y);
-}
-
-MagickExport MagickBooleanType QueryColorname(const Image *image,
-  const PixelInfo *color,const ComplianceType compliance,char *name,
-  ExceptionInfo *exception)
+MagickExport MagickBooleanType QueryColorname(
+  const Image *magick_unused(image),const PixelInfo *color,
+  const ComplianceType compliance,char *name,ExceptionInfo *exception)
 {
   PixelInfo
     pixel;
 
-  MagickRealType
-    opacity;
+  double
+    alpha;
 
   register const ColorInfo
     *p;
@@ -2435,29 +2511,29 @@ MagickExport MagickBooleanType QueryColorname(const Image *image,
   pixel=(*color);
   if (compliance == XPMCompliance)
     {
-      pixel.matte=MagickFalse;
-      pixel.depth=(size_t) MagickMin(1.0*image->depth,16.0);
+      pixel.alpha_trait=UndefinedPixelTrait;
+      if ( pixel.depth > 16 )
+        pixel.depth=16;
     }
-  GetColorTuple(&pixel,compliance != SVGCompliance ? MagickTrue : MagickFalse,
-    name);
-  if (IsRGBColorspace(pixel.colorspace) == MagickFalse)
+  GetColorTuple(&pixel,IsMagickTrue(compliance != SVGCompliance),name);
+  if (IfMagickFalse(IssRGBColorspace(pixel.colorspace)))
     return(MagickFalse);
+  alpha=color->alpha_trait == BlendPixelTrait ? color->alpha : OpaqueAlpha;
   (void) GetColorInfo("*",exception);
-  ResetLinkedListIterator(color_list);
-  opacity=image->matte != MagickFalse ? color->alpha : OpaqueAlpha;
-  p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
+  ResetLinkedListIterator(color_cache);
+  p=(const ColorInfo *) GetNextValueInLinkedList(color_cache);
   while (p != (const ColorInfo *) NULL)
   {
     if (((p->compliance & compliance) != 0) &&
         ((fabs(p->color.red-color->red) < MagickEpsilon)) &&
          (fabs(p->color.green-color->green) < MagickEpsilon) &&
          (fabs(p->color.blue-color->blue) < MagickEpsilon) &&
-         (fabs(p->color.alpha-opacity) < MagickEpsilon))
+         (fabs(p->color.alpha-alpha) < MagickEpsilon))
       {
         (void) CopyMagickString(name,p->name,MaxTextExtent);
         break;
       }
-    p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
+    p=(const ColorInfo *) GetNextValueInLinkedList(color_cache);
   }
   return(MagickTrue);
 }