diff --git a/magick/cache.c b/magick/cache.c
index 48e2ce8..89fdcad 100644
--- a/magick/cache.c
+++ b/magick/cache.c
@@ -2132,7 +2132,7 @@
     }
   (void) UnlockSemaphoreInfo(cache_info->semaphore);
   if (destroy != MagickFalse)
-    cache_info=DestroyPixelCache(cache_info);
+    cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
   if (status != MagickFalse)
     {
       /*
diff --git a/magick/color.c b/magick/color.c
index 65e3ee5..8c054b8 100644
--- a/magick/color.c
+++ b/magick/color.c
@@ -70,8 +70,6 @@
   Define declarations.
 */
 #define ColorFilename  "colors.xml"
-#define MaxTreeDepth  8
-#define NodesInAList  1536
 
 /*
   Declare color map.
@@ -337,53 +335,6 @@
     "</colormap>";
 
 /*
-  Typedef declarations.
-*/
-typedef struct _NodeInfo
-{
-  struct _NodeInfo
-    *child[16];
-
-  ColorPacket
-    *list;
-
-  MagickSizeType
-    number_unique;
-
-  unsigned long
-    level;
-} NodeInfo;
-
-typedef struct _Nodes
-{
-  NodeInfo
-    nodes[NodesInAList];
-
-  struct _Nodes
-    *next;
-} Nodes;
-
-typedef struct _CubeInfo
-{
-  NodeInfo
-    *root;
-
-  long
-    x,
-    progress;
-
-  unsigned long
-    colors,
-    free_nodes;
-
-  NodeInfo
-    *node_info;
-
-  Nodes
-    *node_queue;
-} CubeInfo;
-
-/*
   Static declarations.
 */
 static LinkedListInfo
@@ -398,191 +349,9 @@
 /*
   Forward declarations.
 */
-static CubeInfo
-  *GetCubeInfo(void);
-
-static NodeInfo
-  *GetNodeInfo(CubeInfo *,const unsigned long);
-
 static MagickBooleanType
   InitializeColorList(ExceptionInfo *),
   LoadColorLists(const char *,ExceptionInfo *);
-
-static void
-  DestroyColorCube(const Image *,NodeInfo *);
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-+   C l a s s i f y I m a g e C o l o r s                                     %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  ClassifyImageColors() builds a populated CubeInfo tree for the specified
-%  image.  The returned tree should be deallocated using DestroyCubeInfo()
-%  once it is no longer needed.
-%
-%  The format of the ClassifyImageColors() method is:
-%
-%      CubeInfo *ClassifyImageColors(const Image *image,
-%        ExceptionInfo *exception)
-%
-%  A description of each parameter follows.
-%
-%    o image: the image.
-%
-%    o exception: return any errors or warnings in this structure.
-%
-*/
-
-static inline unsigned long ColorToNodeId(const Image *image,
-  const MagickPixelPacket *pixel,unsigned long index)
-{
-  unsigned long
-    id;
-
-  id=(unsigned long) (
-    ((ScaleQuantumToChar(RoundToQuantum(pixel->red)) >> index) & 0x01) |
-    ((ScaleQuantumToChar(RoundToQuantum(pixel->green)) >> index) & 0x01) << 1 |
-    ((ScaleQuantumToChar(RoundToQuantum(pixel->blue)) >> index) & 0x01) << 2);
-  if (image->matte != MagickFalse)
-    id|=((ScaleQuantumToChar(RoundToQuantum(pixel->opacity)) >> index) &
-      0x01) << 3;
-  return(id);
-}
-
-static CubeInfo *ClassifyImageColors(const Image *image,
-  ExceptionInfo *exception)
-{
-#define EvaluateImageTag  "  Compute image colors...  "
-
-  CubeInfo
-    *cube_info;
-
-  long
-    y;
-
-  MagickBooleanType
-    proceed;
-
-  MagickPixelPacket
-    pixel,
-    target;
-
-  NodeInfo
-    *node_info;
-
-  register const IndexPacket
-    *indexes;
-
-  register const PixelPacket
-    *p;
-
-  register long
-    i,
-    x;
-
-  register unsigned long
-    id,
-    index,
-    level;
-
-  CacheView
-    *image_view;
-
-  /*
-    Initialize color description tree.
-  */
-  assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  cube_info=GetCubeInfo();
-  if (cube_info == (CubeInfo *) NULL)
-    {
-      (void) ThrowMagickException(exception,GetMagickModule(),
-        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
-      return(cube_info);
-    }
-  GetMagickPixelPacket(image,&pixel);
-  GetMagickPixelPacket(image,&target);
-  image_view=AcquireCacheView(image);
-  for (y=0; y < (long) image->rows; y++)
-  {
-    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
-    if (p == (const PixelPacket *) NULL)
-      break;
-    indexes=GetCacheViewVirtualIndexQueue(image_view);
-    for (x=0; x < (long) image->columns; x++)
-    {
-      /*
-        Start at the root and proceed level by level.
-      */
-      node_info=cube_info->root;
-      index=MaxTreeDepth-1;
-      for (level=1; level < MaxTreeDepth; level++)
-      {
-        SetMagickPixelPacket(image,p,indexes+x,&pixel);
-        id=ColorToNodeId(image,&pixel,index);
-        if (node_info->child[id] == (NodeInfo *) NULL)
-          {
-            node_info->child[id]=GetNodeInfo(cube_info,level);
-            if (node_info->child[id] == (NodeInfo *) NULL)
-              {
-                (void) ThrowMagickException(exception,GetMagickModule(),
-                  ResourceLimitError,"MemoryAllocationFailed","`%s'",
-                  image->filename);
-                return(0);
-              }
-          }
-        node_info=node_info->child[id];
-        index--;
-      }
-      for (i=0; i < (long) node_info->number_unique; i++)
-      {
-        SetMagickPixelPacket(image,&node_info->list[i].pixel,
-          &node_info->list[i].index,&target);
-        if (IsMagickColorEqual(&pixel,&target) != MagickFalse)
-          break;
-      }
-      if (i < (long) node_info->number_unique)
-        node_info->list[i].count++;
-      else
-        {
-          if (node_info->number_unique == 0)
-            node_info->list=(ColorPacket *) AcquireMagickMemory(
-              sizeof(*node_info->list));
-          else
-            node_info->list=(ColorPacket *) ResizeQuantumMemory(node_info->list,
-              (size_t) (i+1),sizeof(*node_info->list));
-          if (node_info->list == (ColorPacket *) NULL)
-            {
-              (void) ThrowMagickException(exception,GetMagickModule(),
-                ResourceLimitError,"MemoryAllocationFailed","`%s'",
-                image->filename);
-              return(0);
-            }
-          node_info->list[i].pixel=(*p);
-          if ((image->colorspace == CMYKColorspace) ||
-              (image->storage_class == PseudoClass))
-            node_info->list[i].index=indexes[x];
-          node_info->list[i].count=1;
-          node_info->number_unique++;
-          cube_info->colors++;
-        }
-      p++;
-    }
-    proceed=SetImageProgress(image,EvaluateImageTag,y,image->rows);
-    if (proceed == MagickFalse)
-      break;
-  }
-  image_view=DestroyCacheView(image_view);
-  return(cube_info);
-}
 
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -698,69 +467,6 @@
 %                                                                             %
 %                                                                             %
 %                                                                             %
-+   D e f i n e I m a g e H i s t o g r a m                                   %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  DefineImageHistogram() traverses the color cube tree and notes each colormap
-%  entry.  A colormap entry is any node in the color cube tree where the
-%  of unique colors is not zero.
-%
-%  The format of the DefineImageHistogram method is:
-%
-%      DefineImageHistogram(const Image *image,NodeInfo *node_info,
-%        ColorPacket **unique_colors)
-%
-%  A description of each parameter follows.
-%
-%    o image: the image.
-%
-%    o node_info: the address of a structure of type NodeInfo which points to a
-%      node in the color cube tree that is to be pruned.
-%
-%    o histogram: the image histogram.
-%
-*/
-static void DefineImageHistogram(const Image *image,NodeInfo *node_info,
-  ColorPacket **histogram)
-{
-  register long
-    i;
-
-  unsigned long
-    number_children;
-
-  /*
-    Traverse any children.
-  */
-  number_children=image->matte == MagickFalse ? 8UL : 16UL;
-  for (i=0; i < (long) number_children; i++)
-    if (node_info->child[i] != (NodeInfo *) NULL)
-      DefineImageHistogram(image,node_info->child[i],histogram);
-  if (node_info->level == (MaxTreeDepth-1))
-    {
-      register ColorPacket
-        *p;
-
-      p=node_info->list;
-      for (i=0; i < (long) node_info->number_unique; i++)
-      {
-        (*histogram)->pixel=p->pixel;
-        (*histogram)->index=p->index;
-        (*histogram)->count=p->count;
-        (*histogram)++;
-        p++;
-      }
-    }
-}
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
 +   D e s t r o y C o l o r L i s t                                           %
 %                                                                             %
 %                                                                             %
@@ -804,94 +510,6 @@
 %                                                                             %
 %                                                                             %
 %                                                                             %
-+   D e s t r o y C u b e I n f o                                             %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  DestroyCubeInfo() deallocates memory associated with a CubeInfo structure.
-%
-%  The format of the DestroyCubeInfo method is:
-%
-%      DestroyCubeInfo(const Image *image,CubeInfo *cube_info)
-%
-%  A description of each parameter follows:
-%
-%    o image: the image.
-%
-%    o cube_info: the address of a structure of type CubeInfo.
-%
-*/
-static CubeInfo *DestroyCubeInfo(const Image *image,CubeInfo *cube_info)
-{
-  register Nodes
-    *nodes;
-
-  /*
-    Release color cube tree storage.
-  */
-  DestroyColorCube(image,cube_info->root);
-  do
-  {
-    nodes=cube_info->node_queue->next;
-    cube_info->node_queue=(Nodes *)
-      RelinquishMagickMemory(cube_info->node_queue);
-    cube_info->node_queue=nodes;
-  } while (cube_info->node_queue != (Nodes *) NULL);
-  return((CubeInfo *) RelinquishMagickMemory(cube_info));
-}
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-+  D e s t r o y C o l o r C u b e                                            %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  DestroyColorCube() traverses the color cube tree and frees the list of
-%  unique colors.
-%
-%  The format of the DestroyColorCube method is:
-%
-%      void DestroyColorCube(const Image *image,const NodeInfo *node_info)
-%
-%  A description of each parameter follows.
-%
-%    o image: the image.
-%
-%    o node_info: the address of a structure of type NodeInfo which points to a
-%      node in the color cube tree that is to be pruned.
-%
-*/
-static void DestroyColorCube(const Image *image,NodeInfo *node_info)
-{
-  register long
-    i;
-
-  unsigned long
-    number_children;
-
-  /*
-    Traverse any children.
-  */
-  number_children=image->matte == MagickFalse ? 8UL : 16UL;
-  for (i=0; i < (long) number_children; i++)
-    if (node_info->child[i] != (NodeInfo *) NULL)
-      DestroyColorCube(image,node_info->child[i]);
-  if (node_info->list != (ColorPacket *) NULL)
-    node_info->list=(ColorPacket *) RelinquishMagickMemory(node_info->list);
-}
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
 +   G e t C o l o r I n f o                                                   %
 %                                                                             %
 %                                                                             %
@@ -1335,294 +953,6 @@
 %                                                                             %
 %                                                                             %
 %                                                                             %
-+   G e t C u b e I n f o                                                     %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  GetCubeInfo() initializes the CubeInfo data structure.
-%
-%  The format of the GetCubeInfo method is:
-%
-%      cube_info=GetCubeInfo()
-%
-%  A description of each parameter follows.
-%
-%    o cube_info: A pointer to the Cube structure.
-%
-*/
-static CubeInfo *GetCubeInfo(void)
-{
-  CubeInfo
-    *cube_info;
-
-  /*
-    Initialize tree to describe color cube.
-  */
-  cube_info=(CubeInfo *) AcquireMagickMemory(sizeof(*cube_info));
-  if (cube_info == (CubeInfo *) NULL)
-    return((CubeInfo *) NULL);
-  (void) ResetMagickMemory(cube_info,0,sizeof(*cube_info));
-  /*
-    Initialize root node.
-  */
-  cube_info->root=GetNodeInfo(cube_info,0);
-  if (cube_info->root == (NodeInfo *) NULL)
-    return((CubeInfo *) NULL);
-  return(cube_info);
-}
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%  G e t I m a g e H i s t o g r a m                                          %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  GetImageHistogram() returns the unique colors in an image.
-%
-%  The format of the GetImageHistogram method is:
-%
-%      unsigned long GetImageHistogram(const Image *image,
-%        unsigned long *number_colors,ExceptionInfo *exception)
-%
-%  A description of each parameter follows.
-%
-%    o image: the image.
-%
-%    o file:  Write a histogram of the color distribution to this file handle.
-%
-%    o exception: return any errors or warnings in this structure.
-%
-*/
-MagickExport ColorPacket *GetImageHistogram(const Image *image,
-  unsigned long *number_colors,ExceptionInfo *exception)
-{
-  ColorPacket
-    *histogram;
-
-  CubeInfo
-    *cube_info;
-
-  *number_colors=0;
-  histogram=(ColorPacket *) NULL;
-  cube_info=ClassifyImageColors(image,exception);
-  if (cube_info != (CubeInfo *) NULL)
-    {
-      histogram=(ColorPacket *) AcquireQuantumMemory((size_t) cube_info->colors,
-        sizeof(*histogram));
-      if (histogram == (ColorPacket *) NULL)
-        (void) ThrowMagickException(exception,GetMagickModule(),
-          ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
-      else
-        {
-          ColorPacket
-            *root;
-
-          *number_colors=cube_info->colors;
-          root=histogram;
-          DefineImageHistogram(image,cube_info->root,&root);
-        }
-    }
-  cube_info=DestroyCubeInfo(image,cube_info);
-  return(histogram);
-}
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-+  G e t N o d e I n f o                                                      %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  GetNodeInfo() allocates memory for a new node in the color cube tree and
-%  presets all fields to zero.
-%
-%  The format of the GetNodeInfo method is:
-%
-%      NodeInfo *GetNodeInfo(CubeInfo *cube_info,const unsigned long level)
-%
-%  A description of each parameter follows.
-%
-%    o cube_info: A pointer to the CubeInfo structure.
-%
-%    o level: Specifies the level in the storage_class the node resides.
-%
-*/
-static NodeInfo *GetNodeInfo(CubeInfo *cube_info,const unsigned long level)
-{
-  NodeInfo
-    *node_info;
-
-  if (cube_info->free_nodes == 0)
-    {
-      Nodes
-        *nodes;
-
-      /*
-        Allocate a new nodes of nodes.
-      */
-      nodes=(Nodes *) AcquireMagickMemory(sizeof(*nodes));
-      if (nodes == (Nodes *) NULL)
-        return((NodeInfo *) NULL);
-      nodes->next=cube_info->node_queue;
-      cube_info->node_queue=nodes;
-      cube_info->node_info=nodes->nodes;
-      cube_info->free_nodes=NodesInAList;
-    }
-  cube_info->free_nodes--;
-  node_info=cube_info->node_info++;
-  (void) ResetMagickMemory(node_info,0,sizeof(*node_info));
-  node_info->level=level;
-  return(node_info);
-}
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%  G e t N u m b e r C o l o r s                                              %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  GetNumberColors() returns the number of unique colors in an image.
-%
-%  The format of the GetNumberColors method is:
-%
-%      unsigned long GetNumberColors(const Image *image,FILE *file,
-%        ExceptionInfo *exception)
-%
-%  A description of each parameter follows.
-%
-%    o image: the image.
-%
-%    o file:  Write a histogram of the color distribution to this file handle.
-%
-%    o exception: return any errors or warnings in this structure.
-%
-*/
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-static int HistogramCompare(const void *x,const void *y)
-{
-  const ColorPacket
-    *color_1,
-    *color_2;
-
-  color_1=(const ColorPacket *) x;
-  color_2=(const ColorPacket *) y;
-  if (color_2->pixel.red != color_1->pixel.red)
-    return((int) color_1->pixel.red-(int) color_2->pixel.red);
-  if (color_2->pixel.green != color_1->pixel.green)
-    return((int) color_1->pixel.green-(int) color_2->pixel.green);
-  if (color_2->pixel.blue != color_1->pixel.blue)
-    return((int) color_1->pixel.blue-(int) color_2->pixel.blue);
-  return((int) color_2->count-(int) color_1->count);
-}
-
-#if defined(__cplusplus) || defined(c_plusplus)
-}
-#endif
-
-MagickExport unsigned long GetNumberColors(const Image *image,FILE *file,
-  ExceptionInfo *exception)
-{
-#define HistogramImageTag  "Histogram/Image"
-
-  char
-    color[MaxTextExtent],
-    hex[MaxTextExtent],
-    tuple[MaxTextExtent];
-
-  ColorPacket
-    *histogram;
-
-  MagickPixelPacket
-    pixel;
-
-  register ColorPacket
-    *p;
-
-  register long
-    i;
-
-  unsigned long
-    number_colors;
-
-  number_colors=0;
-  if (file == (FILE *) NULL)
-    {
-      CubeInfo
-        *cube_info;
-
-      cube_info=ClassifyImageColors(image,exception);
-      if (cube_info != (CubeInfo *) NULL)
-        number_colors=cube_info->colors;
-      cube_info=DestroyCubeInfo(image,cube_info);
-      return(number_colors);
-    }
-  histogram=GetImageHistogram(image,&number_colors,exception);
-  if (histogram == (ColorPacket *) NULL)
-    return(number_colors);
-  qsort((void *) histogram,(size_t) number_colors,sizeof(*histogram),
-    HistogramCompare);
-  GetMagickPixelPacket(image,&pixel);
-  p=histogram;
-  for (i=0; i < (long) number_colors; i++)
-  {
-    SetMagickPixelPacket(image,&p->pixel,&p->index,&pixel);
-    (void) CopyMagickString(tuple,"(",MaxTextExtent);
-    ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
-    (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
-    ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
-    (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
-    ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
-    if (pixel.colorspace == CMYKColorspace)
-      {
-        (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
-        ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
-      }
-    if (pixel.matte != MagickFalse)
-      {
-        (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
-        ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
-      }
-    (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
-    (void) QueryMagickColorname(image,&pixel,SVGCompliance,color,exception);
-    GetColorTuple(&pixel,MagickTrue,hex);
-    (void) fprintf(file,MagickSizeFormat,p->count);
-    (void) fprintf(file,": %s %s %s\n",tuple,hex,color);
-    if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
-        (QuantumTick(i,number_colors) != MagickFalse))
-      (void) image->progress_monitor(HistogramImageTag,i,number_colors,
-        image->client_data);
-    p++;
-  }
-  (void) fflush(file);
-  histogram=(ColorPacket *) RelinquishMagickMemory(histogram);
-  return(number_colors);
-}
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
 +   I n i t i a l i z e C o l o r L i s t                                     %
 %                                                                             %
 %                                                                             %
@@ -1848,171 +1178,6 @@
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%  I s H i s t o g r a m I m a g e                                            %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  IsHistogramImage() returns MagickTrue if the image has 1024 unique colors or
-%  less.
-%
-%  The format of the IsHistogramImage method is:
-%
-%      MagickBooleanType IsHistogramImage(const Image *image,
-%        ExceptionInfo *exception)
-%
-%  A description of each parameter follows.
-%
-%    o image: the image.
-%
-%    o exception: return any errors or warnings in this structure.
-%
-*/
-MagickExport MagickBooleanType IsHistogramImage(const Image *image,
-  ExceptionInfo *exception)
-{
-#define MaximumUniqueColors  1024
-
-  CubeInfo
-    *cube_info;
-
-  long
-    y;
-
-  MagickPixelPacket
-    pixel,
-    target;
-
-  register const IndexPacket
-    *indexes;
-
-  register const PixelPacket
-    *p;
-
-  register long
-    x;
-
-  register NodeInfo
-    *node_info;
-
-  register long
-    i;
-
-  unsigned long
-    id,
-    index,
-    level;
-
-  CacheView
-    *image_view;
-
-  assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  if ((image->storage_class == PseudoClass) && (image->colors <= 256))
-    return(MagickTrue);
-  if (image->storage_class == PseudoClass)
-    return(MagickFalse);
-  /*
-    Initialize color description tree.
-  */
-  cube_info=GetCubeInfo();
-  if (cube_info == (CubeInfo *) NULL)
-    {
-      (void) ThrowMagickException(exception,GetMagickModule(),
-        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
-      return(MagickFalse);
-    }
-  GetMagickPixelPacket(image,&pixel);
-  GetMagickPixelPacket(image,&target);
-  image_view=AcquireCacheView(image);
-  for (y=0; y < (long) image->rows; y++)
-  {
-    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
-    if (p == (const PixelPacket *) NULL)
-      break;
-    indexes=GetCacheViewVirtualIndexQueue(image_view);
-    for (x=0; x < (long) image->columns; x++)
-    {
-      /*
-        Start at the root and proceed level by level.
-      */
-      node_info=cube_info->root;
-      index=MaxTreeDepth-1;
-      for (level=1; level < MaxTreeDepth; level++)
-      {
-        SetMagickPixelPacket(image,p,indexes+x,&pixel);
-        id=ColorToNodeId(image,&pixel,index);
-        if (node_info->child[id] == (NodeInfo *) NULL)
-          {
-            node_info->child[id]=GetNodeInfo(cube_info,level);
-            if (node_info->child[id] == (NodeInfo *) NULL)
-              {
-                (void) ThrowMagickException(exception,GetMagickModule(),
-                  ResourceLimitError,"MemoryAllocationFailed","`%s'",
-                  image->filename);
-                break;
-              }
-          }
-        node_info=node_info->child[id];
-        index--;
-      }
-      if (level < MaxTreeDepth)
-        break;
-      for (i=0; i < (long) node_info->number_unique; i++)
-      {
-        SetMagickPixelPacket(image,&node_info->list[i].pixel,
-          &node_info->list[i].index,&target);
-        if (IsMagickColorEqual(&pixel,&target) != MagickFalse)
-          break;
-      }
-      if (i < (long) node_info->number_unique)
-        node_info->list[i].count++;
-      else
-        {
-          /*
-            Add this unique color to the color list.
-          */
-          if (node_info->number_unique == 0)
-            node_info->list=(ColorPacket *) AcquireMagickMemory(
-              sizeof(*node_info->list));
-          else
-            node_info->list=(ColorPacket *) ResizeQuantumMemory(node_info->list,
-              (size_t) (i+1),sizeof(*node_info->list));
-          if (node_info->list == (ColorPacket *) NULL)
-            {
-              (void) ThrowMagickException(exception,GetMagickModule(),
-                ResourceLimitError,"MemoryAllocationFailed","`%s'",
-                image->filename);
-              break;
-            }
-          node_info->list[i].pixel=(*p);
-          if ((image->colorspace == CMYKColorspace) ||
-              (image->storage_class == PseudoClass))
-            node_info->list[i].index=indexes[x];
-          node_info->list[i].count=1;
-          node_info->number_unique++;
-          cube_info->colors++;
-          if (cube_info->colors > MaximumUniqueColors)
-            break;
-        }
-      p++;
-    }
-    if (x < (long) image->columns)
-      break;
-  }
-  image_view=DestroyCacheView(image_view);
-  cube_info=DestroyCubeInfo(image,cube_info);
-  return(y < (long) image->rows ? MagickFalse : MagickTrue);
-}
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
 +   I s I m a g e S i m i l a r                                               %
 %                                                                             %
 %                                                                             %
@@ -2454,169 +1619,6 @@
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%  I s P a l e t t e I m a g e                                                %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  IsPaletteImage() returns MagickTrue if the image is PseudoClass and has 256
-%  unique colors or less.
-%
-%  The format of the IsPaletteImage method is:
-%
-%      MagickBooleanType IsPaletteImage(const Image *image,
-%        ExceptionInfo *exception)
-%
-%  A description of each parameter follows.
-%
-%    o image: the image.
-%
-%    o exception: return any errors or warnings in this structure.
-%
-*/
-MagickExport MagickBooleanType IsPaletteImage(const Image *image,
-  ExceptionInfo *exception)
-{
-  CubeInfo
-    *cube_info;
-
-  long
-    y;
-
-  MagickPixelPacket
-    pixel,
-    target;
-
-  register const IndexPacket
-    *indexes;
-
-  register const PixelPacket
-    *p;
-
-  register long
-    x;
-
-  register NodeInfo
-    *node_info;
-
-  register long
-    i;
-
-  unsigned long
-    id,
-    index,
-    level;
-
-  CacheView
-    *image_view;
-
-  assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  if ((image->storage_class == PseudoClass) && (image->colors <= 256))
-    return(MagickTrue);
-  if (image->storage_class == PseudoClass)
-    return(MagickFalse);
-  /*
-    Initialize color description tree.
-  */
-  cube_info=GetCubeInfo();
-  if (cube_info == (CubeInfo *) NULL)
-    {
-      (void) ThrowMagickException(exception,GetMagickModule(),
-        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
-      return(MagickFalse);
-    }
-  GetMagickPixelPacket(image,&pixel);
-  GetMagickPixelPacket(image,&target);
-  image_view=AcquireCacheView(image);
-  for (y=0; y < (long) image->rows; y++)
-  {
-    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
-    if (p == (const PixelPacket *) NULL)
-      break;
-    indexes=GetCacheViewVirtualIndexQueue(image_view);
-    for (x=0; x < (long) image->columns; x++)
-    {
-      /*
-        Start at the root and proceed level by level.
-      */
-      node_info=cube_info->root;
-      index=MaxTreeDepth-1;
-      for (level=1; level < MaxTreeDepth; level++)
-      {
-        SetMagickPixelPacket(image,p,indexes+x,&pixel);
-        id=ColorToNodeId(image,&pixel,index);
-        if (node_info->child[id] == (NodeInfo *) NULL)
-          {
-            node_info->child[id]=GetNodeInfo(cube_info,level);
-            if (node_info->child[id] == (NodeInfo *) NULL)
-              {
-                (void) ThrowMagickException(exception,GetMagickModule(),
-                  ResourceLimitError,"MemoryAllocationFailed","`%s'",
-                  image->filename);
-                break;
-              }
-          }
-        node_info=node_info->child[id];
-        index--;
-      }
-      if (level < MaxTreeDepth)
-        break;
-      for (i=0; i < (long) node_info->number_unique; i++)
-      {
-        SetMagickPixelPacket(image,&node_info->list[i].pixel,
-          &node_info->list[i].index,&target);
-        if (IsMagickColorEqual(&pixel,&target) != MagickFalse)
-          break;
-      }
-      if (i < (long) node_info->number_unique)
-        node_info->list[i].count++;
-      else
-        {
-          /*
-            Add this unique color to the color list.
-          */
-          if (node_info->number_unique == 0)
-            node_info->list=(ColorPacket *) AcquireMagickMemory(
-              sizeof(*node_info->list));
-          else
-            node_info->list=(ColorPacket *) ResizeQuantumMemory(node_info->list,
-              (size_t) (i+1),sizeof(*node_info->list));
-          if (node_info->list == (ColorPacket *) NULL)
-            {
-              (void) ThrowMagickException(exception,GetMagickModule(),
-                ResourceLimitError,"MemoryAllocationFailed","`%s'",
-                image->filename);
-              break;
-            }
-          node_info->list[i].pixel=(*p);
-          if ((image->colorspace == CMYKColorspace) ||
-              (image->storage_class == PseudoClass))
-            node_info->list[i].index=indexes[x];
-          node_info->list[i].count=1;
-          node_info->number_unique++;
-          cube_info->colors++;
-          if (cube_info->colors > 256)
-            break;
-        }
-      p++;
-    }
-    if (x < (long) image->columns)
-      break;
-  }
-  image_view=DestroyCacheView(image_view);
-  cube_info=DestroyCubeInfo(image,cube_info);
-  return(y < (long) image->rows ? MagickFalse : MagickTrue);
-}
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
 %  L i s t C o l o r I n f o                                                  %
 %                                                                             %
 %                                                                             %
@@ -3429,118 +2431,3 @@
   }
   return(MagickTrue);
 }
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%  U n i q u e I m a g e C o l o r s                                          %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  UniqueImageColors() returns the unique colors of an image.
-%
-%  The format of the UniqueImageColors method is:
-%
-%      Image *UniqueImageColors(const Image *image,ExceptionInfo *exception)
-%
-%  A description of each parameter follows.
-%
-%    o image: the image.
-%
-%    o exception: return any errors or warnings in this structure.
-%
-*/
-
-static void UniqueColorsToImage(Image *image,CubeInfo *cube_info,
-  const NodeInfo *node_info,ExceptionInfo *exception)
-{
-#define UniqueColorsImageTag  "UniqueColors/Image"
-
-  register long
-    i;
-
-  unsigned long
-    number_children;
-
-  /*
-    Traverse any children.
-  */
-  number_children=image->matte == MagickFalse ? 8UL : 16UL;
-  for (i=0; i < (long) number_children; i++)
-    if (node_info->child[i] != (NodeInfo *) NULL)
-      UniqueColorsToImage(image,cube_info,node_info->child[i],exception);
-  if (node_info->level == (MaxTreeDepth-1))
-    {
-      register ColorPacket
-        *p;
-
-      register IndexPacket
-        *__restrict indexes;
-
-      register PixelPacket
-        *__restrict q;
-
-      p=node_info->list;
-      for (i=0; i < (long) node_info->number_unique; i++)
-      {
-        q=QueueAuthenticPixels(image,cube_info->x,0,1,1,exception);
-        if (q == (PixelPacket *) NULL)
-          continue;
-        indexes=GetAuthenticIndexQueue(image);
-        *q=p->pixel;
-        if (image->colorspace == CMYKColorspace)
-          *indexes=p->index;
-        if (SyncAuthenticPixels(image,exception) == MagickFalse)
-          break;
-        cube_info->x++;
-        p++;
-      }
-      if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
-          (QuantumTick(cube_info->progress,cube_info->colors) != MagickFalse))
-        (void) image->progress_monitor(UniqueColorsImageTag,cube_info->progress,
-          cube_info->colors,image->client_data);
-      cube_info->progress++;
-    }
-}
-
-MagickExport Image *UniqueImageColors(const Image *image,
-  ExceptionInfo *exception)
-{
-  CubeInfo
-    *cube_info;
-
-  Image
-    *unique_image;
-
-  cube_info=ClassifyImageColors(image,exception);
-  if (cube_info == (CubeInfo *) NULL)
-    return((Image *) NULL);
-  unique_image=CloneImage(image,cube_info->colors,1,MagickTrue,exception);
-  if (unique_image == (Image *) NULL)
-    return(unique_image);
-  if (SetImageStorageClass(unique_image,DirectClass) == MagickFalse)
-    {
-      InheritException(exception,&unique_image->exception);
-      unique_image=DestroyImage(unique_image);
-      return((Image *) NULL);
-    }
-  UniqueColorsToImage(unique_image,cube_info,cube_info->root,exception);
-  if (cube_info->colors < MaxColormapSize)
-    {
-      QuantizeInfo
-        *quantize_info;
-
-      quantize_info=AcquireQuantizeInfo((ImageInfo *) NULL);
-      quantize_info->number_colors=MaxColormapSize;
-      quantize_info->dither=MagickFalse;
-      quantize_info->tree_depth=8;
-      (void) QuantizeImage(quantize_info,unique_image);
-      quantize_info=DestroyQuantizeInfo(quantize_info);
-    }
-  cube_info=DestroyCubeInfo(image,cube_info);
-  return(unique_image);
-}
diff --git a/magick/color.h b/magick/color.h
index eaed174..5ea63ba 100644
--- a/magick/color.h
+++ b/magick/color.h
@@ -58,18 +58,6 @@
     signature;
 } ColorInfo;
 
-typedef struct _ColorPacket
-{
-  PixelPacket
-    pixel;
-
-  IndexPacket
-    index;
-
-  MagickSizeType
-    count;
-} ColorPacket;
-
 typedef struct _ErrorInfo
 {
   double
@@ -85,22 +73,14 @@
   *GetColorInfo(const char *,ExceptionInfo *),
   **GetColorInfoList(const char *,unsigned long *,ExceptionInfo *);
 
-extern MagickExport ColorPacket
-  *GetImageHistogram(const Image *,unsigned long *,ExceptionInfo *);
-
-extern MagickExport Image
-  *UniqueImageColors(const Image *,ExceptionInfo *);
-
 extern MagickExport MagickBooleanType
   IsColorSimilar(const Image *,const PixelPacket *,const PixelPacket *),
   IsGrayImage(const Image *,ExceptionInfo *),
-  IsHistogramImage(const Image *,ExceptionInfo *),
   IsImageSimilar(const Image *,const Image *,long *x,long *y,ExceptionInfo *),
   IsMagickColorSimilar(const MagickPixelPacket *,const MagickPixelPacket *),
   IsMonochromeImage(const Image *,ExceptionInfo *),
   IsOpacitySimilar(const Image *,const PixelPacket *,const PixelPacket *),
   IsOpaqueImage(const Image *,ExceptionInfo *),
-  IsPaletteImage(const Image *,ExceptionInfo *),
   ListColorInfo(FILE *,ExceptionInfo *),
   QueryColorDatabase(const char *,PixelPacket *,ExceptionInfo *),
   QueryColorname(const Image *,const PixelPacket *,const ComplianceType,char *,
@@ -109,9 +89,6 @@
   QueryMagickColorname(const Image *,const MagickPixelPacket *,
     const ComplianceType,char *,ExceptionInfo *);
 
-extern MagickExport unsigned long
-  GetNumberColors(const Image *,FILE *,ExceptionInfo *);
-
 extern MagickExport void
   ConcatenateColorComponent(const MagickPixelPacket *,const ChannelType,
     const ComplianceType,char *),
diff --git a/magick/histogram.c b/magick/histogram.c
index 408ce2e..54bde2b 100644
--- a/magick/histogram.c
+++ b/magick/histogram.c
@@ -42,6 +42,7 @@
 */
 #include "magick/studio.h"
 #include "magick/cache-view.h"
+#include "magick/color-private.h"
 #include "magick/enhance.h"
 #include "magick/exception.h"
 #include "magick/exception-private.h"
@@ -50,7 +51,10 @@
 #include "magick/image.h"
 #include "magick/list.h"
 #include "magick/memory_.h"
+#include "magick/monitor-private.h"
+#include "magick/pixel-private.h"
 #include "magick/prepress.h"
+#include "magick/quantize.h"
 #include "magick/registry.h"
 #include "magick/semaphore.h"
 #include "magick/splay-tree.h"
@@ -58,6 +62,879 @@
 #include "magick/string_.h"
 
 /*
+  Define declarations.
+*/
+#define MaxTreeDepth  8
+#define NodesInAList  1536
+
+/*
+  Typedef declarations.
+*/
+typedef struct _NodeInfo
+{
+  struct _NodeInfo
+    *child[16];
+
+  ColorPacket
+    *list;
+
+  MagickSizeType
+    number_unique;
+
+  unsigned long
+    level;
+} NodeInfo;
+
+typedef struct _Nodes
+{
+  NodeInfo
+    nodes[NodesInAList];
+
+  struct _Nodes
+    *next;
+} Nodes;
+
+typedef struct _CubeInfo
+{
+  NodeInfo
+    *root;
+
+  long
+    x,
+    progress;
+
+  unsigned long
+    colors,
+    free_nodes;
+
+  NodeInfo
+    *node_info;
+
+  Nodes
+    *node_queue;
+} CubeInfo;
+
+/*
+  Forward declarations.
+*/
+static CubeInfo
+  *GetCubeInfo(void);
+
+static NodeInfo
+  *GetNodeInfo(CubeInfo *,const unsigned long);
+
+static void
+  DestroyColorCube(const Image *,NodeInfo *);
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++   C l a s s i f y I m a g e C o l o r s                                     %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ClassifyImageColors() builds a populated CubeInfo tree for the specified
+%  image.  The returned tree should be deallocated using DestroyCubeInfo()
+%  once it is no longer needed.
+%
+%  The format of the ClassifyImageColors() method is:
+%
+%      CubeInfo *ClassifyImageColors(const Image *image,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+
+static inline unsigned long ColorToNodeId(const Image *image,
+  const MagickPixelPacket *pixel,unsigned long index)
+{
+  unsigned long
+    id;
+
+  id=(unsigned long) (
+    ((ScaleQuantumToChar(RoundToQuantum(pixel->red)) >> index) & 0x01) |
+    ((ScaleQuantumToChar(RoundToQuantum(pixel->green)) >> index) & 0x01) << 1 |
+    ((ScaleQuantumToChar(RoundToQuantum(pixel->blue)) >> index) & 0x01) << 2);
+  if (image->matte != MagickFalse)
+    id|=((ScaleQuantumToChar(RoundToQuantum(pixel->opacity)) >> index) &
+      0x01) << 3;
+  return(id);
+}
+
+static CubeInfo *ClassifyImageColors(const Image *image,
+  ExceptionInfo *exception)
+{
+#define EvaluateImageTag  "  Compute image colors...  "
+
+  CubeInfo
+    *cube_info;
+
+  long
+    y;
+
+  MagickBooleanType
+    proceed;
+
+  MagickPixelPacket
+    pixel,
+    target;
+
+  NodeInfo
+    *node_info;
+
+  register const IndexPacket
+    *indexes;
+
+  register const PixelPacket
+    *p;
+
+  register long
+    i,
+    x;
+
+  register unsigned long
+    id,
+    index,
+    level;
+
+  CacheView
+    *image_view;
+
+  /*
+    Initialize color description tree.
+  */
+  assert(image != (const Image *) NULL);
+  assert(image->signature == MagickSignature);
+  if (image->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  cube_info=GetCubeInfo();
+  if (cube_info == (CubeInfo *) NULL)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),
+        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
+      return(cube_info);
+    }
+  GetMagickPixelPacket(image,&pixel);
+  GetMagickPixelPacket(image,&target);
+  image_view=AcquireCacheView(image);
+  for (y=0; y < (long) image->rows; y++)
+  {
+    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
+    if (p == (const PixelPacket *) NULL)
+      break;
+    indexes=GetCacheViewVirtualIndexQueue(image_view);
+    for (x=0; x < (long) image->columns; x++)
+    {
+      /*
+        Start at the root and proceed level by level.
+      */
+      node_info=cube_info->root;
+      index=MaxTreeDepth-1;
+      for (level=1; level < MaxTreeDepth; level++)
+      {
+        SetMagickPixelPacket(image,p,indexes+x,&pixel);
+        id=ColorToNodeId(image,&pixel,index);
+        if (node_info->child[id] == (NodeInfo *) NULL)
+          {
+            node_info->child[id]=GetNodeInfo(cube_info,level);
+            if (node_info->child[id] == (NodeInfo *) NULL)
+              {
+                (void) ThrowMagickException(exception,GetMagickModule(),
+                  ResourceLimitError,"MemoryAllocationFailed","`%s'",
+                  image->filename);
+                return(0);
+              }
+          }
+        node_info=node_info->child[id];
+        index--;
+      }
+      for (i=0; i < (long) node_info->number_unique; i++)
+      {
+        SetMagickPixelPacket(image,&node_info->list[i].pixel,
+          &node_info->list[i].index,&target);
+        if (IsMagickColorEqual(&pixel,&target) != MagickFalse)
+          break;
+      }
+      if (i < (long) node_info->number_unique)
+        node_info->list[i].count++;
+      else
+        {
+          if (node_info->number_unique == 0)
+            node_info->list=(ColorPacket *) AcquireMagickMemory(
+              sizeof(*node_info->list));
+          else
+            node_info->list=(ColorPacket *) ResizeQuantumMemory(node_info->list,
+              (size_t) (i+1),sizeof(*node_info->list));
+          if (node_info->list == (ColorPacket *) NULL)
+            {
+              (void) ThrowMagickException(exception,GetMagickModule(),
+                ResourceLimitError,"MemoryAllocationFailed","`%s'",
+                image->filename);
+              return(0);
+            }
+          node_info->list[i].pixel=(*p);
+          if ((image->colorspace == CMYKColorspace) ||
+              (image->storage_class == PseudoClass))
+            node_info->list[i].index=indexes[x];
+          node_info->list[i].count=1;
+          node_info->number_unique++;
+          cube_info->colors++;
+        }
+      p++;
+    }
+    proceed=SetImageProgress(image,EvaluateImageTag,y,image->rows);
+    if (proceed == MagickFalse)
+      break;
+  }
+  image_view=DestroyCacheView(image_view);
+  return(cube_info);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++   D e f i n e I m a g e H i s t o g r a m                                   %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  DefineImageHistogram() traverses the color cube tree and notes each colormap
+%  entry.  A colormap entry is any node in the color cube tree where the
+%  of unique colors is not zero.
+%
+%  The format of the DefineImageHistogram method is:
+%
+%      DefineImageHistogram(const Image *image,NodeInfo *node_info,
+%        ColorPacket **unique_colors)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+%    o node_info: the address of a structure of type NodeInfo which points to a
+%      node in the color cube tree that is to be pruned.
+%
+%    o histogram: the image histogram.
+%
+*/
+static void DefineImageHistogram(const Image *image,NodeInfo *node_info,
+  ColorPacket **histogram)
+{
+  register long
+    i;
+
+  unsigned long
+    number_children;
+
+  /*
+    Traverse any children.
+  */
+  number_children=image->matte == MagickFalse ? 8UL : 16UL;
+  for (i=0; i < (long) number_children; i++)
+    if (node_info->child[i] != (NodeInfo *) NULL)
+      DefineImageHistogram(image,node_info->child[i],histogram);
+  if (node_info->level == (MaxTreeDepth-1))
+    {
+      register ColorPacket
+        *p;
+
+      p=node_info->list;
+      for (i=0; i < (long) node_info->number_unique; i++)
+      {
+        (*histogram)->pixel=p->pixel;
+        (*histogram)->index=p->index;
+        (*histogram)->count=p->count;
+        (*histogram)++;
+        p++;
+      }
+    }
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++   D e s t r o y C u b e I n f o                                             %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  DestroyCubeInfo() deallocates memory associated with a CubeInfo structure.
+%
+%  The format of the DestroyCubeInfo method is:
+%
+%      DestroyCubeInfo(const Image *image,CubeInfo *cube_info)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+%    o cube_info: the address of a structure of type CubeInfo.
+%
+*/
+static CubeInfo *DestroyCubeInfo(const Image *image,CubeInfo *cube_info)
+{
+  register Nodes
+    *nodes;
+
+  /*
+    Release color cube tree storage.
+  */
+  DestroyColorCube(image,cube_info->root);
+  do
+  {
+    nodes=cube_info->node_queue->next;
+    cube_info->node_queue=(Nodes *)
+      RelinquishMagickMemory(cube_info->node_queue);
+    cube_info->node_queue=nodes;
+  } while (cube_info->node_queue != (Nodes *) NULL);
+  return((CubeInfo *) RelinquishMagickMemory(cube_info));
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++  D e s t r o y C o l o r C u b e                                            %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  DestroyColorCube() traverses the color cube tree and frees the list of
+%  unique colors.
+%
+%  The format of the DestroyColorCube method is:
+%
+%      void DestroyColorCube(const Image *image,const NodeInfo *node_info)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+%    o node_info: the address of a structure of type NodeInfo which points to a
+%      node in the color cube tree that is to be pruned.
+%
+*/
+static void DestroyColorCube(const Image *image,NodeInfo *node_info)
+{
+  register long
+    i;
+
+  unsigned long
+    number_children;
+
+  /*
+    Traverse any children.
+  */
+  number_children=image->matte == MagickFalse ? 8UL : 16UL;
+  for (i=0; i < (long) number_children; i++)
+    if (node_info->child[i] != (NodeInfo *) NULL)
+      DestroyColorCube(image,node_info->child[i]);
+  if (node_info->list != (ColorPacket *) NULL)
+    node_info->list=(ColorPacket *) RelinquishMagickMemory(node_info->list);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++   G e t C u b e I n f o                                                     %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  GetCubeInfo() initializes the CubeInfo data structure.
+%
+%  The format of the GetCubeInfo method is:
+%
+%      cube_info=GetCubeInfo()
+%
+%  A description of each parameter follows.
+%
+%    o cube_info: A pointer to the Cube structure.
+%
+*/
+static CubeInfo *GetCubeInfo(void)
+{
+  CubeInfo
+    *cube_info;
+
+  /*
+    Initialize tree to describe color cube.
+  */
+  cube_info=(CubeInfo *) AcquireMagickMemory(sizeof(*cube_info));
+  if (cube_info == (CubeInfo *) NULL)
+    return((CubeInfo *) NULL);
+  (void) ResetMagickMemory(cube_info,0,sizeof(*cube_info));
+  /*
+    Initialize root node.
+  */
+  cube_info->root=GetNodeInfo(cube_info,0);
+  if (cube_info->root == (NodeInfo *) NULL)
+    return((CubeInfo *) NULL);
+  return(cube_info);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%  G e t I m a g e H i s t o g r a m                                          %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  GetImageHistogram() returns the unique colors in an image.
+%
+%  The format of the GetImageHistogram method is:
+%
+%      unsigned long GetImageHistogram(const Image *image,
+%        unsigned long *number_colors,ExceptionInfo *exception)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+%    o file:  Write a histogram of the color distribution to this file handle.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport ColorPacket *GetImageHistogram(const Image *image,
+  unsigned long *number_colors,ExceptionInfo *exception)
+{
+  ColorPacket
+    *histogram;
+
+  CubeInfo
+    *cube_info;
+
+  *number_colors=0;
+  histogram=(ColorPacket *) NULL;
+  cube_info=ClassifyImageColors(image,exception);
+  if (cube_info != (CubeInfo *) NULL)
+    {
+      histogram=(ColorPacket *) AcquireQuantumMemory((size_t) cube_info->colors,
+        sizeof(*histogram));
+      if (histogram == (ColorPacket *) NULL)
+        (void) ThrowMagickException(exception,GetMagickModule(),
+          ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
+      else
+        {
+          ColorPacket
+            *root;
+
+          *number_colors=cube_info->colors;
+          root=histogram;
+          DefineImageHistogram(image,cube_info->root,&root);
+        }
+    }
+  cube_info=DestroyCubeInfo(image,cube_info);
+  return(histogram);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++  G e t N o d e I n f o                                                      %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  GetNodeInfo() allocates memory for a new node in the color cube tree and
+%  presets all fields to zero.
+%
+%  The format of the GetNodeInfo method is:
+%
+%      NodeInfo *GetNodeInfo(CubeInfo *cube_info,const unsigned long level)
+%
+%  A description of each parameter follows.
+%
+%    o cube_info: A pointer to the CubeInfo structure.
+%
+%    o level: Specifies the level in the storage_class the node resides.
+%
+*/
+static NodeInfo *GetNodeInfo(CubeInfo *cube_info,const unsigned long level)
+{
+  NodeInfo
+    *node_info;
+
+  if (cube_info->free_nodes == 0)
+    {
+      Nodes
+        *nodes;
+
+      /*
+        Allocate a new nodes of nodes.
+      */
+      nodes=(Nodes *) AcquireMagickMemory(sizeof(*nodes));
+      if (nodes == (Nodes *) NULL)
+        return((NodeInfo *) NULL);
+      nodes->next=cube_info->node_queue;
+      cube_info->node_queue=nodes;
+      cube_info->node_info=nodes->nodes;
+      cube_info->free_nodes=NodesInAList;
+    }
+  cube_info->free_nodes--;
+  node_info=cube_info->node_info++;
+  (void) ResetMagickMemory(node_info,0,sizeof(*node_info));
+  node_info->level=level;
+  return(node_info);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%  I s H i s t o g r a m I m a g e                                            %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  IsHistogramImage() returns MagickTrue if the image has 1024 unique colors or
+%  less.
+%
+%  The format of the IsHistogramImage method is:
+%
+%      MagickBooleanType IsHistogramImage(const Image *image,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport MagickBooleanType IsHistogramImage(const Image *image,
+  ExceptionInfo *exception)
+{
+#define MaximumUniqueColors  1024
+
+  CubeInfo
+    *cube_info;
+
+  long
+    y;
+
+  MagickPixelPacket
+    pixel,
+    target;
+
+  register const IndexPacket
+    *indexes;
+
+  register const PixelPacket
+    *p;
+
+  register long
+    x;
+
+  register NodeInfo
+    *node_info;
+
+  register long
+    i;
+
+  unsigned long
+    id,
+    index,
+    level;
+
+  CacheView
+    *image_view;
+
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickSignature);
+  if (image->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  if ((image->storage_class == PseudoClass) && (image->colors <= 256))
+    return(MagickTrue);
+  if (image->storage_class == PseudoClass)
+    return(MagickFalse);
+  /*
+    Initialize color description tree.
+  */
+  cube_info=GetCubeInfo();
+  if (cube_info == (CubeInfo *) NULL)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),
+        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
+      return(MagickFalse);
+    }
+  GetMagickPixelPacket(image,&pixel);
+  GetMagickPixelPacket(image,&target);
+  image_view=AcquireCacheView(image);
+  for (y=0; y < (long) image->rows; y++)
+  {
+    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
+    if (p == (const PixelPacket *) NULL)
+      break;
+    indexes=GetCacheViewVirtualIndexQueue(image_view);
+    for (x=0; x < (long) image->columns; x++)
+    {
+      /*
+        Start at the root and proceed level by level.
+      */
+      node_info=cube_info->root;
+      index=MaxTreeDepth-1;
+      for (level=1; level < MaxTreeDepth; level++)
+      {
+        SetMagickPixelPacket(image,p,indexes+x,&pixel);
+        id=ColorToNodeId(image,&pixel,index);
+        if (node_info->child[id] == (NodeInfo *) NULL)
+          {
+            node_info->child[id]=GetNodeInfo(cube_info,level);
+            if (node_info->child[id] == (NodeInfo *) NULL)
+              {
+                (void) ThrowMagickException(exception,GetMagickModule(),
+                  ResourceLimitError,"MemoryAllocationFailed","`%s'",
+                  image->filename);
+                break;
+              }
+          }
+        node_info=node_info->child[id];
+        index--;
+      }
+      if (level < MaxTreeDepth)
+        break;
+      for (i=0; i < (long) node_info->number_unique; i++)
+      {
+        SetMagickPixelPacket(image,&node_info->list[i].pixel,
+          &node_info->list[i].index,&target);
+        if (IsMagickColorEqual(&pixel,&target) != MagickFalse)
+          break;
+      }
+      if (i < (long) node_info->number_unique)
+        node_info->list[i].count++;
+      else
+        {
+          /*
+            Add this unique color to the color list.
+          */
+          if (node_info->number_unique == 0)
+            node_info->list=(ColorPacket *) AcquireMagickMemory(
+              sizeof(*node_info->list));
+          else
+            node_info->list=(ColorPacket *) ResizeQuantumMemory(node_info->list,
+              (size_t) (i+1),sizeof(*node_info->list));
+          if (node_info->list == (ColorPacket *) NULL)
+            {
+              (void) ThrowMagickException(exception,GetMagickModule(),
+                ResourceLimitError,"MemoryAllocationFailed","`%s'",
+                image->filename);
+              break;
+            }
+          node_info->list[i].pixel=(*p);
+          if ((image->colorspace == CMYKColorspace) ||
+              (image->storage_class == PseudoClass))
+            node_info->list[i].index=indexes[x];
+          node_info->list[i].count=1;
+          node_info->number_unique++;
+          cube_info->colors++;
+          if (cube_info->colors > MaximumUniqueColors)
+            break;
+        }
+      p++;
+    }
+    if (x < (long) image->columns)
+      break;
+  }
+  image_view=DestroyCacheView(image_view);
+  cube_info=DestroyCubeInfo(image,cube_info);
+  return(y < (long) image->rows ? MagickFalse : MagickTrue);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%  I s P a l e t t e I m a g e                                                %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  IsPaletteImage() returns MagickTrue if the image is PseudoClass and has 256
+%  unique colors or less.
+%
+%  The format of the IsPaletteImage method is:
+%
+%      MagickBooleanType IsPaletteImage(const Image *image,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport MagickBooleanType IsPaletteImage(const Image *image,
+  ExceptionInfo *exception)
+{
+  CubeInfo
+    *cube_info;
+
+  long
+    y;
+
+  MagickPixelPacket
+    pixel,
+    target;
+
+  register const IndexPacket
+    *indexes;
+
+  register const PixelPacket
+    *p;
+
+  register long
+    x;
+
+  register NodeInfo
+    *node_info;
+
+  register long
+    i;
+
+  unsigned long
+    id,
+    index,
+    level;
+
+  CacheView
+    *image_view;
+
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickSignature);
+  if (image->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  if ((image->storage_class == PseudoClass) && (image->colors <= 256))
+    return(MagickTrue);
+  if (image->storage_class == PseudoClass)
+    return(MagickFalse);
+  /*
+    Initialize color description tree.
+  */
+  cube_info=GetCubeInfo();
+  if (cube_info == (CubeInfo *) NULL)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),
+        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
+      return(MagickFalse);
+    }
+  GetMagickPixelPacket(image,&pixel);
+  GetMagickPixelPacket(image,&target);
+  image_view=AcquireCacheView(image);
+  for (y=0; y < (long) image->rows; y++)
+  {
+    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
+    if (p == (const PixelPacket *) NULL)
+      break;
+    indexes=GetCacheViewVirtualIndexQueue(image_view);
+    for (x=0; x < (long) image->columns; x++)
+    {
+      /*
+        Start at the root and proceed level by level.
+      */
+      node_info=cube_info->root;
+      index=MaxTreeDepth-1;
+      for (level=1; level < MaxTreeDepth; level++)
+      {
+        SetMagickPixelPacket(image,p,indexes+x,&pixel);
+        id=ColorToNodeId(image,&pixel,index);
+        if (node_info->child[id] == (NodeInfo *) NULL)
+          {
+            node_info->child[id]=GetNodeInfo(cube_info,level);
+            if (node_info->child[id] == (NodeInfo *) NULL)
+              {
+                (void) ThrowMagickException(exception,GetMagickModule(),
+                  ResourceLimitError,"MemoryAllocationFailed","`%s'",
+                  image->filename);
+                break;
+              }
+          }
+        node_info=node_info->child[id];
+        index--;
+      }
+      if (level < MaxTreeDepth)
+        break;
+      for (i=0; i < (long) node_info->number_unique; i++)
+      {
+        SetMagickPixelPacket(image,&node_info->list[i].pixel,
+          &node_info->list[i].index,&target);
+        if (IsMagickColorEqual(&pixel,&target) != MagickFalse)
+          break;
+      }
+      if (i < (long) node_info->number_unique)
+        node_info->list[i].count++;
+      else
+        {
+          /*
+            Add this unique color to the color list.
+          */
+          if (node_info->number_unique == 0)
+            node_info->list=(ColorPacket *) AcquireMagickMemory(
+              sizeof(*node_info->list));
+          else
+            node_info->list=(ColorPacket *) ResizeQuantumMemory(node_info->list,
+              (size_t) (i+1),sizeof(*node_info->list));
+          if (node_info->list == (ColorPacket *) NULL)
+            {
+              (void) ThrowMagickException(exception,GetMagickModule(),
+                ResourceLimitError,"MemoryAllocationFailed","`%s'",
+                image->filename);
+              break;
+            }
+          node_info->list[i].pixel=(*p);
+          if ((image->colorspace == CMYKColorspace) ||
+              (image->storage_class == PseudoClass))
+            node_info->list[i].index=indexes[x];
+          node_info->list[i].count=1;
+          node_info->number_unique++;
+          cube_info->colors++;
+          if (cube_info->colors > 256)
+            break;
+        }
+      p++;
+    }
+    if (x < (long) image->columns)
+      break;
+  }
+  image_view=DestroyCacheView(image_view);
+  cube_info=DestroyCubeInfo(image,cube_info);
+  return(y < (long) image->rows ? MagickFalse : MagickTrue);
+}
+
+/*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                             %
 %                                                                             %
@@ -102,10 +979,8 @@
 %      from the minimum and maximum points by this color value.
 %
 */
-
 MagickExport MagickBooleanType MinMaxStretchImage(Image *image,
-     const ChannelType channel, const double black_value,
-     const double white_value)
+  const ChannelType channel,const double black_value,const double white_value)
 {
   double
     min,max;
@@ -113,52 +988,307 @@
   MagickStatusType
     status;
 
-  if ((channel & SyncChannels) != 0 )
+  if ((channel & SyncChannels) != 0)
     {
       /*
-        autolevel all channels equally
+        Auto-level all channels equally.
       */
-      GetImageChannelRange(image, channel, &min, &max, &image->exception);
-      min += black_value;  max -= white_value;
-      return LevelImageChannel(image, channel, min, max, 1.0);
+      (void) GetImageChannelRange(image,channel,&min,&max,&image->exception);
+      min+=black_value;
+      max-=white_value;
+      return(LevelImageChannel(image,channel,min,max,1.0));
     }
-
   /*
-    autolevel each channel separateally
+    Auto-level each channel separately.
   */
-  status = MagickTrue;
+  status=MagickTrue;
   if ((channel & RedChannel) != 0)
     {
-      GetImageChannelRange(image, RedChannel, &min, &max, &image->exception);
-      min += black_value;  max -= white_value;
-      status = status && LevelImageChannel(image, RedChannel, min, max, 1.0);
+      (void) GetImageChannelRange(image,RedChannel,&min,&max,&image->exception);
+      min+=black_value;
+      max-=white_value;
+      status&=LevelImageChannel(image,RedChannel,min,max,1.0);
     }
   if ((channel & GreenChannel) != 0)
     {
-      GetImageChannelRange(image, GreenChannel, &min, &max, &image->exception);
-      min += black_value;  max -= white_value;
-      status = status && LevelImageChannel(image, GreenChannel, min, max, 1.0);
+      (void) GetImageChannelRange(image,GreenChannel,&min,&max,
+        &image->exception);
+      min+=black_value;
+      max-=white_value;
+      status&=LevelImageChannel(image,GreenChannel,min,max,1.0);
     }
   if ((channel & BlueChannel) != 0)
     {
-      GetImageChannelRange(image, BlueChannel, &min, &max, &image->exception);
-      min += black_value;  max -= white_value;
-      status = status && LevelImageChannel(image, BlueChannel, min, max, 1.0);
+      (void) GetImageChannelRange(image,BlueChannel,&min,&max,
+        &image->exception);
+      min+=black_value;
+      max-=white_value;
+      status&=LevelImageChannel(image,BlueChannel,min,max,1.0);
     }
   if (((channel & OpacityChannel) != 0) &&
-      (image->matte == MagickTrue))
+       (image->matte == MagickTrue))
     {
-      GetImageChannelRange(image, OpacityChannel, &min, &max, &image->exception);
-      min += black_value;  max -= white_value;
-      status = status && LevelImageChannel(image, OpacityChannel, min, max, 1.0);
+      (void) GetImageChannelRange(image,OpacityChannel,&min,&max,
+        &image->exception);
+      min+=black_value;
+      max-=white_value;
+      status&=LevelImageChannel(image,OpacityChannel,min,max,1.0);
     }
   if (((channel & IndexChannel) != 0) &&
-      (image->colorspace == CMYKColorspace))
+       (image->colorspace == CMYKColorspace))
     {
-      GetImageChannelRange(image, IndexChannel, &min, &max, &image->exception);
-      min += black_value;  max -= white_value;
-      status = status && LevelImageChannel(image, IndexChannel, min, max, 1.0);
+      (void) GetImageChannelRange(image,IndexChannel,&min,&max,
+        &image->exception);
+      min+=black_value;
+      max-=white_value;
+      status&=LevelImageChannel(image,IndexChannel,min,max,1.0);
     }
   return(status != 0 ? MagickTrue : MagickFalse);
 }
 
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%  G e t N u m b e r C o l o r s                                              %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  GetNumberColors() returns the number of unique colors in an image.
+%
+%  The format of the GetNumberColors method is:
+%
+%      unsigned long GetNumberColors(const Image *image,FILE *file,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+%    o file:  Write a histogram of the color distribution to this file handle.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+static int HistogramCompare(const void *x,const void *y)
+{
+  const ColorPacket
+    *color_1,
+    *color_2;
+
+  color_1=(const ColorPacket *) x;
+  color_2=(const ColorPacket *) y;
+  if (color_2->pixel.red != color_1->pixel.red)
+    return((int) color_1->pixel.red-(int) color_2->pixel.red);
+  if (color_2->pixel.green != color_1->pixel.green)
+    return((int) color_1->pixel.green-(int) color_2->pixel.green);
+  if (color_2->pixel.blue != color_1->pixel.blue)
+    return((int) color_1->pixel.blue-(int) color_2->pixel.blue);
+  return((int) color_2->count-(int) color_1->count);
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+MagickExport unsigned long GetNumberColors(const Image *image,FILE *file,
+  ExceptionInfo *exception)
+{
+#define HistogramImageTag  "Histogram/Image"
+
+  char
+    color[MaxTextExtent],
+    hex[MaxTextExtent],
+    tuple[MaxTextExtent];
+
+  ColorPacket
+    *histogram;
+
+  MagickPixelPacket
+    pixel;
+
+  register ColorPacket
+    *p;
+
+  register long
+    i;
+
+  unsigned long
+    number_colors;
+
+  number_colors=0;
+  if (file == (FILE *) NULL)
+    {
+      CubeInfo
+        *cube_info;
+
+      cube_info=ClassifyImageColors(image,exception);
+      if (cube_info != (CubeInfo *) NULL)
+        number_colors=cube_info->colors;
+      cube_info=DestroyCubeInfo(image,cube_info);
+      return(number_colors);
+    }
+  histogram=GetImageHistogram(image,&number_colors,exception);
+  if (histogram == (ColorPacket *) NULL)
+    return(number_colors);
+  qsort((void *) histogram,(size_t) number_colors,sizeof(*histogram),
+    HistogramCompare);
+  GetMagickPixelPacket(image,&pixel);
+  p=histogram;
+  for (i=0; i < (long) number_colors; i++)
+  {
+    SetMagickPixelPacket(image,&p->pixel,&p->index,&pixel);
+    (void) CopyMagickString(tuple,"(",MaxTextExtent);
+    ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
+    (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
+    ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
+    (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
+    ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
+    if (pixel.colorspace == CMYKColorspace)
+      {
+        (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
+        ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
+      }
+    if (pixel.matte != MagickFalse)
+      {
+        (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
+        ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
+      }
+    (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
+    (void) QueryMagickColorname(image,&pixel,SVGCompliance,color,exception);
+    GetColorTuple(&pixel,MagickTrue,hex);
+    (void) fprintf(file,MagickSizeFormat,p->count);
+    (void) fprintf(file,": %s %s %s\n",tuple,hex,color);
+    if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
+        (QuantumTick(i,number_colors) != MagickFalse))
+      (void) image->progress_monitor(HistogramImageTag,i,number_colors,
+        image->client_data);
+    p++;
+  }
+  (void) fflush(file);
+  histogram=(ColorPacket *) RelinquishMagickMemory(histogram);
+  return(number_colors);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%  U n i q u e I m a g e C o l o r s                                          %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  UniqueImageColors() returns the unique colors of an image.
+%
+%  The format of the UniqueImageColors method is:
+%
+%      Image *UniqueImageColors(const Image *image,ExceptionInfo *exception)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+
+static void UniqueColorsToImage(Image *image,CubeInfo *cube_info,
+  const NodeInfo *node_info,ExceptionInfo *exception)
+{
+#define UniqueColorsImageTag  "UniqueColors/Image"
+
+  register long
+    i;
+
+  unsigned long
+    number_children;
+
+  /*
+    Traverse any children.
+  */
+  number_children=image->matte == MagickFalse ? 8UL : 16UL;
+  for (i=0; i < (long) number_children; i++)
+    if (node_info->child[i] != (NodeInfo *) NULL)
+      UniqueColorsToImage(image,cube_info,node_info->child[i],exception);
+  if (node_info->level == (MaxTreeDepth-1))
+    {
+      register ColorPacket
+        *p;
+
+      register IndexPacket
+        *__restrict indexes;
+
+      register PixelPacket
+        *__restrict q;
+
+      p=node_info->list;
+      for (i=0; i < (long) node_info->number_unique; i++)
+      {
+        q=QueueAuthenticPixels(image,cube_info->x,0,1,1,exception);
+        if (q == (PixelPacket *) NULL)
+          continue;
+        indexes=GetAuthenticIndexQueue(image);
+        *q=p->pixel;
+        if (image->colorspace == CMYKColorspace)
+          *indexes=p->index;
+        if (SyncAuthenticPixels(image,exception) == MagickFalse)
+          break;
+        cube_info->x++;
+        p++;
+      }
+      if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
+          (QuantumTick(cube_info->progress,cube_info->colors) != MagickFalse))
+        (void) image->progress_monitor(UniqueColorsImageTag,cube_info->progress,
+          cube_info->colors,image->client_data);
+      cube_info->progress++;
+    }
+}
+
+MagickExport Image *UniqueImageColors(const Image *image,
+  ExceptionInfo *exception)
+{
+  CubeInfo
+    *cube_info;
+
+  Image
+    *unique_image;
+
+  cube_info=ClassifyImageColors(image,exception);
+  if (cube_info == (CubeInfo *) NULL)
+    return((Image *) NULL);
+  unique_image=CloneImage(image,cube_info->colors,1,MagickTrue,exception);
+  if (unique_image == (Image *) NULL)
+    return(unique_image);
+  if (SetImageStorageClass(unique_image,DirectClass) == MagickFalse)
+    {
+      InheritException(exception,&unique_image->exception);
+      unique_image=DestroyImage(unique_image);
+      return((Image *) NULL);
+    }
+  UniqueColorsToImage(unique_image,cube_info,cube_info->root,exception);
+  if (cube_info->colors < MaxColormapSize)
+    {
+      QuantizeInfo
+        *quantize_info;
+
+      quantize_info=AcquireQuantizeInfo((ImageInfo *) NULL);
+      quantize_info->number_colors=MaxColormapSize;
+      quantize_info->dither=MagickFalse;
+      quantize_info->tree_depth=8;
+      (void) QuantizeImage(quantize_info,unique_image);
+      quantize_info=DestroyQuantizeInfo(quantize_info);
+    }
+  cube_info=DestroyCubeInfo(image,cube_info);
+  return(unique_image);
+}
diff --git a/magick/histogram.h b/magick/histogram.h
index cbf6ff8..3397998 100644
--- a/magick/histogram.h
+++ b/magick/histogram.h
@@ -22,9 +22,32 @@
 extern "C" {
 #endif
 
+typedef struct _ColorPacket
+{
+  PixelPacket
+    pixel;
+
+  IndexPacket
+    index;
+
+  MagickSizeType
+    count;
+} ColorPacket;
+
+extern MagickExport ColorPacket
+  *GetImageHistogram(const Image *,unsigned long *,ExceptionInfo *);
+
+extern MagickExport Image
+  *UniqueImageColors(const Image *,ExceptionInfo *);
+
 extern MagickExport MagickBooleanType
+  IsHistogramImage(const Image *,ExceptionInfo *),
+  IsPaletteImage(const Image *,ExceptionInfo *),
   MinMaxStretchImage(Image *,const ChannelType,const double,const double);
 
+extern MagickExport unsigned long
+  GetNumberColors(const Image *,FILE *,ExceptionInfo *);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
diff --git a/magick/identify.c b/magick/identify.c
index 76766a9..6554a59 100644
--- a/magick/identify.c
+++ b/magick/identify.c
@@ -60,6 +60,7 @@
 #include "magick/exception-private.h"
 #include "magick/gem.h"
 #include "magick/geometry.h"
+#include "magick/histogram.h"
 #include "magick/identify.h"
 #include "magick/image.h"
 #include "magick/image-private.h"
diff --git a/magick/image.c b/magick/image.c
index 24230f1..e53aa53 100644
--- a/magick/image.c
+++ b/magick/image.c
@@ -66,8 +66,9 @@
 #include "magick/exception-private.h"
 #include "magick/gem.h"
 #include "magick/geometry.h"
-#include "magick/list.h"
+#include "magick/histogram.h"
 #include "magick/image-private.h"
+#include "magick/list.h"
 #include "magick/magic.h"
 #include "magick/magick.h"
 #include "magick/memory_.h"
diff --git a/magick/magick.c b/magick/magick.c
index 0d52e87..3b03176 100644
--- a/magick/magick.c
+++ b/magick/magick.c
@@ -805,6 +805,7 @@
 
 static MagickBooleanType InitializeMagickList(ExceptionInfo *exception)
 {
+  (void) exception;
   if ((magick_list == (SplayTreeInfo *) NULL) &&
       (instantiate_magick == MagickFalse))
     {
diff --git a/magick/property.c b/magick/property.c
index 155b4ae..abd9024 100644
--- a/magick/property.c
+++ b/magick/property.c
@@ -53,6 +53,8 @@
 #include "magick/fx-private.h"
 #include "magick/gem.h"
 #include "magick/geometry.h"
+#include "magick/histogram.h"
+#include "magick/image.h"
 #include "magick/image.h"
 #include "magick/layer.h"
 #include "magick/list.h"
diff --git a/magick/quantize.c b/magick/quantize.c
index 1fb3c3c..7dc2131 100644
--- a/magick/quantize.c
+++ b/magick/quantize.c
@@ -182,6 +182,7 @@
 #include "magick/enhance.h"
 #include "magick/exception.h"
 #include "magick/exception-private.h"
+#include "magick/histogram.h"
 #include "magick/image.h"
 #include "magick/image-private.h"
 #include "magick/list.h"
diff --git a/magick/version.h b/magick/version.h
index 9dd6add..343c1a5 100644
--- a/magick/version.h
+++ b/magick/version.h
@@ -31,8 +31,8 @@
 #define MagickLibVersionText  "6.5.7"
 #define MagickLibVersionNumber  2,0,0
 #define MagickLibSubversion  "-0"
-#define MagickReleaseDate  "2009-10-12"
-#define MagickChangeDate   "20091010"
+#define MagickReleaseDate  "2009-10-13"
+#define MagickChangeDate   "20091014"
 #define MagickAuthoritativeURL  "http://www.imagemagick.org"
 #define MagickHomeURL  "file:///usr/local/share/doc/ImageMagick-6.5.7/index.html"
 #if (MAGICKCORE_QUANTUM_DEPTH == 8)