1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %           QQQ   U   U   AAA   N   N  TTTTT  IIIII   ZZZZZ  EEEEE            %
7 %          Q   Q  U   U  A   A  NN  N    T      I        ZZ  E                %
8 %          Q   Q  U   U  AAAAA  N N N    T      I      ZZZ   EEEEE            %
9 %          Q  QQ  U   U  A   A  N  NN    T      I     ZZ     E                %
10 %           QQQQ   UUU   A   A  N   N    T    IIIII   ZZZZZ  EEEEE            %
11 %                                                                             %
12 %                                                                             %
13 %    MagickCore Methods to Reduce the Number of Unique Colors in an Image     %
14 %                                                                             %
15 %                           Software Design                                   %
16 %                                Cristy                                       %
17 %                              July 1992                                      %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    https://imagemagick.org/script/license.php                               %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %  Realism in computer graphics typically requires using 24 bits/pixel to
37 %  generate an image.  Yet many graphic display devices do not contain the
38 %  amount of memory necessary to match the spatial and color resolution of
39 %  the human eye.  The Quantize methods takes a 24 bit image and reduces
40 %  the number of colors so it can be displayed on raster device with less
41 %  bits per pixel.  In most instances, the quantized image closely
42 %  resembles the original reference image.
43 %
44 %  A reduction of colors in an image is also desirable for image
45 %  transmission and real-time animation.
46 %
47 %  QuantizeImage() takes a standard RGB or monochrome images and quantizes
48 %  them down to some fixed number of colors.
49 %
50 %  For purposes of color allocation, an image is a set of n pixels, where
51 %  each pixel is a point in RGB space.  RGB space is a 3-dimensional
52 %  vector space, and each pixel, Pi,  is defined by an ordered triple of
53 %  red, green, and blue coordinates, (Ri, Gi, Bi).
54 %
55 %  Each primary color component (red, green, or blue) represents an
56 %  intensity which varies linearly from 0 to a maximum value, Cmax, which
57 %  corresponds to full saturation of that color.  Color allocation is
58 %  defined over a domain consisting of the cube in RGB space with opposite
59 %  vertices at (0,0,0) and (Cmax, Cmax, Cmax).  QUANTIZE requires Cmax =
60 %  255.
61 %
62 %  The algorithm maps this domain onto a tree in which each node
63 %  represents a cube within that domain.  In the following discussion
64 %  these cubes are defined by the coordinate of two opposite vertices (vertex
65 %  nearest the origin in RGB space and the vertex farthest from the origin).
66 %
67 %  The tree's root node represents the entire domain, (0,0,0) through
68 %  (Cmax,Cmax,Cmax).  Each lower level in the tree is generated by
69 %  subdividing one node's cube into eight smaller cubes of equal size.
70 %  This corresponds to bisecting the parent cube with planes passing
71 %  through the midpoints of each edge.
72 %
73 %  The basic algorithm operates in three phases: Classification,
74 %  Reduction, and Assignment.  Classification builds a color description
75 %  tree for the image.  Reduction collapses the tree until the number it
76 %  represents, at most, the number of colors desired in the output image.
77 %  Assignment defines the output image's color map and sets each pixel's
78 %  color by restorage_class in the reduced tree.  Our goal is to minimize
79 %  the numerical discrepancies between the original colors and quantized
80 %  colors (quantization error).
81 %
82 %  Classification begins by initializing a color description tree of
83 %  sufficient depth to represent each possible input color in a leaf.
84 %  However, it is impractical to generate a fully-formed color description
85 %  tree in the storage_class phase for realistic values of Cmax.  If
86 %  colors components in the input image are quantized to k-bit precision,
87 %  so that Cmax= 2k-1, the tree would need k levels below the root node to
88 %  allow representing each possible input color in a leaf.  This becomes
89 %  prohibitive because the tree's total number of nodes is 1 +
90 %  sum(i=1, k, 8k).
91 %
92 %  A complete tree would require 19,173,961 nodes for k = 8, Cmax = 255.
93 %  Therefore, to avoid building a fully populated tree, QUANTIZE: (1)
94 %  Initializes data structures for nodes only as they are needed;  (2)
95 %  Chooses a maximum depth for the tree as a function of the desired
96 %  number of colors in the output image (currently log2(colormap size)).
97 %
98 %  For each pixel in the input image, storage_class scans downward from
99 %  the root of the color description tree.  At each level of the tree it
100 %  identifies the single node which represents a cube in RGB space
101 %  containing the pixel's color.  It updates the following data for each
102 %  such node:
103 %
104 %    n1: Number of pixels whose color is contained in the RGB cube which
105 %    this node represents;
106 %
107 %    n2: Number of pixels whose color is not represented in a node at
108 %    lower depth in the tree;  initially,  n2 = 0 for all nodes except
109 %    leaves of the tree.
110 %
111 %    Sr, Sg, Sb: Sums of the red, green, and blue component values for all
112 %    pixels not classified at a lower depth. The combination of these sums
113 %    and n2 will ultimately characterize the mean color of a set of pixels
114 %    represented by this node.
115 %
116 %    E: the distance squared in RGB space between each pixel contained
117 %    within a node and the nodes' center.  This represents the
118 %    quantization error for a node.
119 %
120 %  Reduction repeatedly prunes the tree until the number of nodes with n2
121 %  > 0 is less than or equal to the maximum number of colors allowed in
122 %  the output image.  On any given iteration over the tree, it selects
123 %  those nodes whose E count is minimal for pruning and merges their color
124 %  statistics upward. It uses a pruning threshold, Ep, to govern node
125 %  selection as follows:
126 %
127 %    Ep = 0
128 %    while number of nodes with (n2 > 0) > required maximum number of colors
129 %      prune all nodes such that E <= Ep
130 %      Set Ep to minimum E in remaining nodes
131 %
132 %  This has the effect of minimizing any quantization error when merging
133 %  two nodes together.
134 %
135 %  When a node to be pruned has offspring, the pruning procedure invokes
136 %  itself recursively in order to prune the tree from the leaves upward.
137 %  n2,  Sr, Sg,  and  Sb in a node being pruned are always added to the
138 %  corresponding data in that node's parent.  This retains the pruned
139 %  node's color characteristics for later averaging.
140 %
141 %  For each node, n2 pixels exist for which that node represents the
142 %  smallest volume in RGB space containing those pixel's colors.  When n2
143 %  > 0 the node will uniquely define a color in the output image. At the
144 %  beginning of reduction,  n2 = 0  for all nodes except a the leaves of
145 %  the tree which represent colors present in the input image.
146 %
147 %  The other pixel count, n1, indicates the total number of colors within
148 %  the cubic volume which the node represents.  This includes n1 - n2
149 %  pixels whose colors should be defined by nodes at a lower level in the
150 %  tree.
151 %
152 %  Assignment generates the output image from the pruned tree.  The output
153 %  image consists of two parts: (1)  A color map, which is an array of
154 %  color descriptions (RGB triples) for each color present in the output
155 %  image;  (2)  A pixel array, which represents each pixel as an index
156 %  into the color map array.
157 %
158 %  First, the assignment phase makes one pass over the pruned color
159 %  description tree to establish the image's color map.  For each node
160 %  with n2  > 0, it divides Sr, Sg, and Sb by n2 .  This produces the mean
161 %  color of all pixels that classify no lower than this node.  Each of
162 %  these colors becomes an entry in the color map.
163 %
164 %  Finally,  the assignment phase reclassifies each pixel in the pruned
165 %  tree to identify the deepest node containing the pixel's color.  The
166 %  pixel's value in the pixel array becomes the index of this node's mean
167 %  color in the color map.
168 %
169 %  This method is based on a similar algorithm written by Paul Raveling.
170 %
171 */
172 
173 /*
174   Include declarations.
175 */
176 #include "MagickCore/studio.h"
177 #include "MagickCore/artifact.h"
178 #include "MagickCore/attribute.h"
179 #include "MagickCore/cache-view.h"
180 #include "MagickCore/color.h"
181 #include "MagickCore/color-private.h"
182 #include "MagickCore/colormap.h"
183 #include "MagickCore/colorspace.h"
184 #include "MagickCore/colorspace-private.h"
185 #include "MagickCore/enhance.h"
186 #include "MagickCore/exception.h"
187 #include "MagickCore/exception-private.h"
188 #include "MagickCore/histogram.h"
189 #include "MagickCore/image.h"
190 #include "MagickCore/image-private.h"
191 #include "MagickCore/list.h"
192 #include "MagickCore/memory_.h"
193 #include "MagickCore/memory-private.h"
194 #include "MagickCore/monitor.h"
195 #include "MagickCore/monitor-private.h"
196 #include "MagickCore/option.h"
197 #include "MagickCore/pixel-accessor.h"
198 #include "MagickCore/pixel-private.h"
199 #include "MagickCore/quantize.h"
200 #include "MagickCore/quantum.h"
201 #include "MagickCore/quantum-private.h"
202 #include "MagickCore/resource_.h"
203 #include "MagickCore/string_.h"
204 #include "MagickCore/string-private.h"
205 #include "MagickCore/thread-private.h"
206 
207 /*
208   Define declarations.
209 */
210 #if !defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
211 #define CacheShift  2
212 #else
213 #define CacheShift  3
214 #endif
215 #define ErrorQueueLength  16
216 #define MaxNodes  266817
217 #define MaxTreeDepth  8
218 #define NodesInAList  1920
219 
220 /*
221   Typdef declarations.
222 */
223 typedef struct _DoublePixelPacket
224 {
225   double
226     red,
227     green,
228     blue,
229     alpha;
230 } DoublePixelPacket;
231 
232 typedef struct _NodeInfo
233 {
234   struct _NodeInfo
235     *parent,
236     *child[16];
237 
238   MagickSizeType
239     number_unique;
240 
241   DoublePixelPacket
242     total_color;
243 
244   double
245     quantize_error;
246 
247   size_t
248     color_number,
249     id,
250     level;
251 } NodeInfo;
252 
253 typedef struct _Nodes
254 {
255   NodeInfo
256     *nodes;
257 
258   struct _Nodes
259     *next;
260 } Nodes;
261 
262 typedef struct _CubeInfo
263 {
264   NodeInfo
265     *root;
266 
267   size_t
268     colors,
269     maximum_colors;
270 
271   ssize_t
272     transparent_index;
273 
274   MagickSizeType
275     transparent_pixels;
276 
277   DoublePixelPacket
278     target;
279 
280   double
281     distance,
282     pruning_threshold,
283     next_threshold;
284 
285   size_t
286     nodes,
287     free_nodes,
288     color_number;
289 
290   NodeInfo
291     *next_node;
292 
293   Nodes
294     *node_queue;
295 
296   MemoryInfo
297     *memory_info;
298 
299   ssize_t
300     *cache;
301 
302   DoublePixelPacket
303     error[ErrorQueueLength];
304 
305   double
306     weights[ErrorQueueLength];
307 
308   QuantizeInfo
309     *quantize_info;
310 
311   MagickBooleanType
312     associate_alpha;
313 
314   ssize_t
315     x,
316     y;
317 
318   size_t
319     depth;
320 
321   MagickOffsetType
322     offset;
323 
324   MagickSizeType
325     span;
326 } CubeInfo;
327 
328 /*
329   Method prototypes.
330 */
331 static CubeInfo
332   *GetCubeInfo(const QuantizeInfo *,const size_t,const size_t);
333 
334 static NodeInfo
335   *GetNodeInfo(CubeInfo *,const size_t,const size_t,NodeInfo *);
336 
337 static MagickBooleanType
338   AssignImageColors(Image *,CubeInfo *,ExceptionInfo *),
339   ClassifyImageColors(CubeInfo *,const Image *,ExceptionInfo *),
340   DitherImage(Image *,CubeInfo *,ExceptionInfo *),
341   SetGrayscaleImage(Image *,ExceptionInfo *);
342 
343 static size_t
344   DefineImageColormap(Image *,CubeInfo *,NodeInfo *);
345 
346 static void
347   ClosestColor(const Image *,CubeInfo *,const NodeInfo *),
348   DestroyCubeInfo(CubeInfo *),
349   PruneLevel(CubeInfo *,const NodeInfo *),
350   PruneToCubeDepth(CubeInfo *,const NodeInfo *),
351   ReduceImageColors(const Image *,CubeInfo *);
352 
353 /*
354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
355 %                                                                             %
356 %                                                                             %
357 %                                                                             %
358 %   A c q u i r e Q u a n t i z e I n f o                                     %
359 %                                                                             %
360 %                                                                             %
361 %                                                                             %
362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
363 %
364 %  AcquireQuantizeInfo() allocates the QuantizeInfo structure.
365 %
366 %  The format of the AcquireQuantizeInfo method is:
367 %
368 %      QuantizeInfo *AcquireQuantizeInfo(const ImageInfo *image_info)
369 %
370 %  A description of each parameter follows:
371 %
372 %    o image_info: the image info.
373 %
374 */
AcquireQuantizeInfo(const ImageInfo * image_info)375 MagickExport QuantizeInfo *AcquireQuantizeInfo(const ImageInfo *image_info)
376 {
377   QuantizeInfo
378     *quantize_info;
379 
380   quantize_info=(QuantizeInfo *) AcquireCriticalMemory(sizeof(*quantize_info));
381   GetQuantizeInfo(quantize_info);
382   if (image_info != (ImageInfo *) NULL)
383     {
384       const char
385         *option;
386 
387       quantize_info->dither_method=image_info->dither == MagickFalse ?
388         NoDitherMethod : RiemersmaDitherMethod;
389       option=GetImageOption(image_info,"dither");
390       if (option != (const char *) NULL)
391         quantize_info->dither_method=(DitherMethod) ParseCommandOption(
392           MagickDitherOptions,MagickFalse,option);
393       quantize_info->measure_error=image_info->verbose;
394     }
395   return(quantize_info);
396 }
397 
398 /*
399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
400 %                                                                             %
401 %                                                                             %
402 %                                                                             %
403 +   A s s i g n I m a g e C o l o r s                                         %
404 %                                                                             %
405 %                                                                             %
406 %                                                                             %
407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
408 %
409 %  AssignImageColors() generates the output image from the pruned tree.  The
410 %  output image consists of two parts: (1)  A color map, which is an array
411 %  of color descriptions (RGB triples) for each color present in the
412 %  output image;  (2)  A pixel array, which represents each pixel as an
413 %  index into the color map array.
414 %
415 %  First, the assignment phase makes one pass over the pruned color
416 %  description tree to establish the image's color map.  For each node
417 %  with n2  > 0, it divides Sr, Sg, and Sb by n2 .  This produces the mean
418 %  color of all pixels that classify no lower than this node.  Each of
419 %  these colors becomes an entry in the color map.
420 %
421 %  Finally,  the assignment phase reclassifies each pixel in the pruned
422 %  tree to identify the deepest node containing the pixel's color.  The
423 %  pixel's value in the pixel array becomes the index of this node's mean
424 %  color in the color map.
425 %
426 %  The format of the AssignImageColors() method is:
427 %
428 %      MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info)
429 %
430 %  A description of each parameter follows.
431 %
432 %    o image: the image.
433 %
434 %    o cube_info: A pointer to the Cube structure.
435 %
436 */
437 
AssociateAlphaPixel(const Image * image,const CubeInfo * cube_info,const Quantum * pixel,DoublePixelPacket * alpha_pixel)438 static inline void AssociateAlphaPixel(const Image *image,
439   const CubeInfo *cube_info,const Quantum *pixel,DoublePixelPacket *alpha_pixel)
440 {
441   double
442     alpha;
443 
444   if ((cube_info->associate_alpha == MagickFalse) ||
445       (GetPixelAlpha(image,pixel) == OpaqueAlpha))
446     {
447       alpha_pixel->red=(double) GetPixelRed(image,pixel);
448       alpha_pixel->green=(double) GetPixelGreen(image,pixel);
449       alpha_pixel->blue=(double) GetPixelBlue(image,pixel);
450       alpha_pixel->alpha=(double) GetPixelAlpha(image,pixel);
451       return;
452     }
453   alpha=(double) (QuantumScale*GetPixelAlpha(image,pixel));
454   alpha_pixel->red=alpha*GetPixelRed(image,pixel);
455   alpha_pixel->green=alpha*GetPixelGreen(image,pixel);
456   alpha_pixel->blue=alpha*GetPixelBlue(image,pixel);
457   alpha_pixel->alpha=(double) GetPixelAlpha(image,pixel);
458 }
459 
AssociateAlphaPixelInfo(const CubeInfo * cube_info,const PixelInfo * pixel,DoublePixelPacket * alpha_pixel)460 static inline void AssociateAlphaPixelInfo(const CubeInfo *cube_info,
461   const PixelInfo *pixel,DoublePixelPacket *alpha_pixel)
462 {
463   double
464     alpha;
465 
466   if ((cube_info->associate_alpha == MagickFalse) ||
467       (pixel->alpha == OpaqueAlpha))
468     {
469       alpha_pixel->red=(double) pixel->red;
470       alpha_pixel->green=(double) pixel->green;
471       alpha_pixel->blue=(double) pixel->blue;
472       alpha_pixel->alpha=(double) pixel->alpha;
473       return;
474     }
475   alpha=(double) (QuantumScale*pixel->alpha);
476   alpha_pixel->red=alpha*pixel->red;
477   alpha_pixel->green=alpha*pixel->green;
478   alpha_pixel->blue=alpha*pixel->blue;
479   alpha_pixel->alpha=(double) pixel->alpha;
480 }
481 
ColorToNodeId(const CubeInfo * cube_info,const DoublePixelPacket * pixel,size_t index)482 static inline size_t ColorToNodeId(const CubeInfo *cube_info,
483   const DoublePixelPacket *pixel,size_t index)
484 {
485   size_t
486     id;
487 
488   id=(size_t) (((ScaleQuantumToChar(ClampPixel(pixel->red)) >> index) & 0x01) |
489     ((ScaleQuantumToChar(ClampPixel(pixel->green)) >> index) & 0x01) << 1 |
490     ((ScaleQuantumToChar(ClampPixel(pixel->blue)) >> index) & 0x01) << 2);
491   if (cube_info->associate_alpha != MagickFalse)
492     id|=((ScaleQuantumToChar(ClampPixel(pixel->alpha)) >> index) & 0x1) << 3;
493   return(id);
494 }
495 
AssignImageColors(Image * image,CubeInfo * cube_info,ExceptionInfo * exception)496 static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info,
497   ExceptionInfo *exception)
498 {
499 #define AssignImageTag  "Assign/Image"
500 
501   ColorspaceType
502     colorspace;
503 
504   ssize_t
505     y;
506 
507   /*
508     Allocate image colormap.
509   */
510   colorspace=image->colorspace;
511   if (cube_info->quantize_info->colorspace != UndefinedColorspace)
512     (void) TransformImageColorspace(image,cube_info->quantize_info->colorspace,
513       exception);
514   if (AcquireImageColormap(image,cube_info->colors,exception) == MagickFalse)
515     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
516       image->filename);
517   image->colors=0;
518   cube_info->transparent_pixels=0;
519   cube_info->transparent_index=(-1);
520   (void) DefineImageColormap(image,cube_info,cube_info->root);
521   /*
522     Create a reduced color image.
523   */
524   if (cube_info->quantize_info->dither_method != NoDitherMethod)
525     (void) DitherImage(image,cube_info,exception);
526   else
527     {
528       CacheView
529         *image_view;
530 
531       MagickBooleanType
532         status;
533 
534       status=MagickTrue;
535       image_view=AcquireAuthenticCacheView(image,exception);
536 #if defined(MAGICKCORE_OPENMP_SUPPORT)
537       #pragma omp parallel for schedule(static) shared(status) \
538         magick_number_threads(image,image,image->rows,1)
539 #endif
540       for (y=0; y < (ssize_t) image->rows; y++)
541       {
542         CubeInfo
543           cube;
544 
545         register Quantum
546           *magick_restrict q;
547 
548         register ssize_t
549           x;
550 
551         ssize_t
552           count;
553 
554         if (status == MagickFalse)
555           continue;
556         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
557           exception);
558         if (q == (Quantum *) NULL)
559           {
560             status=MagickFalse;
561             continue;
562           }
563         cube=(*cube_info);
564         for (x=0; x < (ssize_t) image->columns; x+=count)
565         {
566           DoublePixelPacket
567             pixel;
568 
569           register const NodeInfo
570             *node_info;
571 
572           register ssize_t
573             i;
574 
575           size_t
576             id,
577             index;
578 
579           /*
580             Identify the deepest node containing the pixel's color.
581           */
582           for (count=1; (x+count) < (ssize_t) image->columns; count++)
583           {
584             PixelInfo
585               packet;
586 
587             GetPixelInfoPixel(image,q+count*GetPixelChannels(image),&packet);
588             if (IsPixelEquivalent(image,q,&packet) == MagickFalse)
589               break;
590           }
591           AssociateAlphaPixel(image,&cube,q,&pixel);
592           node_info=cube.root;
593           for (index=MaxTreeDepth-1; (ssize_t) index > 0; index--)
594           {
595             id=ColorToNodeId(&cube,&pixel,index);
596             if (node_info->child[id] == (NodeInfo *) NULL)
597               break;
598             node_info=node_info->child[id];
599           }
600           /*
601             Find closest color among siblings and their children.
602           */
603           cube.target=pixel;
604           cube.distance=(double) (4.0*(QuantumRange+1.0)*(QuantumRange+1.0)+
605             1.0);
606           ClosestColor(image,&cube,node_info->parent);
607           index=cube.color_number;
608           for (i=0; i < (ssize_t) count; i++)
609           {
610             if (image->storage_class == PseudoClass)
611               SetPixelIndex(image,(Quantum) index,q);
612             if (cube.quantize_info->measure_error == MagickFalse)
613               {
614                 SetPixelRed(image,ClampToQuantum(
615                   image->colormap[index].red),q);
616                 SetPixelGreen(image,ClampToQuantum(
617                   image->colormap[index].green),q);
618                 SetPixelBlue(image,ClampToQuantum(
619                   image->colormap[index].blue),q);
620                 if (cube.associate_alpha != MagickFalse)
621                   SetPixelAlpha(image,ClampToQuantum(
622                     image->colormap[index].alpha),q);
623               }
624             q+=GetPixelChannels(image);
625           }
626         }
627         if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
628           status=MagickFalse;
629         if (image->progress_monitor != (MagickProgressMonitor) NULL)
630           {
631             MagickBooleanType
632               proceed;
633 
634             proceed=SetImageProgress(image,AssignImageTag,(MagickOffsetType) y,
635               image->rows);
636             if (proceed == MagickFalse)
637               status=MagickFalse;
638           }
639       }
640       image_view=DestroyCacheView(image_view);
641     }
642   if (cube_info->quantize_info->measure_error != MagickFalse)
643     (void) GetImageQuantizeError(image,exception);
644   if ((cube_info->quantize_info->number_colors == 2) &&
645       ((cube_info->quantize_info->colorspace == LinearGRAYColorspace) ||
646        (cube_info->quantize_info->colorspace == GRAYColorspace)))
647     {
648       double
649         intensity;
650 
651       /*
652         Monochrome image.
653       */
654       intensity=0.0;
655       if ((image->colors > 1) &&
656           (GetPixelInfoLuma(image->colormap+0) >
657            GetPixelInfoLuma(image->colormap+1)))
658         intensity=(double) QuantumRange;
659       image->colormap[0].red=intensity;
660       image->colormap[0].green=intensity;
661       image->colormap[0].blue=intensity;
662       if (image->colors > 1)
663         {
664           image->colormap[1].red=(double) QuantumRange-intensity;
665           image->colormap[1].green=(double) QuantumRange-intensity;
666           image->colormap[1].blue=(double) QuantumRange-intensity;
667         }
668     }
669   (void) SyncImage(image,exception);
670   if ((cube_info->quantize_info->colorspace != UndefinedColorspace) &&
671       (IssRGBCompatibleColorspace(colorspace) == MagickFalse))
672     (void) TransformImageColorspace(image,colorspace,exception);
673   return(MagickTrue);
674 }
675 
676 /*
677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
678 %                                                                             %
679 %                                                                             %
680 %                                                                             %
681 +   C l a s s i f y I m a g e C o l o r s                                     %
682 %                                                                             %
683 %                                                                             %
684 %                                                                             %
685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
686 %
687 %  ClassifyImageColors() begins by initializing a color description tree
688 %  of sufficient depth to represent each possible input color in a leaf.
689 %  However, it is impractical to generate a fully-formed color
690 %  description tree in the storage_class phase for realistic values of
691 %  Cmax.  If colors components in the input image are quantized to k-bit
692 %  precision, so that Cmax= 2k-1, the tree would need k levels below the
693 %  root node to allow representing each possible input color in a leaf.
694 %  This becomes prohibitive because the tree's total number of nodes is
695 %  1 + sum(i=1,k,8k).
696 %
697 %  A complete tree would require 19,173,961 nodes for k = 8, Cmax = 255.
698 %  Therefore, to avoid building a fully populated tree, QUANTIZE: (1)
699 %  Initializes data structures for nodes only as they are needed;  (2)
700 %  Chooses a maximum depth for the tree as a function of the desired
701 %  number of colors in the output image (currently log2(colormap size)).
702 %
703 %  For each pixel in the input image, storage_class scans downward from
704 %  the root of the color description tree.  At each level of the tree it
705 %  identifies the single node which represents a cube in RGB space
706 %  containing It updates the following data for each such node:
707 %
708 %    n1 : Number of pixels whose color is contained in the RGB cube
709 %    which this node represents;
710 %
711 %    n2 : Number of pixels whose color is not represented in a node at
712 %    lower depth in the tree;  initially,  n2 = 0 for all nodes except
713 %    leaves of the tree.
714 %
715 %    Sr, Sg, Sb : Sums of the red, green, and blue component values for
716 %    all pixels not classified at a lower depth. The combination of
717 %    these sums and n2 will ultimately characterize the mean color of a
718 %    set of pixels represented by this node.
719 %
720 %    E: the distance squared in RGB space between each pixel contained
721 %    within a node and the nodes' center.  This represents the quantization
722 %    error for a node.
723 %
724 %  The format of the ClassifyImageColors() method is:
725 %
726 %      MagickBooleanType ClassifyImageColors(CubeInfo *cube_info,
727 %        const Image *image,ExceptionInfo *exception)
728 %
729 %  A description of each parameter follows.
730 %
731 %    o cube_info: A pointer to the Cube structure.
732 %
733 %    o image: the image.
734 %
735 */
736 
SetAssociatedAlpha(const Image * image,CubeInfo * cube_info)737 static inline void SetAssociatedAlpha(const Image *image,CubeInfo *cube_info)
738 {
739   MagickBooleanType
740     associate_alpha;
741 
742   associate_alpha=image->alpha_trait == BlendPixelTrait ? MagickTrue :
743     MagickFalse;
744   if ((cube_info->quantize_info->number_colors == 2) &&
745       ((cube_info->quantize_info->colorspace == LinearGRAYColorspace) ||
746        (cube_info->quantize_info->colorspace == GRAYColorspace)))
747     associate_alpha=MagickFalse;
748   cube_info->associate_alpha=associate_alpha;
749 }
750 
ClassifyImageColors(CubeInfo * cube_info,const Image * image,ExceptionInfo * exception)751 static MagickBooleanType ClassifyImageColors(CubeInfo *cube_info,
752   const Image *image,ExceptionInfo *exception)
753 {
754 #define ClassifyImageTag  "Classify/Image"
755 
756   CacheView
757     *image_view;
758 
759   DoublePixelPacket
760     error,
761     mid,
762     midpoint,
763     pixel;
764 
765   MagickBooleanType
766     proceed;
767 
768   double
769     bisect;
770 
771   NodeInfo
772     *node_info;
773 
774   size_t
775     count,
776     id,
777     index,
778     level;
779 
780   ssize_t
781     y;
782 
783   /*
784     Classify the first cube_info->maximum_colors colors to a tree depth of 8.
785   */
786   SetAssociatedAlpha(image,cube_info);
787   if ((cube_info->quantize_info->colorspace != UndefinedColorspace) &&
788       (cube_info->quantize_info->colorspace != CMYKColorspace))
789     (void) TransformImageColorspace((Image *) image,
790       cube_info->quantize_info->colorspace,exception);
791   else
792     if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
793       (void) TransformImageColorspace((Image *) image,sRGBColorspace,exception);
794   midpoint.red=(double) QuantumRange/2.0;
795   midpoint.green=(double) QuantumRange/2.0;
796   midpoint.blue=(double) QuantumRange/2.0;
797   midpoint.alpha=(double) QuantumRange/2.0;
798   error.alpha=0.0;
799   image_view=AcquireVirtualCacheView(image,exception);
800   for (y=0; y < (ssize_t) image->rows; y++)
801   {
802     register const Quantum
803       *magick_restrict p;
804 
805     register ssize_t
806       x;
807 
808     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
809     if (p == (const Quantum *) NULL)
810       break;
811     if (cube_info->nodes > MaxNodes)
812       {
813         /*
814           Prune one level if the color tree is too large.
815         */
816         PruneLevel(cube_info,cube_info->root);
817         cube_info->depth--;
818       }
819     for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) count)
820     {
821       /*
822         Start at the root and descend the color cube tree.
823       */
824       for (count=1; (x+(ssize_t) count) < (ssize_t) image->columns; count++)
825       {
826         PixelInfo
827           packet;
828 
829         GetPixelInfoPixel(image,p+count*GetPixelChannels(image),&packet);
830         if (IsPixelEquivalent(image,p,&packet) == MagickFalse)
831           break;
832       }
833       AssociateAlphaPixel(image,cube_info,p,&pixel);
834       index=MaxTreeDepth-1;
835       bisect=((double) QuantumRange+1.0)/2.0;
836       mid=midpoint;
837       node_info=cube_info->root;
838       for (level=1; level <= MaxTreeDepth; level++)
839       {
840         double
841           distance;
842 
843         bisect*=0.5;
844         id=ColorToNodeId(cube_info,&pixel,index);
845         mid.red+=(id & 1) != 0 ? bisect : -bisect;
846         mid.green+=(id & 2) != 0 ? bisect : -bisect;
847         mid.blue+=(id & 4) != 0 ? bisect : -bisect;
848         mid.alpha+=(id & 8) != 0 ? bisect : -bisect;
849         if (node_info->child[id] == (NodeInfo *) NULL)
850           {
851             /*
852               Set colors of new node to contain pixel.
853             */
854             node_info->child[id]=GetNodeInfo(cube_info,id,level,node_info);
855             if (node_info->child[id] == (NodeInfo *) NULL)
856               {
857                 (void) ThrowMagickException(exception,GetMagickModule(),
858                   ResourceLimitError,"MemoryAllocationFailed","`%s'",
859                   image->filename);
860                 continue;
861               }
862             if (level == MaxTreeDepth)
863               cube_info->colors++;
864           }
865         /*
866           Approximate the quantization error represented by this node.
867         */
868         node_info=node_info->child[id];
869         error.red=QuantumScale*(pixel.red-mid.red);
870         error.green=QuantumScale*(pixel.green-mid.green);
871         error.blue=QuantumScale*(pixel.blue-mid.blue);
872         if (cube_info->associate_alpha != MagickFalse)
873           error.alpha=QuantumScale*(pixel.alpha-mid.alpha);
874         distance=(double) (error.red*error.red+error.green*error.green+
875           error.blue*error.blue+error.alpha*error.alpha);
876         if (IsNaN(distance))
877           distance=0.0;
878         node_info->quantize_error+=count*sqrt(distance);
879         cube_info->root->quantize_error+=node_info->quantize_error;
880         index--;
881       }
882       /*
883         Sum RGB for this leaf for later derivation of the mean cube color.
884       */
885       node_info->number_unique+=count;
886       node_info->total_color.red+=count*QuantumScale*ClampPixel(pixel.red);
887       node_info->total_color.green+=count*QuantumScale*ClampPixel(pixel.green);
888       node_info->total_color.blue+=count*QuantumScale*ClampPixel(pixel.blue);
889       if (cube_info->associate_alpha != MagickFalse)
890         node_info->total_color.alpha+=count*QuantumScale*
891           ClampPixel(pixel.alpha);
892       else
893         node_info->total_color.alpha+=count*QuantumScale*
894           ClampPixel((MagickRealType) OpaqueAlpha);
895       p+=count*GetPixelChannels(image);
896     }
897     if (cube_info->colors > cube_info->maximum_colors)
898       {
899         PruneToCubeDepth(cube_info,cube_info->root);
900         break;
901       }
902     proceed=SetImageProgress(image,ClassifyImageTag,(MagickOffsetType) y,
903       image->rows);
904     if (proceed == MagickFalse)
905       break;
906   }
907   for (y++; y < (ssize_t) image->rows; y++)
908   {
909     register const Quantum
910       *magick_restrict p;
911 
912     register ssize_t
913       x;
914 
915     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
916     if (p == (const Quantum *) NULL)
917       break;
918     if (cube_info->nodes > MaxNodes)
919       {
920         /*
921           Prune one level if the color tree is too large.
922         */
923         PruneLevel(cube_info,cube_info->root);
924         cube_info->depth--;
925       }
926     for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) count)
927     {
928       /*
929         Start at the root and descend the color cube tree.
930       */
931       for (count=1; (x+(ssize_t) count) < (ssize_t) image->columns; count++)
932       {
933         PixelInfo
934           packet;
935 
936         GetPixelInfoPixel(image,p+count*GetPixelChannels(image),&packet);
937         if (IsPixelEquivalent(image,p,&packet) == MagickFalse)
938           break;
939       }
940       AssociateAlphaPixel(image,cube_info,p,&pixel);
941       index=MaxTreeDepth-1;
942       bisect=((double) QuantumRange+1.0)/2.0;
943       mid=midpoint;
944       node_info=cube_info->root;
945       for (level=1; level <= cube_info->depth; level++)
946       {
947         double
948           distance;
949 
950         bisect*=0.5;
951         id=ColorToNodeId(cube_info,&pixel,index);
952         mid.red+=(id & 1) != 0 ? bisect : -bisect;
953         mid.green+=(id & 2) != 0 ? bisect : -bisect;
954         mid.blue+=(id & 4) != 0 ? bisect : -bisect;
955         mid.alpha+=(id & 8) != 0 ? bisect : -bisect;
956         if (node_info->child[id] == (NodeInfo *) NULL)
957           {
958             /*
959               Set colors of new node to contain pixel.
960             */
961             node_info->child[id]=GetNodeInfo(cube_info,id,level,node_info);
962             if (node_info->child[id] == (NodeInfo *) NULL)
963               {
964                 (void) ThrowMagickException(exception,GetMagickModule(),
965                   ResourceLimitError,"MemoryAllocationFailed","%s",
966                   image->filename);
967                 continue;
968               }
969             if (level == cube_info->depth)
970               cube_info->colors++;
971           }
972         /*
973           Approximate the quantization error represented by this node.
974         */
975         node_info=node_info->child[id];
976         error.red=QuantumScale*(pixel.red-mid.red);
977         error.green=QuantumScale*(pixel.green-mid.green);
978         error.blue=QuantumScale*(pixel.blue-mid.blue);
979         if (cube_info->associate_alpha != MagickFalse)
980           error.alpha=QuantumScale*(pixel.alpha-mid.alpha);
981         distance=(double) (error.red*error.red+error.green*error.green+
982           error.blue*error.blue+error.alpha*error.alpha);
983         if (IsNaN(distance) != MagickFalse)
984           distance=0.0;
985         node_info->quantize_error+=count*sqrt(distance);
986         cube_info->root->quantize_error+=node_info->quantize_error;
987         index--;
988       }
989       /*
990         Sum RGB for this leaf for later derivation of the mean cube color.
991       */
992       node_info->number_unique+=count;
993       node_info->total_color.red+=count*QuantumScale*ClampPixel(pixel.red);
994       node_info->total_color.green+=count*QuantumScale*ClampPixel(pixel.green);
995       node_info->total_color.blue+=count*QuantumScale*ClampPixel(pixel.blue);
996       if (cube_info->associate_alpha != MagickFalse)
997         node_info->total_color.alpha+=count*QuantumScale*
998           ClampPixel(pixel.alpha);
999       else
1000         node_info->total_color.alpha+=count*QuantumScale*
1001           ClampPixel((MagickRealType) OpaqueAlpha);
1002       p+=count*GetPixelChannels(image);
1003     }
1004     proceed=SetImageProgress(image,ClassifyImageTag,(MagickOffsetType) y,
1005       image->rows);
1006     if (proceed == MagickFalse)
1007       break;
1008   }
1009   image_view=DestroyCacheView(image_view);
1010   if ((cube_info->quantize_info->colorspace != UndefinedColorspace) &&
1011       (cube_info->quantize_info->colorspace != CMYKColorspace))
1012     (void) TransformImageColorspace((Image *) image,sRGBColorspace,exception);
1013   return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
1014 }
1015 
1016 /*
1017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1018 %                                                                             %
1019 %                                                                             %
1020 %                                                                             %
1021 %   C l o n e Q u a n t i z e I n f o                                         %
1022 %                                                                             %
1023 %                                                                             %
1024 %                                                                             %
1025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1026 %
1027 %  CloneQuantizeInfo() makes a duplicate of the given quantize info structure,
1028 %  or if quantize info is NULL, a new one.
1029 %
1030 %  The format of the CloneQuantizeInfo method is:
1031 %
1032 %      QuantizeInfo *CloneQuantizeInfo(const QuantizeInfo *quantize_info)
1033 %
1034 %  A description of each parameter follows:
1035 %
1036 %    o clone_info: Method CloneQuantizeInfo returns a duplicate of the given
1037 %      quantize info, or if image info is NULL a new one.
1038 %
1039 %    o quantize_info: a structure of type info.
1040 %
1041 */
CloneQuantizeInfo(const QuantizeInfo * quantize_info)1042 MagickExport QuantizeInfo *CloneQuantizeInfo(const QuantizeInfo *quantize_info)
1043 {
1044   QuantizeInfo
1045     *clone_info;
1046 
1047   clone_info=(QuantizeInfo *) AcquireCriticalMemory(sizeof(*clone_info));
1048   GetQuantizeInfo(clone_info);
1049   if (quantize_info == (QuantizeInfo *) NULL)
1050     return(clone_info);
1051   clone_info->number_colors=quantize_info->number_colors;
1052   clone_info->tree_depth=quantize_info->tree_depth;
1053   clone_info->dither_method=quantize_info->dither_method;
1054   clone_info->colorspace=quantize_info->colorspace;
1055   clone_info->measure_error=quantize_info->measure_error;
1056   return(clone_info);
1057 }
1058 
1059 /*
1060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1061 %                                                                             %
1062 %                                                                             %
1063 %                                                                             %
1064 +   C l o s e s t C o l o r                                                   %
1065 %                                                                             %
1066 %                                                                             %
1067 %                                                                             %
1068 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1069 %
1070 %  ClosestColor() traverses the color cube tree at a particular node and
1071 %  determines which colormap entry best represents the input color.
1072 %
1073 %  The format of the ClosestColor method is:
1074 %
1075 %      void ClosestColor(const Image *image,CubeInfo *cube_info,
1076 %        const NodeInfo *node_info)
1077 %
1078 %  A description of each parameter follows.
1079 %
1080 %    o image: the image.
1081 %
1082 %    o cube_info: A pointer to the Cube structure.
1083 %
1084 %    o node_info: the address of a structure of type NodeInfo which points to a
1085 %      node in the color cube tree that is to be pruned.
1086 %
1087 */
ClosestColor(const Image * image,CubeInfo * cube_info,const NodeInfo * node_info)1088 static void ClosestColor(const Image *image,CubeInfo *cube_info,
1089   const NodeInfo *node_info)
1090 {
1091   register ssize_t
1092     i;
1093 
1094   size_t
1095     number_children;
1096 
1097   /*
1098     Traverse any children.
1099   */
1100   number_children=cube_info->associate_alpha == MagickFalse ? 8UL : 16UL;
1101   for (i=0; i < (ssize_t) number_children; i++)
1102     if (node_info->child[i] != (NodeInfo *) NULL)
1103       ClosestColor(image,cube_info,node_info->child[i]);
1104   if (node_info->number_unique != 0)
1105     {
1106       double
1107         pixel;
1108 
1109       register double
1110         alpha,
1111         beta,
1112         distance;
1113 
1114       register DoublePixelPacket
1115         *magick_restrict q;
1116 
1117       register PixelInfo
1118         *magick_restrict p;
1119 
1120       /*
1121         Determine if this color is "closest".
1122       */
1123       p=image->colormap+node_info->color_number;
1124       q=(&cube_info->target);
1125       alpha=1.0;
1126       beta=1.0;
1127       if (cube_info->associate_alpha != MagickFalse)
1128         {
1129           alpha=(double) (QuantumScale*p->alpha);
1130           beta=(double) (QuantumScale*q->alpha);
1131         }
1132       pixel=alpha*p->red-beta*q->red;
1133       distance=pixel*pixel;
1134       if (distance <= cube_info->distance)
1135         {
1136           pixel=alpha*p->green-beta*q->green;
1137           distance+=pixel*pixel;
1138           if (distance <= cube_info->distance)
1139             {
1140               pixel=alpha*p->blue-beta*q->blue;
1141               distance+=pixel*pixel;
1142               if (distance <= cube_info->distance)
1143                 {
1144                   if (cube_info->associate_alpha != MagickFalse)
1145                     {
1146                       pixel=p->alpha-q->alpha;
1147                       distance+=pixel*pixel;
1148                     }
1149                   if (distance <= cube_info->distance)
1150                     {
1151                       cube_info->distance=distance;
1152                       cube_info->color_number=node_info->color_number;
1153                     }
1154                 }
1155             }
1156         }
1157     }
1158 }
1159 
1160 /*
1161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1162 %                                                                             %
1163 %                                                                             %
1164 %                                                                             %
1165 %   C o m p r e s s I m a g e C o l o r m a p                                 %
1166 %                                                                             %
1167 %                                                                             %
1168 %                                                                             %
1169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1170 %
1171 %  CompressImageColormap() compresses an image colormap by removing any
1172 %  duplicate or unused color entries.
1173 %
1174 %  The format of the CompressImageColormap method is:
1175 %
1176 %      MagickBooleanType CompressImageColormap(Image *image,
1177 %        ExceptionInfo *exception)
1178 %
1179 %  A description of each parameter follows:
1180 %
1181 %    o image: the image.
1182 %
1183 %    o exception: return any errors or warnings in this structure.
1184 %
1185 */
CompressImageColormap(Image * image,ExceptionInfo * exception)1186 MagickExport MagickBooleanType CompressImageColormap(Image *image,
1187   ExceptionInfo *exception)
1188 {
1189   QuantizeInfo
1190     quantize_info;
1191 
1192   assert(image != (Image *) NULL);
1193   assert(image->signature == MagickCoreSignature);
1194   if (image->debug != MagickFalse)
1195     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1196   if (IsPaletteImage(image) == MagickFalse)
1197     return(MagickFalse);
1198   GetQuantizeInfo(&quantize_info);
1199   quantize_info.number_colors=image->colors;
1200   quantize_info.tree_depth=MaxTreeDepth;
1201   return(QuantizeImage(&quantize_info,image,exception));
1202 }
1203 
1204 /*
1205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1206 %                                                                             %
1207 %                                                                             %
1208 %                                                                             %
1209 +   D e f i n e I m a g e C o l o r m a p                                     %
1210 %                                                                             %
1211 %                                                                             %
1212 %                                                                             %
1213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1214 %
1215 %  DefineImageColormap() traverses the color cube tree and notes each colormap
1216 %  entry.  A colormap entry is any node in the color cube tree where the
1217 %  of unique colors is not zero.  DefineImageColormap() returns the number of
1218 %  colors in the image colormap.
1219 %
1220 %  The format of the DefineImageColormap method is:
1221 %
1222 %      size_t DefineImageColormap(Image *image,CubeInfo *cube_info,
1223 %        NodeInfo *node_info)
1224 %
1225 %  A description of each parameter follows.
1226 %
1227 %    o image: the image.
1228 %
1229 %    o cube_info: A pointer to the Cube structure.
1230 %
1231 %    o node_info: the address of a structure of type NodeInfo which points to a
1232 %      node in the color cube tree that is to be pruned.
1233 %
1234 */
DefineImageColormap(Image * image,CubeInfo * cube_info,NodeInfo * node_info)1235 static size_t DefineImageColormap(Image *image,CubeInfo *cube_info,
1236   NodeInfo *node_info)
1237 {
1238   register ssize_t
1239     i;
1240 
1241   size_t
1242     number_children;
1243 
1244   /*
1245     Traverse any children.
1246   */
1247   number_children=cube_info->associate_alpha == MagickFalse ? 8UL : 16UL;
1248   for (i=0; i < (ssize_t) number_children; i++)
1249     if (node_info->child[i] != (NodeInfo *) NULL)
1250       (void) DefineImageColormap(image,cube_info,node_info->child[i]);
1251   if (node_info->number_unique != 0)
1252     {
1253       register double
1254         alpha;
1255 
1256       register PixelInfo
1257         *magick_restrict q;
1258 
1259       /*
1260         Colormap entry is defined by the mean color in this cube.
1261       */
1262       q=image->colormap+image->colors;
1263       alpha=(double) ((MagickOffsetType) node_info->number_unique);
1264       alpha=PerceptibleReciprocal(alpha);
1265       if (cube_info->associate_alpha == MagickFalse)
1266         {
1267           q->red=(double) ClampToQuantum(alpha*QuantumRange*
1268             node_info->total_color.red);
1269           q->green=(double) ClampToQuantum(alpha*QuantumRange*
1270             node_info->total_color.green);
1271           q->blue=(double) ClampToQuantum(alpha*QuantumRange*
1272             node_info->total_color.blue);
1273           q->alpha=(double) OpaqueAlpha;
1274         }
1275       else
1276         {
1277           double
1278             opacity;
1279 
1280           opacity=(double) (alpha*QuantumRange*node_info->total_color.alpha);
1281           q->alpha=(double) ClampToQuantum(opacity);
1282           if (q->alpha == OpaqueAlpha)
1283             {
1284               q->red=(double) ClampToQuantum(alpha*QuantumRange*
1285                 node_info->total_color.red);
1286               q->green=(double) ClampToQuantum(alpha*QuantumRange*
1287                 node_info->total_color.green);
1288               q->blue=(double) ClampToQuantum(alpha*QuantumRange*
1289                 node_info->total_color.blue);
1290             }
1291           else
1292             {
1293               double
1294                 gamma;
1295 
1296               gamma=(double) (QuantumScale*q->alpha);
1297               gamma=PerceptibleReciprocal(gamma);
1298               q->red=(double) ClampToQuantum(alpha*gamma*QuantumRange*
1299                 node_info->total_color.red);
1300               q->green=(double) ClampToQuantum(alpha*gamma*QuantumRange*
1301                 node_info->total_color.green);
1302               q->blue=(double) ClampToQuantum(alpha*gamma*QuantumRange*
1303                 node_info->total_color.blue);
1304               if (node_info->number_unique > cube_info->transparent_pixels)
1305                 {
1306                   cube_info->transparent_pixels=node_info->number_unique;
1307                   cube_info->transparent_index=(ssize_t) image->colors;
1308                 }
1309             }
1310         }
1311       node_info->color_number=image->colors++;
1312     }
1313   return(image->colors);
1314 }
1315 
1316 /*
1317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1318 %                                                                             %
1319 %                                                                             %
1320 %                                                                             %
1321 +   D e s t r o y C u b e I n f o                                             %
1322 %                                                                             %
1323 %                                                                             %
1324 %                                                                             %
1325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1326 %
1327 %  DestroyCubeInfo() deallocates memory associated with an image.
1328 %
1329 %  The format of the DestroyCubeInfo method is:
1330 %
1331 %      DestroyCubeInfo(CubeInfo *cube_info)
1332 %
1333 %  A description of each parameter follows:
1334 %
1335 %    o cube_info: the address of a structure of type CubeInfo.
1336 %
1337 */
DestroyCubeInfo(CubeInfo * cube_info)1338 static void DestroyCubeInfo(CubeInfo *cube_info)
1339 {
1340   register Nodes
1341     *nodes;
1342 
1343   /*
1344     Release color cube tree storage.
1345   */
1346   do
1347   {
1348     nodes=cube_info->node_queue->next;
1349     cube_info->node_queue->nodes=(NodeInfo *) RelinquishMagickMemory(
1350       cube_info->node_queue->nodes);
1351     cube_info->node_queue=(Nodes *) RelinquishMagickMemory(
1352       cube_info->node_queue);
1353     cube_info->node_queue=nodes;
1354   } while (cube_info->node_queue != (Nodes *) NULL);
1355   if (cube_info->memory_info != (MemoryInfo *) NULL)
1356     cube_info->memory_info=RelinquishVirtualMemory(cube_info->memory_info);
1357   cube_info->quantize_info=DestroyQuantizeInfo(cube_info->quantize_info);
1358   cube_info=(CubeInfo *) RelinquishMagickMemory(cube_info);
1359 }
1360 
1361 /*
1362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1363 %                                                                             %
1364 %                                                                             %
1365 %                                                                             %
1366 %   D e s t r o y Q u a n t i z e I n f o                                     %
1367 %                                                                             %
1368 %                                                                             %
1369 %                                                                             %
1370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1371 %
1372 %  DestroyQuantizeInfo() deallocates memory associated with an QuantizeInfo
1373 %  structure.
1374 %
1375 %  The format of the DestroyQuantizeInfo method is:
1376 %
1377 %      QuantizeInfo *DestroyQuantizeInfo(QuantizeInfo *quantize_info)
1378 %
1379 %  A description of each parameter follows:
1380 %
1381 %    o quantize_info: Specifies a pointer to an QuantizeInfo structure.
1382 %
1383 */
DestroyQuantizeInfo(QuantizeInfo * quantize_info)1384 MagickExport QuantizeInfo *DestroyQuantizeInfo(QuantizeInfo *quantize_info)
1385 {
1386   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1387   assert(quantize_info != (QuantizeInfo *) NULL);
1388   assert(quantize_info->signature == MagickCoreSignature);
1389   quantize_info->signature=(~MagickCoreSignature);
1390   quantize_info=(QuantizeInfo *) RelinquishMagickMemory(quantize_info);
1391   return(quantize_info);
1392 }
1393 
1394 /*
1395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1396 %                                                                             %
1397 %                                                                             %
1398 %                                                                             %
1399 +   D i t h e r I m a g e                                                     %
1400 %                                                                             %
1401 %                                                                             %
1402 %                                                                             %
1403 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1404 %
1405 %  DitherImage() distributes the difference between an original image and
1406 %  the corresponding color reduced algorithm to neighboring pixels using
1407 %  serpentine-scan Floyd-Steinberg error diffusion. DitherImage returns
1408 %  MagickTrue if the image is dithered otherwise MagickFalse.
1409 %
1410 %  The format of the DitherImage method is:
1411 %
1412 %      MagickBooleanType DitherImage(Image *image,CubeInfo *cube_info,
1413 %        ExceptionInfo *exception)
1414 %
1415 %  A description of each parameter follows.
1416 %
1417 %    o image: the image.
1418 %
1419 %    o cube_info: A pointer to the Cube structure.
1420 %
1421 %    o exception: return any errors or warnings in this structure.
1422 %
1423 */
1424 
DestroyPixelThreadSet(DoublePixelPacket ** pixels)1425 static DoublePixelPacket **DestroyPixelThreadSet(DoublePixelPacket **pixels)
1426 {
1427   register ssize_t
1428     i;
1429 
1430   assert(pixels != (DoublePixelPacket **) NULL);
1431   for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
1432     if (pixels[i] != (DoublePixelPacket *) NULL)
1433       pixels[i]=(DoublePixelPacket *) RelinquishMagickMemory(pixels[i]);
1434   pixels=(DoublePixelPacket **) RelinquishMagickMemory(pixels);
1435   return(pixels);
1436 }
1437 
AcquirePixelThreadSet(const size_t count)1438 static DoublePixelPacket **AcquirePixelThreadSet(const size_t count)
1439 {
1440   DoublePixelPacket
1441     **pixels;
1442 
1443   register ssize_t
1444     i;
1445 
1446   size_t
1447     number_threads;
1448 
1449   number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
1450   pixels=(DoublePixelPacket **) AcquireQuantumMemory(number_threads,
1451     sizeof(*pixels));
1452   if (pixels == (DoublePixelPacket **) NULL)
1453     return((DoublePixelPacket **) NULL);
1454   (void) memset(pixels,0,number_threads*sizeof(*pixels));
1455   for (i=0; i < (ssize_t) number_threads; i++)
1456   {
1457     pixels[i]=(DoublePixelPacket *) AcquireQuantumMemory(count,2*
1458       sizeof(**pixels));
1459     if (pixels[i] == (DoublePixelPacket *) NULL)
1460       return(DestroyPixelThreadSet(pixels));
1461   }
1462   return(pixels);
1463 }
1464 
CacheOffset(CubeInfo * cube_info,const DoublePixelPacket * pixel)1465 static inline ssize_t CacheOffset(CubeInfo *cube_info,
1466   const DoublePixelPacket *pixel)
1467 {
1468 #define RedShift(pixel) (((pixel) >> CacheShift) << (0*(8-CacheShift)))
1469 #define GreenShift(pixel) (((pixel) >> CacheShift) << (1*(8-CacheShift)))
1470 #define BlueShift(pixel) (((pixel) >> CacheShift) << (2*(8-CacheShift)))
1471 #define AlphaShift(pixel) (((pixel) >> CacheShift) << (3*(8-CacheShift)))
1472 
1473   ssize_t
1474     offset;
1475 
1476   offset=(ssize_t) (RedShift(ScaleQuantumToChar(ClampPixel(pixel->red))) |
1477     GreenShift(ScaleQuantumToChar(ClampPixel(pixel->green))) |
1478     BlueShift(ScaleQuantumToChar(ClampPixel(pixel->blue))));
1479   if (cube_info->associate_alpha != MagickFalse)
1480     offset|=AlphaShift(ScaleQuantumToChar(ClampPixel(pixel->alpha)));
1481   return(offset);
1482 }
1483 
FloydSteinbergDither(Image * image,CubeInfo * cube_info,ExceptionInfo * exception)1484 static MagickBooleanType FloydSteinbergDither(Image *image,CubeInfo *cube_info,
1485   ExceptionInfo *exception)
1486 {
1487 #define DitherImageTag  "Dither/Image"
1488 
1489   CacheView
1490     *image_view;
1491 
1492   const char
1493     *artifact;
1494 
1495   double
1496     amount;
1497 
1498   DoublePixelPacket
1499     **pixels;
1500 
1501   MagickBooleanType
1502     status;
1503 
1504   ssize_t
1505     y;
1506 
1507   /*
1508     Distribute quantization error using Floyd-Steinberg.
1509   */
1510   pixels=AcquirePixelThreadSet(image->columns);
1511   if (pixels == (DoublePixelPacket **) NULL)
1512     return(MagickFalse);
1513   status=MagickTrue;
1514   amount=1.0;
1515   artifact=GetImageArtifact(image,"dither:diffusion-amount");
1516   if (artifact != (const char *) NULL)
1517     amount=StringToDoubleInterval(artifact,1.0);
1518   image_view=AcquireAuthenticCacheView(image,exception);
1519   for (y=0; y < (ssize_t) image->rows; y++)
1520   {
1521     const int
1522       id = GetOpenMPThreadId();
1523 
1524     CubeInfo
1525       cube;
1526 
1527     DoublePixelPacket
1528       *current,
1529       *previous;
1530 
1531     register Quantum
1532       *magick_restrict q;
1533 
1534     register ssize_t
1535       x;
1536 
1537     size_t
1538       index;
1539 
1540     ssize_t
1541       v;
1542 
1543     if (status == MagickFalse)
1544       continue;
1545     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1546     if (q == (Quantum *) NULL)
1547       {
1548         status=MagickFalse;
1549         continue;
1550       }
1551     cube=(*cube_info);
1552     current=pixels[id]+(y & 0x01)*image->columns;
1553     previous=pixels[id]+((y+1) & 0x01)*image->columns;
1554     v=(ssize_t) ((y & 0x01) != 0 ? -1 : 1);
1555     for (x=0; x < (ssize_t) image->columns; x++)
1556     {
1557       DoublePixelPacket
1558         color,
1559         pixel;
1560 
1561       register ssize_t
1562         i;
1563 
1564       ssize_t
1565         u;
1566 
1567       u=(y & 0x01) != 0 ? (ssize_t) image->columns-1-x : x;
1568       AssociateAlphaPixel(image,&cube,q+u*GetPixelChannels(image),&pixel);
1569       if (x > 0)
1570         {
1571           pixel.red+=7.0*amount*current[u-v].red/16;
1572           pixel.green+=7.0*amount*current[u-v].green/16;
1573           pixel.blue+=7.0*amount*current[u-v].blue/16;
1574           if (cube.associate_alpha != MagickFalse)
1575             pixel.alpha+=7.0*amount*current[u-v].alpha/16;
1576         }
1577       if (y > 0)
1578         {
1579           if (x < (ssize_t) (image->columns-1))
1580             {
1581               pixel.red+=previous[u+v].red/16;
1582               pixel.green+=previous[u+v].green/16;
1583               pixel.blue+=previous[u+v].blue/16;
1584               if (cube.associate_alpha != MagickFalse)
1585                 pixel.alpha+=previous[u+v].alpha/16;
1586             }
1587           pixel.red+=5.0*amount*previous[u].red/16;
1588           pixel.green+=5.0*amount*previous[u].green/16;
1589           pixel.blue+=5.0*amount*previous[u].blue/16;
1590           if (cube.associate_alpha != MagickFalse)
1591             pixel.alpha+=5.0*amount*previous[u].alpha/16;
1592           if (x > 0)
1593             {
1594               pixel.red+=3.0*amount*previous[u-v].red/16;
1595               pixel.green+=3.0*amount*previous[u-v].green/16;
1596               pixel.blue+=3.0*amount*previous[u-v].blue/16;
1597               if (cube.associate_alpha != MagickFalse)
1598                 pixel.alpha+=3.0*amount*previous[u-v].alpha/16;
1599             }
1600         }
1601       pixel.red=(double) ClampPixel(pixel.red);
1602       pixel.green=(double) ClampPixel(pixel.green);
1603       pixel.blue=(double) ClampPixel(pixel.blue);
1604       if (cube.associate_alpha != MagickFalse)
1605         pixel.alpha=(double) ClampPixel(pixel.alpha);
1606       i=CacheOffset(&cube,&pixel);
1607       if (cube.cache[i] < 0)
1608         {
1609           register NodeInfo
1610             *node_info;
1611 
1612           register size_t
1613             node_id;
1614 
1615           /*
1616             Identify the deepest node containing the pixel's color.
1617           */
1618           node_info=cube.root;
1619           for (index=MaxTreeDepth-1; (ssize_t) index > 0; index--)
1620           {
1621             node_id=ColorToNodeId(&cube,&pixel,index);
1622             if (node_info->child[node_id] == (NodeInfo *) NULL)
1623               break;
1624             node_info=node_info->child[node_id];
1625           }
1626           /*
1627             Find closest color among siblings and their children.
1628           */
1629           cube.target=pixel;
1630           cube.distance=(double) (4.0*(QuantumRange+1.0)*(QuantumRange+1.0)+
1631             1.0);
1632           ClosestColor(image,&cube,node_info->parent);
1633           cube.cache[i]=(ssize_t) cube.color_number;
1634         }
1635       /*
1636         Assign pixel to closest colormap entry.
1637       */
1638       index=(size_t) cube.cache[i];
1639       if (image->storage_class == PseudoClass)
1640         SetPixelIndex(image,(Quantum) index,q+u*GetPixelChannels(image));
1641       if (cube.quantize_info->measure_error == MagickFalse)
1642         {
1643           SetPixelRed(image,ClampToQuantum(image->colormap[index].red),
1644             q+u*GetPixelChannels(image));
1645           SetPixelGreen(image,ClampToQuantum(image->colormap[index].green),
1646             q+u*GetPixelChannels(image));
1647           SetPixelBlue(image,ClampToQuantum(image->colormap[index].blue),
1648             q+u*GetPixelChannels(image));
1649           if (cube.associate_alpha != MagickFalse)
1650             SetPixelAlpha(image,ClampToQuantum(image->colormap[index].alpha),
1651               q+u*GetPixelChannels(image));
1652         }
1653       if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1654         status=MagickFalse;
1655       /*
1656         Store the error.
1657       */
1658       AssociateAlphaPixelInfo(&cube,image->colormap+index,&color);
1659       current[u].red=pixel.red-color.red;
1660       current[u].green=pixel.green-color.green;
1661       current[u].blue=pixel.blue-color.blue;
1662       if (cube.associate_alpha != MagickFalse)
1663         current[u].alpha=pixel.alpha-color.alpha;
1664       if (image->progress_monitor != (MagickProgressMonitor) NULL)
1665         {
1666           MagickBooleanType
1667             proceed;
1668 
1669           proceed=SetImageProgress(image,DitherImageTag,(MagickOffsetType) y,
1670             image->rows);
1671           if (proceed == MagickFalse)
1672             status=MagickFalse;
1673         }
1674     }
1675   }
1676   image_view=DestroyCacheView(image_view);
1677   pixels=DestroyPixelThreadSet(pixels);
1678   return(MagickTrue);
1679 }
1680 
1681 static MagickBooleanType
1682   RiemersmaDither(Image *,CacheView *,CubeInfo *,const unsigned int,
1683     ExceptionInfo *);
1684 
Riemersma(Image * image,CacheView * image_view,CubeInfo * cube_info,const size_t level,const unsigned int direction,ExceptionInfo * exception)1685 static void Riemersma(Image *image,CacheView *image_view,CubeInfo *cube_info,
1686   const size_t level,const unsigned int direction,ExceptionInfo *exception)
1687 {
1688   if (level == 1)
1689     switch (direction)
1690     {
1691       case WestGravity:
1692       {
1693         (void) RiemersmaDither(image,image_view,cube_info,EastGravity,
1694           exception);
1695         (void) RiemersmaDither(image,image_view,cube_info,SouthGravity,
1696           exception);
1697         (void) RiemersmaDither(image,image_view,cube_info,WestGravity,
1698           exception);
1699         break;
1700       }
1701       case EastGravity:
1702       {
1703         (void) RiemersmaDither(image,image_view,cube_info,WestGravity,
1704           exception);
1705         (void) RiemersmaDither(image,image_view,cube_info,NorthGravity,
1706           exception);
1707         (void) RiemersmaDither(image,image_view,cube_info,EastGravity,
1708           exception);
1709         break;
1710       }
1711       case NorthGravity:
1712       {
1713         (void) RiemersmaDither(image,image_view,cube_info,SouthGravity,
1714           exception);
1715         (void) RiemersmaDither(image,image_view,cube_info,EastGravity,
1716           exception);
1717         (void) RiemersmaDither(image,image_view,cube_info,NorthGravity,
1718           exception);
1719         break;
1720       }
1721       case SouthGravity:
1722       {
1723         (void) RiemersmaDither(image,image_view,cube_info,NorthGravity,
1724           exception);
1725         (void) RiemersmaDither(image,image_view,cube_info,WestGravity,
1726           exception);
1727         (void) RiemersmaDither(image,image_view,cube_info,SouthGravity,
1728           exception);
1729         break;
1730       }
1731       default:
1732         break;
1733     }
1734   else
1735     switch (direction)
1736     {
1737       case WestGravity:
1738       {
1739         Riemersma(image,image_view,cube_info,level-1,NorthGravity,
1740           exception);
1741         (void) RiemersmaDither(image,image_view,cube_info,EastGravity,
1742           exception);
1743         Riemersma(image,image_view,cube_info,level-1,WestGravity,
1744           exception);
1745         (void) RiemersmaDither(image,image_view,cube_info,SouthGravity,
1746           exception);
1747         Riemersma(image,image_view,cube_info,level-1,WestGravity,
1748           exception);
1749         (void) RiemersmaDither(image,image_view,cube_info,WestGravity,
1750           exception);
1751         Riemersma(image,image_view,cube_info,level-1,SouthGravity,
1752           exception);
1753         break;
1754       }
1755       case EastGravity:
1756       {
1757         Riemersma(image,image_view,cube_info,level-1,SouthGravity,
1758           exception);
1759         (void) RiemersmaDither(image,image_view,cube_info,WestGravity,
1760           exception);
1761         Riemersma(image,image_view,cube_info,level-1,EastGravity,
1762           exception);
1763         (void) RiemersmaDither(image,image_view,cube_info,NorthGravity,
1764           exception);
1765         Riemersma(image,image_view,cube_info,level-1,EastGravity,
1766           exception);
1767         (void) RiemersmaDither(image,image_view,cube_info,EastGravity,
1768           exception);
1769         Riemersma(image,image_view,cube_info,level-1,NorthGravity,
1770           exception);
1771         break;
1772       }
1773       case NorthGravity:
1774       {
1775         Riemersma(image,image_view,cube_info,level-1,WestGravity,
1776           exception);
1777         (void) RiemersmaDither(image,image_view,cube_info,SouthGravity,
1778           exception);
1779         Riemersma(image,image_view,cube_info,level-1,NorthGravity,
1780           exception);
1781         (void) RiemersmaDither(image,image_view,cube_info,EastGravity,
1782           exception);
1783         Riemersma(image,image_view,cube_info,level-1,NorthGravity,
1784           exception);
1785         (void) RiemersmaDither(image,image_view,cube_info,NorthGravity,
1786           exception);
1787         Riemersma(image,image_view,cube_info,level-1,EastGravity,
1788           exception);
1789         break;
1790       }
1791       case SouthGravity:
1792       {
1793         Riemersma(image,image_view,cube_info,level-1,EastGravity,
1794           exception);
1795         (void) RiemersmaDither(image,image_view,cube_info,NorthGravity,
1796           exception);
1797         Riemersma(image,image_view,cube_info,level-1,SouthGravity,
1798           exception);
1799         (void) RiemersmaDither(image,image_view,cube_info,WestGravity,
1800           exception);
1801         Riemersma(image,image_view,cube_info,level-1,SouthGravity,
1802           exception);
1803         (void) RiemersmaDither(image,image_view,cube_info,SouthGravity,
1804           exception);
1805         Riemersma(image,image_view,cube_info,level-1,WestGravity,
1806           exception);
1807         break;
1808       }
1809       default:
1810         break;
1811     }
1812 }
1813 
RiemersmaDither(Image * image,CacheView * image_view,CubeInfo * cube_info,const unsigned int direction,ExceptionInfo * exception)1814 static MagickBooleanType RiemersmaDither(Image *image,CacheView *image_view,
1815   CubeInfo *cube_info,const unsigned int direction,ExceptionInfo *exception)
1816 {
1817 #define DitherImageTag  "Dither/Image"
1818 
1819   DoublePixelPacket
1820     color,
1821     pixel;
1822 
1823   MagickBooleanType
1824     proceed;
1825 
1826   register CubeInfo
1827     *p;
1828 
1829   size_t
1830     index;
1831 
1832   p=cube_info;
1833   if ((p->x >= 0) && (p->x < (ssize_t) image->columns) &&
1834       (p->y >= 0) && (p->y < (ssize_t) image->rows))
1835     {
1836       register Quantum
1837         *magick_restrict q;
1838 
1839       register ssize_t
1840         i;
1841 
1842       /*
1843         Distribute error.
1844       */
1845       q=GetCacheViewAuthenticPixels(image_view,p->x,p->y,1,1,exception);
1846       if (q == (Quantum *) NULL)
1847         return(MagickFalse);
1848       AssociateAlphaPixel(image,cube_info,q,&pixel);
1849       for (i=0; i < ErrorQueueLength; i++)
1850       {
1851         pixel.red+=p->weights[i]*p->error[i].red;
1852         pixel.green+=p->weights[i]*p->error[i].green;
1853         pixel.blue+=p->weights[i]*p->error[i].blue;
1854         if (cube_info->associate_alpha != MagickFalse)
1855           pixel.alpha+=p->weights[i]*p->error[i].alpha;
1856       }
1857       pixel.red=(double) ClampPixel(pixel.red);
1858       pixel.green=(double) ClampPixel(pixel.green);
1859       pixel.blue=(double) ClampPixel(pixel.blue);
1860       if (cube_info->associate_alpha != MagickFalse)
1861         pixel.alpha=(double) ClampPixel(pixel.alpha);
1862       i=CacheOffset(cube_info,&pixel);
1863       if (p->cache[i] < 0)
1864         {
1865           register NodeInfo
1866             *node_info;
1867 
1868           register size_t
1869             id;
1870 
1871           /*
1872             Identify the deepest node containing the pixel's color.
1873           */
1874           node_info=p->root;
1875           for (index=MaxTreeDepth-1; (ssize_t) index > 0; index--)
1876           {
1877             id=ColorToNodeId(cube_info,&pixel,index);
1878             if (node_info->child[id] == (NodeInfo *) NULL)
1879               break;
1880             node_info=node_info->child[id];
1881           }
1882           /*
1883             Find closest color among siblings and their children.
1884           */
1885           p->target=pixel;
1886           p->distance=(double) (4.0*(QuantumRange+1.0)*((double)
1887             QuantumRange+1.0)+1.0);
1888           ClosestColor(image,p,node_info->parent);
1889           p->cache[i]=(ssize_t) p->color_number;
1890         }
1891       /*
1892         Assign pixel to closest colormap entry.
1893       */
1894       index=(size_t) p->cache[i];
1895       if (image->storage_class == PseudoClass)
1896         SetPixelIndex(image,(Quantum) index,q);
1897       if (cube_info->quantize_info->measure_error == MagickFalse)
1898         {
1899           SetPixelRed(image,ClampToQuantum(image->colormap[index].red),q);
1900           SetPixelGreen(image,ClampToQuantum(image->colormap[index].green),q);
1901           SetPixelBlue(image,ClampToQuantum(image->colormap[index].blue),q);
1902           if (cube_info->associate_alpha != MagickFalse)
1903             SetPixelAlpha(image,ClampToQuantum(image->colormap[index].alpha),q);
1904         }
1905       if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1906         return(MagickFalse);
1907       /*
1908         Propagate the error as the last entry of the error queue.
1909       */
1910       (void) memmove(p->error,p->error+1,(ErrorQueueLength-1)*
1911         sizeof(p->error[0]));
1912       AssociateAlphaPixelInfo(cube_info,image->colormap+index,&color);
1913       p->error[ErrorQueueLength-1].red=pixel.red-color.red;
1914       p->error[ErrorQueueLength-1].green=pixel.green-color.green;
1915       p->error[ErrorQueueLength-1].blue=pixel.blue-color.blue;
1916       if (cube_info->associate_alpha != MagickFalse)
1917         p->error[ErrorQueueLength-1].alpha=pixel.alpha-color.alpha;
1918       proceed=SetImageProgress(image,DitherImageTag,p->offset,p->span);
1919       if (proceed == MagickFalse)
1920         return(MagickFalse);
1921       p->offset++;
1922     }
1923   switch (direction)
1924   {
1925     case WestGravity: p->x--; break;
1926     case EastGravity: p->x++; break;
1927     case NorthGravity: p->y--; break;
1928     case SouthGravity: p->y++; break;
1929   }
1930   return(MagickTrue);
1931 }
1932 
DitherImage(Image * image,CubeInfo * cube_info,ExceptionInfo * exception)1933 static MagickBooleanType DitherImage(Image *image,CubeInfo *cube_info,
1934   ExceptionInfo *exception)
1935 {
1936   CacheView
1937     *image_view;
1938 
1939   MagickBooleanType
1940     status;
1941 
1942   register ssize_t
1943     i;
1944 
1945   size_t
1946     depth;
1947 
1948   if (cube_info->quantize_info->dither_method != RiemersmaDitherMethod)
1949     return(FloydSteinbergDither(image,cube_info,exception));
1950   /*
1951     Distribute quantization error along a Hilbert curve.
1952   */
1953   (void) memset(cube_info->error,0,ErrorQueueLength*
1954     sizeof(*cube_info->error));
1955   cube_info->x=0;
1956   cube_info->y=0;
1957   i=MagickMax((ssize_t) image->columns,(ssize_t) image->rows);
1958   for (depth=1; i != 0; depth++)
1959     i>>=1;
1960   if ((ssize_t) (1L << depth) < MagickMax((ssize_t) image->columns,(ssize_t) image->rows))
1961     depth++;
1962   cube_info->offset=0;
1963   cube_info->span=(MagickSizeType) image->columns*image->rows;
1964   image_view=AcquireAuthenticCacheView(image,exception);
1965   if (depth > 1)
1966     Riemersma(image,image_view,cube_info,depth-1,NorthGravity,exception);
1967   status=RiemersmaDither(image,image_view,cube_info,ForgetGravity,exception);
1968   image_view=DestroyCacheView(image_view);
1969   return(status);
1970 }
1971 
1972 /*
1973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1974 %                                                                             %
1975 %                                                                             %
1976 %                                                                             %
1977 +   G e t C u b e I n f o                                                     %
1978 %                                                                             %
1979 %                                                                             %
1980 %                                                                             %
1981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1982 %
1983 %  GetCubeInfo() initialize the Cube data structure.
1984 %
1985 %  The format of the GetCubeInfo method is:
1986 %
1987 %      CubeInfo GetCubeInfo(const QuantizeInfo *quantize_info,
1988 %        const size_t depth,const size_t maximum_colors)
1989 %
1990 %  A description of each parameter follows.
1991 %
1992 %    o quantize_info: Specifies a pointer to an QuantizeInfo structure.
1993 %
1994 %    o depth: Normally, this integer value is zero or one.  A zero or
1995 %      one tells Quantize to choose a optimal tree depth of Log4(number_colors).
1996 %      A tree of this depth generally allows the best representation of the
1997 %      reference image with the least amount of memory and the fastest
1998 %      computational speed.  In some cases, such as an image with low color
1999 %      dispersion (a few number of colors), a value other than
2000 %      Log4(number_colors) is required.  To expand the color tree completely,
2001 %      use a value of 8.
2002 %
2003 %    o maximum_colors: maximum colors.
2004 %
2005 */
GetCubeInfo(const QuantizeInfo * quantize_info,const size_t depth,const size_t maximum_colors)2006 static CubeInfo *GetCubeInfo(const QuantizeInfo *quantize_info,
2007   const size_t depth,const size_t maximum_colors)
2008 {
2009   CubeInfo
2010     *cube_info;
2011 
2012   double
2013     sum,
2014     weight;
2015 
2016   register ssize_t
2017     i;
2018 
2019   size_t
2020     length;
2021 
2022   /*
2023     Initialize tree to describe color cube_info.
2024   */
2025   cube_info=(CubeInfo *) AcquireMagickMemory(sizeof(*cube_info));
2026   if (cube_info == (CubeInfo *) NULL)
2027     return((CubeInfo *) NULL);
2028   (void) memset(cube_info,0,sizeof(*cube_info));
2029   cube_info->depth=depth;
2030   if (cube_info->depth > MaxTreeDepth)
2031     cube_info->depth=MaxTreeDepth;
2032   if (cube_info->depth < 2)
2033     cube_info->depth=2;
2034   cube_info->maximum_colors=maximum_colors;
2035   /*
2036     Initialize root node.
2037   */
2038   cube_info->root=GetNodeInfo(cube_info,0,0,(NodeInfo *) NULL);
2039   if (cube_info->root == (NodeInfo *) NULL)
2040     return((CubeInfo *) NULL);
2041   cube_info->root->parent=cube_info->root;
2042   cube_info->quantize_info=CloneQuantizeInfo(quantize_info);
2043   if (cube_info->quantize_info->dither_method == NoDitherMethod)
2044     return(cube_info);
2045   /*
2046     Initialize dither resources.
2047   */
2048   length=(size_t) (1UL << (4*(8-CacheShift)));
2049   cube_info->memory_info=AcquireVirtualMemory(length,sizeof(*cube_info->cache));
2050   if (cube_info->memory_info == (MemoryInfo *) NULL)
2051     return((CubeInfo *) NULL);
2052   cube_info->cache=(ssize_t *) GetVirtualMemoryBlob(cube_info->memory_info);
2053   /*
2054     Initialize color cache.
2055   */
2056   (void) memset(cube_info->cache,(-1),sizeof(*cube_info->cache)*
2057     length);
2058   /*
2059     Distribute weights along a curve of exponential decay.
2060   */
2061   weight=1.0;
2062   for (i=0; i < ErrorQueueLength; i++)
2063   {
2064     cube_info->weights[ErrorQueueLength-i-1]=PerceptibleReciprocal(weight);
2065     weight*=exp(log(((double) QuantumRange+1.0))/(ErrorQueueLength-1.0));
2066   }
2067   /*
2068     Normalize the weighting factors.
2069   */
2070   weight=0.0;
2071   for (i=0; i < ErrorQueueLength; i++)
2072     weight+=cube_info->weights[i];
2073   sum=0.0;
2074   for (i=0; i < ErrorQueueLength; i++)
2075   {
2076     cube_info->weights[i]/=weight;
2077     sum+=cube_info->weights[i];
2078   }
2079   cube_info->weights[0]+=1.0-sum;
2080   return(cube_info);
2081 }
2082 
2083 /*
2084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2085 %                                                                             %
2086 %                                                                             %
2087 %                                                                             %
2088 +   G e t N o d e I n f o                                                     %
2089 %                                                                             %
2090 %                                                                             %
2091 %                                                                             %
2092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2093 %
2094 %  GetNodeInfo() allocates memory for a new node in the color cube tree and
2095 %  presets all fields to zero.
2096 %
2097 %  The format of the GetNodeInfo method is:
2098 %
2099 %      NodeInfo *GetNodeInfo(CubeInfo *cube_info,const size_t id,
2100 %        const size_t level,NodeInfo *parent)
2101 %
2102 %  A description of each parameter follows.
2103 %
2104 %    o node: The GetNodeInfo method returns a pointer to a queue of nodes.
2105 %
2106 %    o id: Specifies the child number of the node.
2107 %
2108 %    o level: Specifies the level in the storage_class the node resides.
2109 %
2110 */
GetNodeInfo(CubeInfo * cube_info,const size_t id,const size_t level,NodeInfo * parent)2111 static NodeInfo *GetNodeInfo(CubeInfo *cube_info,const size_t id,
2112   const size_t level,NodeInfo *parent)
2113 {
2114   NodeInfo
2115     *node_info;
2116 
2117   if (cube_info->free_nodes == 0)
2118     {
2119       Nodes
2120         *nodes;
2121 
2122       /*
2123         Allocate a new queue of nodes.
2124       */
2125       nodes=(Nodes *) AcquireMagickMemory(sizeof(*nodes));
2126       if (nodes == (Nodes *) NULL)
2127         return((NodeInfo *) NULL);
2128       nodes->nodes=(NodeInfo *) AcquireQuantumMemory(NodesInAList,
2129         sizeof(*nodes->nodes));
2130       if (nodes->nodes == (NodeInfo *) NULL)
2131         return((NodeInfo *) NULL);
2132       nodes->next=cube_info->node_queue;
2133       cube_info->node_queue=nodes;
2134       cube_info->next_node=nodes->nodes;
2135       cube_info->free_nodes=NodesInAList;
2136     }
2137   cube_info->nodes++;
2138   cube_info->free_nodes--;
2139   node_info=cube_info->next_node++;
2140   (void) memset(node_info,0,sizeof(*node_info));
2141   node_info->parent=parent;
2142   node_info->id=id;
2143   node_info->level=level;
2144   return(node_info);
2145 }
2146 
2147 /*
2148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2149 %                                                                             %
2150 %                                                                             %
2151 %                                                                             %
2152 %  G e t I m a g e Q u a n t i z e E r r o r                                  %
2153 %                                                                             %
2154 %                                                                             %
2155 %                                                                             %
2156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2157 %
2158 %  GetImageQuantizeError() measures the difference between the original
2159 %  and quantized images.  This difference is the total quantization error.
2160 %  The error is computed by summing over all pixels in an image the distance
2161 %  squared in RGB space between each reference pixel value and its quantized
2162 %  value.  These values are computed:
2163 %
2164 %    o mean_error_per_pixel:  This value is the mean error for any single
2165 %      pixel in the image.
2166 %
2167 %    o normalized_mean_square_error:  This value is the normalized mean
2168 %      quantization error for any single pixel in the image.  This distance
2169 %      measure is normalized to a range between 0 and 1.  It is independent
2170 %      of the range of red, green, and blue values in the image.
2171 %
2172 %    o normalized_maximum_square_error:  Thsi value is the normalized
2173 %      maximum quantization error for any single pixel in the image.  This
2174 %      distance measure is normalized to a range between 0 and 1.  It is
2175 %      independent of the range of red, green, and blue values in your image.
2176 %
2177 %  The format of the GetImageQuantizeError method is:
2178 %
2179 %      MagickBooleanType GetImageQuantizeError(Image *image,
2180 %        ExceptionInfo *exception)
2181 %
2182 %  A description of each parameter follows.
2183 %
2184 %    o image: the image.
2185 %
2186 %    o exception: return any errors or warnings in this structure.
2187 %
2188 */
GetImageQuantizeError(Image * image,ExceptionInfo * exception)2189 MagickExport MagickBooleanType GetImageQuantizeError(Image *image,
2190   ExceptionInfo *exception)
2191 {
2192   CacheView
2193     *image_view;
2194 
2195   double
2196     alpha,
2197     area,
2198     beta,
2199     distance,
2200     maximum_error,
2201     mean_error,
2202     mean_error_per_pixel;
2203 
2204   size_t
2205     index;
2206 
2207   ssize_t
2208     y;
2209 
2210   assert(image != (Image *) NULL);
2211   assert(image->signature == MagickCoreSignature);
2212   if (image->debug != MagickFalse)
2213     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2214   image->total_colors=GetNumberColors(image,(FILE *) NULL,exception);
2215   (void) memset(&image->error,0,sizeof(image->error));
2216   if (image->storage_class == DirectClass)
2217     return(MagickTrue);
2218   alpha=1.0;
2219   beta=1.0;
2220   area=3.0*image->columns*image->rows;
2221   maximum_error=0.0;
2222   mean_error_per_pixel=0.0;
2223   mean_error=0.0;
2224   image_view=AcquireVirtualCacheView(image,exception);
2225   for (y=0; y < (ssize_t) image->rows; y++)
2226   {
2227     register const Quantum
2228       *magick_restrict p;
2229 
2230     register ssize_t
2231       x;
2232 
2233     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
2234     if (p == (const Quantum *) NULL)
2235       break;
2236     for (x=0; x < (ssize_t) image->columns; x++)
2237     {
2238       index=GetPixelIndex(image,p);
2239       if (image->alpha_trait == BlendPixelTrait)
2240         {
2241           alpha=(double) (QuantumScale*GetPixelAlpha(image,p));
2242           beta=(double) (QuantumScale*image->colormap[index].alpha);
2243         }
2244       distance=fabs((double) (alpha*GetPixelRed(image,p)-beta*
2245         image->colormap[index].red));
2246       mean_error_per_pixel+=distance;
2247       mean_error+=distance*distance;
2248       if (distance > maximum_error)
2249         maximum_error=distance;
2250       distance=fabs((double) (alpha*GetPixelGreen(image,p)-beta*
2251         image->colormap[index].green));
2252       mean_error_per_pixel+=distance;
2253       mean_error+=distance*distance;
2254       if (distance > maximum_error)
2255         maximum_error=distance;
2256       distance=fabs((double) (alpha*GetPixelBlue(image,p)-beta*
2257         image->colormap[index].blue));
2258       mean_error_per_pixel+=distance;
2259       mean_error+=distance*distance;
2260       if (distance > maximum_error)
2261         maximum_error=distance;
2262       p+=GetPixelChannels(image);
2263     }
2264   }
2265   image_view=DestroyCacheView(image_view);
2266   image->error.mean_error_per_pixel=(double) mean_error_per_pixel/area;
2267   image->error.normalized_mean_error=(double) QuantumScale*QuantumScale*
2268     mean_error/area;
2269   image->error.normalized_maximum_error=(double) QuantumScale*maximum_error;
2270   return(MagickTrue);
2271 }
2272 
2273 /*
2274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2275 %                                                                             %
2276 %                                                                             %
2277 %                                                                             %
2278 %   G e t Q u a n t i z e I n f o                                             %
2279 %                                                                             %
2280 %                                                                             %
2281 %                                                                             %
2282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2283 %
2284 %  GetQuantizeInfo() initializes the QuantizeInfo structure.
2285 %
2286 %  The format of the GetQuantizeInfo method is:
2287 %
2288 %      GetQuantizeInfo(QuantizeInfo *quantize_info)
2289 %
2290 %  A description of each parameter follows:
2291 %
2292 %    o quantize_info: Specifies a pointer to a QuantizeInfo structure.
2293 %
2294 */
GetQuantizeInfo(QuantizeInfo * quantize_info)2295 MagickExport void GetQuantizeInfo(QuantizeInfo *quantize_info)
2296 {
2297   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2298   assert(quantize_info != (QuantizeInfo *) NULL);
2299   (void) memset(quantize_info,0,sizeof(*quantize_info));
2300   quantize_info->number_colors=256;
2301   quantize_info->dither_method=RiemersmaDitherMethod;
2302   quantize_info->colorspace=UndefinedColorspace;
2303   quantize_info->measure_error=MagickFalse;
2304   quantize_info->signature=MagickCoreSignature;
2305 }
2306 
2307 /*
2308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2309 %                                                                             %
2310 %                                                                             %
2311 %                                                                             %
2312 %     P o s t e r i z e I m a g e                                             %
2313 %                                                                             %
2314 %                                                                             %
2315 %                                                                             %
2316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2317 %
2318 %  PosterizeImage() reduces the image to a limited number of colors for a
2319 %  "poster" effect.
2320 %
2321 %  The format of the PosterizeImage method is:
2322 %
2323 %      MagickBooleanType PosterizeImage(Image *image,const size_t levels,
2324 %        const DitherMethod dither_method,ExceptionInfo *exception)
2325 %
2326 %  A description of each parameter follows:
2327 %
2328 %    o image: Specifies a pointer to an Image structure.
2329 %
2330 %    o levels: Number of color levels allowed in each channel.  Very low values
2331 %      (2, 3, or 4) have the most visible effect.
2332 %
2333 %    o dither_method: choose from UndefinedDitherMethod, NoDitherMethod,
2334 %      RiemersmaDitherMethod, FloydSteinbergDitherMethod.
2335 %
2336 %    o exception: return any errors or warnings in this structure.
2337 %
2338 */
2339 
MagickRound(double x)2340 static inline double MagickRound(double x)
2341 {
2342   /*
2343     Round the fraction to nearest integer.
2344   */
2345   if ((x-floor(x)) < (ceil(x)-x))
2346     return(floor(x));
2347   return(ceil(x));
2348 }
2349 
PosterizeImage(Image * image,const size_t levels,const DitherMethod dither_method,ExceptionInfo * exception)2350 MagickExport MagickBooleanType PosterizeImage(Image *image,const size_t levels,
2351   const DitherMethod dither_method,ExceptionInfo *exception)
2352 {
2353 #define PosterizeImageTag  "Posterize/Image"
2354 #define PosterizePixel(pixel) (Quantum) (QuantumRange*(MagickRound( \
2355   QuantumScale*pixel*(levels-1)))/MagickMax((ssize_t) levels-1,1))
2356 
2357   CacheView
2358     *image_view;
2359 
2360   MagickBooleanType
2361     status;
2362 
2363   MagickOffsetType
2364     progress;
2365 
2366   QuantizeInfo
2367     *quantize_info;
2368 
2369   register ssize_t
2370     i;
2371 
2372   ssize_t
2373     y;
2374 
2375   assert(image != (Image *) NULL);
2376   assert(image->signature == MagickCoreSignature);
2377   if (image->debug != MagickFalse)
2378     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2379   assert(exception != (ExceptionInfo *) NULL);
2380   assert(exception->signature == MagickCoreSignature);
2381   if (image->storage_class == PseudoClass)
2382 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2383     #pragma omp parallel for schedule(static) shared(progress,status) \
2384       magick_number_threads(image,image,image->colors,1)
2385 #endif
2386     for (i=0; i < (ssize_t) image->colors; i++)
2387     {
2388       /*
2389         Posterize colormap.
2390       */
2391       if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
2392         image->colormap[i].red=(double)
2393           PosterizePixel(image->colormap[i].red);
2394       if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
2395         image->colormap[i].green=(double)
2396           PosterizePixel(image->colormap[i].green);
2397       if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
2398         image->colormap[i].blue=(double)
2399           PosterizePixel(image->colormap[i].blue);
2400       if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
2401         image->colormap[i].alpha=(double)
2402           PosterizePixel(image->colormap[i].alpha);
2403     }
2404   /*
2405     Posterize image.
2406   */
2407   status=MagickTrue;
2408   progress=0;
2409   image_view=AcquireAuthenticCacheView(image,exception);
2410 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2411   #pragma omp parallel for schedule(static) shared(progress,status) \
2412     magick_number_threads(image,image,image->rows,1)
2413 #endif
2414   for (y=0; y < (ssize_t) image->rows; y++)
2415   {
2416     register Quantum
2417       *magick_restrict q;
2418 
2419     register ssize_t
2420       x;
2421 
2422     if (status == MagickFalse)
2423       continue;
2424     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2425     if (q == (Quantum *) NULL)
2426       {
2427         status=MagickFalse;
2428         continue;
2429       }
2430     for (x=0; x < (ssize_t) image->columns; x++)
2431     {
2432       if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
2433         SetPixelRed(image,PosterizePixel(GetPixelRed(image,q)),q);
2434       if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
2435         SetPixelGreen(image,PosterizePixel(GetPixelGreen(image,q)),q);
2436       if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
2437         SetPixelBlue(image,PosterizePixel(GetPixelBlue(image,q)),q);
2438       if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
2439           (image->colorspace == CMYKColorspace))
2440         SetPixelBlack(image,PosterizePixel(GetPixelBlack(image,q)),q);
2441       if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
2442           (image->alpha_trait == BlendPixelTrait))
2443         SetPixelAlpha(image,PosterizePixel(GetPixelAlpha(image,q)),q);
2444       q+=GetPixelChannels(image);
2445     }
2446     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2447       status=MagickFalse;
2448     if (image->progress_monitor != (MagickProgressMonitor) NULL)
2449       {
2450         MagickBooleanType
2451           proceed;
2452 
2453 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2454         #pragma omp atomic
2455 #endif
2456         progress++;
2457         proceed=SetImageProgress(image,PosterizeImageTag,progress,image->rows);
2458         if (proceed == MagickFalse)
2459           status=MagickFalse;
2460       }
2461   }
2462   image_view=DestroyCacheView(image_view);
2463   quantize_info=AcquireQuantizeInfo((ImageInfo *) NULL);
2464   quantize_info->number_colors=(size_t) MagickMin((ssize_t) levels*levels*
2465     levels,MaxColormapSize+1);
2466   quantize_info->dither_method=dither_method;
2467   quantize_info->tree_depth=MaxTreeDepth;
2468   status=QuantizeImage(quantize_info,image,exception);
2469   quantize_info=DestroyQuantizeInfo(quantize_info);
2470   return(status);
2471 }
2472 
2473 /*
2474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2475 %                                                                             %
2476 %                                                                             %
2477 %                                                                             %
2478 +   P r u n e C h i l d                                                       %
2479 %                                                                             %
2480 %                                                                             %
2481 %                                                                             %
2482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2483 %
2484 %  PruneChild() deletes the given node and merges its statistics into its
2485 %  parent.
2486 %
2487 %  The format of the PruneSubtree method is:
2488 %
2489 %      PruneChild(CubeInfo *cube_info,const NodeInfo *node_info)
2490 %
2491 %  A description of each parameter follows.
2492 %
2493 %    o cube_info: A pointer to the Cube structure.
2494 %
2495 %    o node_info: pointer to node in color cube tree that is to be pruned.
2496 %
2497 */
PruneChild(CubeInfo * cube_info,const NodeInfo * node_info)2498 static void PruneChild(CubeInfo *cube_info,const NodeInfo *node_info)
2499 {
2500   NodeInfo
2501     *parent;
2502 
2503   register ssize_t
2504     i;
2505 
2506   size_t
2507     number_children;
2508 
2509   /*
2510     Traverse any children.
2511   */
2512   number_children=cube_info->associate_alpha == MagickFalse ? 8UL : 16UL;
2513   for (i=0; i < (ssize_t) number_children; i++)
2514     if (node_info->child[i] != (NodeInfo *) NULL)
2515       PruneChild(cube_info,node_info->child[i]);
2516   /*
2517     Merge color statistics into parent.
2518   */
2519   parent=node_info->parent;
2520   parent->number_unique+=node_info->number_unique;
2521   parent->total_color.red+=node_info->total_color.red;
2522   parent->total_color.green+=node_info->total_color.green;
2523   parent->total_color.blue+=node_info->total_color.blue;
2524   parent->total_color.alpha+=node_info->total_color.alpha;
2525   parent->child[node_info->id]=(NodeInfo *) NULL;
2526   cube_info->nodes--;
2527 }
2528 
2529 /*
2530 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2531 %                                                                             %
2532 %                                                                             %
2533 %                                                                             %
2534 +  P r u n e L e v e l                                                        %
2535 %                                                                             %
2536 %                                                                             %
2537 %                                                                             %
2538 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2539 %
2540 %  PruneLevel() deletes all nodes at the bottom level of the color tree merging
2541 %  their color statistics into their parent node.
2542 %
2543 %  The format of the PruneLevel method is:
2544 %
2545 %      PruneLevel(CubeInfo *cube_info,const NodeInfo *node_info)
2546 %
2547 %  A description of each parameter follows.
2548 %
2549 %    o cube_info: A pointer to the Cube structure.
2550 %
2551 %    o node_info: pointer to node in color cube tree that is to be pruned.
2552 %
2553 */
PruneLevel(CubeInfo * cube_info,const NodeInfo * node_info)2554 static void PruneLevel(CubeInfo *cube_info,const NodeInfo *node_info)
2555 {
2556   register ssize_t
2557     i;
2558 
2559   size_t
2560     number_children;
2561 
2562   /*
2563     Traverse any children.
2564   */
2565   number_children=cube_info->associate_alpha == MagickFalse ? 8UL : 16UL;
2566   for (i=0; i < (ssize_t) number_children; i++)
2567     if (node_info->child[i] != (NodeInfo *) NULL)
2568       PruneLevel(cube_info,node_info->child[i]);
2569   if (node_info->level == cube_info->depth)
2570     PruneChild(cube_info,node_info);
2571 }
2572 
2573 /*
2574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2575 %                                                                             %
2576 %                                                                             %
2577 %                                                                             %
2578 +  P r u n e T o C u b e D e p t h                                            %
2579 %                                                                             %
2580 %                                                                             %
2581 %                                                                             %
2582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2583 %
2584 %  PruneToCubeDepth() deletes any nodes at a depth greater than
2585 %  cube_info->depth while merging their color statistics into their parent
2586 %  node.
2587 %
2588 %  The format of the PruneToCubeDepth method is:
2589 %
2590 %      PruneToCubeDepth(CubeInfo *cube_info,const NodeInfo *node_info)
2591 %
2592 %  A description of each parameter follows.
2593 %
2594 %    o cube_info: A pointer to the Cube structure.
2595 %
2596 %    o node_info: pointer to node in color cube tree that is to be pruned.
2597 %
2598 */
PruneToCubeDepth(CubeInfo * cube_info,const NodeInfo * node_info)2599 static void PruneToCubeDepth(CubeInfo *cube_info,const NodeInfo *node_info)
2600 {
2601   register ssize_t
2602     i;
2603 
2604   size_t
2605     number_children;
2606 
2607   /*
2608     Traverse any children.
2609   */
2610   number_children=cube_info->associate_alpha == MagickFalse ? 8UL : 16UL;
2611   for (i=0; i < (ssize_t) number_children; i++)
2612     if (node_info->child[i] != (NodeInfo *) NULL)
2613       PruneToCubeDepth(cube_info,node_info->child[i]);
2614   if (node_info->level > cube_info->depth)
2615     PruneChild(cube_info,node_info);
2616 }
2617 
2618 /*
2619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2620 %                                                                             %
2621 %                                                                             %
2622 %                                                                             %
2623 %  Q u a n t i z e I m a g e                                                  %
2624 %                                                                             %
2625 %                                                                             %
2626 %                                                                             %
2627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2628 %
2629 %  QuantizeImage() analyzes the colors within a reference image and chooses a
2630 %  fixed number of colors to represent the image.  The goal of the algorithm
2631 %  is to minimize the color difference between the input and output image while
2632 %  minimizing the processing time.
2633 %
2634 %  The format of the QuantizeImage method is:
2635 %
2636 %      MagickBooleanType QuantizeImage(const QuantizeInfo *quantize_info,
2637 %        Image *image,ExceptionInfo *exception)
2638 %
2639 %  A description of each parameter follows:
2640 %
2641 %    o quantize_info: Specifies a pointer to an QuantizeInfo structure.
2642 %
2643 %    o image: the image.
2644 %
2645 %    o exception: return any errors or warnings in this structure.
2646 %
2647 */
QuantizeImage(const QuantizeInfo * quantize_info,Image * image,ExceptionInfo * exception)2648 MagickExport MagickBooleanType QuantizeImage(const QuantizeInfo *quantize_info,
2649   Image *image,ExceptionInfo *exception)
2650 {
2651   CubeInfo
2652     *cube_info;
2653 
2654   MagickBooleanType
2655     status;
2656 
2657   size_t
2658     depth,
2659     maximum_colors;
2660 
2661   assert(quantize_info != (const QuantizeInfo *) NULL);
2662   assert(quantize_info->signature == MagickCoreSignature);
2663   assert(image != (Image *) NULL);
2664   assert(image->signature == MagickCoreSignature);
2665   if (image->debug != MagickFalse)
2666     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2667   assert(exception != (ExceptionInfo *) NULL);
2668   assert(exception->signature == MagickCoreSignature);
2669   maximum_colors=quantize_info->number_colors;
2670   if (maximum_colors == 0)
2671     maximum_colors=MaxColormapSize;
2672   if (maximum_colors > MaxColormapSize)
2673     maximum_colors=MaxColormapSize;
2674   if (image->alpha_trait != BlendPixelTrait)
2675     {
2676       if (SetImageGray(image,exception) != MagickFalse)
2677         (void) SetGrayscaleImage(image,exception);
2678     }
2679   if ((image->storage_class == PseudoClass) &&
2680       (image->colors <= maximum_colors))
2681     {
2682       if ((quantize_info->colorspace != UndefinedColorspace) &&
2683           (quantize_info->colorspace != CMYKColorspace))
2684         (void) TransformImageColorspace(image,quantize_info->colorspace,
2685           exception);
2686       return(MagickTrue);
2687     }
2688   depth=quantize_info->tree_depth;
2689   if (depth == 0)
2690     {
2691       size_t
2692         colors;
2693 
2694       /*
2695         Depth of color tree is: Log4(colormap size)+2.
2696       */
2697       colors=maximum_colors;
2698       for (depth=1; colors != 0; depth++)
2699         colors>>=2;
2700       if ((quantize_info->dither_method != NoDitherMethod) && (depth > 2))
2701         depth--;
2702       if ((image->alpha_trait == BlendPixelTrait) && (depth > 5))
2703         depth--;
2704       if (SetImageGray(image,exception) != MagickFalse)
2705         depth=MaxTreeDepth;
2706     }
2707   /*
2708     Initialize color cube.
2709   */
2710   cube_info=GetCubeInfo(quantize_info,depth,maximum_colors);
2711   if (cube_info == (CubeInfo *) NULL)
2712     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2713       image->filename);
2714   status=ClassifyImageColors(cube_info,image,exception);
2715   if (status != MagickFalse)
2716     {
2717       /*
2718         Reduce the number of colors in the image if it contains more than the
2719         maximum, otherwise we can disable dithering to improve the performance.
2720       */
2721       if (cube_info->colors > cube_info->maximum_colors)
2722         ReduceImageColors(image,cube_info);
2723       else
2724         cube_info->quantize_info->dither_method=NoDitherMethod;
2725       status=AssignImageColors(image,cube_info,exception);
2726     }
2727   DestroyCubeInfo(cube_info);
2728   return(status);
2729 }
2730 
2731 /*
2732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2733 %                                                                             %
2734 %                                                                             %
2735 %                                                                             %
2736 %   Q u a n t i z e I m a g e s                                               %
2737 %                                                                             %
2738 %                                                                             %
2739 %                                                                             %
2740 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2741 %
2742 %  QuantizeImages() analyzes the colors within a set of reference images and
2743 %  chooses a fixed number of colors to represent the set.  The goal of the
2744 %  algorithm is to minimize the color difference between the input and output
2745 %  images while minimizing the processing time.
2746 %
2747 %  The format of the QuantizeImages method is:
2748 %
2749 %      MagickBooleanType QuantizeImages(const QuantizeInfo *quantize_info,
2750 %        Image *images,ExceptionInfo *exception)
2751 %
2752 %  A description of each parameter follows:
2753 %
2754 %    o quantize_info: Specifies a pointer to an QuantizeInfo structure.
2755 %
2756 %    o images: Specifies a pointer to a list of Image structures.
2757 %
2758 %    o exception: return any errors or warnings in this structure.
2759 %
2760 */
QuantizeImages(const QuantizeInfo * quantize_info,Image * images,ExceptionInfo * exception)2761 MagickExport MagickBooleanType QuantizeImages(const QuantizeInfo *quantize_info,
2762   Image *images,ExceptionInfo *exception)
2763 {
2764   CubeInfo
2765     *cube_info;
2766 
2767   Image
2768     *image;
2769 
2770   MagickBooleanType
2771     proceed,
2772     status;
2773 
2774   MagickProgressMonitor
2775     progress_monitor;
2776 
2777   register ssize_t
2778     i;
2779 
2780   size_t
2781     depth,
2782     maximum_colors,
2783     number_images;
2784 
2785   assert(quantize_info != (const QuantizeInfo *) NULL);
2786   assert(quantize_info->signature == MagickCoreSignature);
2787   assert(images != (Image *) NULL);
2788   assert(images->signature == MagickCoreSignature);
2789   if (images->debug != MagickFalse)
2790     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
2791   assert(exception != (ExceptionInfo *) NULL);
2792   assert(exception->signature == MagickCoreSignature);
2793   if (GetNextImageInList(images) == (Image *) NULL)
2794     {
2795       /*
2796         Handle a single image with QuantizeImage.
2797       */
2798       status=QuantizeImage(quantize_info,images,exception);
2799       return(status);
2800     }
2801   status=MagickFalse;
2802   maximum_colors=quantize_info->number_colors;
2803   if (maximum_colors == 0)
2804     maximum_colors=MaxColormapSize;
2805   if (maximum_colors > MaxColormapSize)
2806     maximum_colors=MaxColormapSize;
2807   depth=quantize_info->tree_depth;
2808   if (depth == 0)
2809     {
2810       size_t
2811         colors;
2812 
2813       /*
2814         Depth of color tree is: Log4(colormap size)+2.
2815       */
2816       colors=maximum_colors;
2817       for (depth=1; colors != 0; depth++)
2818         colors>>=2;
2819       if (quantize_info->dither_method != NoDitherMethod)
2820         depth--;
2821     }
2822   /*
2823     Initialize color cube.
2824   */
2825   cube_info=GetCubeInfo(quantize_info,depth,maximum_colors);
2826   if (cube_info == (CubeInfo *) NULL)
2827     {
2828       (void) ThrowMagickException(exception,GetMagickModule(),
2829         ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
2830       return(MagickFalse);
2831     }
2832   number_images=GetImageListLength(images);
2833   image=images;
2834   for (i=0; image != (Image *) NULL; i++)
2835   {
2836     progress_monitor=SetImageProgressMonitor(image,(MagickProgressMonitor) NULL,
2837       image->client_data);
2838     status=ClassifyImageColors(cube_info,image,exception);
2839     if (status == MagickFalse)
2840       break;
2841     (void) SetImageProgressMonitor(image,progress_monitor,image->client_data);
2842     proceed=SetImageProgress(image,AssignImageTag,(MagickOffsetType) i,
2843       number_images);
2844     if (proceed == MagickFalse)
2845       break;
2846     image=GetNextImageInList(image);
2847   }
2848   if (status != MagickFalse)
2849     {
2850       /*
2851         Reduce the number of colors in an image sequence.
2852       */
2853       ReduceImageColors(images,cube_info);
2854       image=images;
2855       for (i=0; image != (Image *) NULL; i++)
2856       {
2857         progress_monitor=SetImageProgressMonitor(image,(MagickProgressMonitor)
2858           NULL,image->client_data);
2859         status=AssignImageColors(image,cube_info,exception);
2860         if (status == MagickFalse)
2861           break;
2862         (void) SetImageProgressMonitor(image,progress_monitor,
2863           image->client_data);
2864         proceed=SetImageProgress(image,AssignImageTag,(MagickOffsetType) i,
2865           number_images);
2866         if (proceed == MagickFalse)
2867           break;
2868         image=GetNextImageInList(image);
2869       }
2870     }
2871   DestroyCubeInfo(cube_info);
2872   return(status);
2873 }
2874 
2875 /*
2876 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2877 %                                                                             %
2878 %                                                                             %
2879 %                                                                             %
2880 +   Q u a n t i z e E r r o r F l a t t e n                                   %
2881 %                                                                             %
2882 %                                                                             %
2883 %                                                                             %
2884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2885 %
2886 %  QuantizeErrorFlatten() traverses the color cube and flattens the quantization
2887 %  error into a sorted 1D array.  This accelerates the color reduction process.
2888 %
2889 %  Contributed by Yoya.
2890 %
2891 %  The format of the QuantizeErrorFlatten method is:
2892 %
2893 %      size_t QuantizeErrorFlatten(const CubeInfo *cube_info,
2894 %        const NodeInfo *node_info,const ssize_t offset,
2895 %        double *quantize_error)
2896 %
2897 %  A description of each parameter follows.
2898 %
2899 %    o cube_info: A pointer to the Cube structure.
2900 %
2901 %    o node_info: pointer to node in color cube tree that is current pointer.
2902 %
2903 %    o offset: quantize error offset.
2904 %
2905 %    o quantize_error: the quantization error vector.
2906 %
2907 */
QuantizeErrorFlatten(const CubeInfo * cube_info,const NodeInfo * node_info,const ssize_t offset,double * quantize_error)2908 static size_t QuantizeErrorFlatten(const CubeInfo *cube_info,
2909   const NodeInfo *node_info,const ssize_t offset,double *quantize_error)
2910 {
2911   register ssize_t
2912     i;
2913 
2914   size_t
2915     n,
2916     number_children;
2917 
2918   if (offset >= (ssize_t) cube_info->nodes)
2919     return(0);
2920   quantize_error[offset]=node_info->quantize_error;
2921   n=1;
2922   number_children=cube_info->associate_alpha == MagickFalse ? 8UL : 16UL;
2923   for (i=0; i < (ssize_t) number_children ; i++)
2924     if (node_info->child[i] != (NodeInfo *) NULL)
2925       n+=QuantizeErrorFlatten(cube_info,node_info->child[i],offset+n,
2926         quantize_error);
2927   return(n);
2928 }
2929 
2930 /*
2931 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2932 %                                                                             %
2933 %                                                                             %
2934 %                                                                             %
2935 +   R e d u c e                                                               %
2936 %                                                                             %
2937 %                                                                             %
2938 %                                                                             %
2939 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2940 %
2941 %  Reduce() traverses the color cube tree and prunes any node whose
2942 %  quantization error falls below a particular threshold.
2943 %
2944 %  The format of the Reduce method is:
2945 %
2946 %      Reduce(CubeInfo *cube_info,const NodeInfo *node_info)
2947 %
2948 %  A description of each parameter follows.
2949 %
2950 %    o cube_info: A pointer to the Cube structure.
2951 %
2952 %    o node_info: pointer to node in color cube tree that is to be pruned.
2953 %
2954 */
Reduce(CubeInfo * cube_info,const NodeInfo * node_info)2955 static void Reduce(CubeInfo *cube_info,const NodeInfo *node_info)
2956 {
2957   register ssize_t
2958     i;
2959 
2960   size_t
2961     number_children;
2962 
2963   /*
2964     Traverse any children.
2965   */
2966   number_children=cube_info->associate_alpha == MagickFalse ? 8UL : 16UL;
2967   for (i=0; i < (ssize_t) number_children; i++)
2968     if (node_info->child[i] != (NodeInfo *) NULL)
2969       Reduce(cube_info,node_info->child[i]);
2970   if (node_info->quantize_error <= cube_info->pruning_threshold)
2971     PruneChild(cube_info,node_info);
2972   else
2973     {
2974       /*
2975         Find minimum pruning threshold.
2976       */
2977       if (node_info->number_unique > 0)
2978         cube_info->colors++;
2979       if (node_info->quantize_error < cube_info->next_threshold)
2980         cube_info->next_threshold=node_info->quantize_error;
2981     }
2982 }
2983 
2984 /*
2985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2986 %                                                                             %
2987 %                                                                             %
2988 %                                                                             %
2989 +   R e d u c e I m a g e C o l o r s                                         %
2990 %                                                                             %
2991 %                                                                             %
2992 %                                                                             %
2993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2994 %
2995 %  ReduceImageColors() repeatedly prunes the tree until the number of nodes
2996 %  with n2 > 0 is less than or equal to the maximum number of colors allowed
2997 %  in the output image.  On any given iteration over the tree, it selects
2998 %  those nodes whose E value is minimal for pruning and merges their
2999 %  color statistics upward. It uses a pruning threshold, Ep, to govern
3000 %  node selection as follows:
3001 %
3002 %    Ep = 0
3003 %    while number of nodes with (n2 > 0) > required maximum number of colors
3004 %      prune all nodes such that E <= Ep
3005 %      Set Ep to minimum E in remaining nodes
3006 %
3007 %  This has the effect of minimizing any quantization error when merging
3008 %  two nodes together.
3009 %
3010 %  When a node to be pruned has offspring, the pruning procedure invokes
3011 %  itself recursively in order to prune the tree from the leaves upward.
3012 %  n2,  Sr, Sg,  and  Sb in a node being pruned are always added to the
3013 %  corresponding data in that node's parent.  This retains the pruned
3014 %  node's color characteristics for later averaging.
3015 %
3016 %  For each node, n2 pixels exist for which that node represents the
3017 %  smallest volume in RGB space containing those pixel's colors.  When n2
3018 %  > 0 the node will uniquely define a color in the output image. At the
3019 %  beginning of reduction,  n2 = 0  for all nodes except a the leaves of
3020 %  the tree which represent colors present in the input image.
3021 %
3022 %  The other pixel count, n1, indicates the total number of colors
3023 %  within the cubic volume which the node represents.  This includes n1 -
3024 %  n2  pixels whose colors should be defined by nodes at a lower level in
3025 %  the tree.
3026 %
3027 %  The format of the ReduceImageColors method is:
3028 %
3029 %      ReduceImageColors(const Image *image,CubeInfo *cube_info)
3030 %
3031 %  A description of each parameter follows.
3032 %
3033 %    o image: the image.
3034 %
3035 %    o cube_info: A pointer to the Cube structure.
3036 %
3037 */
3038 
QuantizeErrorCompare(const void * error_p,const void * error_q)3039 static int QuantizeErrorCompare(const void *error_p,const void *error_q)
3040 {
3041   double
3042     *p,
3043     *q;
3044 
3045   p=(double *) error_p;
3046   q=(double *) error_q;
3047   if (*p > *q)
3048     return(1);
3049   if (fabs(*q-*p) <= MagickEpsilon)
3050     return(0);
3051   return(-1);
3052 }
3053 
ReduceImageColors(const Image * image,CubeInfo * cube_info)3054 static void ReduceImageColors(const Image *image,CubeInfo *cube_info)
3055 {
3056 #define ReduceImageTag  "Reduce/Image"
3057 
3058   MagickBooleanType
3059     proceed;
3060 
3061   MagickOffsetType
3062     offset;
3063 
3064   size_t
3065     span;
3066 
3067   cube_info->next_threshold=0.0;
3068   if (cube_info->colors > cube_info->maximum_colors)
3069     {
3070       double
3071         *quantize_error;
3072 
3073       /*
3074         Enable rapid reduction of the number of unique colors.
3075       */
3076       quantize_error=(double *) AcquireQuantumMemory(cube_info->nodes,
3077         sizeof(*quantize_error));
3078       if (quantize_error != (double *) NULL)
3079         {
3080           (void) QuantizeErrorFlatten(cube_info,cube_info->root,0,
3081             quantize_error);
3082           qsort(quantize_error,cube_info->nodes,sizeof(double),
3083             QuantizeErrorCompare);
3084           if (cube_info->nodes > (110*(cube_info->maximum_colors+1)/100))
3085             cube_info->next_threshold=quantize_error[cube_info->nodes-110*
3086               (cube_info->maximum_colors+1)/100];
3087           quantize_error=(double *) RelinquishMagickMemory(quantize_error);
3088         }
3089   }
3090   for (span=cube_info->colors; cube_info->colors > cube_info->maximum_colors; )
3091   {
3092     cube_info->pruning_threshold=cube_info->next_threshold;
3093     cube_info->next_threshold=cube_info->root->quantize_error-1;
3094     cube_info->colors=0;
3095     Reduce(cube_info,cube_info->root);
3096     offset=(MagickOffsetType) span-cube_info->colors;
3097     proceed=SetImageProgress(image,ReduceImageTag,offset,span-
3098       cube_info->maximum_colors+1);
3099     if (proceed == MagickFalse)
3100       break;
3101   }
3102 }
3103 
3104 /*
3105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3106 %                                                                             %
3107 %                                                                             %
3108 %                                                                             %
3109 %   R e m a p I m a g e                                                       %
3110 %                                                                             %
3111 %                                                                             %
3112 %                                                                             %
3113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3114 %
3115 %  RemapImage() replaces the colors of an image with the closest of the colors
3116 %  from the reference image.
3117 %
3118 %  The format of the RemapImage method is:
3119 %
3120 %      MagickBooleanType RemapImage(const QuantizeInfo *quantize_info,
3121 %        Image *image,const Image *remap_image,ExceptionInfo *exception)
3122 %
3123 %  A description of each parameter follows:
3124 %
3125 %    o quantize_info: Specifies a pointer to an QuantizeInfo structure.
3126 %
3127 %    o image: the image.
3128 %
3129 %    o remap_image: the reference image.
3130 %
3131 %    o exception: return any errors or warnings in this structure.
3132 %
3133 */
RemapImage(const QuantizeInfo * quantize_info,Image * image,const Image * remap_image,ExceptionInfo * exception)3134 MagickExport MagickBooleanType RemapImage(const QuantizeInfo *quantize_info,
3135   Image *image,const Image *remap_image,ExceptionInfo *exception)
3136 {
3137   CubeInfo
3138     *cube_info;
3139 
3140   MagickBooleanType
3141     status;
3142 
3143   /*
3144     Initialize color cube.
3145   */
3146   assert(image != (Image *) NULL);
3147   assert(image->signature == MagickCoreSignature);
3148   if (image->debug != MagickFalse)
3149     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3150   assert(remap_image != (Image *) NULL);
3151   assert(remap_image->signature == MagickCoreSignature);
3152   assert(exception != (ExceptionInfo *) NULL);
3153   assert(exception->signature == MagickCoreSignature);
3154   cube_info=GetCubeInfo(quantize_info,MaxTreeDepth,
3155     quantize_info->number_colors);
3156   if (cube_info == (CubeInfo *) NULL)
3157     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3158       image->filename);
3159   status=ClassifyImageColors(cube_info,remap_image,exception);
3160   if (status != MagickFalse)
3161     {
3162       /*
3163         Classify image colors from the reference image.
3164       */
3165       cube_info->quantize_info->number_colors=cube_info->colors;
3166       status=AssignImageColors(image,cube_info,exception);
3167     }
3168   DestroyCubeInfo(cube_info);
3169   return(status);
3170 }
3171 
3172 /*
3173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3174 %                                                                             %
3175 %                                                                             %
3176 %                                                                             %
3177 %   R e m a p I m a g e s                                                     %
3178 %                                                                             %
3179 %                                                                             %
3180 %                                                                             %
3181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3182 %
3183 %  RemapImages() replaces the colors of a sequence of images with the
3184 %  closest color from a reference image.
3185 %
3186 %  The format of the RemapImage method is:
3187 %
3188 %      MagickBooleanType RemapImages(const QuantizeInfo *quantize_info,
3189 %        Image *images,Image *remap_image,ExceptionInfo *exception)
3190 %
3191 %  A description of each parameter follows:
3192 %
3193 %    o quantize_info: Specifies a pointer to an QuantizeInfo structure.
3194 %
3195 %    o images: the image sequence.
3196 %
3197 %    o remap_image: the reference image.
3198 %
3199 %    o exception: return any errors or warnings in this structure.
3200 %
3201 */
RemapImages(const QuantizeInfo * quantize_info,Image * images,const Image * remap_image,ExceptionInfo * exception)3202 MagickExport MagickBooleanType RemapImages(const QuantizeInfo *quantize_info,
3203   Image *images,const Image *remap_image,ExceptionInfo *exception)
3204 {
3205   CubeInfo
3206     *cube_info;
3207 
3208   Image
3209     *image;
3210 
3211   MagickBooleanType
3212     status;
3213 
3214   assert(images != (Image *) NULL);
3215   assert(images->signature == MagickCoreSignature);
3216   if (images->debug != MagickFalse)
3217     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
3218   assert(exception != (ExceptionInfo *) NULL);
3219   assert(exception->signature == MagickCoreSignature);
3220   image=images;
3221   if (remap_image == (Image *) NULL)
3222     {
3223       /*
3224         Create a global colormap for an image sequence.
3225       */
3226       status=QuantizeImages(quantize_info,images,exception);
3227       return(status);
3228     }
3229   /*
3230     Classify image colors from the reference image.
3231   */
3232   cube_info=GetCubeInfo(quantize_info,MaxTreeDepth,
3233     quantize_info->number_colors);
3234   if (cube_info == (CubeInfo *) NULL)
3235     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3236       image->filename);
3237   status=ClassifyImageColors(cube_info,remap_image,exception);
3238   if (status != MagickFalse)
3239     {
3240       /*
3241         Classify image colors from the reference image.
3242       */
3243       cube_info->quantize_info->number_colors=cube_info->colors;
3244       image=images;
3245       for ( ; image != (Image *) NULL; image=GetNextImageInList(image))
3246       {
3247         status=AssignImageColors(image,cube_info,exception);
3248         if (status == MagickFalse)
3249           break;
3250       }
3251     }
3252   DestroyCubeInfo(cube_info);
3253   return(status);
3254 }
3255 
3256 /*
3257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3258 %                                                                             %
3259 %                                                                             %
3260 %                                                                             %
3261 %   S e t G r a y s c a l e I m a g e                                         %
3262 %                                                                             %
3263 %                                                                             %
3264 %                                                                             %
3265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3266 %
3267 %  SetGrayscaleImage() converts an image to a PseudoClass grayscale image.
3268 %
3269 %  The format of the SetGrayscaleImage method is:
3270 %
3271 %      MagickBooleanType SetGrayscaleImage(Image *image,
3272 %        ExceptionInfo *exception)
3273 %
3274 %  A description of each parameter follows:
3275 %
3276 %    o image: The image.
3277 %
3278 %    o exception: return any errors or warnings in this structure.
3279 %
3280 */
3281 
3282 #if defined(__cplusplus) || defined(c_plusplus)
3283 extern "C" {
3284 #endif
3285 
IntensityCompare(const void * x,const void * y)3286 static int IntensityCompare(const void *x,const void *y)
3287 {
3288   double
3289     intensity;
3290 
3291   PixelInfo
3292     *color_1,
3293     *color_2;
3294 
3295   color_1=(PixelInfo *) x;
3296   color_2=(PixelInfo *) y;
3297   intensity=GetPixelInfoIntensity((const Image *) NULL,color_1)-
3298     GetPixelInfoIntensity((const Image *) NULL,color_2);
3299   return((int) intensity);
3300 }
3301 
3302 #if defined(__cplusplus) || defined(c_plusplus)
3303 }
3304 #endif
3305 
SetGrayscaleImage(Image * image,ExceptionInfo * exception)3306 static MagickBooleanType SetGrayscaleImage(Image *image,
3307   ExceptionInfo *exception)
3308 {
3309   CacheView
3310     *image_view;
3311 
3312   MagickBooleanType
3313     status;
3314 
3315   PixelInfo
3316     *colormap;
3317 
3318   register ssize_t
3319     i;
3320 
3321   ssize_t
3322     *colormap_index,
3323     j,
3324     y;
3325 
3326   assert(image != (Image *) NULL);
3327   assert(image->signature == MagickCoreSignature);
3328   if (image->type != GrayscaleType)
3329     (void) TransformImageColorspace(image,GRAYColorspace,exception);
3330   if (image->storage_class == PseudoClass)
3331     colormap_index=(ssize_t *) AcquireQuantumMemory(image->colors+1,
3332       sizeof(*colormap_index));
3333   else
3334     colormap_index=(ssize_t *) AcquireQuantumMemory(MaxColormapSize+1,
3335       sizeof(*colormap_index));
3336   if (colormap_index == (ssize_t *) NULL)
3337     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3338       image->filename);
3339   if (image->storage_class != PseudoClass)
3340     {
3341       (void) memset(colormap_index,(-1),MaxColormapSize*
3342         sizeof(*colormap_index));
3343       if (AcquireImageColormap(image,MaxColormapSize,exception) == MagickFalse)
3344         {
3345           colormap_index=(ssize_t *) RelinquishMagickMemory(colormap_index);
3346           ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3347             image->filename);
3348         }
3349       image->colors=0;
3350       status=MagickTrue;
3351       image_view=AcquireAuthenticCacheView(image,exception);
3352 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3353       #pragma omp parallel for schedule(static) shared(status) \
3354         magick_number_threads(image,image,image->rows,1)
3355 #endif
3356       for (y=0; y < (ssize_t) image->rows; y++)
3357       {
3358         register Quantum
3359           *magick_restrict q;
3360 
3361         register ssize_t
3362           x;
3363 
3364         if (status == MagickFalse)
3365           continue;
3366         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3367           exception);
3368         if (q == (Quantum *) NULL)
3369           {
3370             status=MagickFalse;
3371             continue;
3372           }
3373         for (x=0; x < (ssize_t) image->columns; x++)
3374         {
3375           register size_t
3376             intensity;
3377 
3378           intensity=ScaleQuantumToMap(GetPixelRed(image,q));
3379           if (colormap_index[intensity] < 0)
3380             {
3381 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3382               #pragma omp critical (MagickCore_SetGrayscaleImage)
3383 #endif
3384               if (colormap_index[intensity] < 0)
3385                 {
3386                   colormap_index[intensity]=(ssize_t) image->colors;
3387                   image->colormap[image->colors].red=(double)
3388                     GetPixelRed(image,q);
3389                   image->colormap[image->colors].green=(double)
3390                     GetPixelGreen(image,q);
3391                   image->colormap[image->colors].blue=(double)
3392                     GetPixelBlue(image,q);
3393                   image->colors++;
3394                }
3395             }
3396           SetPixelIndex(image,(Quantum) colormap_index[intensity],q);
3397           q+=GetPixelChannels(image);
3398         }
3399         if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3400           status=MagickFalse;
3401       }
3402       image_view=DestroyCacheView(image_view);
3403     }
3404   for (i=0; i < (ssize_t) image->colors; i++)
3405     image->colormap[i].alpha=(double) i;
3406   qsort((void *) image->colormap,image->colors,sizeof(PixelInfo),
3407     IntensityCompare);
3408   colormap=(PixelInfo *) AcquireQuantumMemory(image->colors,sizeof(*colormap));
3409   if (colormap == (PixelInfo *) NULL)
3410     {
3411       colormap_index=(ssize_t *) RelinquishMagickMemory(colormap_index);
3412       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3413         image->filename);
3414     }
3415   j=0;
3416   colormap[j]=image->colormap[0];
3417   for (i=0; i < (ssize_t) image->colors; i++)
3418   {
3419     if (IsPixelInfoEquivalent(&colormap[j],&image->colormap[i]) == MagickFalse)
3420       {
3421         j++;
3422         colormap[j]=image->colormap[i];
3423       }
3424     colormap_index[(ssize_t) image->colormap[i].alpha]=j;
3425   }
3426   image->colors=(size_t) (j+1);
3427   image->colormap=(PixelInfo *) RelinquishMagickMemory(image->colormap);
3428   image->colormap=colormap;
3429   status=MagickTrue;
3430   image_view=AcquireAuthenticCacheView(image,exception);
3431 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3432   #pragma omp parallel for schedule(static) shared(status) \
3433     magick_number_threads(image,image,image->rows,1)
3434 #endif
3435   for (y=0; y < (ssize_t) image->rows; y++)
3436   {
3437     register Quantum
3438       *magick_restrict q;
3439 
3440     register ssize_t
3441       x;
3442 
3443     if (status == MagickFalse)
3444       continue;
3445     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3446     if (q == (Quantum *) NULL)
3447       {
3448         status=MagickFalse;
3449         continue;
3450       }
3451     for (x=0; x < (ssize_t) image->columns; x++)
3452     {
3453       SetPixelIndex(image,(Quantum) colormap_index[ScaleQuantumToMap(
3454         GetPixelIndex(image,q))],q);
3455       q+=GetPixelChannels(image);
3456     }
3457     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3458       status=MagickFalse;
3459   }
3460   image_view=DestroyCacheView(image_view);
3461   colormap_index=(ssize_t *) RelinquishMagickMemory(colormap_index);
3462   image->type=GrayscaleType;
3463   if (SetImageMonochrome(image,exception) != MagickFalse)
3464     image->type=BilevelType;
3465   return(status);
3466 }
3467