MagickCore  6.7.5
quantize.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %           QQQ   U   U   AAA   N   N  TTTTT  IIIII   ZZZZZ  EEEEE            %
00007 %          Q   Q  U   U  A   A  NN  N    T      I        ZZ  E                %
00008 %          Q   Q  U   U  AAAAA  N N N    T      I      ZZZ   EEEEE            %
00009 %          Q  QQ  U   U  A   A  N  NN    T      I     ZZ     E                %
00010 %           QQQQ   UUU   A   A  N   N    T    IIIII   ZZZZZ  EEEEE            %
00011 %                                                                             %
00012 %                                                                             %
00013 %    MagickCore Methods to Reduce the Number of Unique Colors in an Image     %
00014 %                                                                             %
00015 %                           Software Design                                   %
00016 %                             John Cristy                                     %
00017 %                              July 1992                                      %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %  Realism in computer graphics typically requires using 24 bits/pixel to
00037 %  generate an image.  Yet many graphic display devices do not contain the
00038 %  amount of memory necessary to match the spatial and color resolution of
00039 %  the human eye.  The Quantize methods takes a 24 bit image and reduces
00040 %  the number of colors so it can be displayed on raster device with less
00041 %  bits per pixel.  In most instances, the quantized image closely
00042 %  resembles the original reference image.
00043 %
00044 %  A reduction of colors in an image is also desirable for image
00045 %  transmission and real-time animation.
00046 %
00047 %  QuantizeImage() takes a standard RGB or monochrome images and quantizes
00048 %  them down to some fixed number of colors.
00049 %
00050 %  For purposes of color allocation, an image is a set of n pixels, where
00051 %  each pixel is a point in RGB space.  RGB space is a 3-dimensional
00052 %  vector space, and each pixel, Pi,  is defined by an ordered triple of
00053 %  red, green, and blue coordinates, (Ri, Gi, Bi).
00054 %
00055 %  Each primary color component (red, green, or blue) represents an
00056 %  intensity which varies linearly from 0 to a maximum value, Cmax, which
00057 %  corresponds to full saturation of that color.  Color allocation is
00058 %  defined over a domain consisting of the cube in RGB space with opposite
00059 %  vertices at (0,0,0) and (Cmax, Cmax, Cmax).  QUANTIZE requires Cmax =
00060 %  255.
00061 %
00062 %  The algorithm maps this domain onto a tree in which each node
00063 %  represents a cube within that domain.  In the following discussion
00064 %  these cubes are defined by the coordinate of two opposite vertices:
00065 %  The vertex nearest the origin in RGB space and the vertex farthest from
00066 %  the origin.
00067 %
00068 %  The tree's root node represents the entire domain, (0,0,0) through
00069 %  (Cmax,Cmax,Cmax).  Each lower level in the tree is generated by
00070 %  subdividing one node's cube into eight smaller cubes of equal size.
00071 %  This corresponds to bisecting the parent cube with planes passing
00072 %  through the midpoints of each edge.
00073 %
00074 %  The basic algorithm operates in three phases: Classification,
00075 %  Reduction, and Assignment.  Classification builds a color description
00076 %  tree for the image.  Reduction collapses the tree until the number it
00077 %  represents, at most, the number of colors desired in the output image.
00078 %  Assignment defines the output image's color map and sets each pixel's
00079 %  color by restorage_class in the reduced tree.  Our goal is to minimize
00080 %  the numerical discrepancies between the original colors and quantized
00081 %  colors (quantization error).
00082 %
00083 %  Classification begins by initializing a color description tree of
00084 %  sufficient depth to represent each possible input color in a leaf.
00085 %  However, it is impractical to generate a fully-formed color description
00086 %  tree in the storage_class phase for realistic values of Cmax.  If
00087 %  colors components in the input image are quantized to k-bit precision,
00088 %  so that Cmax= 2k-1, the tree would need k levels below the root node to
00089 %  allow representing each possible input color in a leaf.  This becomes
00090 %  prohibitive because the tree's total number of nodes is 1 +
00091 %  sum(i=1, k, 8k).
00092 %
00093 %  A complete tree would require 19,173,961 nodes for k = 8, Cmax = 255.
00094 %  Therefore, to avoid building a fully populated tree, QUANTIZE: (1)
00095 %  Initializes data structures for nodes only as they are needed;  (2)
00096 %  Chooses a maximum depth for the tree as a function of the desired
00097 %  number of colors in the output image (currently log2(colormap size)).
00098 %
00099 %  For each pixel in the input image, storage_class scans downward from
00100 %  the root of the color description tree.  At each level of the tree it
00101 %  identifies the single node which represents a cube in RGB space
00102 %  containing the pixel's color.  It updates the following data for each
00103 %  such node:
00104 %
00105 %    n1: Number of pixels whose color is contained in the RGB cube which
00106 %    this node represents;
00107 %
00108 %    n2: Number of pixels whose color is not represented in a node at
00109 %    lower depth in the tree;  initially,  n2 = 0 for all nodes except
00110 %    leaves of the tree.
00111 %
00112 %    Sr, Sg, Sb: Sums of the red, green, and blue component values for all
00113 %    pixels not classified at a lower depth. The combination of these sums
00114 %    and n2  will ultimately characterize the mean color of a set of
00115 %    pixels represented by this node.
00116 %
00117 %    E: the distance squared in RGB space between each pixel contained
00118 %    within a node and the nodes' center.  This represents the
00119 %    quantization error for a node.
00120 %
00121 %  Reduction repeatedly prunes the tree until the number of nodes with n2
00122 %  > 0 is less than or equal to the maximum number of colors allowed in
00123 %  the output image.  On any given iteration over the tree, it selects
00124 %  those nodes whose E count is minimal for pruning and merges their color
00125 %  statistics upward. It uses a pruning threshold, Ep, to govern node
00126 %  selection as follows:
00127 %
00128 %    Ep = 0
00129 %    while number of nodes with (n2 > 0) > required maximum number of colors
00130 %      prune all nodes such that E <= Ep
00131 %      Set Ep to minimum E in remaining nodes
00132 %
00133 %  This has the effect of minimizing any quantization error when merging
00134 %  two nodes together.
00135 %
00136 %  When a node to be pruned has offspring, the pruning procedure invokes
00137 %  itself recursively in order to prune the tree from the leaves upward.
00138 %  n2,  Sr, Sg,  and  Sb in a node being pruned are always added to the
00139 %  corresponding data in that node's parent.  This retains the pruned
00140 %  node's color characteristics for later averaging.
00141 %
00142 %  For each node, n2 pixels exist for which that node represents the
00143 %  smallest volume in RGB space containing those pixel's colors.  When n2
00144 %  > 0 the node will uniquely define a color in the output image. At the
00145 %  beginning of reduction,  n2 = 0  for all nodes except a the leaves of
00146 %  the tree which represent colors present in the input image.
00147 %
00148 %  The other pixel count, n1, indicates the total number of colors within
00149 %  the cubic volume which the node represents.  This includes n1 - n2
00150 %  pixels whose colors should be defined by nodes at a lower level in the
00151 %  tree.
00152 %
00153 %  Assignment generates the output image from the pruned tree.  The output
00154 %  image consists of two parts: (1)  A color map, which is an array of
00155 %  color descriptions (RGB triples) for each color present in the output
00156 %  image;  (2)  A pixel array, which represents each pixel as an index
00157 %  into the color map array.
00158 %
00159 %  First, the assignment phase makes one pass over the pruned color
00160 %  description tree to establish the image's color map.  For each node
00161 %  with n2  > 0, it divides Sr, Sg, and Sb by n2 .  This produces the mean
00162 %  color of all pixels that classify no lower than this node.  Each of
00163 %  these colors becomes an entry in the color map.
00164 %
00165 %  Finally,  the assignment phase reclassifies each pixel in the pruned
00166 %  tree to identify the deepest node containing the pixel's color.  The
00167 %  pixel's value in the pixel array becomes the index of this node's mean
00168 %  color in the color map.
00169 %
00170 %  This method is based on a similar algorithm written by Paul Raveling.
00171 %
00172 */
00173 
00174 /*
00175   Include declarations.
00176 */
00177 #include "MagickCore/studio.h"
00178 #include "MagickCore/attribute.h"
00179 #include "MagickCore/cache-view.h"
00180 #include "MagickCore/color.h"
00181 #include "MagickCore/color-private.h"
00182 #include "MagickCore/colormap.h"
00183 #include "MagickCore/colorspace.h"
00184 #include "MagickCore/colorspace-private.h"
00185 #include "MagickCore/enhance.h"
00186 #include "MagickCore/exception.h"
00187 #include "MagickCore/exception-private.h"
00188 #include "MagickCore/histogram.h"
00189 #include "MagickCore/image.h"
00190 #include "MagickCore/image-private.h"
00191 #include "MagickCore/list.h"
00192 #include "MagickCore/memory_.h"
00193 #include "MagickCore/monitor.h"
00194 #include "MagickCore/monitor-private.h"
00195 #include "MagickCore/option.h"
00196 #include "MagickCore/pixel-accessor.h"
00197 #include "MagickCore/quantize.h"
00198 #include "MagickCore/quantum.h"
00199 #include "MagickCore/quantum-private.h"
00200 #include "MagickCore/string_.h"
00201 #include "MagickCore/thread-private.h"
00202 
00203 /*
00204   Define declarations.
00205 */
00206 #if !defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
00207 #define CacheShift  2
00208 #else
00209 #define CacheShift  3
00210 #endif
00211 #define ErrorQueueLength  16
00212 #define MaxNodes  266817
00213 #define MaxTreeDepth  8
00214 #define NodesInAList  1920
00215 
00216 /*
00217   Typdef declarations.
00218 */
00219 typedef struct _RealPixelInfo
00220 {
00221   MagickRealType
00222     red,
00223     green,
00224     blue,
00225     alpha;
00226 } RealPixelInfo;
00227 
00228 typedef struct _NodeInfo
00229 {
00230   struct _NodeInfo
00231     *parent,
00232     *child[16];
00233 
00234   MagickSizeType
00235     number_unique;
00236 
00237   RealPixelInfo
00238     total_color;
00239 
00240   MagickRealType
00241     quantize_error;
00242 
00243   size_t
00244     color_number,
00245     id,
00246     level;
00247 } NodeInfo;
00248 
00249 typedef struct _Nodes
00250 {
00251   NodeInfo
00252     *nodes;
00253 
00254   struct _Nodes
00255     *next;
00256 } Nodes;
00257 
00258 typedef struct _CubeInfo
00259 {
00260   NodeInfo
00261     *root;
00262 
00263   size_t
00264     colors,
00265     maximum_colors;
00266 
00267   ssize_t
00268     transparent_index;
00269 
00270   MagickSizeType
00271     transparent_pixels;
00272 
00273   RealPixelInfo
00274     target;
00275 
00276   MagickRealType
00277     distance,
00278     pruning_threshold,
00279     next_threshold;
00280 
00281   size_t
00282     nodes,
00283     free_nodes,
00284     color_number;
00285 
00286   NodeInfo
00287     *next_node;
00288 
00289   Nodes
00290     *node_queue;
00291 
00292   ssize_t
00293     *cache;
00294 
00295   RealPixelInfo
00296     error[ErrorQueueLength];
00297 
00298   MagickRealType
00299     weights[ErrorQueueLength];
00300 
00301   QuantizeInfo
00302     *quantize_info;
00303 
00304   MagickBooleanType
00305     associate_alpha;
00306 
00307   ssize_t
00308     x,
00309     y;
00310 
00311   size_t
00312     depth;
00313 
00314   MagickOffsetType
00315     offset;
00316 
00317   MagickSizeType
00318     span;
00319 } CubeInfo;
00320 
00321 /*
00322   Method prototypes.
00323 */
00324 static CubeInfo
00325   *GetCubeInfo(const QuantizeInfo *,const size_t,const size_t);
00326 
00327 static NodeInfo
00328   *GetNodeInfo(CubeInfo *,const size_t,const size_t,NodeInfo *);
00329 
00330 static MagickBooleanType
00331   AssignImageColors(Image *,CubeInfo *,ExceptionInfo *),
00332   ClassifyImageColors(CubeInfo *,const Image *,ExceptionInfo *),
00333   DitherImage(Image *,CubeInfo *,ExceptionInfo *),
00334   SetGrayscaleImage(Image *,ExceptionInfo *);
00335 
00336 static size_t
00337   DefineImageColormap(Image *,CubeInfo *,NodeInfo *);
00338 
00339 static void
00340   ClosestColor(const Image *,CubeInfo *,const NodeInfo *),
00341   DestroyCubeInfo(CubeInfo *),
00342   PruneLevel(const Image *,CubeInfo *,const NodeInfo *),
00343   PruneToCubeDepth(const Image *,CubeInfo *,const NodeInfo *),
00344   ReduceImageColors(const Image *,CubeInfo *);
00345 
00346 /*
00347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00348 %                                                                             %
00349 %                                                                             %
00350 %                                                                             %
00351 %   A c q u i r e Q u a n t i z e I n f o                                     %
00352 %                                                                             %
00353 %                                                                             %
00354 %                                                                             %
00355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00356 %
00357 %  AcquireQuantizeInfo() allocates the QuantizeInfo structure.
00358 %
00359 %  The format of the AcquireQuantizeInfo method is:
00360 %
00361 %      QuantizeInfo *AcquireQuantizeInfo(const ImageInfo *image_info)
00362 %
00363 %  A description of each parameter follows:
00364 %
00365 %    o image_info: the image info.
00366 %
00367 */
00368 MagickExport QuantizeInfo *AcquireQuantizeInfo(const ImageInfo *image_info)
00369 {
00370   QuantizeInfo
00371     *quantize_info;
00372 
00373   quantize_info=(QuantizeInfo *) AcquireMagickMemory(sizeof(*quantize_info));
00374   if (quantize_info == (QuantizeInfo *) NULL)
00375     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00376   GetQuantizeInfo(quantize_info);
00377   if (image_info != (ImageInfo *) NULL)
00378     {
00379       const char
00380         *option;
00381 
00382       quantize_info->dither=image_info->dither;
00383       option=GetImageOption(image_info,"dither");
00384       if (option != (const char *) NULL)
00385         quantize_info->dither_method=(DitherMethod) ParseCommandOption(
00386           MagickDitherOptions,MagickFalse,option);
00387       quantize_info->measure_error=image_info->verbose;
00388     }
00389   return(quantize_info);
00390 }
00391 
00392 /*
00393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00394 %                                                                             %
00395 %                                                                             %
00396 %                                                                             %
00397 +   A s s i g n I m a g e C o l o r s                                         %
00398 %                                                                             %
00399 %                                                                             %
00400 %                                                                             %
00401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00402 %
00403 %  AssignImageColors() generates the output image from the pruned tree.  The
00404 %  output image consists of two parts: (1)  A color map, which is an array
00405 %  of color descriptions (RGB triples) for each color present in the
00406 %  output image;  (2)  A pixel array, which represents each pixel as an
00407 %  index into the color map array.
00408 %
00409 %  First, the assignment phase makes one pass over the pruned color
00410 %  description tree to establish the image's color map.  For each node
00411 %  with n2  > 0, it divides Sr, Sg, and Sb by n2 .  This produces the mean
00412 %  color of all pixels that classify no lower than this node.  Each of
00413 %  these colors becomes an entry in the color map.
00414 %
00415 %  Finally,  the assignment phase reclassifies each pixel in the pruned
00416 %  tree to identify the deepest node containing the pixel's color.  The
00417 %  pixel's value in the pixel array becomes the index of this node's mean
00418 %  color in the color map.
00419 %
00420 %  The format of the AssignImageColors() method is:
00421 %
00422 %      MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info)
00423 %
00424 %  A description of each parameter follows.
00425 %
00426 %    o image: the image.
00427 %
00428 %    o cube_info: A pointer to the Cube structure.
00429 %
00430 */
00431 
00432 static inline void AssociateAlphaPixel(const Image *image,
00433   const CubeInfo *cube_info,const Quantum *pixel,RealPixelInfo *alpha_pixel)
00434 {
00435   MagickRealType
00436     alpha;
00437 
00438   if ((cube_info->associate_alpha == MagickFalse) ||
00439       (GetPixelAlpha(image,pixel)== OpaqueAlpha))
00440     {
00441       alpha_pixel->red=(MagickRealType) GetPixelRed(image,pixel);
00442       alpha_pixel->green=(MagickRealType) GetPixelGreen(image,pixel);
00443       alpha_pixel->blue=(MagickRealType) GetPixelBlue(image,pixel);
00444       alpha_pixel->alpha=(MagickRealType) GetPixelAlpha(image,pixel);
00445       return;
00446     }
00447   alpha=(MagickRealType) (QuantumScale*GetPixelAlpha(image,pixel));
00448   alpha_pixel->red=alpha*GetPixelRed(image,pixel);
00449   alpha_pixel->green=alpha*GetPixelGreen(image,pixel);
00450   alpha_pixel->blue=alpha*GetPixelBlue(image,pixel);
00451   alpha_pixel->alpha=(MagickRealType) GetPixelAlpha(image,pixel);
00452 }
00453 
00454 static inline void AssociateAlphaPixelInfo(const Image *image,
00455   const CubeInfo *cube_info,const PixelInfo *pixel,
00456   RealPixelInfo *alpha_pixel)
00457 {
00458   MagickRealType
00459     alpha;
00460 
00461   if ((cube_info->associate_alpha == MagickFalse) ||
00462       (pixel->alpha == OpaqueAlpha))
00463     {
00464       alpha_pixel->red=(MagickRealType) pixel->red;
00465       alpha_pixel->green=(MagickRealType) pixel->green;
00466       alpha_pixel->blue=(MagickRealType) pixel->blue;
00467       alpha_pixel->alpha=(MagickRealType) pixel->alpha;
00468       return;
00469     }
00470   alpha=(MagickRealType) (QuantumScale*pixel->alpha);
00471   alpha_pixel->red=alpha*pixel->red;
00472   alpha_pixel->green=alpha*pixel->green;
00473   alpha_pixel->blue=alpha*pixel->blue;
00474   alpha_pixel->alpha=(MagickRealType) pixel->alpha;
00475 }
00476 
00477 static inline Quantum ClampToUnsignedQuantum(const MagickRealType value)
00478 {
00479   if (value <= 0.0)
00480     return((Quantum) 0);
00481   if (value >= QuantumRange)
00482     return((Quantum) QuantumRange);
00483   return((Quantum) (value+0.5));
00484 }
00485 
00486 static inline size_t ColorToNodeId(const CubeInfo *cube_info,
00487   const RealPixelInfo *pixel,size_t index)
00488 {
00489   size_t
00490     id;
00491 
00492   id=(size_t) (((ScaleQuantumToChar(ClampToUnsignedQuantum(pixel->red)) >> index) & 0x01) |
00493     ((ScaleQuantumToChar(ClampToUnsignedQuantum(pixel->green)) >> index) & 0x01) << 1 |
00494     ((ScaleQuantumToChar(ClampToUnsignedQuantum(pixel->blue)) >> index) & 0x01) << 2);
00495   if (cube_info->associate_alpha != MagickFalse)
00496     id|=((ScaleQuantumToChar(ClampToUnsignedQuantum(pixel->alpha)) >> index) & 0x1) << 3;
00497   return(id);
00498 }
00499 
00500 static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info,
00501   ExceptionInfo *exception)
00502 {
00503 #define AssignImageTag  "Assign/Image"
00504 
00505   ssize_t
00506     y;
00507 
00508   /*
00509     Allocate image colormap.
00510   */
00511   if ((cube_info->quantize_info->colorspace != UndefinedColorspace) &&
00512       (cube_info->quantize_info->colorspace != CMYKColorspace))
00513     (void) TransformImageColorspace((Image *) image,
00514       cube_info->quantize_info->colorspace,exception);
00515   else
00516     if ((image->colorspace != GRAYColorspace) &&
00517         (IsRGBColorspace(image->colorspace) == MagickFalse) &&
00518         (image->colorspace != CMYColorspace))
00519       (void) TransformImageColorspace((Image *) image,RGBColorspace,exception);
00520   if (AcquireImageColormap(image,cube_info->colors,exception) == MagickFalse)
00521     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
00522       image->filename);
00523   image->colors=0;
00524   cube_info->transparent_pixels=0;
00525   cube_info->transparent_index=(-1);
00526   (void) DefineImageColormap(image,cube_info,cube_info->root);
00527   /*
00528     Create a reduced color image.
00529   */
00530   if ((cube_info->quantize_info->dither != MagickFalse) &&
00531       (cube_info->quantize_info->dither_method != NoDitherMethod))
00532     (void) DitherImage(image,cube_info,exception);
00533   else
00534     {
00535       CacheView
00536         *image_view;
00537 
00538       ExceptionInfo
00539         *exception;
00540 
00541       MagickBooleanType
00542         status;
00543 
00544       status=MagickTrue;
00545       image_view=AcquireCacheView(image);
00546 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00547       #pragma omp parallel for schedule(static,4) shared(status)
00548 #endif
00549       for (y=0; y < (ssize_t) image->rows; y++)
00550       {
00551         CubeInfo
00552           cube;
00553 
00554         register Quantum
00555           *restrict q;
00556 
00557         register ssize_t
00558           x;
00559 
00560         ssize_t
00561           count;
00562 
00563         if (status == MagickFalse)
00564           continue;
00565         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
00566           exception);
00567         if (q == (Quantum *) NULL)
00568           {
00569             status=MagickFalse;
00570             continue;
00571           }
00572         cube=(*cube_info);
00573         for (x=0; x < (ssize_t) image->columns; x+=count)
00574         {
00575           RealPixelInfo
00576             pixel;
00577 
00578           register const NodeInfo
00579             *node_info;
00580 
00581           register ssize_t
00582             i;
00583 
00584           size_t
00585             id,
00586             index;
00587 
00588           /*
00589             Identify the deepest node containing the pixel's color.
00590           */
00591           for (count=1; (x+count) < (ssize_t) image->columns; count++)
00592           {
00593             PixelInfo
00594               packet;
00595 
00596             GetPixelInfoPixel(image,q+count*GetPixelChannels(image),&packet);
00597             if (IsPixelEquivalent(image,q,&packet) == MagickFalse)
00598               break;
00599           }
00600           AssociateAlphaPixel(image,&cube,q,&pixel);
00601           node_info=cube.root;
00602           for (index=MaxTreeDepth-1; (ssize_t) index > 0; index--)
00603           {
00604             id=ColorToNodeId(&cube,&pixel,index);
00605             if (node_info->child[id] == (NodeInfo *) NULL)
00606               break;
00607             node_info=node_info->child[id];
00608           }
00609           /*
00610             Find closest color among siblings and their children.
00611           */
00612           cube.target=pixel;
00613           cube.distance=(MagickRealType) (4.0*(QuantumRange+1.0)*
00614             (QuantumRange+1.0)+1.0);
00615           ClosestColor(image,&cube,node_info->parent);
00616           index=cube.color_number;
00617           for (i=0; i < (ssize_t) count; i++)
00618           {
00619             if (image->storage_class == PseudoClass)
00620               SetPixelIndex(image,(Quantum) index,q);
00621             if (cube.quantize_info->measure_error == MagickFalse)
00622               {
00623                 SetPixelRed(image,image->colormap[index].red,q);
00624                 SetPixelGreen(image,image->colormap[index].green,q);
00625                 SetPixelBlue(image,image->colormap[index].blue,q);
00626                 if (cube.associate_alpha != MagickFalse)
00627                   SetPixelAlpha(image,image->colormap[index].alpha,q);
00628               }
00629             q+=GetPixelChannels(image);
00630           }
00631         }
00632         if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
00633           status=MagickFalse;
00634         if (image->progress_monitor != (MagickProgressMonitor) NULL)
00635           {
00636             MagickBooleanType
00637               proceed;
00638 
00639 #if defined(MAGICKCORE_OPENMP_SUPPORT)
00640             #pragma omp critical (MagickCore_AssignImageColors)
00641 #endif
00642             proceed=SetImageProgress(image,AssignImageTag,(MagickOffsetType) y,
00643               image->rows);
00644             if (proceed == MagickFalse)
00645               status=MagickFalse;
00646           }
00647       }
00648       image_view=DestroyCacheView(image_view);
00649     }
00650   if (cube_info->quantize_info->measure_error != MagickFalse)
00651     (void) GetImageQuantizeError(image,exception);
00652   if ((cube_info->quantize_info->number_colors == 2) &&
00653       (cube_info->quantize_info->colorspace == GRAYColorspace))
00654     {
00655       Quantum
00656         intensity;
00657 
00658       register PixelInfo
00659         *restrict q;
00660 
00661       register ssize_t
00662         i;
00663 
00664       /*
00665         Monochrome image.
00666       */
00667       q=image->colormap;
00668       for (i=0; i < (ssize_t) image->colors; i++)
00669       {
00670         intensity=(Quantum) ((MagickRealType) GetPixelInfoIntensity(q) <
00671           ((MagickRealType) QuantumRange/2.0) ? 0 : QuantumRange);
00672         q->red=intensity;
00673         q->green=intensity;
00674         q->blue=intensity;
00675         q++;
00676       }
00677     }
00678   (void) SyncImage(image,exception);
00679   if ((cube_info->quantize_info->colorspace != UndefinedColorspace) &&
00680       (cube_info->quantize_info->colorspace != CMYKColorspace))
00681     (void) TransformImageColorspace((Image *) image,RGBColorspace,exception);
00682   return(MagickTrue);
00683 }
00684 
00685 /*
00686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00687 %                                                                             %
00688 %                                                                             %
00689 %                                                                             %
00690 +   C l a s s i f y I m a g e C o l o r s                                     %
00691 %                                                                             %
00692 %                                                                             %
00693 %                                                                             %
00694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00695 %
00696 %  ClassifyImageColors() begins by initializing a color description tree
00697 %  of sufficient depth to represent each possible input color in a leaf.
00698 %  However, it is impractical to generate a fully-formed color
00699 %  description tree in the storage_class phase for realistic values of
00700 %  Cmax.  If colors components in the input image are quantized to k-bit
00701 %  precision, so that Cmax= 2k-1, the tree would need k levels below the
00702 %  root node to allow representing each possible input color in a leaf.
00703 %  This becomes prohibitive because the tree's total number of nodes is
00704 %  1 + sum(i=1,k,8k).
00705 %
00706 %  A complete tree would require 19,173,961 nodes for k = 8, Cmax = 255.
00707 %  Therefore, to avoid building a fully populated tree, QUANTIZE: (1)
00708 %  Initializes data structures for nodes only as they are needed;  (2)
00709 %  Chooses a maximum depth for the tree as a function of the desired
00710 %  number of colors in the output image (currently log2(colormap size)).
00711 %
00712 %  For each pixel in the input image, storage_class scans downward from
00713 %  the root of the color description tree.  At each level of the tree it
00714 %  identifies the single node which represents a cube in RGB space
00715 %  containing It updates the following data for each such node:
00716 %
00717 %    n1 : Number of pixels whose color is contained in the RGB cube
00718 %    which this node represents;
00719 %
00720 %    n2 : Number of pixels whose color is not represented in a node at
00721 %    lower depth in the tree;  initially,  n2 = 0 for all nodes except
00722 %    leaves of the tree.
00723 %
00724 %    Sr, Sg, Sb : Sums of the red, green, and blue component values for
00725 %    all pixels not classified at a lower depth. The combination of
00726 %    these sums and n2  will ultimately characterize the mean color of a
00727 %    set of pixels represented by this node.
00728 %
00729 %    E: the distance squared in RGB space between each pixel contained
00730 %    within a node and the nodes' center.  This represents the quantization
00731 %    error for a node.
00732 %
00733 %  The format of the ClassifyImageColors() method is:
00734 %
00735 %      MagickBooleanType ClassifyImageColors(CubeInfo *cube_info,
00736 %        const Image *image,ExceptionInfo *exception)
00737 %
00738 %  A description of each parameter follows.
00739 %
00740 %    o cube_info: A pointer to the Cube structure.
00741 %
00742 %    o image: the image.
00743 %
00744 */
00745 
00746 static inline void SetAssociatedAlpha(const Image *image,CubeInfo *cube_info)
00747 {
00748   MagickBooleanType
00749     associate_alpha;
00750 
00751   associate_alpha=image->matte;
00752   if (cube_info->quantize_info->colorspace == TransparentColorspace)
00753     associate_alpha=MagickFalse;
00754   if ((cube_info->quantize_info->number_colors == 2) &&
00755       (cube_info->quantize_info->colorspace == GRAYColorspace))
00756     associate_alpha=MagickFalse;
00757   cube_info->associate_alpha=associate_alpha;
00758 }
00759 
00760 static MagickBooleanType ClassifyImageColors(CubeInfo *cube_info,
00761   const Image *image,ExceptionInfo *exception)
00762 {
00763 #define ClassifyImageTag  "Classify/Image"
00764 
00765   CacheView
00766     *image_view;
00767 
00768   MagickBooleanType
00769     proceed;
00770 
00771   MagickRealType
00772     bisect;
00773 
00774   NodeInfo
00775     *node_info;
00776 
00777   RealPixelInfo
00778     error,
00779     mid,
00780     midpoint,
00781     pixel;
00782 
00783   size_t
00784     count,
00785     id,
00786     index,
00787     level;
00788 
00789   ssize_t
00790     y;
00791 
00792   /*
00793     Classify the first cube_info->maximum_colors colors to a tree depth of 8.
00794   */
00795   SetAssociatedAlpha(image,cube_info);
00796   if ((cube_info->quantize_info->colorspace != UndefinedColorspace) &&
00797       (cube_info->quantize_info->colorspace != CMYKColorspace))
00798     (void) TransformImageColorspace((Image *) image,
00799       cube_info->quantize_info->colorspace,exception);
00800   else
00801     if ((image->colorspace != GRAYColorspace) &&
00802         (image->colorspace != CMYColorspace) &&
00803         (IsRGBColorspace(image->colorspace) == MagickFalse))
00804       (void) TransformImageColorspace((Image *) image,RGBColorspace,exception);
00805   midpoint.red=(MagickRealType) QuantumRange/2.0;
00806   midpoint.green=(MagickRealType) QuantumRange/2.0;
00807   midpoint.blue=(MagickRealType) QuantumRange/2.0;
00808   midpoint.alpha=(MagickRealType) QuantumRange/2.0;
00809   error.alpha=0.0;
00810   image_view=AcquireCacheView(image);
00811   for (y=0; y < (ssize_t) image->rows; y++)
00812   {
00813     register const Quantum
00814       *restrict p;
00815 
00816     register ssize_t
00817       x;
00818 
00819     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
00820     if (p == (const Quantum *) NULL)
00821       break;
00822     if (cube_info->nodes > MaxNodes)
00823       {
00824         /*
00825           Prune one level if the color tree is too large.
00826         */
00827         PruneLevel(image,cube_info,cube_info->root);
00828         cube_info->depth--;
00829       }
00830     for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) count)
00831     {
00832       /*
00833         Start at the root and descend the color cube tree.
00834       */
00835       for (count=1; (x+(ssize_t) count) < (ssize_t) image->columns; count++)
00836       {
00837         PixelInfo
00838           packet;
00839 
00840         GetPixelInfoPixel(image,p+count*GetPixelChannels(image),&packet);
00841         if (IsPixelEquivalent(image,p,&packet) == MagickFalse)
00842           break;
00843       }
00844       AssociateAlphaPixel(image,cube_info,p,&pixel);
00845       index=MaxTreeDepth-1;
00846       bisect=((MagickRealType) QuantumRange+1.0)/2.0;
00847       mid=midpoint;
00848       node_info=cube_info->root;
00849       for (level=1; level <= MaxTreeDepth; level++)
00850       {
00851         bisect*=0.5;
00852         id=ColorToNodeId(cube_info,&pixel,index);
00853         mid.red+=(id & 1) != 0 ? bisect : -bisect;
00854         mid.green+=(id & 2) != 0 ? bisect : -bisect;
00855         mid.blue+=(id & 4) != 0 ? bisect : -bisect;
00856         mid.alpha+=(id & 8) != 0 ? bisect : -bisect;
00857         if (node_info->child[id] == (NodeInfo *) NULL)
00858           {
00859             /*
00860               Set colors of new node to contain pixel.
00861             */
00862             node_info->child[id]=GetNodeInfo(cube_info,id,level,node_info);
00863             if (node_info->child[id] == (NodeInfo *) NULL)
00864               (void) ThrowMagickException(exception,GetMagickModule(),
00865                 ResourceLimitError,"MemoryAllocationFailed","`%s'",
00866                 image->filename);
00867             if (level == MaxTreeDepth)
00868               cube_info->colors++;
00869           }
00870         /*
00871           Approximate the quantization error represented by this node.
00872         */
00873         node_info=node_info->child[id];
00874         error.red=QuantumScale*(pixel.red-mid.red);
00875         error.green=QuantumScale*(pixel.green-mid.green);
00876         error.blue=QuantumScale*(pixel.blue-mid.blue);
00877         if (cube_info->associate_alpha != MagickFalse)
00878           error.alpha=QuantumScale*(pixel.alpha-mid.alpha);
00879         node_info->quantize_error+=sqrt((double) (count*error.red*error.red+
00880           count*error.green*error.green+count*error.blue*error.blue+
00881           count*error.alpha*error.alpha));
00882         cube_info->root->quantize_error+=node_info->quantize_error;
00883         index--;
00884       }
00885       /*
00886         Sum RGB for this leaf for later derivation of the mean cube color.
00887       */
00888       node_info->number_unique+=count;
00889       node_info->total_color.red+=count*QuantumScale*pixel.red;
00890       node_info->total_color.green+=count*QuantumScale*pixel.green;
00891       node_info->total_color.blue+=count*QuantumScale*pixel.blue;
00892       if (cube_info->associate_alpha != MagickFalse)
00893         node_info->total_color.alpha+=count*QuantumScale*pixel.alpha;
00894       p+=count*GetPixelChannels(image);
00895     }
00896     if (cube_info->colors > cube_info->maximum_colors)
00897       {
00898         PruneToCubeDepth(image,cube_info,cube_info->root);
00899         break;
00900       }
00901     proceed=SetImageProgress(image,ClassifyImageTag,(MagickOffsetType) y,
00902       image->rows);
00903     if (proceed == MagickFalse)
00904       break;
00905   }
00906   for (y++; y < (ssize_t) image->rows; y++)
00907   {
00908     register const Quantum
00909       *restrict p;
00910 
00911     register ssize_t
00912       x;
00913 
00914     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
00915     if (p == (const Quantum *) NULL)
00916       break;
00917     if (cube_info->nodes > MaxNodes)
00918       {
00919         /*
00920           Prune one level if the color tree is too large.
00921         */
00922         PruneLevel(image,cube_info,cube_info->root);
00923         cube_info->depth--;
00924       }
00925     for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) count)
00926     {
00927       /*
00928         Start at the root and descend the color cube tree.
00929       */
00930       for (count=1; (x+(ssize_t) count) < (ssize_t) image->columns; count++)
00931       {
00932         PixelInfo
00933           packet;
00934 
00935         GetPixelInfoPixel(image,p+count*GetPixelChannels(image),&packet);
00936         if (IsPixelEquivalent(image,p,&packet) == MagickFalse)
00937           break;
00938       }
00939       AssociateAlphaPixel(image,cube_info,p,&pixel);
00940       index=MaxTreeDepth-1;
00941       bisect=((MagickRealType) QuantumRange+1.0)/2.0;
00942       mid=midpoint;
00943       node_info=cube_info->root;
00944       for (level=1; level <= cube_info->depth; level++)
00945       {
00946         bisect*=0.5;
00947         id=ColorToNodeId(cube_info,&pixel,index);
00948         mid.red+=(id & 1) != 0 ? bisect : -bisect;
00949         mid.green+=(id & 2) != 0 ? bisect : -bisect;
00950         mid.blue+=(id & 4) != 0 ? bisect : -bisect;
00951         mid.alpha+=(id & 8) != 0 ? bisect : -bisect;
00952         if (node_info->child[id] == (NodeInfo *) NULL)
00953           {
00954             /*
00955               Set colors of new node to contain pixel.
00956             */
00957             node_info->child[id]=GetNodeInfo(cube_info,id,level,node_info);
00958             if (node_info->child[id] == (NodeInfo *) NULL)
00959               (void) ThrowMagickException(exception,GetMagickModule(),
00960                 ResourceLimitError,"MemoryAllocationFailed","%s",
00961                 image->filename);
00962             if (level == cube_info->depth)
00963               cube_info->colors++;
00964           }
00965         /*
00966           Approximate the quantization error represented by this node.
00967         */
00968         node_info=node_info->child[id];
00969         error.red=QuantumScale*(pixel.red-mid.red);
00970         error.green=QuantumScale*(pixel.green-mid.green);
00971         error.blue=QuantumScale*(pixel.blue-mid.blue);
00972         if (cube_info->associate_alpha != MagickFalse)
00973           error.alpha=QuantumScale*(pixel.alpha-mid.alpha);
00974         node_info->quantize_error+=sqrt((double) (count*error.red*error.red+
00975           count*error.green*error.green+count*error.blue*error.blue+
00976           count*error.alpha*error.alpha));
00977         cube_info->root->quantize_error+=node_info->quantize_error;
00978         index--;
00979       }
00980       /*
00981         Sum RGB for this leaf for later derivation of the mean cube color.
00982       */
00983       node_info->number_unique+=count;
00984       node_info->total_color.red+=count*QuantumScale*pixel.red;
00985       node_info->total_color.green+=count*QuantumScale*pixel.green;
00986       node_info->total_color.blue+=count*QuantumScale*pixel.blue;
00987       if (cube_info->associate_alpha != MagickFalse)
00988         node_info->total_color.alpha+=count*QuantumScale*pixel.alpha;
00989       p+=count*GetPixelChannels(image);
00990     }
00991     proceed=SetImageProgress(image,ClassifyImageTag,(MagickOffsetType) y,
00992       image->rows);
00993     if (proceed == MagickFalse)
00994       break;
00995   }
00996   image_view=DestroyCacheView(image_view);
00997   if ((cube_info->quantize_info->colorspace != UndefinedColorspace) &&
00998       (cube_info->quantize_info->colorspace != CMYKColorspace))
00999     (void) TransformImageColorspace((Image *) image,RGBColorspace,exception);
01000   return(MagickTrue);
01001 }
01002 
01003 /*
01004 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01005 %                                                                             %
01006 %                                                                             %
01007 %                                                                             %
01008 %   C l o n e Q u a n t i z e I n f o                                         %
01009 %                                                                             %
01010 %                                                                             %
01011 %                                                                             %
01012 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01013 %
01014 %  CloneQuantizeInfo() makes a duplicate of the given quantize info structure,
01015 %  or if quantize info is NULL, a new one.
01016 %
01017 %  The format of the CloneQuantizeInfo method is:
01018 %
01019 %      QuantizeInfo *CloneQuantizeInfo(const QuantizeInfo *quantize_info)
01020 %
01021 %  A description of each parameter follows:
01022 %
01023 %    o clone_info: Method CloneQuantizeInfo returns a duplicate of the given
01024 %      quantize info, or if image info is NULL a new one.
01025 %
01026 %    o quantize_info: a structure of type info.
01027 %
01028 */
01029 MagickExport QuantizeInfo *CloneQuantizeInfo(const QuantizeInfo *quantize_info)
01030 {
01031   QuantizeInfo
01032     *clone_info;
01033 
01034   clone_info=(QuantizeInfo *) AcquireMagickMemory(sizeof(*clone_info));
01035   if (clone_info == (QuantizeInfo *) NULL)
01036     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01037   GetQuantizeInfo(clone_info);
01038   if (quantize_info == (QuantizeInfo *) NULL)
01039     return(clone_info);
01040   clone_info->number_colors=quantize_info->number_colors;
01041   clone_info->tree_depth=quantize_info->tree_depth;
01042   clone_info->dither=quantize_info->dither;
01043   clone_info->dither_method=quantize_info->dither_method;
01044   clone_info->colorspace=quantize_info->colorspace;
01045   clone_info->measure_error=quantize_info->measure_error;
01046   return(clone_info);
01047 }
01048 
01049 /*
01050 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01051 %                                                                             %
01052 %                                                                             %
01053 %                                                                             %
01054 +   C l o s e s t C o l o r                                                   %
01055 %                                                                             %
01056 %                                                                             %
01057 %                                                                             %
01058 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01059 %
01060 %  ClosestColor() traverses the color cube tree at a particular node and
01061 %  determines which colormap entry best represents the input color.
01062 %
01063 %  The format of the ClosestColor method is:
01064 %
01065 %      void ClosestColor(const Image *image,CubeInfo *cube_info,
01066 %        const NodeInfo *node_info)
01067 %
01068 %  A description of each parameter follows.
01069 %
01070 %    o image: the image.
01071 %
01072 %    o cube_info: A pointer to the Cube structure.
01073 %
01074 %    o node_info: the address of a structure of type NodeInfo which points to a
01075 %      node in the color cube tree that is to be pruned.
01076 %
01077 */
01078 static void ClosestColor(const Image *image,CubeInfo *cube_info,
01079   const NodeInfo *node_info)
01080 {
01081   register ssize_t
01082     i;
01083 
01084   size_t
01085     number_children;
01086 
01087   /*
01088     Traverse any children.
01089   */
01090   number_children=cube_info->associate_alpha == MagickFalse ? 8UL : 16UL;
01091   for (i=0; i < (ssize_t) number_children; i++)
01092     if (node_info->child[i] != (NodeInfo *) NULL)
01093       ClosestColor(image,cube_info,node_info->child[i]);
01094   if (node_info->number_unique != 0)
01095     {
01096       MagickRealType
01097         pixel;
01098 
01099       register MagickRealType
01100         alpha,
01101         beta,
01102         distance;
01103 
01104       register PixelInfo
01105         *restrict p;
01106 
01107       register RealPixelInfo
01108         *restrict q;
01109 
01110       /*
01111         Determine if this color is "closest".
01112       */
01113       p=image->colormap+node_info->color_number;
01114       q=(&cube_info->target);
01115       alpha=1.0;
01116       beta=1.0;
01117       if (cube_info->associate_alpha != MagickFalse)
01118         {
01119           alpha=(MagickRealType) (QuantumScale*p->alpha);
01120           beta=(MagickRealType) (QuantumScale*q->alpha);
01121         }
01122       pixel=alpha*p->red-beta*q->red;
01123       distance=pixel*pixel;
01124       if (distance <= cube_info->distance)
01125         {
01126           pixel=alpha*p->green-beta*q->green;
01127           distance+=pixel*pixel;
01128           if (distance <= cube_info->distance)
01129             {
01130               pixel=alpha*p->blue-beta*q->blue;
01131               distance+=pixel*pixel;
01132               if (distance <= cube_info->distance)
01133                 {
01134                   pixel=alpha-beta;
01135                   distance+=pixel*pixel;
01136                   if (distance <= cube_info->distance)
01137                     {
01138                       cube_info->distance=distance;
01139                       cube_info->color_number=node_info->color_number;
01140                     }
01141                 }
01142             }
01143         }
01144     }
01145 }
01146 
01147 /*
01148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01149 %                                                                             %
01150 %                                                                             %
01151 %                                                                             %
01152 %   C o m p r e s s I m a g e C o l o r m a p                                 %
01153 %                                                                             %
01154 %                                                                             %
01155 %                                                                             %
01156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01157 %
01158 %  CompressImageColormap() compresses an image colormap by removing any
01159 %  duplicate or unused color entries.
01160 %
01161 %  The format of the CompressImageColormap method is:
01162 %
01163 %      MagickBooleanType CompressImageColormap(Image *image,
01164 %        ExceptionInfo *exception)
01165 %
01166 %  A description of each parameter follows:
01167 %
01168 %    o image: the image.
01169 %
01170 %    o exception: return any errors or warnings in this structure.
01171 %
01172 */
01173 MagickExport MagickBooleanType CompressImageColormap(Image *image,
01174   ExceptionInfo *exception)
01175 {
01176   QuantizeInfo
01177     quantize_info;
01178 
01179   assert(image != (Image *) NULL);
01180   assert(image->signature == MagickSignature);
01181   if (image->debug != MagickFalse)
01182     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01183   if (IsPaletteImage(image,exception) == MagickFalse)
01184     return(MagickFalse);
01185   GetQuantizeInfo(&quantize_info);
01186   quantize_info.number_colors=image->colors;
01187   quantize_info.tree_depth=MaxTreeDepth;
01188   return(QuantizeImage(&quantize_info,image,exception));
01189 }
01190 
01191 /*
01192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01193 %                                                                             %
01194 %                                                                             %
01195 %                                                                             %
01196 +   D e f i n e I m a g e C o l o r m a p                                     %
01197 %                                                                             %
01198 %                                                                             %
01199 %                                                                             %
01200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01201 %
01202 %  DefineImageColormap() traverses the color cube tree and notes each colormap
01203 %  entry.  A colormap entry is any node in the color cube tree where the
01204 %  of unique colors is not zero.  DefineImageColormap() returns the number of
01205 %  colors in the image colormap.
01206 %
01207 %  The format of the DefineImageColormap method is:
01208 %
01209 %      size_t DefineImageColormap(Image *image,CubeInfo *cube_info,
01210 %        NodeInfo *node_info)
01211 %
01212 %  A description of each parameter follows.
01213 %
01214 %    o image: the image.
01215 %
01216 %    o cube_info: A pointer to the Cube structure.
01217 %
01218 %    o node_info: the address of a structure of type NodeInfo which points to a
01219 %      node in the color cube tree that is to be pruned.
01220 %
01221 */
01222 static size_t DefineImageColormap(Image *image,CubeInfo *cube_info,
01223   NodeInfo *node_info)
01224 {
01225   register ssize_t
01226     i;
01227 
01228   size_t
01229     number_children;
01230 
01231   /*
01232     Traverse any children.
01233   */
01234   number_children=cube_info->associate_alpha == MagickFalse ? 8UL : 16UL;
01235   for (i=0; i < (ssize_t) number_children; i++)
01236     if (node_info->child[i] != (NodeInfo *) NULL)
01237       (void) DefineImageColormap(image,cube_info,node_info->child[i]);
01238   if (node_info->number_unique != 0)
01239     {
01240       register MagickRealType
01241         alpha;
01242 
01243       register PixelInfo
01244         *restrict q;
01245 
01246       /*
01247         Colormap entry is defined by the mean color in this cube.
01248       */
01249       q=image->colormap+image->colors;
01250       alpha=(MagickRealType) ((MagickOffsetType) node_info->number_unique);
01251       alpha=1.0/(fabs(alpha) <= MagickEpsilon ? 1.0 : alpha);
01252       if (cube_info->associate_alpha == MagickFalse)
01253         {
01254           q->red=ClampToQuantum((MagickRealType)
01255             (alpha*QuantumRange*node_info->total_color.red));
01256           q->green=ClampToQuantum((MagickRealType)
01257             (alpha*QuantumRange*node_info->total_color.green));
01258           q->blue=ClampToQuantum((MagickRealType)
01259             (alpha*QuantumRange*node_info->total_color.blue));
01260           q->alpha=OpaqueAlpha;
01261         }
01262       else
01263         {
01264           MagickRealType
01265             opacity;
01266 
01267           opacity=(MagickRealType) (alpha*QuantumRange*
01268             node_info->total_color.alpha);
01269           q->alpha=ClampToQuantum(opacity);
01270           if (q->alpha == OpaqueAlpha)
01271             {
01272               q->red=ClampToQuantum((MagickRealType)
01273                 (alpha*QuantumRange*node_info->total_color.red));
01274               q->green=ClampToQuantum((MagickRealType)
01275                 (alpha*QuantumRange*node_info->total_color.green));
01276               q->blue=ClampToQuantum((MagickRealType)
01277                 (alpha*QuantumRange*node_info->total_color.blue));
01278             }
01279           else
01280             {
01281               MagickRealType
01282                 gamma;
01283 
01284               gamma=(MagickRealType) (QuantumScale*q->alpha);
01285               gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
01286               q->red=ClampToQuantum((MagickRealType)
01287                 (alpha*gamma*QuantumRange*node_info->total_color.red));
01288               q->green=ClampToQuantum((MagickRealType)
01289                 (alpha*gamma*QuantumRange*node_info->total_color.green));
01290               q->blue=ClampToQuantum((MagickRealType)
01291                 (alpha*gamma*QuantumRange*node_info->total_color.blue));
01292               if (node_info->number_unique > cube_info->transparent_pixels)
01293                 {
01294                   cube_info->transparent_pixels=node_info->number_unique;
01295                   cube_info->transparent_index=(ssize_t) image->colors;
01296                 }
01297             }
01298         }
01299       node_info->color_number=image->colors++;
01300     }
01301   return(image->colors);
01302 }
01303 
01304 /*
01305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01306 %                                                                             %
01307 %                                                                             %
01308 %                                                                             %
01309 +   D e s t r o y C u b e I n f o                                             %
01310 %                                                                             %
01311 %                                                                             %
01312 %                                                                             %
01313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01314 %
01315 %  DestroyCubeInfo() deallocates memory associated with an image.
01316 %
01317 %  The format of the DestroyCubeInfo method is:
01318 %
01319 %      DestroyCubeInfo(CubeInfo *cube_info)
01320 %
01321 %  A description of each parameter follows:
01322 %
01323 %    o cube_info: the address of a structure of type CubeInfo.
01324 %
01325 */
01326 static void DestroyCubeInfo(CubeInfo *cube_info)
01327 {
01328   register Nodes
01329     *nodes;
01330 
01331   /*
01332     Release color cube tree storage.
01333   */
01334   do
01335   {
01336     nodes=cube_info->node_queue->next;
01337     cube_info->node_queue->nodes=(NodeInfo *) RelinquishMagickMemory(
01338       cube_info->node_queue->nodes);
01339     cube_info->node_queue=(Nodes *) RelinquishMagickMemory(
01340       cube_info->node_queue);
01341     cube_info->node_queue=nodes;
01342   } while (cube_info->node_queue != (Nodes *) NULL);
01343   if (cube_info->cache != (ssize_t *) NULL)
01344     cube_info->cache=(ssize_t *) RelinquishMagickMemory(cube_info->cache);
01345   cube_info->quantize_info=DestroyQuantizeInfo(cube_info->quantize_info);
01346   cube_info=(CubeInfo *) RelinquishMagickMemory(cube_info);
01347 }
01348 
01349 /*
01350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01351 %                                                                             %
01352 %                                                                             %
01353 %                                                                             %
01354 %   D e s t r o y Q u a n t i z e I n f o                                     %
01355 %                                                                             %
01356 %                                                                             %
01357 %                                                                             %
01358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01359 %
01360 %  DestroyQuantizeInfo() deallocates memory associated with an QuantizeInfo
01361 %  structure.
01362 %
01363 %  The format of the DestroyQuantizeInfo method is:
01364 %
01365 %      QuantizeInfo *DestroyQuantizeInfo(QuantizeInfo *quantize_info)
01366 %
01367 %  A description of each parameter follows:
01368 %
01369 %    o quantize_info: Specifies a pointer to an QuantizeInfo structure.
01370 %
01371 */
01372 MagickExport QuantizeInfo *DestroyQuantizeInfo(QuantizeInfo *quantize_info)
01373 {
01374   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01375   assert(quantize_info != (QuantizeInfo *) NULL);
01376   assert(quantize_info->signature == MagickSignature);
01377   quantize_info->signature=(~MagickSignature);
01378   quantize_info=(QuantizeInfo *) RelinquishMagickMemory(quantize_info);
01379   return(quantize_info);
01380 }
01381 
01382 /*
01383 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01384 %                                                                             %
01385 %                                                                             %
01386 %                                                                             %
01387 +   D i t h e r I m a g e                                                     %
01388 %                                                                             %
01389 %                                                                             %
01390 %                                                                             %
01391 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01392 %
01393 %  DitherImage() distributes the difference between an original image and
01394 %  the corresponding color reduced algorithm to neighboring pixels using
01395 %  serpentine-scan Floyd-Steinberg error diffusion. DitherImage returns
01396 %  MagickTrue if the image is dithered otherwise MagickFalse.
01397 %
01398 %  The format of the DitherImage method is:
01399 %
01400 %      MagickBooleanType DitherImage(Image *image,CubeInfo *cube_info,
01401 %        ExceptionInfo *exception)
01402 %
01403 %  A description of each parameter follows.
01404 %
01405 %    o image: the image.
01406 %
01407 %    o cube_info: A pointer to the Cube structure.
01408 %
01409 %    o exception: return any errors or warnings in this structure.
01410 %
01411 */
01412 
01413 static RealPixelInfo **DestroyPixelThreadSet(RealPixelInfo **pixels)
01414 {
01415   register ssize_t
01416     i;
01417 
01418   assert(pixels != (RealPixelInfo **) NULL);
01419   for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
01420     if (pixels[i] != (RealPixelInfo *) NULL)
01421       pixels[i]=(RealPixelInfo *) RelinquishMagickMemory(pixels[i]);
01422   pixels=(RealPixelInfo **) RelinquishMagickMemory(pixels);
01423   return(pixels);
01424 }
01425 
01426 static RealPixelInfo **AcquirePixelThreadSet(const size_t count)
01427 {
01428   RealPixelInfo
01429     **pixels;
01430 
01431   register ssize_t
01432     i;
01433 
01434   size_t
01435     number_threads;
01436 
01437   number_threads=GetOpenMPMaximumThreads();
01438   pixels=(RealPixelInfo **) AcquireQuantumMemory(number_threads,
01439     sizeof(*pixels));
01440   if (pixels == (RealPixelInfo **) NULL)
01441     return((RealPixelInfo **) NULL);
01442   (void) ResetMagickMemory(pixels,0,number_threads*sizeof(*pixels));
01443   for (i=0; i < (ssize_t) number_threads; i++)
01444   {
01445     pixels[i]=(RealPixelInfo *) AcquireQuantumMemory(count,
01446       2*sizeof(**pixels));
01447     if (pixels[i] == (RealPixelInfo *) NULL)
01448       return(DestroyPixelThreadSet(pixels));
01449   }
01450   return(pixels);
01451 }
01452 
01453 static inline ssize_t CacheOffset(CubeInfo *cube_info,
01454   const RealPixelInfo *pixel)
01455 {
01456 #define RedShift(pixel) (((pixel) >> CacheShift) << (0*(8-CacheShift)))
01457 #define GreenShift(pixel) (((pixel) >> CacheShift) << (1*(8-CacheShift)))
01458 #define BlueShift(pixel) (((pixel) >> CacheShift) << (2*(8-CacheShift)))
01459 #define AlphaShift(pixel) (((pixel) >> CacheShift) << (3*(8-CacheShift)))
01460 
01461   ssize_t
01462     offset;
01463 
01464   offset=(ssize_t)
01465     (RedShift(ScaleQuantumToChar(ClampToUnsignedQuantum(pixel->red))) |
01466     GreenShift(ScaleQuantumToChar(ClampToUnsignedQuantum(pixel->green))) |
01467     BlueShift(ScaleQuantumToChar(ClampToUnsignedQuantum(pixel->blue))));
01468   if (cube_info->associate_alpha != MagickFalse)
01469     offset|=AlphaShift(ScaleQuantumToChar(ClampToUnsignedQuantum(
01470       pixel->alpha)));
01471   return(offset);
01472 }
01473 
01474 static MagickBooleanType FloydSteinbergDither(Image *image,CubeInfo *cube_info,
01475   ExceptionInfo *exception)
01476 {
01477 #define DitherImageTag  "Dither/Image"
01478 
01479   CacheView
01480     *image_view;
01481 
01482   MagickBooleanType
01483     status;
01484 
01485   RealPixelInfo
01486     **pixels;
01487 
01488   ssize_t
01489     y;
01490 
01491   /*
01492     Distribute quantization error using Floyd-Steinberg.
01493   */
01494   pixels=AcquirePixelThreadSet(image->columns);
01495   if (pixels == (RealPixelInfo **) NULL)
01496     return(MagickFalse);
01497   status=MagickTrue;
01498   image_view=AcquireCacheView(image);
01499   for (y=0; y < (ssize_t) image->rows; y++)
01500   {
01501     const int
01502       id = GetOpenMPThreadId();
01503 
01504     CubeInfo
01505       cube;
01506 
01507     RealPixelInfo
01508       *current,
01509       *previous;
01510 
01511     register Quantum
01512       *restrict q;
01513 
01514     register ssize_t
01515       x;
01516 
01517     size_t
01518       index;
01519 
01520     ssize_t
01521       v;
01522 
01523     if (status == MagickFalse)
01524       continue;
01525     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
01526     if (q == (Quantum *) NULL)
01527       {
01528         status=MagickFalse;
01529         continue;
01530       }
01531     q+=(y & 0x01)*image->columns*GetPixelChannels(image);
01532     cube=(*cube_info);
01533     current=pixels[id]+(y & 0x01)*image->columns;
01534     previous=pixels[id]+((y+1) & 0x01)*image->columns;
01535     v=(ssize_t) ((y & 0x01) != 0 ? -1 : 1);
01536     for (x=0; x < (ssize_t) image->columns; x++)
01537     {
01538       RealPixelInfo
01539         color,
01540         pixel;
01541 
01542       register ssize_t
01543         i;
01544 
01545       ssize_t
01546         u;
01547 
01548       q-=(y & 0x01)*GetPixelChannels(image);
01549       u=(y & 0x01) != 0 ? (ssize_t) image->columns-1-x : x;
01550       AssociateAlphaPixel(image,&cube,q,&pixel);
01551       if (x > 0)
01552         {
01553           pixel.red+=7*current[u-v].red/16;
01554           pixel.green+=7*current[u-v].green/16;
01555           pixel.blue+=7*current[u-v].blue/16;
01556           if (cube.associate_alpha != MagickFalse)
01557             pixel.alpha+=7*current[u-v].alpha/16;
01558         }
01559       if (y > 0)
01560         {
01561           if (x < (ssize_t) (image->columns-1))
01562             {
01563               pixel.red+=previous[u+v].red/16;
01564               pixel.green+=previous[u+v].green/16;
01565               pixel.blue+=previous[u+v].blue/16;
01566               if (cube.associate_alpha != MagickFalse)
01567                 pixel.alpha+=previous[u+v].alpha/16;
01568             }
01569           pixel.red+=5*previous[u].red/16;
01570           pixel.green+=5*previous[u].green/16;
01571           pixel.blue+=5*previous[u].blue/16;
01572           if (cube.associate_alpha != MagickFalse)
01573             pixel.alpha+=5*previous[u].alpha/16;
01574           if (x > 0)
01575             {
01576               pixel.red+=3*previous[u-v].red/16;
01577               pixel.green+=3*previous[u-v].green/16;
01578               pixel.blue+=3*previous[u-v].blue/16;
01579               if (cube.associate_alpha != MagickFalse)
01580                 pixel.alpha+=3*previous[u-v].alpha/16;
01581             }
01582         }
01583       pixel.red=(MagickRealType) ClampToUnsignedQuantum(pixel.red);
01584       pixel.green=(MagickRealType) ClampToUnsignedQuantum(pixel.green);
01585       pixel.blue=(MagickRealType) ClampToUnsignedQuantum(pixel.blue);
01586       if (cube.associate_alpha != MagickFalse)
01587         pixel.alpha=(MagickRealType) ClampToUnsignedQuantum(pixel.alpha);
01588       i=CacheOffset(&cube,&pixel);
01589       if (cube.cache[i] < 0)
01590         {
01591           register NodeInfo
01592             *node_info;
01593 
01594           register size_t
01595             id;
01596 
01597           /*
01598             Identify the deepest node containing the pixel's color.
01599           */
01600           node_info=cube.root;
01601           for (index=MaxTreeDepth-1; (ssize_t) index > 0; index--)
01602           {
01603             id=ColorToNodeId(&cube,&pixel,index);
01604             if (node_info->child[id] == (NodeInfo *) NULL)
01605               break;
01606             node_info=node_info->child[id];
01607           }
01608           /*
01609             Find closest color among siblings and their children.
01610           */
01611           cube.target=pixel;
01612           cube.distance=(MagickRealType) (4.0*(QuantumRange+1.0)*(QuantumRange+
01613             1.0)+1.0);
01614           ClosestColor(image,&cube,node_info->parent);
01615           cube.cache[i]=(ssize_t) cube.color_number;
01616         }
01617       /*
01618         Assign pixel to closest colormap entry.
01619       */
01620       index=(size_t) cube.cache[i];
01621       if (image->storage_class == PseudoClass)
01622         SetPixelIndex(image,(Quantum) index,q);
01623       if (cube.quantize_info->measure_error == MagickFalse)
01624         {
01625           SetPixelRed(image,image->colormap[index].red,q);
01626           SetPixelGreen(image,image->colormap[index].green,q);
01627           SetPixelBlue(image,image->colormap[index].blue,q);
01628           if (cube.associate_alpha != MagickFalse)
01629             SetPixelAlpha(image,image->colormap[index].alpha,q);
01630         }
01631       if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
01632         status=MagickFalse;
01633       /*
01634         Store the error.
01635       */
01636       AssociateAlphaPixelInfo(image,&cube,image->colormap+index,&color);
01637       current[u].red=pixel.red-color.red;
01638       current[u].green=pixel.green-color.green;
01639       current[u].blue=pixel.blue-color.blue;
01640       if (cube.associate_alpha != MagickFalse)
01641         current[u].alpha=pixel.alpha-color.alpha;
01642       if (image->progress_monitor != (MagickProgressMonitor) NULL)
01643         {
01644           MagickBooleanType
01645             proceed;
01646 
01647 #if defined(MAGICKCORE_OPENMP_SUPPORT)
01648           #pragma omp critical (MagickCore_FloydSteinbergDither)
01649 #endif
01650           proceed=SetImageProgress(image,DitherImageTag,(MagickOffsetType) y,
01651             image->rows);
01652           if (proceed == MagickFalse)
01653             status=MagickFalse;
01654         }
01655       q+=((y+1) & 0x01)*GetPixelChannels(image);
01656     }
01657   }
01658   image_view=DestroyCacheView(image_view);
01659   pixels=DestroyPixelThreadSet(pixels);
01660   return(MagickTrue);
01661 }
01662 
01663 static MagickBooleanType
01664   RiemersmaDither(Image *,CacheView *,CubeInfo *,const unsigned int,
01665     ExceptionInfo *exception);
01666 
01667 static void Riemersma(Image *image,CacheView *image_view,CubeInfo *cube_info,
01668   const size_t level,const unsigned int direction,ExceptionInfo *exception)
01669 {
01670   if (level == 1)
01671     switch (direction)
01672     {
01673       case WestGravity:
01674       {
01675         (void) RiemersmaDither(image,image_view,cube_info,EastGravity,
01676           exception);
01677         (void) RiemersmaDither(image,image_view,cube_info,SouthGravity,
01678           exception);
01679         (void) RiemersmaDither(image,image_view,cube_info,WestGravity,
01680           exception);
01681         break;
01682       }
01683       case EastGravity:
01684       {
01685         (void) RiemersmaDither(image,image_view,cube_info,WestGravity,
01686           exception);
01687         (void) RiemersmaDither(image,image_view,cube_info,NorthGravity,
01688           exception);
01689         (void) RiemersmaDither(image,image_view,cube_info,EastGravity,
01690           exception);
01691         break;
01692       }
01693       case NorthGravity:
01694       {
01695         (void) RiemersmaDither(image,image_view,cube_info,SouthGravity,
01696           exception);
01697         (void) RiemersmaDither(image,image_view,cube_info,EastGravity,
01698           exception);
01699         (void) RiemersmaDither(image,image_view,cube_info,NorthGravity,
01700           exception);
01701         break;
01702       }
01703       case SouthGravity:
01704       {
01705         (void) RiemersmaDither(image,image_view,cube_info,NorthGravity,
01706           exception);
01707         (void) RiemersmaDither(image,image_view,cube_info,WestGravity,
01708           exception);
01709         (void) RiemersmaDither(image,image_view,cube_info,SouthGravity,
01710           exception);
01711         break;
01712       }
01713       default:
01714         break;
01715     }
01716   else
01717     switch (direction)
01718     {
01719       case WestGravity:
01720       {
01721         Riemersma(image,image_view,cube_info,level-1,NorthGravity,
01722           exception);
01723         (void) RiemersmaDither(image,image_view,cube_info,EastGravity,
01724           exception);
01725         Riemersma(image,image_view,cube_info,level-1,WestGravity,
01726           exception);
01727         (void) RiemersmaDither(image,image_view,cube_info,SouthGravity,
01728           exception);
01729         Riemersma(image,image_view,cube_info,level-1,WestGravity,
01730           exception);
01731         (void) RiemersmaDither(image,image_view,cube_info,WestGravity,
01732           exception);
01733         Riemersma(image,image_view,cube_info,level-1,SouthGravity,
01734           exception);
01735         break;
01736       }
01737       case EastGravity:
01738       {
01739         Riemersma(image,image_view,cube_info,level-1,SouthGravity,
01740           exception);
01741         (void) RiemersmaDither(image,image_view,cube_info,WestGravity,
01742           exception);
01743         Riemersma(image,image_view,cube_info,level-1,EastGravity,
01744           exception);
01745         (void) RiemersmaDither(image,image_view,cube_info,NorthGravity,
01746           exception);
01747         Riemersma(image,image_view,cube_info,level-1,EastGravity,
01748           exception);
01749         (void) RiemersmaDither(image,image_view,cube_info,EastGravity,
01750           exception);
01751         Riemersma(image,image_view,cube_info,level-1,NorthGravity,
01752           exception);
01753         break;
01754       }
01755       case NorthGravity:
01756       {
01757         Riemersma(image,image_view,cube_info,level-1,WestGravity,
01758           exception);
01759         (void) RiemersmaDither(image,image_view,cube_info,SouthGravity,
01760           exception);
01761         Riemersma(image,image_view,cube_info,level-1,NorthGravity,
01762           exception);
01763         (void) RiemersmaDither(image,image_view,cube_info,EastGravity,
01764           exception);
01765         Riemersma(image,image_view,cube_info,level-1,NorthGravity,
01766           exception);
01767         (void) RiemersmaDither(image,image_view,cube_info,NorthGravity,
01768           exception);
01769         Riemersma(image,image_view,cube_info,level-1,EastGravity,
01770           exception);
01771         break;
01772       }
01773       case SouthGravity:
01774       {
01775         Riemersma(image,image_view,cube_info,level-1,EastGravity,
01776           exception);
01777         (void) RiemersmaDither(image,image_view,cube_info,NorthGravity,
01778           exception);
01779         Riemersma(image,image_view,cube_info,level-1,SouthGravity,
01780           exception);
01781         (void) RiemersmaDither(image,image_view,cube_info,WestGravity,
01782           exception);
01783         Riemersma(image,image_view,cube_info,level-1,SouthGravity,
01784           exception);
01785         (void) RiemersmaDither(image,image_view,cube_info,SouthGravity,
01786           exception);
01787         Riemersma(image,image_view,cube_info,level-1,WestGravity,
01788           exception);
01789         break;
01790       }
01791       default:
01792         break;
01793     }
01794 }
01795 
01796 static MagickBooleanType RiemersmaDither(Image *image,CacheView *image_view,
01797   CubeInfo *cube_info,const unsigned int direction,ExceptionInfo *exception)
01798 {
01799 #define DitherImageTag  "Dither/Image"
01800 
01801   MagickBooleanType
01802     proceed;
01803 
01804   RealPixelInfo
01805     color,
01806     pixel;
01807 
01808   register CubeInfo
01809     *p;
01810 
01811   size_t
01812     index;
01813 
01814   p=cube_info;
01815   if ((p->x >= 0) && (p->x < (ssize_t) image->columns) &&
01816       (p->y >= 0) && (p->y < (ssize_t) image->rows))
01817     {
01818       register Quantum
01819         *restrict q;
01820 
01821       register ssize_t
01822         i;
01823 
01824       /*
01825         Distribute error.
01826       */
01827       q=GetCacheViewAuthenticPixels(image_view,p->x,p->y,1,1,exception);
01828       if (q == (Quantum *) NULL)
01829         return(MagickFalse);
01830       AssociateAlphaPixel(image,cube_info,q,&pixel);
01831       for (i=0; i < ErrorQueueLength; i++)
01832       {
01833         pixel.red+=p->weights[i]*p->error[i].red;
01834         pixel.green+=p->weights[i]*p->error[i].green;
01835         pixel.blue+=p->weights[i]*p->error[i].blue;
01836         if (cube_info->associate_alpha != MagickFalse)
01837           pixel.alpha+=p->weights[i]*p->error[i].alpha;
01838       }
01839       pixel.red=(MagickRealType) ClampToUnsignedQuantum(pixel.red);
01840       pixel.green=(MagickRealType) ClampToUnsignedQuantum(pixel.green);
01841       pixel.blue=(MagickRealType) ClampToUnsignedQuantum(pixel.blue);
01842       if (cube_info->associate_alpha != MagickFalse)
01843         pixel.alpha=(MagickRealType) ClampToUnsignedQuantum(pixel.alpha);
01844       i=CacheOffset(cube_info,&pixel);
01845       if (p->cache[i] < 0)
01846         {
01847           register NodeInfo
01848             *node_info;
01849 
01850           register size_t
01851             id;
01852 
01853           /*
01854             Identify the deepest node containing the pixel's color.
01855           */
01856           node_info=p->root;
01857           for (index=MaxTreeDepth-1; (ssize_t) index > 0; index--)
01858           {
01859             id=ColorToNodeId(cube_info,&pixel,index);
01860             if (node_info->child[id] == (NodeInfo *) NULL)
01861               break;
01862             node_info=node_info->child[id];
01863           }
01864           node_info=node_info->parent;
01865           /*
01866             Find closest color among siblings and their children.
01867           */
01868           p->target=pixel;
01869           p->distance=(MagickRealType) (4.0*(QuantumRange+1.0)*((MagickRealType)
01870             QuantumRange+1.0)+1.0);
01871           ClosestColor(image,p,node_info->parent);
01872           p->cache[i]=(ssize_t) p->color_number;
01873         }
01874       /*
01875         Assign pixel to closest colormap entry.
01876       */
01877       index=(size_t) p->cache[i];
01878       if (image->storage_class == PseudoClass)
01879         SetPixelIndex(image,(Quantum) index,q);
01880       if (cube_info->quantize_info->measure_error == MagickFalse)
01881         {
01882           SetPixelRed(image,image->colormap[index].red,q);
01883           SetPixelGreen(image,image->colormap[index].green,q);
01884           SetPixelBlue(image,image->colormap[index].blue,q);
01885           if (cube_info->associate_alpha != MagickFalse)
01886             SetPixelAlpha(image,image->colormap[index].alpha,q);
01887         }
01888       if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
01889         return(MagickFalse);
01890       /*
01891         Propagate the error as the last entry of the error queue.
01892       */
01893       (void) CopyMagickMemory(p->error,p->error+1,(ErrorQueueLength-1)*
01894         sizeof(p->error[0]));
01895       AssociateAlphaPixelInfo(image,cube_info,image->colormap+index,&color);
01896       p->error[ErrorQueueLength-1].red=pixel.red-color.red;
01897       p->error[ErrorQueueLength-1].green=pixel.green-color.green;
01898       p->error[ErrorQueueLength-1].blue=pixel.blue-color.blue;
01899       if (cube_info->associate_alpha != MagickFalse)
01900         p->error[ErrorQueueLength-1].alpha=pixel.alpha-color.alpha;
01901       proceed=SetImageProgress(image,DitherImageTag,p->offset,p->span);
01902       if (proceed == MagickFalse)
01903         return(MagickFalse);
01904       p->offset++;
01905     }
01906   switch (direction)
01907   {
01908     case WestGravity: p->x--; break;
01909     case EastGravity: p->x++; break;
01910     case NorthGravity: p->y--; break;
01911     case SouthGravity: p->y++; break;
01912   }
01913   return(MagickTrue);
01914 }
01915 
01916 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
01917 {
01918   if (x > y)
01919     return(x);
01920   return(y);
01921 }
01922 
01923 static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
01924 {
01925   if (x < y)
01926     return(x);
01927   return(y);
01928 }
01929 
01930 static MagickBooleanType DitherImage(Image *image,CubeInfo *cube_info,
01931   ExceptionInfo *exception)
01932 {
01933   CacheView
01934     *image_view;
01935 
01936   MagickBooleanType
01937     status;
01938 
01939   register ssize_t
01940     i;
01941 
01942   size_t
01943     depth;
01944 
01945   if (cube_info->quantize_info->dither_method != RiemersmaDitherMethod)
01946     return(FloydSteinbergDither(image,cube_info,exception));
01947   /*
01948     Distribute quantization error along a Hilbert curve.
01949   */
01950   (void) ResetMagickMemory(cube_info->error,0,ErrorQueueLength*
01951     sizeof(*cube_info->error));
01952   cube_info->x=0;
01953   cube_info->y=0;
01954   i=MagickMax((ssize_t) image->columns,(ssize_t) image->rows);
01955   for (depth=1; i != 0; depth++)
01956     i>>=1;
01957   if ((ssize_t) (1L << depth) < MagickMax((ssize_t) image->columns,(ssize_t) image->rows))
01958     depth++;
01959   cube_info->offset=0;
01960   cube_info->span=(MagickSizeType) image->columns*image->rows;
01961   image_view=AcquireCacheView(image);
01962   if (depth > 1)
01963     Riemersma(image,image_view,cube_info,depth-1,NorthGravity,exception);
01964   status=RiemersmaDither(image,image_view,cube_info,ForgetGravity,exception);
01965   image_view=DestroyCacheView(image_view);
01966   return(status);
01967 }
01968 
01969 /*
01970 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01971 %                                                                             %
01972 %                                                                             %
01973 %                                                                             %
01974 +   G e t C u b e I n f o                                                     %
01975 %                                                                             %
01976 %                                                                             %
01977 %                                                                             %
01978 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01979 %
01980 %  GetCubeInfo() initialize the Cube data structure.
01981 %
01982 %  The format of the GetCubeInfo method is:
01983 %
01984 %      CubeInfo GetCubeInfo(const QuantizeInfo *quantize_info,
01985 %        const size_t depth,const size_t maximum_colors)
01986 %
01987 %  A description of each parameter follows.
01988 %
01989 %    o quantize_info: Specifies a pointer to an QuantizeInfo structure.
01990 %
01991 %    o depth: Normally, this integer value is zero or one.  A zero or
01992 %      one tells Quantize to choose a optimal tree depth of Log4(number_colors).
01993 %      A tree of this depth generally allows the best representation of the
01994 %      reference image with the least amount of memory and the fastest
01995 %      computational speed.  In some cases, such as an image with low color
01996 %      dispersion (a few number of colors), a value other than
01997 %      Log4(number_colors) is required.  To expand the color tree completely,
01998 %      use a value of 8.
01999 %
02000 %    o maximum_colors: maximum colors.
02001 %
02002 */
02003 static CubeInfo *GetCubeInfo(const QuantizeInfo *quantize_info,
02004   const size_t depth,const size_t maximum_colors)
02005 {
02006   CubeInfo
02007     *cube_info;
02008 
02009   MagickRealType
02010     sum,
02011     weight;
02012 
02013   register ssize_t
02014     i;
02015 
02016   size_t
02017     length;
02018 
02019   /*
02020     Initialize tree to describe color cube_info.
02021   */
02022   cube_info=(CubeInfo *) AcquireMagickMemory(sizeof(*cube_info));
02023   if (cube_info == (CubeInfo *) NULL)
02024     return((CubeInfo *) NULL);
02025   (void) ResetMagickMemory(cube_info,0,sizeof(*cube_info));
02026   cube_info->depth=depth;
02027   if (cube_info->depth > MaxTreeDepth)
02028     cube_info->depth=MaxTreeDepth;
02029   if (cube_info->depth < 2)
02030     cube_info->depth=2;
02031   cube_info->maximum_colors=maximum_colors;
02032   /*
02033     Initialize root node.
02034   */
02035   cube_info->root=GetNodeInfo(cube_info,0,0,(NodeInfo *) NULL);
02036   if (cube_info->root == (NodeInfo *) NULL)
02037     return((CubeInfo *) NULL);
02038   cube_info->root->parent=cube_info->root;
02039   cube_info->quantize_info=CloneQuantizeInfo(quantize_info);
02040   if (cube_info->quantize_info->dither == MagickFalse)
02041     return(cube_info);
02042   /*
02043     Initialize dither resources.
02044   */
02045   length=(size_t) (1UL << (4*(8-CacheShift)));
02046   cube_info->cache=(ssize_t *) AcquireQuantumMemory(length,
02047     sizeof(*cube_info->cache));
02048   if (cube_info->cache == (ssize_t *) NULL)
02049     return((CubeInfo *) NULL);
02050   /*
02051     Initialize color cache.
02052   */
02053   for (i=0; i < (ssize_t) length; i++)
02054     cube_info->cache[i]=(-1);
02055   /*
02056     Distribute weights along a curve of exponential decay.
02057   */
02058   weight=1.0;
02059   for (i=0; i < ErrorQueueLength; i++)
02060   {
02061     cube_info->weights[ErrorQueueLength-i-1]=1.0/weight;
02062     weight*=exp(log(((double) QuantumRange+1.0))/(ErrorQueueLength-1.0));
02063   }
02064   /*
02065     Normalize the weighting factors.
02066   */
02067   weight=0.0;
02068   for (i=0; i < ErrorQueueLength; i++)
02069     weight+=cube_info->weights[i];
02070   sum=0.0;
02071   for (i=0; i < ErrorQueueLength; i++)
02072   {
02073     cube_info->weights[i]/=weight;
02074     sum+=cube_info->weights[i];
02075   }
02076   cube_info->weights[0]+=1.0-sum;
02077   return(cube_info);
02078 }
02079 
02080 /*
02081 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02082 %                                                                             %
02083 %                                                                             %
02084 %                                                                             %
02085 +   G e t N o d e I n f o                                                     %
02086 %                                                                             %
02087 %                                                                             %
02088 %                                                                             %
02089 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02090 %
02091 %  GetNodeInfo() allocates memory for a new node in the color cube tree and
02092 %  presets all fields to zero.
02093 %
02094 %  The format of the GetNodeInfo method is:
02095 %
02096 %      NodeInfo *GetNodeInfo(CubeInfo *cube_info,const size_t id,
02097 %        const size_t level,NodeInfo *parent)
02098 %
02099 %  A description of each parameter follows.
02100 %
02101 %    o node: The GetNodeInfo method returns a pointer to a queue of nodes.
02102 %
02103 %    o id: Specifies the child number of the node.
02104 %
02105 %    o level: Specifies the level in the storage_class the node resides.
02106 %
02107 */
02108 static NodeInfo *GetNodeInfo(CubeInfo *cube_info,const size_t id,
02109   const size_t level,NodeInfo *parent)
02110 {
02111   NodeInfo
02112     *node_info;
02113 
02114   if (cube_info->free_nodes == 0)
02115     {
02116       Nodes
02117         *nodes;
02118 
02119       /*
02120         Allocate a new queue of nodes.
02121       */
02122       nodes=(Nodes *) AcquireMagickMemory(sizeof(*nodes));
02123       if (nodes == (Nodes *) NULL)
02124         return((NodeInfo *) NULL);
02125       nodes->nodes=(NodeInfo *) AcquireQuantumMemory(NodesInAList,
02126         sizeof(*nodes->nodes));
02127       if (nodes->nodes == (NodeInfo *) NULL)
02128         return((NodeInfo *) NULL);
02129       nodes->next=cube_info->node_queue;
02130       cube_info->node_queue=nodes;
02131       cube_info->next_node=nodes->nodes;
02132       cube_info->free_nodes=NodesInAList;
02133     }
02134   cube_info->nodes++;
02135   cube_info->free_nodes--;
02136   node_info=cube_info->next_node++;
02137   (void) ResetMagickMemory(node_info,0,sizeof(*node_info));
02138   node_info->parent=parent;
02139   node_info->id=id;
02140   node_info->level=level;
02141   return(node_info);
02142 }
02143 
02144 /*
02145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02146 %                                                                             %
02147 %                                                                             %
02148 %                                                                             %
02149 %  G e t I m a g e Q u a n t i z e E r r o r                                  %
02150 %                                                                             %
02151 %                                                                             %
02152 %                                                                             %
02153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02154 %
02155 %  GetImageQuantizeError() measures the difference between the original
02156 %  and quantized images.  This difference is the total quantization error.
02157 %  The error is computed by summing over all pixels in an image the distance
02158 %  squared in RGB space between each reference pixel value and its quantized
02159 %  value.  These values are computed:
02160 %
02161 %    o mean_error_per_pixel:  This value is the mean error for any single
02162 %      pixel in the image.
02163 %
02164 %    o normalized_mean_square_error:  This value is the normalized mean
02165 %      quantization error for any single pixel in the image.  This distance
02166 %      measure is normalized to a range between 0 and 1.  It is independent
02167 %      of the range of red, green, and blue values in the image.
02168 %
02169 %    o normalized_maximum_square_error:  Thsi value is the normalized
02170 %      maximum quantization error for any single pixel in the image.  This
02171 %      distance measure is normalized to a range between 0 and 1.  It is
02172 %      independent of the range of red, green, and blue values in your image.
02173 %
02174 %  The format of the GetImageQuantizeError method is:
02175 %
02176 %      MagickBooleanType GetImageQuantizeError(Image *image,
02177 %        ExceptionInfo *exception)
02178 %
02179 %  A description of each parameter follows.
02180 %
02181 %    o image: the image.
02182 %
02183 %    o exception: return any errors or warnings in this structure.
02184 %
02185 */
02186 MagickExport MagickBooleanType GetImageQuantizeError(Image *image,
02187   ExceptionInfo *exception)
02188 {
02189   CacheView
02190     *image_view;
02191 
02192   MagickRealType
02193     alpha,
02194     area,
02195     beta,
02196     distance,
02197     maximum_error,
02198     mean_error,
02199     mean_error_per_pixel;
02200 
02201   size_t
02202     index;
02203 
02204   ssize_t
02205     y;
02206 
02207   assert(image != (Image *) NULL);
02208   assert(image->signature == MagickSignature);
02209   if (image->debug != MagickFalse)
02210     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02211   image->total_colors=GetNumberColors(image,(FILE *) NULL,exception);
02212   (void) ResetMagickMemory(&image->error,0,sizeof(image->error));
02213   if (image->storage_class == DirectClass)
02214     return(MagickTrue);
02215   alpha=1.0;
02216   beta=1.0;
02217   area=3.0*image->columns*image->rows;
02218   maximum_error=0.0;
02219   mean_error_per_pixel=0.0;
02220   mean_error=0.0;
02221   image_view=AcquireCacheView(image);
02222   for (y=0; y < (ssize_t) image->rows; y++)
02223   {
02224     register const Quantum
02225       *restrict p;
02226 
02227     register ssize_t
02228       x;
02229 
02230     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
02231     if (p == (const Quantum *) NULL)
02232       break;
02233     for (x=0; x < (ssize_t) image->columns; x++)
02234     {
02235       index=1UL*GetPixelIndex(image,p);
02236       if (image->matte != MagickFalse)
02237         {
02238           alpha=(MagickRealType) (QuantumScale*GetPixelAlpha(image,p));
02239           beta=(MagickRealType) (QuantumScale*image->colormap[index].alpha);
02240         }
02241       distance=fabs(alpha*GetPixelRed(image,p)-beta*
02242         image->colormap[index].red);
02243       mean_error_per_pixel+=distance;
02244       mean_error+=distance*distance;
02245       if (distance > maximum_error)
02246         maximum_error=distance;
02247       distance=fabs(alpha*GetPixelGreen(image,p)-beta*
02248         image->colormap[index].green);
02249       mean_error_per_pixel+=distance;
02250       mean_error+=distance*distance;
02251       if (distance > maximum_error)
02252         maximum_error=distance;
02253       distance=fabs(alpha*GetPixelBlue(image,p)-beta*
02254         image->colormap[index].blue);
02255       mean_error_per_pixel+=distance;
02256       mean_error+=distance*distance;
02257       if (distance > maximum_error)
02258         maximum_error=distance;
02259       p+=GetPixelChannels(image);
02260     }
02261   }
02262   image_view=DestroyCacheView(image_view);
02263   image->error.mean_error_per_pixel=(double) mean_error_per_pixel/area;
02264   image->error.normalized_mean_error=(double) QuantumScale*QuantumScale*
02265     mean_error/area;
02266   image->error.normalized_maximum_error=(double) QuantumScale*maximum_error;
02267   return(MagickTrue);
02268 }
02269 
02270 /*
02271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02272 %                                                                             %
02273 %                                                                             %
02274 %                                                                             %
02275 %   G e t Q u a n t i z e I n f o                                             %
02276 %                                                                             %
02277 %                                                                             %
02278 %                                                                             %
02279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02280 %
02281 %  GetQuantizeInfo() initializes the QuantizeInfo structure.
02282 %
02283 %  The format of the GetQuantizeInfo method is:
02284 %
02285 %      GetQuantizeInfo(QuantizeInfo *quantize_info)
02286 %
02287 %  A description of each parameter follows:
02288 %
02289 %    o quantize_info: Specifies a pointer to a QuantizeInfo structure.
02290 %
02291 */
02292 MagickExport void GetQuantizeInfo(QuantizeInfo *quantize_info)
02293 {
02294   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02295   assert(quantize_info != (QuantizeInfo *) NULL);
02296   (void) ResetMagickMemory(quantize_info,0,sizeof(*quantize_info));
02297   quantize_info->number_colors=256;
02298   quantize_info->dither=MagickTrue;
02299   quantize_info->dither_method=RiemersmaDitherMethod;
02300   quantize_info->colorspace=UndefinedColorspace;
02301   quantize_info->measure_error=MagickFalse;
02302   quantize_info->signature=MagickSignature;
02303 }
02304 
02305 /*
02306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02307 %                                                                             %
02308 %                                                                             %
02309 %                                                                             %
02310 %     P o s t e r i z e I m a g e                                             %
02311 %                                                                             %
02312 %                                                                             %
02313 %                                                                             %
02314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02315 %
02316 %  PosterizeImage() reduces the image to a limited number of colors for a
02317 %  "poster" effect.
02318 %
02319 %  The format of the PosterizeImage method is:
02320 %
02321 %      MagickBooleanType PosterizeImage(Image *image,const size_t levels,
02322 %        const MagickBooleanType dither,ExceptionInfo *exception)
02323 %
02324 %  A description of each parameter follows:
02325 %
02326 %    o image: Specifies a pointer to an Image structure.
02327 %
02328 %    o levels: Number of color levels allowed in each channel.  Very low values
02329 %      (2, 3, or 4) have the most visible effect.
02330 %
02331 %    o dither: Set this integer value to something other than zero to dither
02332 %      the mapped image.
02333 %
02334 %    o exception: return any errors or warnings in this structure.
02335 %
02336 */
02337 
02338 static inline ssize_t MagickRound(MagickRealType x)
02339 {
02340   /*
02341     Round the fraction to nearest integer.
02342   */
02343   if (x >= 0.0)
02344     return((ssize_t) (x+0.5));
02345   return((ssize_t) (x-0.5));
02346 }
02347 
02348 MagickExport MagickBooleanType PosterizeImage(Image *image,const size_t levels,
02349   const MagickBooleanType dither,ExceptionInfo *exception)
02350 {
02351 #define PosterizeImageTag  "Posterize/Image"
02352 #define PosterizePixel(pixel) (Quantum) (QuantumRange*(MagickRound( \
02353   QuantumScale*pixel*(levels-1)))/MagickMax((ssize_t) levels-1,1))
02354 
02355   CacheView
02356     *image_view;
02357 
02358   MagickBooleanType
02359     status;
02360 
02361   MagickOffsetType
02362     progress;
02363 
02364   QuantizeInfo
02365     *quantize_info;
02366 
02367   register ssize_t
02368     i;
02369 
02370   ssize_t
02371     y;
02372 
02373   assert(image != (Image *) NULL);
02374   assert(image->signature == MagickSignature);
02375   if (image->debug != MagickFalse)
02376     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02377   if (image->storage_class == PseudoClass)
02378 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02379     #pragma omp parallel for schedule(static,4) shared(progress,status)
02380 #endif
02381     for (i=0; i < (ssize_t) image->colors; i++)
02382     {
02383       /*
02384         Posterize colormap.
02385       */
02386       if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
02387         image->colormap[i].red=PosterizePixel(image->colormap[i].red);
02388       if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
02389         image->colormap[i].green=PosterizePixel(image->colormap[i].green);
02390       if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
02391         image->colormap[i].blue=PosterizePixel(image->colormap[i].blue);
02392       if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
02393         image->colormap[i].alpha=PosterizePixel(image->colormap[i].alpha);
02394     }
02395   /*
02396     Posterize image.
02397   */
02398   status=MagickTrue;
02399   progress=0;
02400   image_view=AcquireCacheView(image);
02401 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02402   #pragma omp parallel for schedule(static,4) shared(progress,status)
02403 #endif
02404   for (y=0; y < (ssize_t) image->rows; y++)
02405   {
02406     register Quantum
02407       *restrict q;
02408 
02409     register ssize_t
02410       x;
02411 
02412     if (status == MagickFalse)
02413       continue;
02414     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
02415     if (q == (Quantum *) NULL)
02416       {
02417         status=MagickFalse;
02418         continue;
02419       }
02420     for (x=0; x < (ssize_t) image->columns; x++)
02421     {
02422       if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
02423         SetPixelRed(image,PosterizePixel(GetPixelRed(image,q)),q);
02424       if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
02425         SetPixelGreen(image,PosterizePixel(GetPixelGreen(image,q)),q);
02426       if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
02427         SetPixelBlue(image,PosterizePixel(GetPixelBlue(image,q)),q);
02428       if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
02429           (image->colorspace == CMYKColorspace))
02430         SetPixelBlack(image,PosterizePixel(GetPixelBlack(image,q)),q);
02431       if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
02432           (image->matte == MagickTrue))
02433         SetPixelAlpha(image,PosterizePixel(GetPixelAlpha(image,q)),q);
02434       q+=GetPixelChannels(image);
02435     }
02436     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
02437       status=MagickFalse;
02438     if (image->progress_monitor != (MagickProgressMonitor) NULL)
02439       {
02440         MagickBooleanType
02441           proceed;
02442 
02443 #if defined(MAGICKCORE_OPENMP_SUPPORT)
02444         #pragma omp critical (MagickCore_PosterizeImage)
02445 #endif
02446         proceed=SetImageProgress(image,PosterizeImageTag,progress++,
02447           image->rows);
02448         if (proceed == MagickFalse)
02449           status=MagickFalse;
02450       }
02451   }
02452   image_view=DestroyCacheView(image_view);
02453   quantize_info=AcquireQuantizeInfo((ImageInfo *) NULL);
02454   quantize_info->number_colors=(size_t) MagickMin((ssize_t) levels*levels*
02455     levels,MaxColormapSize+1);
02456   quantize_info->dither=dither;
02457   quantize_info->tree_depth=MaxTreeDepth;
02458   status=QuantizeImage(quantize_info,image,exception);
02459   quantize_info=DestroyQuantizeInfo(quantize_info);
02460   return(status);
02461 }
02462 
02463 /*
02464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02465 %                                                                             %
02466 %                                                                             %
02467 %                                                                             %
02468 +   P r u n e C h i l d                                                       %
02469 %                                                                             %
02470 %                                                                             %
02471 %                                                                             %
02472 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02473 %
02474 %  PruneChild() deletes the given node and merges its statistics into its
02475 %  parent.
02476 %
02477 %  The format of the PruneSubtree method is:
02478 %
02479 %      PruneChild(const Image *image,CubeInfo *cube_info,
02480 %        const NodeInfo *node_info)
02481 %
02482 %  A description of each parameter follows.
02483 %
02484 %    o image: the image.
02485 %
02486 %    o cube_info: A pointer to the Cube structure.
02487 %
02488 %    o node_info: pointer to node in color cube tree that is to be pruned.
02489 %
02490 */
02491 static void PruneChild(const Image *image,CubeInfo *cube_info,
02492   const NodeInfo *node_info)
02493 {
02494   NodeInfo
02495     *parent;
02496 
02497   register ssize_t
02498     i;
02499 
02500   size_t
02501     number_children;
02502 
02503   /*
02504     Traverse any children.
02505   */
02506   number_children=cube_info->associate_alpha == MagickFalse ? 8UL : 16UL;
02507   for (i=0; i < (ssize_t) number_children; i++)
02508     if (node_info->child[i] != (NodeInfo *) NULL)
02509       PruneChild(image,cube_info,node_info->child[i]);
02510   /*
02511     Merge color statistics into parent.
02512   */
02513   parent=node_info->parent;
02514   parent->number_unique+=node_info->number_unique;
02515   parent->total_color.red+=node_info->total_color.red;
02516   parent->total_color.green+=node_info->total_color.green;
02517   parent->total_color.blue+=node_info->total_color.blue;
02518   parent->total_color.alpha+=node_info->total_color.alpha;
02519   parent->child[node_info->id]=(NodeInfo *) NULL;
02520   cube_info->nodes--;
02521 }
02522 
02523 /*
02524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02525 %                                                                             %
02526 %                                                                             %
02527 %                                                                             %
02528 +  P r u n e L e v e l                                                        %
02529 %                                                                             %
02530 %                                                                             %
02531 %                                                                             %
02532 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02533 %
02534 %  PruneLevel() deletes all nodes at the bottom level of the color tree merging
02535 %  their color statistics into their parent node.
02536 %
02537 %  The format of the PruneLevel method is:
02538 %
02539 %      PruneLevel(const Image *image,CubeInfo *cube_info,
02540 %        const NodeInfo *node_info)
02541 %
02542 %  A description of each parameter follows.
02543 %
02544 %    o image: the image.
02545 %
02546 %    o cube_info: A pointer to the Cube structure.
02547 %
02548 %    o node_info: pointer to node in color cube tree that is to be pruned.
02549 %
02550 */
02551 static void PruneLevel(const Image *image,CubeInfo *cube_info,
02552   const NodeInfo *node_info)
02553 {
02554   register ssize_t
02555     i;
02556 
02557   size_t
02558     number_children;
02559 
02560   /*
02561     Traverse any children.
02562   */
02563   number_children=cube_info->associate_alpha == MagickFalse ? 8UL : 16UL;
02564   for (i=0; i < (ssize_t) number_children; i++)
02565     if (node_info->child[i] != (NodeInfo *) NULL)
02566       PruneLevel(image,cube_info,node_info->child[i]);
02567   if (node_info->level == cube_info->depth)
02568     PruneChild(image,cube_info,node_info);
02569 }
02570 
02571 /*
02572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02573 %                                                                             %
02574 %                                                                             %
02575 %                                                                             %
02576 +  P r u n e T o C u b e D e p t h                                            %
02577 %                                                                             %
02578 %                                                                             %
02579 %                                                                             %
02580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02581 %
02582 %  PruneToCubeDepth() deletes any nodes at a depth greater than
02583 %  cube_info->depth while merging their color statistics into their parent
02584 %  node.
02585 %
02586 %  The format of the PruneToCubeDepth method is:
02587 %
02588 %      PruneToCubeDepth(const Image *image,CubeInfo *cube_info,
02589 %        const NodeInfo *node_info)
02590 %
02591 %  A description of each parameter follows.
02592 %
02593 %    o cube_info: A pointer to the Cube structure.
02594 %
02595 %    o node_info: pointer to node in color cube tree that is to be pruned.
02596 %
02597 */
02598 static void PruneToCubeDepth(const Image *image,CubeInfo *cube_info,
02599   const NodeInfo *node_info)
02600 {
02601   register ssize_t
02602     i;
02603 
02604   size_t
02605     number_children;
02606 
02607   /*
02608     Traverse any children.
02609   */
02610   number_children=cube_info->associate_alpha == MagickFalse ? 8UL : 16UL;
02611   for (i=0; i < (ssize_t) number_children; i++)
02612     if (node_info->child[i] != (NodeInfo *) NULL)
02613       PruneToCubeDepth(image,cube_info,node_info->child[i]);
02614   if (node_info->level > cube_info->depth)
02615     PruneChild(image,cube_info,node_info);
02616 }
02617 
02618 /*
02619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02620 %                                                                             %
02621 %                                                                             %
02622 %                                                                             %
02623 %  Q u a n t i z e I m a g e                                                  %
02624 %                                                                             %
02625 %                                                                             %
02626 %                                                                             %
02627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02628 %
02629 %  QuantizeImage() analyzes the colors within a reference image and chooses a
02630 %  fixed number of colors to represent the image.  The goal of the algorithm
02631 %  is to minimize the color difference between the input and output image while
02632 %  minimizing the processing time.
02633 %
02634 %  The format of the QuantizeImage method is:
02635 %
02636 %      MagickBooleanType QuantizeImage(const QuantizeInfo *quantize_info,
02637 %        Image *image,ExceptionInfo *exception)
02638 %
02639 %  A description of each parameter follows:
02640 %
02641 %    o quantize_info: Specifies a pointer to an QuantizeInfo structure.
02642 %
02643 %    o image: the image.
02644 %
02645 %    o exception: return any errors or warnings in this structure.
02646 %
02647 */
02648 
02649 static MagickBooleanType DirectToColormapImage(Image *image,
02650   ExceptionInfo *exception)
02651 {
02652   CacheView
02653     *image_view;
02654 
02655   MagickBooleanType
02656     status;
02657 
02658   register ssize_t
02659     i;
02660 
02661   size_t
02662     number_colors;
02663 
02664   ssize_t
02665     y;
02666 
02667   status=MagickTrue;
02668   number_colors=(size_t) (image->columns*image->rows);
02669   if (AcquireImageColormap(image,number_colors,exception) == MagickFalse)
02670     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
02671       image->filename);
02672   if (image->colors != number_colors)
02673     return(MagickFalse);
02674   i=0;
02675   image_view=AcquireCacheView(image);
02676   for (y=0; y < (ssize_t) image->rows; y++)
02677   {
02678     MagickBooleanType
02679       proceed;
02680 
02681     register Quantum
02682       *restrict q;
02683 
02684     register ssize_t
02685       x;
02686 
02687     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
02688     if (q == (Quantum *) NULL)
02689       break;
02690     for (x=0; x < (ssize_t) image->columns; x++)
02691     {
02692       image->colormap[i].red=GetPixelRed(image,q);
02693       image->colormap[i].green=GetPixelGreen(image,q);
02694       image->colormap[i].blue=GetPixelBlue(image,q);
02695       image->colormap[i].alpha=GetPixelAlpha(image,q);
02696       SetPixelIndex(image,(Quantum) i,q);
02697       i++;
02698       q+=GetPixelChannels(image);
02699     }
02700     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
02701       break;
02702     proceed=SetImageProgress(image,AssignImageTag,(MagickOffsetType) y,
02703       image->rows);
02704     if (proceed == MagickFalse)
02705       status=MagickFalse;
02706   }
02707   image_view=DestroyCacheView(image_view);
02708   return(status);
02709 }
02710 
02711 MagickExport MagickBooleanType QuantizeImage(const QuantizeInfo *quantize_info,
02712   Image *image,ExceptionInfo *exception)
02713 {
02714   CubeInfo
02715     *cube_info;
02716 
02717   MagickBooleanType
02718     status;
02719 
02720   size_t
02721     depth,
02722     maximum_colors;
02723 
02724   assert(quantize_info != (const QuantizeInfo *) NULL);
02725   assert(quantize_info->signature == MagickSignature);
02726   assert(image != (Image *) NULL);
02727   assert(image->signature == MagickSignature);
02728   if (image->debug != MagickFalse)
02729     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02730   maximum_colors=quantize_info->number_colors;
02731   if (maximum_colors == 0)
02732     maximum_colors=MaxColormapSize;
02733   if (maximum_colors > MaxColormapSize)
02734     maximum_colors=MaxColormapSize;
02735   if ((image->columns*image->rows) <= maximum_colors)
02736     (void) DirectToColormapImage(image,exception);
02737   if ((IsImageGray(image,exception) != MagickFalse) &&
02738       (image->matte == MagickFalse))
02739     (void) SetGrayscaleImage(image,exception);
02740   if ((image->storage_class == PseudoClass) &&
02741       (image->colors <= maximum_colors))
02742     return(MagickTrue);
02743   depth=quantize_info->tree_depth;
02744   if (depth == 0)
02745     {
02746       size_t
02747         colors;
02748 
02749       /*
02750         Depth of color tree is: Log4(colormap size)+2.
02751       */
02752       colors=maximum_colors;
02753       for (depth=1; colors != 0; depth++)
02754         colors>>=2;
02755       if ((quantize_info->dither != MagickFalse) && (depth > 2))
02756         depth--;
02757       if ((image->matte != MagickFalse) && (depth > 5))
02758         depth--;
02759     }
02760   /*
02761     Initialize color cube.
02762   */
02763   cube_info=GetCubeInfo(quantize_info,depth,maximum_colors);
02764   if (cube_info == (CubeInfo *) NULL)
02765     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
02766       image->filename);
02767   status=ClassifyImageColors(cube_info,image,exception);
02768   if (status != MagickFalse)
02769     {
02770       /*
02771         Reduce the number of colors in the image.
02772       */
02773       ReduceImageColors(image,cube_info);
02774       status=AssignImageColors(image,cube_info,exception);
02775     }
02776   DestroyCubeInfo(cube_info);
02777   return(status);
02778 }
02779 
02780 /*
02781 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02782 %                                                                             %
02783 %                                                                             %
02784 %                                                                             %
02785 %   Q u a n t i z e I m a g e s                                               %
02786 %                                                                             %
02787 %                                                                             %
02788 %                                                                             %
02789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02790 %
02791 %  QuantizeImages() analyzes the colors within a set of reference images and
02792 %  chooses a fixed number of colors to represent the set.  The goal of the
02793 %  algorithm is to minimize the color difference between the input and output
02794 %  images while minimizing the processing time.
02795 %
02796 %  The format of the QuantizeImages method is:
02797 %
02798 %      MagickBooleanType QuantizeImages(const QuantizeInfo *quantize_info,
02799 %        Image *images,ExceptionInfo *exception)
02800 %
02801 %  A description of each parameter follows:
02802 %
02803 %    o quantize_info: Specifies a pointer to an QuantizeInfo structure.
02804 %
02805 %    o images: Specifies a pointer to a list of Image structures.
02806 %
02807 %    o exception: return any errors or warnings in this structure.
02808 %
02809 */
02810 MagickExport MagickBooleanType QuantizeImages(const QuantizeInfo *quantize_info,
02811   Image *images,ExceptionInfo *exception)
02812 {
02813   CubeInfo
02814     *cube_info;
02815 
02816   Image
02817     *image;
02818 
02819   MagickBooleanType
02820     proceed,
02821     status;
02822 
02823   MagickProgressMonitor
02824     progress_monitor;
02825 
02826   register ssize_t
02827     i;
02828 
02829   size_t
02830     depth,
02831     maximum_colors,
02832     number_images;
02833 
02834   assert(quantize_info != (const QuantizeInfo *) NULL);
02835   assert(quantize_info->signature == MagickSignature);
02836   assert(images != (Image *) NULL);
02837   assert(images->signature == MagickSignature);
02838   if (images->debug != MagickFalse)
02839     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
02840   if (GetNextImageInList(images) == (Image *) NULL)
02841     {
02842       /*
02843         Handle a single image with QuantizeImage.
02844       */
02845       status=QuantizeImage(quantize_info,images,exception);
02846       return(status);
02847     }
02848   status=MagickFalse;
02849   maximum_colors=quantize_info->number_colors;
02850   if (maximum_colors == 0)
02851     maximum_colors=MaxColormapSize;
02852   if (maximum_colors > MaxColormapSize)
02853     maximum_colors=MaxColormapSize;
02854   depth=quantize_info->tree_depth;
02855   if (depth == 0)
02856     {
02857       size_t
02858         colors;
02859 
02860       /*
02861         Depth of color tree is: Log4(colormap size)+2.
02862       */
02863       colors=maximum_colors;
02864       for (depth=1; colors != 0; depth++)
02865         colors>>=2;
02866       if (quantize_info->dither != MagickFalse)
02867         depth--;
02868     }
02869   /*
02870     Initialize color cube.
02871   */
02872   cube_info=GetCubeInfo(quantize_info,depth,maximum_colors);
02873   if (cube_info == (CubeInfo *) NULL)
02874     {
02875       (void) ThrowMagickException(exception,GetMagickModule(),
02876         ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
02877       return(MagickFalse);
02878     }
02879   number_images=GetImageListLength(images);
02880   image=images;
02881   for (i=0; image != (Image *) NULL; i++)
02882   {
02883     progress_monitor=SetImageProgressMonitor(image,(MagickProgressMonitor) NULL,
02884       image->client_data);
02885     status=ClassifyImageColors(cube_info,image,exception);
02886     if (status == MagickFalse)
02887       break;
02888     (void) SetImageProgressMonitor(image,progress_monitor,image->client_data);
02889     proceed=SetImageProgress(image,AssignImageTag,(MagickOffsetType) i,
02890       number_images);
02891     if (proceed == MagickFalse)
02892       break;
02893     image=GetNextImageInList(image);
02894   }
02895   if (status != MagickFalse)
02896     {
02897       /*
02898         Reduce the number of colors in an image sequence.
02899       */
02900       ReduceImageColors(images,cube_info);
02901       image=images;
02902       for (i=0; image != (Image *) NULL; i++)
02903       {
02904         progress_monitor=SetImageProgressMonitor(image,(MagickProgressMonitor)
02905           NULL,image->client_data);
02906         status=AssignImageColors(image,cube_info,exception);
02907         if (status == MagickFalse)
02908           break;
02909         (void) SetImageProgressMonitor(image,progress_monitor,
02910           image->client_data);
02911         proceed=SetImageProgress(image,AssignImageTag,(MagickOffsetType) i,
02912           number_images);
02913         if (proceed == MagickFalse)
02914           break;
02915         image=GetNextImageInList(image);
02916       }
02917     }
02918   DestroyCubeInfo(cube_info);
02919   return(status);
02920 }
02921 
02922 /*
02923 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02924 %                                                                             %
02925 %                                                                             %
02926 %                                                                             %
02927 +   R e d u c e                                                               %
02928 %                                                                             %
02929 %                                                                             %
02930 %                                                                             %
02931 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02932 %
02933 %  Reduce() traverses the color cube tree and prunes any node whose
02934 %  quantization error falls below a particular threshold.
02935 %
02936 %  The format of the Reduce method is:
02937 %
02938 %      Reduce(const Image *image,CubeInfo *cube_info,const NodeInfo *node_info)
02939 %
02940 %  A description of each parameter follows.
02941 %
02942 %    o image: the image.
02943 %
02944 %    o cube_info: A pointer to the Cube structure.
02945 %
02946 %    o node_info: pointer to node in color cube tree that is to be pruned.
02947 %
02948 */
02949 static void Reduce(const Image *image,CubeInfo *cube_info,
02950   const NodeInfo *node_info)
02951 {
02952   register ssize_t
02953     i;
02954 
02955   size_t
02956     number_children;
02957 
02958   /*
02959     Traverse any children.
02960   */
02961   number_children=cube_info->associate_alpha == MagickFalse ? 8UL : 16UL;
02962   for (i=0; i < (ssize_t) number_children; i++)
02963     if (node_info->child[i] != (NodeInfo *) NULL)
02964       Reduce(image,cube_info,node_info->child[i]);
02965   if (node_info->quantize_error <= cube_info->pruning_threshold)
02966     PruneChild(image,cube_info,node_info);
02967   else
02968     {
02969       /*
02970         Find minimum pruning threshold.
02971       */
02972       if (node_info->number_unique > 0)
02973         cube_info->colors++;
02974       if (node_info->quantize_error < cube_info->next_threshold)
02975         cube_info->next_threshold=node_info->quantize_error;
02976     }
02977 }
02978 
02979 /*
02980 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02981 %                                                                             %
02982 %                                                                             %
02983 %                                                                             %
02984 +   R e d u c e I m a g e C o l o r s                                         %
02985 %                                                                             %
02986 %                                                                             %
02987 %                                                                             %
02988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02989 %
02990 %  ReduceImageColors() repeatedly prunes the tree until the number of nodes
02991 %  with n2 > 0 is less than or equal to the maximum number of colors allowed
02992 %  in the output image.  On any given iteration over the tree, it selects
02993 %  those nodes whose E value is minimal for pruning and merges their
02994 %  color statistics upward. It uses a pruning threshold, Ep, to govern
02995 %  node selection as follows:
02996 %
02997 %    Ep = 0
02998 %    while number of nodes with (n2 > 0) > required maximum number of colors
02999 %      prune all nodes such that E <= Ep
03000 %      Set Ep to minimum E in remaining nodes
03001 %
03002 %  This has the effect of minimizing any quantization error when merging
03003 %  two nodes together.
03004 %
03005 %  When a node to be pruned has offspring, the pruning procedure invokes
03006 %  itself recursively in order to prune the tree from the leaves upward.
03007 %  n2,  Sr, Sg,  and  Sb in a node being pruned are always added to the
03008 %  corresponding data in that node's parent.  This retains the pruned
03009 %  node's color characteristics for later averaging.
03010 %
03011 %  For each node, n2 pixels exist for which that node represents the
03012 %  smallest volume in RGB space containing those pixel's colors.  When n2
03013 %  > 0 the node will uniquely define a color in the output image. At the
03014 %  beginning of reduction,  n2 = 0  for all nodes except a the leaves of
03015 %  the tree which represent colors present in the input image.
03016 %
03017 %  The other pixel count, n1, indicates the total number of colors
03018 %  within the cubic volume which the node represents.  This includes n1 -
03019 %  n2  pixels whose colors should be defined by nodes at a lower level in
03020 %  the tree.
03021 %
03022 %  The format of the ReduceImageColors method is:
03023 %
03024 %      ReduceImageColors(const Image *image,CubeInfo *cube_info)
03025 %
03026 %  A description of each parameter follows.
03027 %
03028 %    o image: the image.
03029 %
03030 %    o cube_info: A pointer to the Cube structure.
03031 %
03032 */
03033 static void ReduceImageColors(const Image *image,CubeInfo *cube_info)
03034 {
03035 #define ReduceImageTag  "Reduce/Image"
03036 
03037   MagickBooleanType
03038     proceed;
03039 
03040   MagickOffsetType
03041     offset;
03042 
03043   size_t
03044     span;
03045 
03046   cube_info->next_threshold=0.0;
03047   for (span=cube_info->colors; cube_info->colors > cube_info->maximum_colors; )
03048   {
03049     cube_info->pruning_threshold=cube_info->next_threshold;
03050     cube_info->next_threshold=cube_info->root->quantize_error-1;
03051     cube_info->colors=0;
03052     Reduce(image,cube_info,cube_info->root);
03053     offset=(MagickOffsetType) span-cube_info->colors;
03054     proceed=SetImageProgress(image,ReduceImageTag,offset,span-
03055       cube_info->maximum_colors+1);
03056     if (proceed == MagickFalse)
03057       break;
03058   }
03059 }
03060 
03061 /*
03062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03063 %                                                                             %
03064 %                                                                             %
03065 %                                                                             %
03066 %   R e m a p I m a g e                                                       %
03067 %                                                                             %
03068 %                                                                             %
03069 %                                                                             %
03070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03071 %
03072 %  RemapImage() replaces the colors of an image with a dither of the colors
03073 %  provided.
03074 %
03075 %  The format of the RemapImage method is:
03076 %
03077 %      MagickBooleanType RemapImage(const QuantizeInfo *quantize_info,
03078 %        Image *image,const Image *remap_image,ExceptionInfo *exception)
03079 %
03080 %  A description of each parameter follows:
03081 %
03082 %    o quantize_info: Specifies a pointer to an QuantizeInfo structure.
03083 %
03084 %    o image: the image.
03085 %
03086 %    o remap_image: the reference image.
03087 %
03088 %    o exception: return any errors or warnings in this structure.
03089 %
03090 */
03091 MagickExport MagickBooleanType RemapImage(const QuantizeInfo *quantize_info,
03092   Image *image,const Image *remap_image,ExceptionInfo *exception)
03093 {
03094   CubeInfo
03095     *cube_info;
03096 
03097   MagickBooleanType
03098     status;
03099 
03100   /*
03101     Initialize color cube.
03102   */
03103   assert(image != (Image *) NULL);
03104   assert(image->signature == MagickSignature);
03105   if (image->debug != MagickFalse)
03106     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03107   assert(remap_image != (Image *) NULL);
03108   assert(remap_image->signature == MagickSignature);
03109   cube_info=GetCubeInfo(quantize_info,MaxTreeDepth,
03110     quantize_info->number_colors);
03111   if (cube_info == (CubeInfo *) NULL)
03112     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
03113       image->filename);
03114   status=ClassifyImageColors(cube_info,remap_image,exception);
03115   if (status != MagickFalse)
03116     {
03117       /*
03118         Classify image colors from the reference image.
03119       */
03120       cube_info->quantize_info->number_colors=cube_info->colors;
03121       status=AssignImageColors(image,cube_info,exception);
03122     }
03123   DestroyCubeInfo(cube_info);
03124   return(status);
03125 }
03126 
03127 /*
03128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03129 %                                                                             %
03130 %                                                                             %
03131 %                                                                             %
03132 %   R e m a p I m a g e s                                                     %
03133 %                                                                             %
03134 %                                                                             %
03135 %                                                                             %
03136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03137 %
03138 %  RemapImages() replaces the colors of a sequence of images with the
03139 %  closest color from a reference image.
03140 %
03141 %  The format of the RemapImage method is:
03142 %
03143 %      MagickBooleanType RemapImages(const QuantizeInfo *quantize_info,
03144 %        Image *images,Image *remap_image,ExceptionInfo *exception)
03145 %
03146 %  A description of each parameter follows:
03147 %
03148 %    o quantize_info: Specifies a pointer to an QuantizeInfo structure.
03149 %
03150 %    o images: the image sequence.
03151 %
03152 %    o remap_image: the reference image.
03153 %
03154 %    o exception: return any errors or warnings in this structure.
03155 %
03156 */
03157 MagickExport MagickBooleanType RemapImages(const QuantizeInfo *quantize_info,
03158   Image *images,const Image *remap_image,ExceptionInfo *exception)
03159 {
03160   CubeInfo
03161     *cube_info;
03162 
03163   Image
03164     *image;
03165 
03166   MagickBooleanType
03167     status;
03168 
03169   assert(images != (Image *) NULL);
03170   assert(images->signature == MagickSignature);
03171   if (images->debug != MagickFalse)
03172     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
03173   image=images;
03174   if (remap_image == (Image *) NULL)
03175     {
03176       /*
03177         Create a global colormap for an image sequence.
03178       */
03179       status=QuantizeImages(quantize_info,images,exception);
03180       return(status);
03181     }
03182   /*
03183     Classify image colors from the reference image.
03184   */
03185   cube_info=GetCubeInfo(quantize_info,MaxTreeDepth,
03186     quantize_info->number_colors);
03187   if (cube_info == (CubeInfo *) NULL)
03188     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
03189       image->filename);
03190   status=ClassifyImageColors(cube_info,remap_image,exception);
03191   if (status != MagickFalse)
03192     {
03193       /*
03194         Classify image colors from the reference image.
03195       */
03196       cube_info->quantize_info->number_colors=cube_info->colors;
03197       image=images;
03198       for ( ; image != (Image *) NULL; image=GetNextImageInList(image))
03199       {
03200         status=AssignImageColors(image,cube_info,exception);
03201         if (status == MagickFalse)
03202           break;
03203       }
03204     }
03205   DestroyCubeInfo(cube_info);
03206   return(status);
03207 }
03208 
03209 /*
03210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03211 %                                                                             %
03212 %                                                                             %
03213 %                                                                             %
03214 %   S e t G r a y s c a l e I m a g e                                         %
03215 %                                                                             %
03216 %                                                                             %
03217 %                                                                             %
03218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03219 %
03220 %  SetGrayscaleImage() converts an image to a PseudoClass grayscale image.
03221 %
03222 %  The format of the SetGrayscaleImage method is:
03223 %
03224 %      MagickBooleanType SetGrayscaleImage(Image *image,ExceptionInfo *exeption)
03225 %
03226 %  A description of each parameter follows:
03227 %
03228 %    o image: The image.
03229 %
03230 %    o exception: return any errors or warnings in this structure.
03231 %
03232 */
03233 
03234 #if defined(__cplusplus) || defined(c_plusplus)
03235 extern "C" {
03236 #endif
03237 
03238 static int IntensityCompare(const void *x,const void *y)
03239 {
03240   PixelInfo
03241     *color_1,
03242     *color_2;
03243 
03244   ssize_t
03245     intensity;
03246 
03247   color_1=(PixelInfo *) x;
03248   color_2=(PixelInfo *) y;
03249   intensity=GetPixelInfoIntensity(color_1)-(ssize_t)
03250     GetPixelInfoIntensity(color_2);
03251   return((int) intensity);
03252 }
03253 
03254 #if defined(__cplusplus) || defined(c_plusplus)
03255 }
03256 #endif
03257 
03258 static MagickBooleanType SetGrayscaleImage(Image *image,
03259   ExceptionInfo *exception)
03260 {
03261   CacheView
03262     *image_view;
03263 
03264   MagickBooleanType
03265     status;
03266 
03267   PixelInfo
03268     *colormap;
03269 
03270   register ssize_t
03271     i;
03272 
03273   ssize_t
03274     *colormap_index,
03275     j,
03276     y;
03277 
03278   assert(image != (Image *) NULL);
03279   assert(image->signature == MagickSignature);
03280   if (image->type != GrayscaleType)
03281     (void) TransformImageColorspace(image,GRAYColorspace,exception);
03282   colormap_index=(ssize_t *) AcquireQuantumMemory(MaxMap+1,
03283     sizeof(*colormap_index));
03284   if (colormap_index == (ssize_t *) NULL)
03285     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
03286       image->filename);
03287   if (image->storage_class != PseudoClass)
03288     {
03289       for (i=0; i <= (ssize_t) MaxMap; i++)
03290         colormap_index[i]=(-1);
03291       if (AcquireImageColormap(image,MaxMap+1,exception) == MagickFalse)
03292         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
03293           image->filename);
03294       image->colors=0;
03295       status=MagickTrue;
03296       image_view=AcquireCacheView(image);
03297 #if defined(MAGICKCORE_OPENMP_SUPPORT)
03298       #pragma omp parallel for schedule(static,4) shared(status)
03299 #endif
03300       for (y=0; y < (ssize_t) image->rows; y++)
03301       {
03302         register Quantum
03303           *restrict q;
03304 
03305         register ssize_t
03306           x;
03307 
03308         if (status == MagickFalse)
03309           continue;
03310         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
03311           exception);
03312         if (q == (Quantum *) NULL)
03313           {
03314             status=MagickFalse;
03315             continue;
03316           }
03317         for (x=0; x < (ssize_t) image->columns; x++)
03318         {
03319           register size_t
03320             intensity;
03321 
03322           intensity=ScaleQuantumToMap(GetPixelRed(image,q));
03323           if (colormap_index[intensity] < 0)
03324             {
03325 #if defined(MAGICKCORE_OPENMP_SUPPORT)
03326     #pragma omp critical (MagickCore_SetGrayscaleImage)
03327 #endif
03328               if (colormap_index[intensity] < 0)
03329                 {
03330                   colormap_index[intensity]=(ssize_t) image->colors;
03331                   image->colormap[image->colors].red=GetPixelRed(image,q);
03332                   image->colormap[image->colors].green=GetPixelGreen(image,q);
03333                   image->colormap[image->colors].blue=GetPixelBlue(image,q);
03334                   image->colors++;
03335                }
03336             }
03337           SetPixelIndex(image,(Quantum) 
03338             colormap_index[intensity],q);
03339           q+=GetPixelChannels(image);
03340         }
03341         if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
03342           status=MagickFalse;
03343       }
03344       image_view=DestroyCacheView(image_view);
03345     }
03346   for (i=0; i < (ssize_t) image->colors; i++)
03347     image->colormap[i].alpha=(unsigned short) i;
03348   qsort((void *) image->colormap,image->colors,sizeof(PixelInfo),
03349     IntensityCompare);
03350   colormap=(PixelInfo *) AcquireQuantumMemory(image->colors,
03351     sizeof(*colormap));
03352   if (colormap == (PixelInfo *) NULL)
03353     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
03354       image->filename);
03355   j=0;
03356   colormap[j]=image->colormap[0];
03357   for (i=0; i < (ssize_t) image->colors; i++)
03358   {
03359     if (IsPixelInfoEquivalent(&colormap[j],&image->colormap[i]) == MagickFalse)
03360       {
03361         j++;
03362         colormap[j]=image->colormap[i];
03363       }
03364     colormap_index[(ssize_t) image->colormap[i].alpha]=j;
03365   }
03366   image->colors=(size_t) (j+1);
03367   image->colormap=(PixelInfo *) RelinquishMagickMemory(image->colormap);
03368   image->colormap=colormap;
03369   status=MagickTrue;
03370   image_view=AcquireCacheView(image);
03371 #if defined(MAGICKCORE_OPENMP_SUPPORT)
03372   #pragma omp parallel for schedule(static,4) shared(status)
03373 #endif
03374   for (y=0; y < (ssize_t) image->rows; y++)
03375   {
03376     register Quantum
03377       *restrict q;
03378 
03379     register ssize_t
03380       x;
03381 
03382     if (status == MagickFalse)
03383       continue;
03384     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
03385     if (q == (Quantum *) NULL)
03386       {
03387         status=MagickFalse;
03388         continue;
03389       }
03390     for (x=0; x < (ssize_t) image->columns; x++)
03391     {
03392       SetPixelIndex(image,(Quantum) colormap_index[ScaleQuantumToMap(
03393         GetPixelIndex(image,q))],q);
03394       q+=GetPixelChannels(image);
03395     }
03396     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
03397       status=MagickFalse;
03398   }
03399   image_view=DestroyCacheView(image_view);
03400   colormap_index=(ssize_t *) RelinquishMagickMemory(colormap_index);
03401   image->type=GrayscaleType;
03402   if (IsImageMonochrome(image,exception) != MagickFalse)
03403     image->type=BilevelType;
03404   return(status);
03405 }