2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 % CCCC OOO L OOO RRRR %
9 % CCCC OOO LLLLL OOO R R %
12 % MagickCore Color Methods %
19 % Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization %
20 % dedicated to making software imaging solutions freely available. %
22 % You may not use this file except in compliance with the License. You may %
23 % obtain a copy of the License at %
25 % http://www.imagemagick.org/script/license.php %
27 % Unless required by applicable law or agreed to in writing, software %
28 % distributed under the License is distributed on an "AS IS" BASIS, %
29 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
30 % See the License for the specific language governing permissions and %
31 % limitations under the License. %
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 % We use linked-lists because splay-trees do not currently support duplicate
36 % key / value pairs (.e.g X11 green compliance and SVG green compliance).
43 #include "magick/studio.h"
44 #include "magick/blob.h"
45 #include "magick/cache-view.h"
46 #include "magick/cache.h"
47 #include "magick/color.h"
48 #include "magick/color-private.h"
49 #include "magick/client.h"
50 #include "magick/configure.h"
51 #include "magick/exception.h"
52 #include "magick/exception-private.h"
53 #include "magick/gem.h"
54 #include "magick/geometry.h"
55 #include "magick/image-private.h"
56 #include "magick/memory_.h"
57 #include "magick/monitor.h"
58 #include "magick/monitor-private.h"
59 #include "magick/option.h"
60 #include "magick/pixel-private.h"
61 #include "magick/quantize.h"
62 #include "magick/quantum.h"
63 #include "magick/semaphore.h"
64 #include "magick/string_.h"
65 #include "magick/token.h"
66 #include "magick/utility.h"
67 #include "magick/xml-tree.h"
72 #define ColorFilename "colors.xml"
73 #define MaxTreeDepth 8
74 #define NodesInAList 1536
80 *ColorMap = (const char *)
81 "<?xml version=\"1.0\"?>"
83 " <color name=\"none\" color=\"rgba(0,0,0,0)\" compliance=\"SVG\" />"
84 " <color name=\"black\" color=\"rgb(0,0,0)\" compliance=\"SVG, X11, XPM\" />"
85 " <color name=\"red\" color=\"rgb(255,0,0)\" compliance=\"SVG, X11, XPM\" />"
86 " <color name=\"magenta\" color=\"rgb(255,0,255)\" compliance=\"SVG, X11, XPM\" />"
87 " <color name=\"green\" color=\"rgb(0,128,0)\" compliance=\"SVG\" />"
88 " <color name=\"cyan\" color=\"rgb(0,255,255)\" compliance=\"SVG, X11, XPM\" />"
89 " <color name=\"blue\" color=\"rgb(0,0,255)\" compliance=\"SVG, X11, XPM\" />"
90 " <color name=\"yellow\" color=\"rgb(255,255,0)\" compliance=\"SVG, X11, XPM\" />"
91 " <color name=\"white\" color=\"rgb(255,255,255)\" compliance=\"SVG, X11\" />"
92 " <color name=\"AliceBlue\" color=\"rgb(240,248,255)\" compliance=\"SVG, X11, XPM\" />"
93 " <color name=\"AntiqueWhite\" color=\"rgb(250,235,215)\" compliance=\"SVG, X11, XPM\" />"
94 " <color name=\"aqua\" color=\"rgb(0,255,255)\" compliance=\"SVG\" />"
95 " <color name=\"aquamarine\" color=\"rgb(127,255,212)\" compliance=\"SVG, X11, XPM\" />"
96 " <color name=\"azure\" color=\"rgb(240,255,255)\" compliance=\"SVG, X11, XPM\" />"
97 " <color name=\"beige\" color=\"rgb(245,245,220)\" compliance=\"SVG, X11, XPM\" />"
98 " <color name=\"bisque\" color=\"rgb(255,228,196)\" compliance=\"SVG, X11, XPM\" />"
99 " <color name=\"BlanchedAlmond\" color=\"rgb(255,235,205)\" compliance=\"SVG, X11, XPM\" />"
100 " <color name=\"BlueViolet\" color=\"rgb(138,43,226)\" compliance=\"SVG, X11, XPM\" />"
101 " <color name=\"brown\" color=\"rgb(165,42,42)\" compliance=\"SVG, X11, XPM\" />"
102 " <color name=\"burlywood\" color=\"rgb(222,184,135)\" compliance=\"SVG, X11, XPM\" />"
103 " <color name=\"CadetBlue\" color=\"rgb(95,158,160)\" compliance=\"SVG, X11, XPM\" />"
104 " <color name=\"chartreuse\" color=\"rgb(127,255,0)\" compliance=\"SVG, X11, XPM\" />"
105 " <color name=\"chocolate\" color=\"rgb(210,105,30)\" compliance=\"SVG, X11, XPM\" />"
106 " <color name=\"coral\" color=\"rgb(255,127,80)\" compliance=\"SVG, X11, XPM\" />"
107 " <color name=\"CornflowerBlue\" color=\"rgb(100,149,237)\" compliance=\"SVG, X11, XPM\" />"
108 " <color name=\"cornsilk\" color=\"rgb(255,248,220)\" compliance=\"SVG, X11, XPM\" />"
109 " <color name=\"crimson\" color=\"rgb(220,20,60)\" compliance=\"SVG\" />"
110 " <color name=\"DarkBlue\" color=\"rgb(0,0,139)\" compliance=\"SVG, X11\" />"
111 " <color name=\"DarkCyan\" color=\"rgb(0,139,139)\" compliance=\"SVG, X11\" />"
112 " <color name=\"DarkGoldenrod\" color=\"rgb(184,134,11)\" compliance=\"SVG, X11, XPM\" />"
113 " <color name=\"DarkGray\" color=\"rgb(169,169,169)\" compliance=\"SVG, X11\" />"
114 " <color name=\"DarkGreen\" color=\"rgb(0,100,0)\" compliance=\"SVG, X11, XPM\" />"
115 " <color name=\"DarkGrey\" color=\"rgb(169,169,169)\" compliance=\"SVG, X11\" />"
116 " <color name=\"DarkKhaki\" color=\"rgb(189,183,107)\" compliance=\"SVG, X11, XPM\" />"
117 " <color name=\"DarkMagenta\" color=\"rgb(139,0,139)\" compliance=\"SVG, X11\" />"
118 " <color name=\"DarkOliveGreen\" color=\"rgb(85,107,47)\" compliance=\"SVG, X11, XPM\" />"
119 " <color name=\"DarkOrange\" color=\"rgb(255,140,0)\" compliance=\"SVG, X11, XPM\" />"
120 " <color name=\"DarkOrchid\" color=\"rgb(153,50,204)\" compliance=\"SVG, X11, XPM\" />"
121 " <color name=\"DarkRed\" color=\"rgb(139,0,0)\" compliance=\"SVG, X11\" />"
122 " <color name=\"DarkSalmon\" color=\"rgb(233,150,122)\" compliance=\"SVG, X11, XPM\" />"
123 " <color name=\"DarkSeaGreen\" color=\"rgb(143,188,143)\" compliance=\"SVG, X11, XPM\" />"
124 " <color name=\"DarkSlateBlue\" color=\"rgb(72,61,139)\" compliance=\"SVG, X11, XPM\" />"
125 " <color name=\"DarkSlateGray\" color=\"rgb(47,79,79)\" compliance=\"SVG, X11, XPM\" />"
126 " <color name=\"DarkSlateGrey\" color=\"rgb(47,79,79)\" compliance=\"SVG, X11\" />"
127 " <color name=\"DarkTurquoise\" color=\"rgb(0,206,209)\" compliance=\"SVG, X11, XPM\" />"
128 " <color name=\"DarkViolet\" color=\"rgb(148,0,211)\" compliance=\"SVG, X11, XPM\" />"
129 " <color name=\"DeepPink\" color=\"rgb(255,20,147)\" compliance=\"SVG, X11, XPM\" />"
130 " <color name=\"DeepSkyBlue\" color=\"rgb(0,191,255)\" compliance=\"SVG, X11, XPM\" />"
131 " <color name=\"DimGray\" color=\"rgb(105,105,105)\" compliance=\"SVG, X11, XPM\" />"
132 " <color name=\"DimGrey\" color=\"rgb(105,105,105)\" compliance=\"SVG, X11\" />"
133 " <color name=\"DodgerBlue\" color=\"rgb(30,144,255)\" compliance=\"SVG, X11, XPM\" />"
134 " <color name=\"firebrick\" color=\"rgb(178,34,34)\" compliance=\"SVG, X11, XPM\" />"
135 " <color name=\"FloralWhite\" color=\"rgb(255,250,240)\" compliance=\"SVG, X11, XPM\" />"
136 " <color name=\"ForestGreen\" color=\"rgb(34,139,34)\" compliance=\"SVG, X11, XPM\" />"
137 " <color name=\"fractal\" color=\"rgb(128,128,128)\" compliance=\"SVG\" />"
138 " <color name=\"fuchsia\" color=\"rgb(255,0,255)\" compliance=\"SVG\" />"
139 " <color name=\"gainsboro\" color=\"rgb(220,220,220)\" compliance=\"SVG, X11, XPM\" />"
140 " <color name=\"GhostWhite\" color=\"rgb(248,248,255)\" compliance=\"SVG, X11, XPM\" />"
141 " <color name=\"gold\" color=\"rgb(255,215,0)\" compliance=\"X11, XPM\" />"
142 " <color name=\"goldenrod\" color=\"rgb(218,165,32)\" compliance=\"SVG, X11, XPM\" />"
143 " <color name=\"gray\" color=\"rgb(126,126,126)\" compliance=\"SVG\" />"
144 " <color name=\"gray74\" color=\"rgb(189,189,189)\" compliance=\"SVG, X11\" />"
145 " <color name=\"gray100\" color=\"rgb(255,255,255)\" compliance=\"SVG, X11\" />"
146 " <color name=\"grey\" color=\"rgb(190,190,190)\" compliance=\"SVG, X11\" />"
147 " <color name=\"grey0\" color=\"rgb(0,0,0)\" compliance=\"SVG, X11\" />"
148 " <color name=\"grey1\" color=\"rgb(3,3,3)\" compliance=\"SVG, X11\" />"
149 " <color name=\"grey10\" color=\"rgb(26,26,26)\" compliance=\"SVG, X11\" />"
150 " <color name=\"grey100\" color=\"rgb(255,255,255)\" compliance=\"SVG, X11\" />"
151 " <color name=\"grey11\" color=\"rgb(28,28,28)\" compliance=\"SVG, X11\" />"
152 " <color name=\"grey12\" color=\"rgb(31,31,31)\" compliance=\"SVG, X11\" />"
153 " <color name=\"grey13\" color=\"rgb(33,33,33)\" compliance=\"SVG, X11\" />"
154 " <color name=\"grey14\" color=\"rgb(36,36,36)\" compliance=\"SVG, X11\" />"
155 " <color name=\"grey15\" color=\"rgb(38,38,38)\" compliance=\"SVG, X11\" />"
156 " <color name=\"grey16\" color=\"rgb(41,41,41)\" compliance=\"SVG, X11\" />"
157 " <color name=\"grey17\" color=\"rgb(43,43,43)\" compliance=\"SVG, X11\" />"
158 " <color name=\"grey18\" color=\"rgb(45,45,45)\" compliance=\"SVG, X11\" />"
159 " <color name=\"grey19\" color=\"rgb(48,48,48)\" compliance=\"SVG, X11\" />"
160 " <color name=\"grey2\" color=\"rgb(5,5,5)\" compliance=\"SVG, X11\" />"
161 " <color name=\"grey20\" color=\"rgb(51,51,51)\" compliance=\"SVG, X11\" />"
162 " <color name=\"grey21\" color=\"rgb(54,54,54)\" compliance=\"SVG, X11\" />"
163 " <color name=\"grey22\" color=\"rgb(56,56,56)\" compliance=\"SVG, X11\" />"
164 " <color name=\"grey23\" color=\"rgb(59,59,59)\" compliance=\"SVG, X11\" />"
165 " <color name=\"grey24\" color=\"rgb(61,61,61)\" compliance=\"SVG, X11\" />"
166 " <color name=\"grey25\" color=\"rgb(64,64,64)\" compliance=\"SVG, X11\" />"
167 " <color name=\"grey26\" color=\"rgb(66,66,66)\" compliance=\"SVG, X11\" />"
168 " <color name=\"grey27\" color=\"rgb(69,69,69)\" compliance=\"SVG, X11\" />"
169 " <color name=\"grey28\" color=\"rgb(71,71,71)\" compliance=\"SVG, X11\" />"
170 " <color name=\"grey29\" color=\"rgb(74,74,74)\" compliance=\"SVG, X11\" />"
171 " <color name=\"grey3\" color=\"rgb(8,8,8)\" compliance=\"SVG, X11\" />"
172 " <color name=\"grey30\" color=\"rgb(77,77,77)\" compliance=\"SVG, X11\" />"
173 " <color name=\"grey31\" color=\"rgb(79,79,79)\" compliance=\"SVG, X11\" />"
174 " <color name=\"grey32\" color=\"rgb(82,82,82)\" compliance=\"SVG, X11\" />"
175 " <color name=\"grey33\" color=\"rgb(84,84,84)\" compliance=\"SVG, X11\" />"
176 " <color name=\"grey34\" color=\"rgb(87,87,87)\" compliance=\"SVG, X11\" />"
177 " <color name=\"grey35\" color=\"rgb(89,89,89)\" compliance=\"SVG, X11\" />"
178 " <color name=\"grey36\" color=\"rgb(92,92,92)\" compliance=\"SVG, X11\" />"
179 " <color name=\"grey37\" color=\"rgb(94,94,94)\" compliance=\"SVG, X11\" />"
180 " <color name=\"grey38\" color=\"rgb(97,97,97)\" compliance=\"SVG, X11\" />"
181 " <color name=\"grey39\" color=\"rgb(99,99,99)\" compliance=\"SVG, X11\" />"
182 " <color name=\"grey4\" color=\"rgb(10,10,10)\" compliance=\"SVG, X11\" />"
183 " <color name=\"grey40\" color=\"rgb(102,102,102)\" compliance=\"SVG, X11\" />"
184 " <color name=\"grey41\" color=\"rgb(105,105,105)\" compliance=\"SVG, X11\" />"
185 " <color name=\"grey42\" color=\"rgb(107,107,107)\" compliance=\"SVG, X11\" />"
186 " <color name=\"grey43\" color=\"rgb(110,110,110)\" compliance=\"SVG, X11\" />"
187 " <color name=\"grey44\" color=\"rgb(112,112,112)\" compliance=\"SVG, X11\" />"
188 " <color name=\"grey45\" color=\"rgb(115,115,115)\" compliance=\"SVG, X11\" />"
189 " <color name=\"grey45\" color=\"rgb(117,117,117)\" compliance=\"SVG, X11\" />"
190 " <color name=\"grey47\" color=\"rgb(120,120,120)\" compliance=\"SVG, X11\" />"
191 " <color name=\"grey48\" color=\"rgb(122,122,122)\" compliance=\"SVG, X11\" />"
192 " <color name=\"grey49\" color=\"rgb(125,125,125)\" compliance=\"SVG, X11\" />"
193 " <color name=\"grey5\" color=\"rgb(13,13,13)\" compliance=\"SVG, X11\" />"
194 " <color name=\"grey50\" color=\"rgb(50%,50%,50%)\" compliance=\"SVG, X11\" />"
195 " <color name=\"grey51\" color=\"rgb(130,130,130)\" compliance=\"SVG, X11\" />"
196 " <color name=\"grey52\" color=\"rgb(133,133,133)\" compliance=\"SVG, X11\" />"
197 " <color name=\"grey53\" color=\"rgb(135,135,135)\" compliance=\"SVG, X11\" />"
198 " <color name=\"grey54\" color=\"rgb(138,138,138)\" compliance=\"SVG, X11\" />"
199 " <color name=\"grey55\" color=\"rgb(140,140,140)\" compliance=\"SVG, X11\" />"
200 " <color name=\"grey56\" color=\"rgb(143,143,143)\" compliance=\"SVG, X11\" />"
201 " <color name=\"grey57\" color=\"rgb(145,145,145)\" compliance=\"SVG, X11\" />"
202 " <color name=\"grey58\" color=\"rgb(148,148,148)\" compliance=\"SVG, X11\" />"
203 " <color name=\"grey59\" color=\"rgb(150,150,150)\" compliance=\"SVG, X11\" />"
204 " <color name=\"grey6\" color=\"rgb(15,15,15)\" compliance=\"SVG, X11\" />"
205 " <color name=\"grey60\" color=\"rgb(153,153,153)\" compliance=\"SVG, X11\" />"
206 " <color name=\"grey61\" color=\"rgb(156,156,156)\" compliance=\"SVG, X11\" />"
207 " <color name=\"grey62\" color=\"rgb(158,158,158)\" compliance=\"SVG, X11\" />"
208 " <color name=\"grey63\" color=\"rgb(161,161,161)\" compliance=\"SVG, X11\" />"
209 " <color name=\"grey64\" color=\"rgb(163,163,163)\" compliance=\"SVG, X11\" />"
210 " <color name=\"grey65\" color=\"rgb(166,166,166)\" compliance=\"SVG, X11\" />"
211 " <color name=\"grey66\" color=\"rgb(168,168,168)\" compliance=\"SVG, X11\" />"
212 " <color name=\"grey67\" color=\"rgb(171,171,171)\" compliance=\"SVG, X11\" />"
213 " <color name=\"grey68\" color=\"rgb(173,173,173)\" compliance=\"SVG, X11\" />"
214 " <color name=\"grey69\" color=\"rgb(176,176,176)\" compliance=\"SVG, X11\" />"
215 " <color name=\"grey7\" color=\"rgb(18,18,18)\" compliance=\"SVG, X11\" />"
216 " <color name=\"grey70\" color=\"rgb(179,179,179)\" compliance=\"SVG, X11\" />"
217 " <color name=\"grey71\" color=\"rgb(181,181,181)\" compliance=\"SVG, X11\" />"
218 " <color name=\"grey72\" color=\"rgb(184,184,184)\" compliance=\"SVG, X11\" />"
219 " <color name=\"grey73\" color=\"rgb(186,186,186)\" compliance=\"SVG, X11\" />"
220 " <color name=\"grey74\" color=\"rgb(189,189,189)\" compliance=\"SVG, X11\" />"
221 " <color name=\"grey75\" color=\"rgb(191,191,191)\" compliance=\"SVG, X11\" />"
222 " <color name=\"grey76\" color=\"rgb(194,194,194)\" compliance=\"SVG, X11\" />"
223 " <color name=\"grey77\" color=\"rgb(196,196,196)\" compliance=\"SVG, X11\" />"
224 " <color name=\"grey78\" color=\"rgb(199,199,199)\" compliance=\"SVG, X11\" />"
225 " <color name=\"grey79\" color=\"rgb(201,201,201)\" compliance=\"SVG, X11\" />"
226 " <color name=\"grey8\" color=\"rgb(20,20,20)\" compliance=\"SVG, X11\" />"
227 " <color name=\"grey80\" color=\"rgb(204,204,204)\" compliance=\"SVG, X11\" />"
228 " <color name=\"grey81\" color=\"rgb(207,207,207)\" compliance=\"SVG, X11\" />"
229 " <color name=\"grey82\" color=\"rgb(209,209,209)\" compliance=\"SVG, X11\" />"
230 " <color name=\"grey83\" color=\"rgb(212,212,212)\" compliance=\"SVG, X11\" />"
231 " <color name=\"grey84\" color=\"rgb(214,214,214)\" compliance=\"SVG, X11\" />"
232 " <color name=\"grey85\" color=\"rgb(217,217,217)\" compliance=\"SVG, X11\" />"
233 " <color name=\"grey86\" color=\"rgb(219,219,219)\" compliance=\"SVG, X11\" />"
234 " <color name=\"grey87\" color=\"rgb(222,222,222)\" compliance=\"SVG, X11\" />"
235 " <color name=\"grey88\" color=\"rgb(224,224,224)\" compliance=\"SVG, X11\" />"
236 " <color name=\"grey89\" color=\"rgb(227,227,227)\" compliance=\"SVG, X11\" />"
237 " <color name=\"grey9\" color=\"rgb(23,23,23)\" compliance=\"SVG, X11\" />"
238 " <color name=\"grey90\" color=\"rgb(229,229,229)\" compliance=\"SVG, X11\" />"
239 " <color name=\"grey91\" color=\"rgb(232,232,232)\" compliance=\"SVG, X11\" />"
240 " <color name=\"grey92\" color=\"rgb(235,235,235)\" compliance=\"SVG, X11\" />"
241 " <color name=\"grey93\" color=\"rgb(237,237,237)\" compliance=\"SVG, X11\" />"
242 " <color name=\"grey94\" color=\"rgb(240,240,240)\" compliance=\"SVG, X11\" />"
243 " <color name=\"grey95\" color=\"rgb(242,242,242)\" compliance=\"SVG, X11\" />"
244 " <color name=\"grey96\" color=\"rgb(245,245,245)\" compliance=\"SVG, X11\" />"
245 " <color name=\"grey97\" color=\"rgb(247,247,247)\" compliance=\"SVG, X11\" />"
246 " <color name=\"grey98\" color=\"rgb(250,250,250)\" compliance=\"SVG, X11\" />"
247 " <color name=\"grey99\" color=\"rgb(252,252,252)\" compliance=\"SVG, X11\" />"
248 " <color name=\"honeydew\" color=\"rgb(240,255,240)\" compliance=\"SVG, X11, XPM\" />"
249 " <color name=\"HotPink\" color=\"rgb(255,105,180)\" compliance=\"SVG, X11, XPM\" />"
250 " <color name=\"IndianRed\" color=\"rgb(205,92,92)\" compliance=\"SVG, X11, XPM\" />"
251 " <color name=\"indigo\" color=\"rgb(75,0,130)\" compliance=\"SVG\" />"
252 " <color name=\"ivory\" color=\"rgb(255,255,240)\" compliance=\"SVG, X11, XPM\" />"
253 " <color name=\"khaki\" color=\"rgb(240,230,140)\" compliance=\"SVG, X11, XPM\" />"
254 " <color name=\"lavender\" color=\"rgb(230,230,250)\" compliance=\"SVG, X11, XPM\" />"
255 " <color name=\"LavenderBlush\" color=\"rgb(255,240,245)\" compliance=\"SVG, X11, XPM\" />"
256 " <color name=\"LawnGreen\" color=\"rgb(124,252,0)\" compliance=\"SVG, X11, XPM\" />"
257 " <color name=\"LemonChiffon\" color=\"rgb(255,250,205)\" compliance=\"SVG, X11, XPM\" />"
258 " <color name=\"LightBlue\" color=\"rgb(173,216,230)\" compliance=\"SVG, X11, XPM\" />"
259 " <color name=\"LightCoral\" color=\"rgb(240,128,128)\" compliance=\"SVG, X11, XPM\" />"
260 " <color name=\"LightCyan\" color=\"rgb(224,255,255)\" compliance=\"SVG, X11, XPM\" />"
261 " <color name=\"LightGoldenrodYellow\" color=\"rgb(250,250,210)\" compliance=\"SVG, X11, XPM\" />"
262 " <color name=\"LightGray\" color=\"rgb(211,211,211)\" compliance=\"SVG, X11, XPM\" />"
263 " <color name=\"LightGreen\" color=\"rgb(144,238,144)\" compliance=\"SVG, X11\" />"
264 " <color name=\"LightGrey\" color=\"rgb(211,211,211)\" compliance=\"SVG, X11\" />"
265 " <color name=\"LightPink\" color=\"rgb(255,182,193)\" compliance=\"SVG, X11, XPM\" />"
266 " <color name=\"LightSalmon\" color=\"rgb(255,160,122)\" compliance=\"SVG, X11, XPM\" />"
267 " <color name=\"LightSeaGreen\" color=\"rgb(32,178,170)\" compliance=\"SVG, X11, XPM\" />"
268 " <color name=\"LightSkyBlue\" color=\"rgb(135,206,250)\" compliance=\"SVG, X11, XPM\" />"
269 " <color name=\"LightSlateGray\" color=\"rgb(119,136,153)\" compliance=\"SVG, X11, XPM\" />"
270 " <color name=\"LightSlateGrey\" color=\"rgb(119,136,153)\" compliance=\"SVG, X11\" />"
271 " <color name=\"LightSteelBlue\" color=\"rgb(176,196,222)\" compliance=\"SVG, X11, XPM\" />"
272 " <color name=\"LightYellow\" color=\"rgb(255,255,224)\" compliance=\"SVG, X11, XPM\" />"
273 " <color name=\"lime\" color=\"rgb(0,255,0)\" compliance=\"SVG\" />"
274 " <color name=\"LimeGreen\" color=\"rgb(50,205,50)\" compliance=\"SVG, X11, XPM\" />"
275 " <color name=\"linen\" color=\"rgb(250,240,230)\" compliance=\"SVG, X11, XPM\" />"
276 " <color name=\"maroon\" color=\"rgb(128,0,0)\" compliance=\"SVG\" />"
277 " <color name=\"MediumAquamarine\" color=\"rgb(102,205,170)\" compliance=\"SVG, X11, XPM\" />"
278 " <color name=\"MediumBlue\" color=\"rgb(0,0,205)\" compliance=\"SVG, X11, XPM\" />"
279 " <color name=\"MediumOrchid\" color=\"rgb(186,85,211)\" compliance=\"SVG, X11, XPM\" />"
280 " <color name=\"MediumPurple\" color=\"rgb(147,112,219)\" compliance=\"SVG, X11, XPM\" />"
281 " <color name=\"MediumSeaGreen\" color=\"rgb(60,179,113)\" compliance=\"SVG, X11, XPM\" />"
282 " <color name=\"MediumSlateBlue\" color=\"rgb(123,104,238)\" compliance=\"SVG, X11, XPM\" />"
283 " <color name=\"MediumSpringGreen\" color=\"rgb(0,250,154)\" compliance=\"SVG, X11, XPM\" />"
284 " <color name=\"MediumTurquoise\" color=\"rgb(72,209,204)\" compliance=\"SVG, X11, XPM\" />"
285 " <color name=\"MediumVioletRed\" color=\"rgb(199,21,133)\" compliance=\"SVG, X11, XPM\" />"
286 " <color name=\"MidnightBlue\" color=\"rgb(25,25,112)\" compliance=\"SVG, X11, XPM\" />"
287 " <color name=\"MintCream\" color=\"rgb(245,255,250)\" compliance=\"SVG, X11, XPM\" />"
288 " <color name=\"MistyRose\" color=\"rgb(255,228,225)\" compliance=\"SVG, X11, XPM\" />"
289 " <color name=\"moccasin\" color=\"rgb(255,228,181)\" compliance=\"SVG, X11, XPM\" />"
290 " <color name=\"NavajoWhite\" color=\"rgb(255,222,173)\" compliance=\"SVG, X11, XPM\" />"
291 " <color name=\"navy\" color=\"rgb(0,0,128)\" compliance=\"SVG, X11, XPM\" />"
292 " <color name=\"matte\" color=\"rgb(0,0,0,0)\" compliance=\"SVG\" />"
293 " <color name=\"OldLace\" color=\"rgb(253,245,230)\" compliance=\"SVG, X11, XPM\" />"
294 " <color name=\"olive\" color=\"rgb(128,128,0)\" compliance=\"SVG\" />"
295 " <color name=\"OliveDrab\" color=\"rgb(107,142,35)\" compliance=\"SVG, X11, XPM\" />"
296 " <color name=\"opaque\" color=\"rgb(0,0,0)\" compliance=\"SVG\" />"
297 " <color name=\"orange\" color=\"rgb(255,165,0)\" compliance=\"SVG, X11, XPM\" />"
298 " <color name=\"OrangeRed\" color=\"rgb(255,69,0)\" compliance=\"SVG, X11, XPM\" />"
299 " <color name=\"orchid\" color=\"rgb(218,112,214)\" compliance=\"SVG, X11, XPM\" />"
300 " <color name=\"PaleGoldenrod\" color=\"rgb(238,232,170)\" compliance=\"SVG, X11, XPM\" />"
301 " <color name=\"PaleGreen\" color=\"rgb(152,251,152)\" compliance=\"SVG, X11, XPM\" />"
302 " <color name=\"PaleTurquoise\" color=\"rgb(175,238,238)\" compliance=\"SVG, X11, XPM\" />"
303 " <color name=\"PaleVioletRed\" color=\"rgb(219,112,147)\" compliance=\"SVG, X11, XPM\" />"
304 " <color name=\"PapayaWhip\" color=\"rgb(255,239,213)\" compliance=\"SVG, X11, XPM\" />"
305 " <color name=\"PeachPuff\" color=\"rgb(255,218,185)\" compliance=\"SVG, X11, XPM\" />"
306 " <color name=\"peru\" color=\"rgb(205,133,63)\" compliance=\"SVG, X11, XPM\" />"
307 " <color name=\"pink\" color=\"rgb(255,192,203)\" compliance=\"SVG, X11, XPM\" />"
308 " <color name=\"plum\" color=\"rgb(221,160,221)\" compliance=\"SVG, X11, XPM\" />"
309 " <color name=\"PowderBlue\" color=\"rgb(176,224,230)\" compliance=\"SVG, X11, XPM\" />"
310 " <color name=\"purple\" color=\"rgb(128,0,128)\" compliance=\"SVG\" />"
311 " <color name=\"RosyBrown\" color=\"rgb(188,143,143)\" compliance=\"SVG, X11, XPM\" />"
312 " <color name=\"RoyalBlue\" color=\"rgb(65,105,225)\" compliance=\"SVG, X11, XPM\" />"
313 " <color name=\"SaddleBrown\" color=\"rgb(139,69,19)\" compliance=\"SVG, X11, XPM\" />"
314 " <color name=\"salmon\" color=\"rgb(250,128,114)\" compliance=\"SVG, X11, XPM\" />"
315 " <color name=\"SandyBrown\" color=\"rgb(244,164,96)\" compliance=\"SVG, X11, XPM\" />"
316 " <color name=\"SeaGreen\" color=\"rgb(45,139,87)\" compliance=\"SVG, X11, XPM\" />"
317 " <color name=\"seashell\" color=\"rgb(255,245,238)\" compliance=\"SVG, X11, XPM\" />"
318 " <color name=\"sienna\" color=\"rgb(160,82,45)\" compliance=\"SVG, X11, XPM\" />"
319 " <color name=\"silver\" color=\"rgb(192,192,192)\" compliance=\"SVG\" />"
320 " <color name=\"SkyBlue\" color=\"rgb(135,206,235)\" compliance=\"SVG, X11, XPM\" />"
321 " <color name=\"SlateBlue\" color=\"rgb(106,90,205)\" compliance=\"SVG, X11, XPM\" />"
322 " <color name=\"SlateGray\" color=\"rgb(112,128,144)\" compliance=\"SVG, X11, XPM\" />"
323 " <color name=\"SlateGrey\" color=\"rgb(112,128,144)\" compliance=\"SVG, X11\" />"
324 " <color name=\"snow\" color=\"rgb(255,250,250)\" compliance=\"SVG, X11, XPM\" />"
325 " <color name=\"SpringGreen\" color=\"rgb(0,255,127)\" compliance=\"SVG, X11, XPM\" />"
326 " <color name=\"SteelBlue\" color=\"rgb(70,130,180)\" compliance=\"SVG, X11, XPM\" />"
327 " <color name=\"tan\" color=\"rgb(210,180,140)\" compliance=\"SVG, X11, XPM\" />"
328 " <color name=\"teal\" color=\"rgb(0,128,128)\" compliance=\"SVG\" />"
329 " <color name=\"thistle\" color=\"rgb(216,191,216)\" compliance=\"SVG, X11, XPM\" />"
330 " <color name=\"tomato\" color=\"rgb(255,99,71)\" compliance=\"SVG, X11, XPM\" />"
331 " <color name=\"transparent\" color=\"rgba(0,0,0,0)\" compliance=\"SVG\" />"
332 " <color name=\"turquoise\" color=\"rgb(64,224,208)\" compliance=\"SVG, X11, XPM\" />"
333 " <color name=\"violet\" color=\"rgb(238,130,238)\" compliance=\"SVG, X11, XPM\" />"
334 " <color name=\"wheat\" color=\"rgb(245,222,179)\" compliance=\"SVG, X11, XPM\" />"
335 " <color name=\"WhiteSmoke\" color=\"rgb(245,245,245)\" compliance=\"SVG, X11, XPM\" />"
336 " <color name=\"YellowGreen\" color=\"rgb(154,205,50)\" compliance=\"SVG, X11, XPM\" />"
340 Typedef declarations.
342 typedef struct _NodeInfo
357 typedef struct _Nodes
366 typedef struct _CubeInfo
389 static LinkedListInfo
390 *color_list = (LinkedListInfo *) NULL;
393 *color_semaphore = (SemaphoreInfo *) NULL;
395 static volatile MagickBooleanType
396 instantiate_color = MagickFalse;
399 Forward declarations.
405 *GetNodeInfo(CubeInfo *,const unsigned long);
407 static MagickBooleanType
408 InitializeColorList(ExceptionInfo *),
409 LoadColorLists(const char *,ExceptionInfo *);
412 DestroyColorCube(const Image *,NodeInfo *);
415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
419 + C l a s s i f y I m a g e C o l o r s %
423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
425 % ClassifyImageColors() builds a populated CubeInfo tree for the specified
426 % image. The returned tree should be deallocated using DestroyCubeInfo()
427 % once it is no longer needed.
429 % The format of the ClassifyImageColors() method is:
431 % CubeInfo *ClassifyImageColors(const Image *image,
432 % ExceptionInfo *exception)
434 % A description of each parameter follows.
436 % o image: the image.
438 % o exception: return any errors or warnings in this structure.
442 static inline unsigned long ColorToNodeId(const Image *image,
443 const MagickPixelPacket *pixel,unsigned long index)
449 ((ScaleQuantumToChar(RoundToQuantum(pixel->red)) >> index) & 0x01) |
450 ((ScaleQuantumToChar(RoundToQuantum(pixel->green)) >> index) & 0x01) << 1 |
451 ((ScaleQuantumToChar(RoundToQuantum(pixel->blue)) >> index) & 0x01) << 2);
452 if (image->matte != MagickFalse)
453 id|=((ScaleQuantumToChar(RoundToQuantum(pixel->opacity)) >> index) &
458 static CubeInfo *ClassifyImageColors(const Image *image,
459 ExceptionInfo *exception)
461 #define EvaluateImageTag " Compute image colors... "
479 register const IndexPacket
482 register const PixelPacket
489 register unsigned long
498 Initialize color description tree.
500 assert(image != (const Image *) NULL);
501 assert(image->signature == MagickSignature);
502 if (image->debug != MagickFalse)
503 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
504 cube_info=GetCubeInfo();
505 if (cube_info == (CubeInfo *) NULL)
507 (void) ThrowMagickException(exception,GetMagickModule(),
508 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
511 GetMagickPixelPacket(image,&pixel);
512 GetMagickPixelPacket(image,&target);
513 image_view=AcquireCacheView(image);
514 for (y=0; y < (long) image->rows; y++)
516 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
517 if (p == (const PixelPacket *) NULL)
519 indexes=GetCacheViewVirtualIndexQueue(image_view);
520 for (x=0; x < (long) image->columns; x++)
523 Start at the root and proceed level by level.
525 node_info=cube_info->root;
526 index=MaxTreeDepth-1;
527 for (level=1; level < MaxTreeDepth; level++)
529 SetMagickPixelPacket(image,p,indexes+x,&pixel);
530 id=ColorToNodeId(image,&pixel,index);
531 if (node_info->child[id] == (NodeInfo *) NULL)
533 node_info->child[id]=GetNodeInfo(cube_info,level);
534 if (node_info->child[id] == (NodeInfo *) NULL)
536 (void) ThrowMagickException(exception,GetMagickModule(),
537 ResourceLimitError,"MemoryAllocationFailed","`%s'",
542 node_info=node_info->child[id];
545 for (i=0; i < (long) node_info->number_unique; i++)
547 SetMagickPixelPacket(image,&node_info->list[i].pixel,
548 &node_info->list[i].index,&target);
549 if (IsMagickColorEqual(&pixel,&target) != MagickFalse)
552 if (i < (long) node_info->number_unique)
553 node_info->list[i].count++;
556 if (node_info->number_unique == 0)
557 node_info->list=(ColorPacket *) AcquireMagickMemory(
558 sizeof(*node_info->list));
560 node_info->list=(ColorPacket *) ResizeQuantumMemory(node_info->list,
561 (size_t) (i+1),sizeof(*node_info->list));
562 if (node_info->list == (ColorPacket *) NULL)
564 (void) ThrowMagickException(exception,GetMagickModule(),
565 ResourceLimitError,"MemoryAllocationFailed","`%s'",
569 node_info->list[i].pixel=(*p);
570 if ((image->colorspace == CMYKColorspace) ||
571 (image->storage_class == PseudoClass))
572 node_info->list[i].index=indexes[x];
573 node_info->list[i].count=1;
574 node_info->number_unique++;
579 proceed=SetImageProgress(image,EvaluateImageTag,y,image->rows);
580 if (proceed == MagickFalse)
583 image_view=DestroyCacheView(image_view);
588 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
592 + C o n c a t e n a t e C o l o r C o m p o n e n t %
596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
598 % ConcatenateColorComponent() returns the pixel as a canonical string.
600 % The format of the ConcatenateColorComponent() method is:
602 % void ConcatenateColorComponent(const MagickPixelPacket *pixel,
603 % const ChannelType channel,const ComplianceType compliance,char *tuple)
605 % A description of each parameter follows.
607 % o pixel: The pixel.
609 % channel: The channel.
611 % o compliance: Adhere to this color standard: SVG, X11, or XPM.
613 % tuple: The color tuple.
616 MagickExport void ConcatenateColorComponent(const MagickPixelPacket *pixel,
617 const ChannelType channel,const ComplianceType compliance,char *tuple)
620 component[MaxTextExtent];
645 color=QuantumRange-pixel->opacity;
656 if (compliance != SVGCompliance)
658 if (pixel->depth > 16)
660 (void) FormatMagickString(component,MaxTextExtent,"%10lu",
661 (unsigned long) ScaleQuantumToLong(RoundToQuantum(color)));
662 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
665 if (pixel->depth > 8)
667 (void) FormatMagickString(component,MaxTextExtent,"%5d",
668 ScaleQuantumToShort(RoundToQuantum(color)));
669 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
672 (void) FormatMagickString(component,MaxTextExtent,"%3d",
673 ScaleQuantumToChar(RoundToQuantum(color)));
674 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
677 if (channel == OpacityChannel)
679 (void) FormatMagickString(component,MaxTextExtent,"%g",
680 (double) (QuantumScale*color));
681 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
684 if (pixel->depth > 8)
686 (void) FormatMagickString(component,MaxTextExtent,"%g%%",
687 (double) (100.0*QuantumScale*color));
688 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
691 (void) FormatMagickString(component,MaxTextExtent,"%d",
692 ScaleQuantumToChar(RoundToQuantum(color)));
693 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
697 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
701 + D e f i n e I m a g e H i s t o g r a m %
705 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
707 % DefineImageHistogram() traverses the color cube tree and notes each colormap
708 % entry. A colormap entry is any node in the color cube tree where the
709 % of unique colors is not zero.
711 % The format of the DefineImageHistogram method is:
713 % DefineImageHistogram(const Image *image,NodeInfo *node_info,
714 % ColorPacket **unique_colors)
716 % A description of each parameter follows.
718 % o image: the image.
720 % o node_info: the address of a structure of type NodeInfo which points to a
721 % node in the color cube tree that is to be pruned.
723 % o histogram: the image histogram.
726 static void DefineImageHistogram(const Image *image,NodeInfo *node_info,
727 ColorPacket **histogram)
736 Traverse any children.
738 number_children=image->matte == MagickFalse ? 8UL : 16UL;
739 for (i=0; i < (long) number_children; i++)
740 if (node_info->child[i] != (NodeInfo *) NULL)
741 DefineImageHistogram(image,node_info->child[i],histogram);
742 if (node_info->level == (MaxTreeDepth-1))
748 for (i=0; i < (long) node_info->number_unique; i++)
750 (*histogram)->pixel=p->pixel;
751 (*histogram)->index=p->index;
752 (*histogram)->count=p->count;
760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
764 + D e s t r o y C o l o r L i s t %
768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
770 % DestroyColorList() deallocates memory associated with the color list.
772 % The format of the DestroyColorList method is:
774 % DestroyColorList(void)
778 static void *DestroyColorElement(void *color_info)
783 p=(ColorInfo *) color_info;
784 if (p->path != (char *) NULL)
785 p->path=DestroyString(p->path);
786 if (p->name != (char *) NULL)
787 p->name=DestroyString(p->name);
788 p=(ColorInfo *) RelinquishMagickMemory(p);
789 return((void *) NULL);
792 MagickExport void DestroyColorList(void)
794 AcquireSemaphoreInfo(&color_semaphore);
795 if (color_list != (LinkedListInfo *) NULL)
796 color_list=DestroyLinkedList(color_list,DestroyColorElement);
797 instantiate_color=MagickFalse;
798 RelinquishSemaphoreInfo(color_semaphore);
799 DestroySemaphoreInfo(&color_semaphore);
803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
807 + D e s t r o y C u b e I n f o %
811 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
813 % DestroyCubeInfo() deallocates memory associated with a CubeInfo structure.
815 % The format of the DestroyCubeInfo method is:
817 % DestroyCubeInfo(const Image *image,CubeInfo *cube_info)
819 % A description of each parameter follows:
821 % o image: the image.
823 % o cube_info: the address of a structure of type CubeInfo.
826 static CubeInfo *DestroyCubeInfo(const Image *image,CubeInfo *cube_info)
832 Release color cube tree storage.
834 DestroyColorCube(image,cube_info->root);
837 nodes=cube_info->node_queue->next;
838 cube_info->node_queue=(Nodes *)
839 RelinquishMagickMemory(cube_info->node_queue);
840 cube_info->node_queue=nodes;
841 } while (cube_info->node_queue != (Nodes *) NULL);
842 return((CubeInfo *) RelinquishMagickMemory(cube_info));
846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
850 + D e s t r o y C o l o r C u b e %
854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856 % DestroyColorCube() traverses the color cube tree and frees the list of
859 % The format of the DestroyColorCube method is:
861 % void DestroyColorCube(const Image *image,const NodeInfo *node_info)
863 % A description of each parameter follows.
865 % o image: the image.
867 % o node_info: the address of a structure of type NodeInfo which points to a
868 % node in the color cube tree that is to be pruned.
871 static void DestroyColorCube(const Image *image,NodeInfo *node_info)
880 Traverse any children.
882 number_children=image->matte == MagickFalse ? 8UL : 16UL;
883 for (i=0; i < (long) number_children; i++)
884 if (node_info->child[i] != (NodeInfo *) NULL)
885 DestroyColorCube(image,node_info->child[i]);
886 if (node_info->list != (ColorPacket *) NULL)
887 node_info->list=(ColorPacket *) RelinquishMagickMemory(node_info->list);
891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
895 + G e t C o l o r I n f o %
899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
901 % GetColorInfo() searches the color list for the specified name and if found
902 % returns attributes for that color.
904 % The format of the GetColorInfo method is:
906 % const PixelPacket *GetColorInfo(const char *name,
907 % ExceptionInfo *exception)
909 % A description of each parameter follows:
911 % o color_info: search the color list for the specified name and if found
912 % return attributes for that color.
914 % o name: the color name.
916 % o exception: return any errors or warnings in this structure.
919 MagickExport const ColorInfo *GetColorInfo(const char *name,
920 ExceptionInfo *exception)
923 colorname[MaxTextExtent];
925 register const ColorInfo
931 assert(exception != (ExceptionInfo *) NULL);
932 if ((color_list == (LinkedListInfo *) NULL) ||
933 (instantiate_color == MagickFalse))
934 if (InitializeColorList(exception) == MagickFalse)
935 return((const ColorInfo *) NULL);
936 if ((color_list == (LinkedListInfo *) NULL) ||
937 (IsLinkedListEmpty(color_list) != MagickFalse))
938 return((const ColorInfo *) NULL);
939 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
940 return((const ColorInfo *) GetValueFromLinkedList(color_list,0));
942 Strip names of whitespace.
944 (void) CopyMagickString(colorname,name,MaxTextExtent);
945 for (q=colorname; *q != '\0'; q++)
947 if (isspace((int) ((unsigned char) *q)) == 0)
949 (void) CopyMagickString(q,q+1,MaxTextExtent);
953 Search for color tag.
955 AcquireSemaphoreInfo(&color_semaphore);
956 ResetLinkedListIterator(color_list);
957 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
958 while (p != (const ColorInfo *) NULL)
960 if (LocaleCompare(colorname,p->name) == 0)
962 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
964 if (p == (ColorInfo *) NULL)
965 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
966 "UnrecognizedColor","`%s'",name);
968 (void) InsertValueInLinkedList(color_list,0,
969 RemoveElementByValueFromLinkedList(color_list,p));
970 RelinquishSemaphoreInfo(color_semaphore);
975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
979 % G e t C o l o r I n f o L i s t %
983 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
985 % GetColorInfoList() returns any colors that match the specified pattern.
987 % The format of the GetColorInfoList function is:
989 % const ColorInfo **GetColorInfoList(const char *pattern,
990 % unsigned long *number_colors,ExceptionInfo *exception)
992 % A description of each parameter follows:
994 % o pattern: Specifies a pointer to a text string containing a pattern.
996 % o number_colors: This integer returns the number of colors in the list.
998 % o exception: return any errors or warnings in this structure.
1002 #if defined(__cplusplus) || defined(c_plusplus)
1006 static int ColorInfoCompare(const void *x,const void *y)
1012 p=(const ColorInfo **) x,
1013 q=(const ColorInfo **) y;
1014 if (LocaleCompare((*p)->path,(*q)->path) == 0)
1015 return(LocaleCompare((*p)->name,(*q)->name));
1016 return(LocaleCompare((*p)->path,(*q)->path));
1019 #if defined(__cplusplus) || defined(c_plusplus)
1023 MagickExport const ColorInfo **GetColorInfoList(const char *pattern,
1024 unsigned long *number_colors,ExceptionInfo *exception)
1029 register const ColorInfo
1036 Allocate color list.
1038 assert(pattern != (char *) NULL);
1039 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
1040 assert(number_colors != (unsigned long *) NULL);
1042 p=GetColorInfo("*",exception);
1043 if (p == (const ColorInfo *) NULL)
1044 return((const ColorInfo **) NULL);
1045 colors=(const ColorInfo **) AcquireQuantumMemory((size_t)
1046 GetNumberOfElementsInLinkedList(color_list)+1UL,sizeof(*colors));
1047 if (colors == (const ColorInfo **) NULL)
1048 return((const ColorInfo **) NULL);
1050 Generate color list.
1052 AcquireSemaphoreInfo(&color_semaphore);
1053 ResetLinkedListIterator(color_list);
1054 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
1055 for (i=0; p != (const ColorInfo *) NULL; )
1057 if ((p->stealth == MagickFalse) &&
1058 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
1060 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
1062 RelinquishSemaphoreInfo(color_semaphore);
1063 qsort((void *) colors,(size_t) i,sizeof(*colors),ColorInfoCompare);
1064 colors[i]=(ColorInfo *) NULL;
1065 *number_colors=(unsigned long) i;
1070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1074 % G e t C o l o r L i s t %
1078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1080 % GetColorList() returns any colors that match the specified pattern.
1082 % The format of the GetColorList function is:
1084 % char **GetColorList(const char *pattern,unsigned long *number_colors,
1085 % ExceptionInfo *exception)
1087 % A description of each parameter follows:
1089 % o pattern: Specifies a pointer to a text string containing a pattern.
1091 % o number_colors: This integer returns the number of colors in the list.
1093 % o exception: return any errors or warnings in this structure.
1097 #if defined(__cplusplus) || defined(c_plusplus)
1101 static int ColorCompare(const void *x,const void *y)
1107 p=(const char **) x;
1108 q=(const char **) y;
1109 return(LocaleCompare(*p,*q));
1112 #if defined(__cplusplus) || defined(c_plusplus)
1116 MagickExport char **GetColorList(const char *pattern,
1117 unsigned long *number_colors,ExceptionInfo *exception)
1122 register const ColorInfo
1129 Allocate color list.
1131 assert(pattern != (char *) NULL);
1132 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
1133 assert(number_colors != (unsigned long *) NULL);
1135 p=GetColorInfo("*",exception);
1136 if (p == (const ColorInfo *) NULL)
1137 return((char **) NULL);
1138 colors=(char **) AcquireQuantumMemory((size_t)
1139 GetNumberOfElementsInLinkedList(color_list)+1UL,sizeof(*colors));
1140 if (colors == (char **) NULL)
1141 return((char **) NULL);
1143 Generate color list.
1145 AcquireSemaphoreInfo(&color_semaphore);
1146 ResetLinkedListIterator(color_list);
1147 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
1148 for (i=0; p != (const ColorInfo *) NULL; )
1150 if ((p->stealth == MagickFalse) &&
1151 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
1152 colors[i++]=ConstantString(p->name);
1153 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
1155 RelinquishSemaphoreInfo(color_semaphore);
1156 qsort((void *) colors,(size_t) i,sizeof(*colors),ColorCompare);
1157 colors[i]=(char *) NULL;
1158 *number_colors=(unsigned long) i;
1163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1167 + G e t C o l o r T u p l e %
1171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1173 % GetColorTuple() returns a color as a color tuple string (e.g. rgba(255,0,0))
1174 % or hex string (e.g. #FF0000).
1176 % The format of the GetColorTuple method is:
1178 % GetColorTuple(const MagickPixelPacket *pixel,const MagickBooleanType hex,
1181 % A description of each parameter follows.
1183 % o pixel: the pixel.
1185 % o hex: A value other than zero returns the tuple in a hexidecimal format.
1187 % o tuple: Return the color tuple as this string.
1191 static void ConcatentateHexColorComponent(const MagickPixelPacket *pixel,
1192 const ChannelType channel,char *tuple)
1195 component[MaxTextExtent];
1218 case OpacityChannel:
1220 color=(MagickRealType) QuantumRange-pixel->opacity;
1231 if (pixel->depth > 32)
1233 (void) FormatMagickString(component,MaxTextExtent,"%08lX",
1234 ScaleQuantumToLong(RoundToQuantum(color)));
1235 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
1238 if (pixel->depth > 16)
1240 (void) FormatMagickString(component,MaxTextExtent,"%08X",
1241 (unsigned int) ScaleQuantumToLong(RoundToQuantum(color)));
1242 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
1245 if (pixel->depth > 8)
1247 (void) FormatMagickString(component,MaxTextExtent,"%04X",
1248 ScaleQuantumToShort(RoundToQuantum(color)));
1249 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
1252 (void) FormatMagickString(component,MaxTextExtent,"%02X",
1253 ScaleQuantumToChar(RoundToQuantum(color)));
1254 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
1258 MagickExport void GetColorTuple(const MagickPixelPacket *pixel,
1259 const MagickBooleanType hex,char *tuple)
1264 assert(pixel != (const MagickPixelPacket *) NULL);
1265 assert(tuple != (char *) NULL);
1266 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tuple);
1268 if (hex != MagickFalse)
1271 Convert pixel to hex color.
1273 (void) ConcatenateMagickString(tuple,"#",MaxTextExtent);
1274 ConcatentateHexColorComponent(pixel,RedChannel,tuple);
1275 ConcatentateHexColorComponent(pixel,GreenChannel,tuple);
1276 ConcatentateHexColorComponent(pixel,BlueChannel,tuple);
1277 if (pixel->colorspace == CMYKColorspace)
1278 ConcatentateHexColorComponent(pixel,IndexChannel,tuple);
1279 if ((pixel->matte != MagickFalse) && (pixel->opacity != OpaqueOpacity))
1280 ConcatentateHexColorComponent(pixel,OpacityChannel,tuple);
1284 Convert pixel to rgb() or cmyk() color.
1287 if (color.depth > 8)
1289 #define SVGCompliant(component) ((MagickRealType) \
1290 ScaleCharToQuantum(ScaleQuantumToChar(RoundToQuantum(component))));
1296 SVG requires color depths > 8 expressed as percentages.
1298 status=color.red == SVGCompliant(color.red);
1299 status&=color.green == SVGCompliant(color.green);
1300 status&=color.blue == SVGCompliant(color.blue);
1301 if (color.colorspace != CMYKColorspace)
1302 status&=color.index == SVGCompliant(color.index);
1303 if (color.matte != MagickFalse)
1304 status&=color.opacity == SVGCompliant(color.opacity);
1305 if (status != MagickFalse)
1308 (void) ConcatenateMagickString(tuple,MagickOptionToMnemonic(
1309 MagickColorspaceOptions,(long) color.colorspace),MaxTextExtent);
1310 if (color.matte != MagickFalse)
1311 (void) ConcatenateMagickString(tuple,"a",MaxTextExtent);
1312 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
1313 ConcatenateColorComponent(&color,RedChannel,SVGCompliance,tuple);
1314 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
1315 ConcatenateColorComponent(&color,GreenChannel,SVGCompliance,tuple);
1316 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
1317 ConcatenateColorComponent(&color,BlueChannel,SVGCompliance,tuple);
1318 if (color.colorspace == CMYKColorspace)
1320 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
1321 ConcatenateColorComponent(&color,IndexChannel,SVGCompliance,tuple);
1323 if (color.matte != MagickFalse)
1325 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
1326 ConcatenateColorComponent(&color,AlphaChannel,SVGCompliance,tuple);
1328 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
1334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1338 + G e t C u b e I n f o %
1342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1344 % GetCubeInfo() initializes the CubeInfo data structure.
1346 % The format of the GetCubeInfo method is:
1348 % cube_info=GetCubeInfo()
1350 % A description of each parameter follows.
1352 % o cube_info: A pointer to the Cube structure.
1355 static CubeInfo *GetCubeInfo(void)
1361 Initialize tree to describe color cube.
1363 cube_info=(CubeInfo *) AcquireMagickMemory(sizeof(*cube_info));
1364 if (cube_info == (CubeInfo *) NULL)
1365 return((CubeInfo *) NULL);
1366 (void) ResetMagickMemory(cube_info,0,sizeof(*cube_info));
1368 Initialize root node.
1370 cube_info->root=GetNodeInfo(cube_info,0);
1371 if (cube_info->root == (NodeInfo *) NULL)
1372 return((CubeInfo *) NULL);
1377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1381 % G e t I m a g e H i s t o g r a m %
1385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1387 % GetImageHistogram() returns the unique colors in an image.
1389 % The format of the GetImageHistogram method is:
1391 % unsigned long GetImageHistogram(const Image *image,
1392 % unsigned long *number_colors,ExceptionInfo *exception)
1394 % A description of each parameter follows.
1396 % o image: the image.
1398 % o file: Write a histogram of the color distribution to this file handle.
1400 % o exception: return any errors or warnings in this structure.
1403 MagickExport ColorPacket *GetImageHistogram(const Image *image,
1404 unsigned long *number_colors,ExceptionInfo *exception)
1413 histogram=(ColorPacket *) NULL;
1414 cube_info=ClassifyImageColors(image,exception);
1415 if (cube_info != (CubeInfo *) NULL)
1417 histogram=(ColorPacket *) AcquireQuantumMemory((size_t) cube_info->colors,
1418 sizeof(*histogram));
1419 if (histogram == (ColorPacket *) NULL)
1420 (void) ThrowMagickException(exception,GetMagickModule(),
1421 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1427 *number_colors=cube_info->colors;
1429 DefineImageHistogram(image,cube_info->root,&root);
1432 cube_info=DestroyCubeInfo(image,cube_info);
1437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1441 + G e t N o d e I n f o %
1445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1447 % GetNodeInfo() allocates memory for a new node in the color cube tree and
1448 % presets all fields to zero.
1450 % The format of the GetNodeInfo method is:
1452 % NodeInfo *GetNodeInfo(CubeInfo *cube_info,const unsigned long level)
1454 % A description of each parameter follows.
1456 % o cube_info: A pointer to the CubeInfo structure.
1458 % o level: Specifies the level in the storage_class the node resides.
1461 static NodeInfo *GetNodeInfo(CubeInfo *cube_info,const unsigned long level)
1466 if (cube_info->free_nodes == 0)
1472 Allocate a new nodes of nodes.
1474 nodes=(Nodes *) AcquireMagickMemory(sizeof(*nodes));
1475 if (nodes == (Nodes *) NULL)
1476 return((NodeInfo *) NULL);
1477 nodes->next=cube_info->node_queue;
1478 cube_info->node_queue=nodes;
1479 cube_info->node_info=nodes->nodes;
1480 cube_info->free_nodes=NodesInAList;
1482 cube_info->free_nodes--;
1483 node_info=cube_info->node_info++;
1484 (void) ResetMagickMemory(node_info,0,sizeof(*node_info));
1485 node_info->level=level;
1490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1494 % G e t N u m b e r C o l o r s %
1498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1500 % GetNumberColors() returns the number of unique colors in an image.
1502 % The format of the GetNumberColors method is:
1504 % unsigned long GetNumberColors(const Image *image,FILE *file,
1505 % ExceptionInfo *exception)
1507 % A description of each parameter follows.
1509 % o image: the image.
1511 % o file: Write a histogram of the color distribution to this file handle.
1513 % o exception: return any errors or warnings in this structure.
1517 #if defined(__cplusplus) || defined(c_plusplus)
1521 static int HistogramCompare(const void *x,const void *y)
1527 color_1=(const ColorPacket *) x;
1528 color_2=(const ColorPacket *) y;
1529 if (color_2->pixel.red != color_1->pixel.red)
1530 return((int) color_1->pixel.red-(int) color_2->pixel.red);
1531 if (color_2->pixel.green != color_1->pixel.green)
1532 return((int) color_1->pixel.green-(int) color_2->pixel.green);
1533 if (color_2->pixel.blue != color_1->pixel.blue)
1534 return((int) color_1->pixel.blue-(int) color_2->pixel.blue);
1535 return((int) color_2->count-(int) color_1->count);
1538 #if defined(__cplusplus) || defined(c_plusplus)
1542 MagickExport unsigned long GetNumberColors(const Image *image,FILE *file,
1543 ExceptionInfo *exception)
1545 #define HistogramImageTag "Histogram/Image"
1548 color[MaxTextExtent],
1550 tuple[MaxTextExtent];
1558 register ColorPacket
1568 if (file == (FILE *) NULL)
1573 cube_info=ClassifyImageColors(image,exception);
1574 if (cube_info != (CubeInfo *) NULL)
1575 number_colors=cube_info->colors;
1576 cube_info=DestroyCubeInfo(image,cube_info);
1577 return(number_colors);
1579 histogram=GetImageHistogram(image,&number_colors,exception);
1580 if (histogram == (ColorPacket *) NULL)
1581 return(number_colors);
1582 qsort((void *) histogram,(size_t) number_colors,sizeof(*histogram),
1584 GetMagickPixelPacket(image,&pixel);
1586 for (i=0; i < (long) number_colors; i++)
1588 SetMagickPixelPacket(image,&p->pixel,&p->index,&pixel);
1589 (void) CopyMagickString(tuple,"(",MaxTextExtent);
1590 ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
1591 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
1592 ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
1593 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
1594 ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
1595 if (pixel.colorspace == CMYKColorspace)
1597 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
1598 ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
1600 if (pixel.matte != MagickFalse)
1602 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
1603 ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
1605 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
1606 (void) QueryMagickColorname(image,&pixel,SVGCompliance,color,exception);
1607 GetColorTuple(&pixel,MagickTrue,hex);
1608 (void) fprintf(file,MagickSizeFormat,p->count);
1609 (void) fprintf(file,": %s %s %s\n",tuple,hex,color);
1610 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1611 (QuantumTick(i,number_colors) != MagickFalse))
1612 (void) image->progress_monitor(HistogramImageTag,i,number_colors,
1613 image->client_data);
1616 (void) fflush(file);
1617 histogram=(ColorPacket *) RelinquishMagickMemory(histogram);
1618 return(number_colors);
1622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1626 + I n i t i a l i z e C o l o r L i s t %
1630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1632 % InitializeColorList() initializes the color list.
1634 % The format of the InitializeColorList method is:
1636 % MagickBooleanType InitializeColorList(ExceptionInfo *exception)
1638 % A description of each parameter follows.
1640 % o exception: return any errors or warnings in this structure.
1643 static MagickBooleanType InitializeColorList(ExceptionInfo *exception)
1645 if ((color_list == (LinkedListInfo *) NULL) &&
1646 (instantiate_color == MagickFalse))
1648 AcquireSemaphoreInfo(&color_semaphore);
1649 if ((color_list == (LinkedListInfo *) NULL) &&
1650 (instantiate_color == MagickFalse))
1652 (void) LoadColorLists(ColorFilename,exception);
1653 instantiate_color=MagickTrue;
1655 RelinquishSemaphoreInfo(color_semaphore);
1657 return(color_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
1661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1665 + I s C o l o r S i m i l a r %
1669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1671 % IsColorSimilar() returns MagickTrue if the distance between two colors is
1672 % less than the specified distance in a linear three dimensional color space.
1673 % This method is used by ColorFloodFill() and other algorithms which
1674 % compare two colors.
1676 % The format of the IsColorSimilar method is:
1678 % void IsColorSimilar(const Image *image,const PixelPacket *p,
1679 % const PixelPacket *q)
1681 % A description of each parameter follows:
1683 % o image: the image.
1691 static inline double MagickMax(const double x,const double y)
1698 MagickExport MagickBooleanType IsColorSimilar(const Image *image,
1699 const PixelPacket *p,const PixelPacket *q)
1705 register MagickRealType
1710 if ((image->fuzz == 0.0) && (image->matte == MagickFalse))
1711 return(IsColorEqual(p,q));
1712 fuzz=3.0*MagickMax(image->fuzz,MagickSQ1_2)*MagickMax(image->fuzz,
1716 if (image->matte != MagickFalse)
1718 alpha=(MagickRealType) (QuantumScale*(QuantumRange-p->opacity));
1719 beta=(MagickRealType) (QuantumScale*(QuantumRange-q->opacity));
1721 pixel=alpha*p->red-beta*q->red;
1722 distance=pixel*pixel;
1723 if (distance > fuzz)
1724 return(MagickFalse);
1725 pixel=alpha*p->green-beta*q->green;
1726 distance+=pixel*pixel;
1727 if (distance > fuzz)
1728 return(MagickFalse);
1729 pixel=alpha*p->blue-beta*q->blue;
1730 distance+=pixel*pixel;
1731 if (distance > fuzz)
1732 return(MagickFalse);
1737 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1741 % I s G r a y I m a g e %
1745 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1747 % IsGrayImage() returns MagickTrue if all the pixels in the image have the
1748 % same red, green, and blue intensities.
1750 % The format of the IsGrayImage method is:
1752 % MagickBooleanType IsGrayImage(const Image *image,
1753 % ExceptionInfo *exception)
1755 % A description of each parameter follows:
1757 % o image: the image.
1759 % o exception: return any errors or warnings in this structure.
1762 MagickExport MagickBooleanType IsGrayImage(const Image *image,
1763 ExceptionInfo *exception)
1768 register const PixelPacket
1771 assert(image != (Image *) NULL);
1772 assert(image->signature == MagickSignature);
1773 if (image->debug != MagickFalse)
1774 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1775 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
1776 (image->type == GrayscaleMatteType))
1778 if (image->colorspace == CMYKColorspace)
1779 return(MagickFalse);
1781 switch (image->storage_class)
1784 case UndefinedClass:
1795 image_view=AcquireCacheView(image);
1796 for (y=0; y < (long) image->rows; y++)
1798 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1799 if (p == (const PixelPacket *) NULL)
1801 for (x=0; x < (long) image->columns; x++)
1803 if (IsGrayPixel(p) == MagickFalse)
1808 if ((type == BilevelType) && (IsMonochromePixel(p) == MagickFalse))
1812 if (type == UndefinedType)
1815 image_view=DestroyCacheView(image_view);
1824 for (i=0; i < (long) image->colors; i++)
1826 if (IsGrayPixel(p) == MagickFalse)
1831 if ((type == BilevelType) && (IsMonochromePixel(p) == MagickFalse))
1838 if (type == UndefinedType)
1839 return(MagickFalse);
1840 ((Image *) image)->type=type;
1841 if ((type == GrayscaleType) && (image->matte != MagickFalse))
1842 ((Image *) image)->type=GrayscaleMatteType;
1847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1851 % I s H i s t o g r a m I m a g e %
1855 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1857 % IsHistogramImage() returns MagickTrue if the image has 1024 unique colors or
1860 % The format of the IsHistogramImage method is:
1862 % MagickBooleanType IsHistogramImage(const Image *image,
1863 % ExceptionInfo *exception)
1865 % A description of each parameter follows.
1867 % o image: the image.
1869 % o exception: return any errors or warnings in this structure.
1872 MagickExport MagickBooleanType IsHistogramImage(const Image *image,
1873 ExceptionInfo *exception)
1875 #define MaximumUniqueColors 1024
1887 register const IndexPacket
1890 register const PixelPacket
1910 assert(image != (Image *) NULL);
1911 assert(image->signature == MagickSignature);
1912 if (image->debug != MagickFalse)
1913 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1914 if ((image->storage_class == PseudoClass) && (image->colors <= 256))
1916 if (image->storage_class == PseudoClass)
1917 return(MagickFalse);
1919 Initialize color description tree.
1921 cube_info=GetCubeInfo();
1922 if (cube_info == (CubeInfo *) NULL)
1924 (void) ThrowMagickException(exception,GetMagickModule(),
1925 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1926 return(MagickFalse);
1928 GetMagickPixelPacket(image,&pixel);
1929 GetMagickPixelPacket(image,&target);
1930 image_view=AcquireCacheView(image);
1931 for (y=0; y < (long) image->rows; y++)
1933 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1934 if (p == (const PixelPacket *) NULL)
1936 indexes=GetCacheViewVirtualIndexQueue(image_view);
1937 for (x=0; x < (long) image->columns; x++)
1940 Start at the root and proceed level by level.
1942 node_info=cube_info->root;
1943 index=MaxTreeDepth-1;
1944 for (level=1; level < MaxTreeDepth; level++)
1946 SetMagickPixelPacket(image,p,indexes+x,&pixel);
1947 id=ColorToNodeId(image,&pixel,index);
1948 if (node_info->child[id] == (NodeInfo *) NULL)
1950 node_info->child[id]=GetNodeInfo(cube_info,level);
1951 if (node_info->child[id] == (NodeInfo *) NULL)
1953 (void) ThrowMagickException(exception,GetMagickModule(),
1954 ResourceLimitError,"MemoryAllocationFailed","`%s'",
1959 node_info=node_info->child[id];
1962 if (level < MaxTreeDepth)
1964 for (i=0; i < (long) node_info->number_unique; i++)
1966 SetMagickPixelPacket(image,&node_info->list[i].pixel,
1967 &node_info->list[i].index,&target);
1968 if (IsMagickColorEqual(&pixel,&target) != MagickFalse)
1971 if (i < (long) node_info->number_unique)
1972 node_info->list[i].count++;
1976 Add this unique color to the color list.
1978 if (node_info->number_unique == 0)
1979 node_info->list=(ColorPacket *) AcquireMagickMemory(
1980 sizeof(*node_info->list));
1982 node_info->list=(ColorPacket *) ResizeQuantumMemory(node_info->list,
1983 (size_t) (i+1),sizeof(*node_info->list));
1984 if (node_info->list == (ColorPacket *) NULL)
1986 (void) ThrowMagickException(exception,GetMagickModule(),
1987 ResourceLimitError,"MemoryAllocationFailed","`%s'",
1991 node_info->list[i].pixel=(*p);
1992 if ((image->colorspace == CMYKColorspace) ||
1993 (image->storage_class == PseudoClass))
1994 node_info->list[i].index=indexes[x];
1995 node_info->list[i].count=1;
1996 node_info->number_unique++;
1997 cube_info->colors++;
1998 if (cube_info->colors > MaximumUniqueColors)
2003 if (x < (long) image->columns)
2006 image_view=DestroyCacheView(image_view);
2007 cube_info=DestroyCubeInfo(image,cube_info);
2008 return(y < (long) image->rows ? MagickFalse : MagickTrue);
2012 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2016 + I s I m a g e S i m i l a r %
2020 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2022 % IsImageSimilar() returns true if the target is similar to a region of the
2025 % The format of the IsImageSimilar method is:
2027 % MagickBooleanType IsImageSimilar(const Image *image,
2028 % const Image *target_image,long *x_offset,long *y_offset,
2029 % ExceptionInfo *exception)
2031 % A description of each parameter follows:
2033 % o image: the image.
2035 % o target_image: the target image.
2037 % o x_offset: On input the starting x position to search for a match;
2038 % on output the x position of the first match found.
2040 % o y_offset: On input the starting y position to search for a match;
2041 % on output the y position of the first match found.
2043 % o exception: return any errors or warnings in this structure.
2046 MagickExport MagickBooleanType IsImageSimilar(const Image *image,
2047 const Image *target_image,long *x_offset,long *y_offset,
2048 ExceptionInfo *exception)
2050 #define SearchImageText " Searching image... "
2063 register const PixelPacket
2067 register const IndexPacket
2079 assert(image != (Image *) NULL);
2080 assert(image->signature == MagickSignature);
2081 if (image->debug != MagickFalse)
2082 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2083 assert(target_image != (Image *) NULL);
2084 assert(target_image->signature == MagickSignature);
2085 assert(x_offset != (long *) NULL);
2086 assert(y_offset != (long *) NULL);
2087 assert(exception != (ExceptionInfo *) NULL);
2089 GetMagickPixelPacket(image,&pixel);
2090 GetMagickPixelPacket(image,&target);
2091 image_view=AcquireCacheView(image);
2092 target_view=AcquireCacheView(target_image);
2093 for (y=(*y_offset); y < (long) image->rows; y++)
2095 for (x=y == 0 ? *x_offset : 0; x < (long) image->columns; x++)
2097 for (j=0; j < (long) target_image->rows; j++)
2099 for (i=0; i < (long) target_image->columns; i++)
2101 p=GetCacheViewVirtualPixels(image_view,x+i,y+j,1,1,exception);
2102 indexes=GetCacheViewVirtualIndexQueue(image_view);
2103 SetMagickPixelPacket(image,p,indexes,&pixel);
2104 q=GetCacheViewVirtualPixels(target_view,i,j,1,1,exception);
2105 target_indexes=GetCacheViewVirtualIndexQueue(target_view);
2106 SetMagickPixelPacket(image,q,target_indexes,&target);
2107 if (IsMagickColorSimilar(&pixel,&target) == MagickFalse)
2110 if (i < (long) target_image->columns)
2113 if (j == (long) target_image->rows)
2116 if (x < (long) image->columns)
2118 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
2119 (QuantumTick(y,image->rows) != MagickFalse))
2121 status=image->progress_monitor(SearchImageText,y,image->rows,
2122 image->client_data);
2123 if (status == MagickFalse)
2127 target_view=DestroyCacheView(target_view);
2128 image_view=DestroyCacheView(image_view);
2131 return(y < (long) image->rows ? MagickTrue : MagickFalse);
2135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2139 + I s M a g i c k C o l o r S i m i l a r %
2143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2145 % IsMagickColorSimilar() returns true if the distance between two colors is
2146 % less than the specified distance in a linear three dimensional color space.
2147 % This method is used by ColorFloodFill() and other algorithms which
2148 % compare two colors.
2150 % The format of the IsMagickColorSimilar method is:
2152 % MagickBooleanType IsMagickColorSimilar(const MagickPixelPacket *p,
2153 % const MagickPixelPacket *q)
2155 % A description of each parameter follows:
2162 MagickExport MagickBooleanType IsMagickColorSimilar(const MagickPixelPacket *p,
2163 const MagickPixelPacket *q)
2169 register MagickRealType
2174 if ((p->fuzz == 0.0) && (q->fuzz == 0.0))
2175 return(IsMagickColorEqual(p,q));
2177 fuzz=MagickMax(q->fuzz,MagickSQ1_2)*MagickMax(q->fuzz,MagickSQ1_2);
2180 fuzz=3.0*MagickMax(p->fuzz,MagickSQ1_2)*MagickMax(p->fuzz,MagickSQ1_2);
2182 fuzz=3.0*MagickMax(p->fuzz,MagickSQ1_2)*MagickMax(q->fuzz,MagickSQ1_2);
2184 if (p->matte != MagickFalse)
2185 alpha=(MagickRealType) (QuantumScale*(QuantumRange-p->opacity));
2187 if (q->matte != MagickFalse)
2188 beta=(MagickRealType) (QuantumScale*(QuantumRange-q->opacity));
2189 if (p->colorspace == CMYKColorspace)
2191 alpha*=(MagickRealType) (QuantumScale*(QuantumRange-p->index));
2192 beta*=(MagickRealType) (QuantumScale*(QuantumRange-q->index));
2194 pixel=alpha*p->red-beta*q->red;
2195 if ((p->colorspace == HSLColorspace) || (p->colorspace == HSBColorspace) ||
2196 (p->colorspace == HWBColorspace))
2198 if (fabs(p->red-q->red) > (QuantumRange/2))
2200 if (p->red > (QuantumRange/2))
2201 pixel=alpha*(p->red-QuantumRange)-beta*q->red;
2203 pixel=alpha*p->red-beta*(q->red-QuantumRange);
2207 distance=pixel*pixel;
2208 if (distance > fuzz)
2209 return(MagickFalse);
2210 pixel=alpha*p->green-beta*q->green;
2211 distance+=pixel*pixel;
2212 if (distance > fuzz)
2213 return(MagickFalse);
2214 pixel=alpha*p->blue-beta*q->blue;
2215 distance+=pixel*pixel;
2216 if (distance > fuzz)
2217 return(MagickFalse);
2218 pixel=p->opacity-q->opacity;
2219 distance+=pixel*pixel;
2220 if (distance > fuzz)
2221 return(MagickFalse);
2226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2230 % I s M o n o c h r o m e I m a g e %
2234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2236 % IsMonochromeImage() returns MagickTrue if all the pixels in the image have
2237 % the same red, green, and blue intensities and the intensity is either
2238 % 0 or QuantumRange.
2240 % The format of the IsMonochromeImage method is:
2242 % MagickBooleanType IsMonochromeImage(const Image *image,
2243 % ExceptionInfo *exception)
2245 % A description of each parameter follows:
2247 % o image: the image.
2249 % o exception: return any errors or warnings in this structure.
2252 MagickExport MagickBooleanType IsMonochromeImage(const Image *image,
2253 ExceptionInfo *exception)
2258 register const PixelPacket
2261 assert(image != (Image *) NULL);
2262 assert(image->signature == MagickSignature);
2263 if (image->debug != MagickFalse)
2264 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2265 if (image->type == BilevelType)
2267 if (image->colorspace == CMYKColorspace)
2268 return(MagickFalse);
2270 switch (image->storage_class)
2273 case UndefinedClass:
2284 image_view=AcquireCacheView(image);
2285 for (y=0; y < (long) image->rows; y++)
2287 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
2288 if (p == (const PixelPacket *) NULL)
2290 for (x=0; x < (long) image->columns; x++)
2292 if (IsMonochromePixel(p) == MagickFalse)
2299 if (type == UndefinedType)
2302 image_view=DestroyCacheView(image_view);
2303 if (y == (long) image->rows)
2304 ((Image *) image)->type=BilevelType;
2313 for (i=0; i < (long) image->colors; i++)
2315 if (IsMonochromePixel(p) == MagickFalse)
2325 if (type == UndefinedType)
2326 return(MagickFalse);
2327 ((Image *) image)->type=type;
2332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2336 + I s O p a c i t y S i m i l a r %
2340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2342 % IsOpacitySimilar() returns true if the distance between two opacity
2343 % values is less than the specified distance in a linear color space. This
2344 % method is used by MatteFloodFill() and other algorithms which compare
2345 % two opacity values.
2347 % The format of the IsOpacitySimilar method is:
2349 % void IsOpacitySimilar(const Image *image,const PixelPacket *p,
2350 % const PixelPacket *q)
2352 % A description of each parameter follows:
2354 % o image: the image.
2361 MagickExport MagickBooleanType IsOpacitySimilar(const Image *image,
2362 const PixelPacket *p,const PixelPacket *q)
2368 register MagickRealType
2371 if (image->matte == MagickFalse)
2373 if (p->opacity == q->opacity)
2375 fuzz=MagickMax(image->fuzz,MagickSQ1_2)*MagickMax(image->fuzz,MagickSQ1_2);
2376 pixel=(MagickRealType) p->opacity-(MagickRealType) q->opacity;
2377 distance=pixel*pixel;
2378 if (distance > fuzz)
2379 return(MagickFalse);
2384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2388 % I s O p a q u e I m a g e %
2392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2394 % IsOpaqueImage() returns MagickTrue if none of the pixels in the image have
2395 % an opacity value other than opaque (0).
2397 % The format of the IsOpaqueImage method is:
2399 % MagickBooleanType IsOpaqueImage(const Image *image,
2400 % ExceptionInfo *exception)
2402 % A description of each parameter follows:
2404 % o image: the image.
2406 % o exception: return any errors or warnings in this structure.
2409 MagickExport MagickBooleanType IsOpaqueImage(const Image *image,
2410 ExceptionInfo *exception)
2415 register const PixelPacket
2425 Determine if image is opaque.
2427 assert(image != (Image *) NULL);
2428 assert(image->signature == MagickSignature);
2429 if (image->debug != MagickFalse)
2430 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2431 if (image->matte == MagickFalse)
2433 image_view=AcquireCacheView(image);
2434 for (y=0; y < (long) image->rows; y++)
2436 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
2437 if (p == (const PixelPacket *) NULL)
2439 for (x=0; x < (long) image->columns; x++)
2441 if (p->opacity != OpaqueOpacity)
2445 if (x < (long) image->columns)
2448 image_view=DestroyCacheView(image_view);
2449 return(y < (long) image->rows ? MagickFalse : MagickTrue);
2453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2457 % I s P a l e t t e I m a g e %
2461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2463 % IsPaletteImage() returns MagickTrue if the image is PseudoClass and has 256
2464 % unique colors or less.
2466 % The format of the IsPaletteImage method is:
2468 % MagickBooleanType IsPaletteImage(const Image *image,
2469 % ExceptionInfo *exception)
2471 % A description of each parameter follows.
2473 % o image: the image.
2475 % o exception: return any errors or warnings in this structure.
2478 MagickExport MagickBooleanType IsPaletteImage(const Image *image,
2479 ExceptionInfo *exception)
2491 register const IndexPacket
2494 register const PixelPacket
2514 assert(image != (Image *) NULL);
2515 assert(image->signature == MagickSignature);
2516 if (image->debug != MagickFalse)
2517 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2518 if ((image->storage_class == PseudoClass) && (image->colors <= 256))
2520 if (image->storage_class == PseudoClass)
2521 return(MagickFalse);
2523 Initialize color description tree.
2525 cube_info=GetCubeInfo();
2526 if (cube_info == (CubeInfo *) NULL)
2528 (void) ThrowMagickException(exception,GetMagickModule(),
2529 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
2530 return(MagickFalse);
2532 GetMagickPixelPacket(image,&pixel);
2533 GetMagickPixelPacket(image,&target);
2534 image_view=AcquireCacheView(image);
2535 for (y=0; y < (long) image->rows; y++)
2537 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
2538 if (p == (const PixelPacket *) NULL)
2540 indexes=GetCacheViewVirtualIndexQueue(image_view);
2541 for (x=0; x < (long) image->columns; x++)
2544 Start at the root and proceed level by level.
2546 node_info=cube_info->root;
2547 index=MaxTreeDepth-1;
2548 for (level=1; level < MaxTreeDepth; level++)
2550 SetMagickPixelPacket(image,p,indexes+x,&pixel);
2551 id=ColorToNodeId(image,&pixel,index);
2552 if (node_info->child[id] == (NodeInfo *) NULL)
2554 node_info->child[id]=GetNodeInfo(cube_info,level);
2555 if (node_info->child[id] == (NodeInfo *) NULL)
2557 (void) ThrowMagickException(exception,GetMagickModule(),
2558 ResourceLimitError,"MemoryAllocationFailed","`%s'",
2563 node_info=node_info->child[id];
2566 if (level < MaxTreeDepth)
2568 for (i=0; i < (long) node_info->number_unique; i++)
2570 SetMagickPixelPacket(image,&node_info->list[i].pixel,
2571 &node_info->list[i].index,&target);
2572 if (IsMagickColorEqual(&pixel,&target) != MagickFalse)
2575 if (i < (long) node_info->number_unique)
2576 node_info->list[i].count++;
2580 Add this unique color to the color list.
2582 if (node_info->number_unique == 0)
2583 node_info->list=(ColorPacket *) AcquireMagickMemory(
2584 sizeof(*node_info->list));
2586 node_info->list=(ColorPacket *) ResizeQuantumMemory(node_info->list,
2587 (size_t) (i+1),sizeof(*node_info->list));
2588 if (node_info->list == (ColorPacket *) NULL)
2590 (void) ThrowMagickException(exception,GetMagickModule(),
2591 ResourceLimitError,"MemoryAllocationFailed","`%s'",
2595 node_info->list[i].pixel=(*p);
2596 if ((image->colorspace == CMYKColorspace) ||
2597 (image->storage_class == PseudoClass))
2598 node_info->list[i].index=indexes[x];
2599 node_info->list[i].count=1;
2600 node_info->number_unique++;
2601 cube_info->colors++;
2602 if (cube_info->colors > 256)
2607 if (x < (long) image->columns)
2610 image_view=DestroyCacheView(image_view);
2611 cube_info=DestroyCubeInfo(image,cube_info);
2612 return(y < (long) image->rows ? MagickFalse : MagickTrue);
2616 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2620 % L i s t C o l o r I n f o %
2624 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2626 % ListColorInfo() lists color names to the specified file. Color names
2627 % are a convenience. Rather than defining a color by its red, green, and
2628 % blue intensities just use a color name such as white, blue, or yellow.
2630 % The format of the ListColorInfo method is:
2632 % MagickBooleanType ListColorInfo(FILE *file,ExceptionInfo *exception)
2634 % A description of each parameter follows.
2636 % o file: List color names to this file handle.
2638 % o exception: return any errors or warnings in this structure.
2641 MagickExport MagickBooleanType ListColorInfo(FILE *file,
2642 ExceptionInfo *exception)
2645 tuple[MaxTextExtent];
2660 List name and attributes of each color in the list.
2662 if (file == (const FILE *) NULL)
2664 color_info=GetColorInfoList("*",&number_colors,exception);
2665 if (color_info == (const ColorInfo **) NULL)
2666 return(MagickFalse);
2667 path=(const char *) NULL;
2668 for (i=0; i < (long) number_colors; i++)
2670 if (color_info[i]->stealth != MagickFalse)
2672 if ((path == (const char *) NULL) ||
2673 (LocaleCompare(path,color_info[i]->path) != 0))
2675 if (color_info[i]->path != (char *) NULL)
2676 (void) fprintf(file,"\nPath: %s\n\n",color_info[i]->path);
2677 (void) fprintf(file,"Name Color "
2679 (void) fprintf(file,"-------------------------------------------------"
2680 "------------------------------\n");
2682 path=color_info[i]->path;
2683 (void) fprintf(file,"%-21.21s ",color_info[i]->name);
2684 GetColorTuple(&color_info[i]->color,MagickFalse,tuple);
2685 (void) fprintf(file,"%-45.45s ",tuple);
2686 if ((color_info[i]->compliance & SVGCompliance) != 0)
2687 (void) fprintf(file,"SVG ");
2688 if ((color_info[i]->compliance & X11Compliance) != 0)
2689 (void) fprintf(file,"X11 ");
2690 if ((color_info[i]->compliance & XPMCompliance) != 0)
2691 (void) fprintf(file,"XPM ");
2692 (void) fprintf(file,"\n");
2694 color_info=(const ColorInfo **) RelinquishMagickMemory((void *) color_info);
2695 (void) fflush(file);
2700 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2704 + L o a d C o l o r L i s t %
2708 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2710 % LoadColorList() loads the color configuration file which provides a mapping
2711 % between color attributes and a color name.
2713 % The format of the LoadColorList method is:
2715 % MagickBooleanType LoadColorList(const char *xml,const char *filename,
2716 % const unsigned long depth,ExceptionInfo *exception)
2718 % A description of each parameter follows:
2720 % o xml: The color list in XML format.
2722 % o filename: The color list filename.
2724 % o depth: depth of <include /> statements.
2726 % o exception: return any errors or warnings in this structure.
2729 static MagickBooleanType LoadColorList(const char *xml,const char *filename,
2730 const unsigned long depth,ExceptionInfo *exception)
2733 keyword[MaxTextExtent],
2746 Load the color map file.
2748 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
2749 "Loading color file \"%s\" ...",filename);
2750 if (xml == (char *) NULL)
2751 return(MagickFalse);
2752 if (color_list == (LinkedListInfo *) NULL)
2754 color_list=NewLinkedList(0);
2755 if (color_list == (LinkedListInfo *) NULL)
2757 ThrowFileException(exception,ResourceLimitError,
2758 "MemoryAllocationFailed",filename);
2759 return(MagickFalse);
2763 color_info=(ColorInfo *) NULL;
2764 token=AcquireString(xml);
2765 for (q=(char *) xml; *q != '\0'; )
2770 GetMagickToken(q,&q,token);
2773 (void) CopyMagickString(keyword,token,MaxTextExtent);
2774 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
2779 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
2780 GetMagickToken(q,&q,token);
2783 if (LocaleNCompare(keyword,"<!--",4) == 0)
2788 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
2789 GetMagickToken(q,&q,token);
2792 if (LocaleCompare(keyword,"<include") == 0)
2797 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
2799 (void) CopyMagickString(keyword,token,MaxTextExtent);
2800 GetMagickToken(q,&q,token);
2803 GetMagickToken(q,&q,token);
2804 if (LocaleCompare(keyword,"file") == 0)
2807 (void) ThrowMagickException(exception,GetMagickModule(),
2808 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
2812 path[MaxTextExtent],
2815 GetPathComponent(filename,HeadPath,path);
2817 (void) ConcatenateMagickString(path,DirectorySeparator,
2819 if (*token == *DirectorySeparator)
2820 (void) CopyMagickString(path,token,MaxTextExtent);
2822 (void) ConcatenateMagickString(path,token,MaxTextExtent);
2823 xml=FileToString(path,~0,exception);
2824 if (xml != (char *) NULL)
2826 status=LoadColorList(xml,path,depth+1,exception);
2827 xml=(char *) RelinquishMagickMemory(xml);
2834 if (LocaleCompare(keyword,"<color") == 0)
2839 color_info=(ColorInfo *) AcquireMagickMemory(sizeof(*color_info));
2840 if (color_info == (ColorInfo *) NULL)
2841 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
2842 (void) ResetMagickMemory(color_info,0,sizeof(*color_info));
2843 color_info->path=ConstantString(filename);
2844 color_info->signature=MagickSignature;
2847 if (color_info == (ColorInfo *) NULL)
2849 if (LocaleCompare(keyword,"/>") == 0)
2851 status=AppendValueToLinkedList(color_list,color_info);
2852 if (status == MagickFalse)
2853 (void) ThrowMagickException(exception,GetMagickModule(),
2854 ResourceLimitError,"MemoryAllocationFailed","`%s'",
2856 color_info=(ColorInfo *) NULL;
2858 GetMagickToken(q,(const char **) NULL,token);
2861 GetMagickToken(q,&q,token);
2862 GetMagickToken(q,&q,token);
2868 if (LocaleCompare((char *) keyword,"color") == 0)
2870 (void) QueryMagickColor(token,&color_info->color,exception);
2873 if (LocaleCompare((char *) keyword,"compliance") == 0)
2878 compliance=color_info->compliance;
2879 if (GlobExpression(token,"*SVG*",MagickTrue) != MagickFalse)
2880 compliance|=SVGCompliance;
2881 if (GlobExpression(token,"*X11*",MagickTrue) != MagickFalse)
2882 compliance|=X11Compliance;
2883 if (GlobExpression(token,"*XPM*",MagickTrue) != MagickFalse)
2884 compliance|=XPMCompliance;
2885 color_info->compliance=(ComplianceType) compliance;
2893 if (LocaleCompare((char *) keyword,"name") == 0)
2895 color_info->name=ConstantString(token);
2903 if (LocaleCompare((char *) keyword,"stealth") == 0)
2905 color_info->stealth=IsMagickTrue(token);
2914 token=(char *) RelinquishMagickMemory(token);
2919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2923 % L o a d C o l o r L i s t s %
2927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2929 % LoadColorList() loads one or more color configuration file which provides a
2930 % mapping between color attributes and a color name.
2932 % The format of the LoadColorLists method is:
2934 % MagickBooleanType LoadColorLists(const char *filename,
2935 % ExceptionInfo *exception)
2937 % A description of each parameter follows:
2939 % o filename: the font file name.
2941 % o exception: return any errors or warnings in this structure.
2944 static MagickBooleanType LoadColorLists(const char *filename,
2945 ExceptionInfo *exception)
2947 #if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
2948 return(LoadColorList(ColorMap,"built-in",0,exception));
2960 options=GetConfigureOptions(filename,exception);
2961 option=(const StringInfo *) GetNextValueInLinkedList(options);
2962 while (option != (const StringInfo *) NULL)
2964 status|=LoadColorList((const char *) GetStringInfoDatum(option),
2965 GetStringInfoPath(option),0,exception);
2966 option=(const StringInfo *) GetNextValueInLinkedList(options);
2968 options=DestroyConfigureOptions(options);
2969 if ((color_list == (LinkedListInfo *) NULL) ||
2970 (IsLinkedListEmpty(color_list) != MagickFalse))
2971 status|=LoadColorList(ColorMap,"built-in",0,exception);
2972 return(status != 0 ? MagickTrue : MagickFalse);
2977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2981 % Q u e r y C o l o r D a t a b a s e %
2985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2987 % QueryColorDatabase() returns the red, green, blue, and opacity intensities
2988 % for a given color name.
2990 % The format of the QueryColorDatabase method is:
2992 % MagickBooleanType QueryColorDatabase(const char *name,PixelPacket *color,
2993 % ExceptionInfo *exception)
2995 % A description of each parameter follows:
2997 % o name: the color name (e.g. white, blue, yellow).
2999 % o color: the red, green, blue, and opacity intensities values of the
3000 % named color in this structure.
3002 % o exception: return any errors or warnings in this structure.
3006 static inline double MagickMin(const double x,const double y)
3013 MagickExport MagickBooleanType QueryColorDatabase(const char *name,
3014 PixelPacket *color,ExceptionInfo *exception)
3022 status=QueryMagickColor(name,&pixel,exception);
3023 color->opacity=RoundToQuantum(pixel.opacity);
3024 if (pixel.colorspace == CMYKColorspace)
3026 color->red=RoundToQuantum((MagickRealType) (QuantumRange-MagickMin(
3027 QuantumRange,(MagickRealType) (QuantumScale*pixel.red*(QuantumRange-
3028 pixel.index)+pixel.index))));
3029 color->green=RoundToQuantum((MagickRealType) (QuantumRange-MagickMin(
3030 QuantumRange,(MagickRealType) (QuantumScale*pixel.green*(QuantumRange-
3031 pixel.index)+pixel.index))));
3032 color->blue=RoundToQuantum((MagickRealType) (QuantumRange-MagickMin(
3033 QuantumRange,(MagickRealType) (QuantumScale*pixel.blue*(QuantumRange-
3034 pixel.index)+pixel.index))));
3037 color->red=RoundToQuantum(pixel.red);
3038 color->green=RoundToQuantum(pixel.green);
3039 color->blue=RoundToQuantum(pixel.blue);
3044 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3048 % Q u e r y C o l o r n a m e %
3052 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3054 % QueryColorname() returns a named color for the given color intensity. If
3055 % an exact match is not found, a rgb() color is returned instead.
3057 % The format of the QueryColorname method is:
3059 % MagickBooleanType QueryColorname(const Image *image,
3060 % const PixelPacket *color,const ComplianceType compliance,char *name,
3061 % ExceptionInfo *exception)
3063 % A description of each parameter follows.
3065 % o image: the image.
3067 % o color: the color intensities.
3069 % o compliance: Adhere to this color standard: SVG, X11, or XPM.
3071 % o name: Return the color name or hex value.
3073 % o exception: return any errors or warnings in this structure.
3076 MagickExport MagickBooleanType QueryColorname(const Image *image,
3077 const PixelPacket *color,const ComplianceType compliance,char *name,
3078 ExceptionInfo *exception)
3083 GetMagickPixelPacket(image,&pixel);
3084 SetMagickPixelPacket(image,color,(IndexPacket *) NULL,&pixel);
3085 return(QueryMagickColorname(image,&pixel,compliance,name,exception));
3089 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3093 % Q u e r y M a g i c k C o l o r %
3097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3099 % QueryMagickColor() returns the red, green, blue, and opacity intensities
3100 % for a given color name.
3102 % The format of the QueryMagickColor method is:
3104 % MagickBooleanType QueryMagickColor(const char *name,
3105 % MagickPixelPacket *color,ExceptionInfo *exception)
3107 % A description of each parameter follows:
3109 % o name: the color name (e.g. white, blue, yellow).
3111 % o color: the red, green, blue, and opacity intensities values of the
3112 % named color in this structure.
3114 % o exception: return any errors or warnings in this structure.
3117 MagickExport MagickBooleanType QueryMagickColor(const char *name,
3118 MagickPixelPacket *color,ExceptionInfo *exception)
3132 register const ColorInfo
3139 Initialize color return value.
3141 assert(name != (const char *) NULL);
3142 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3143 assert(color != (MagickPixelPacket *) NULL);
3144 GetMagickPixelPacket((Image *) NULL,color);
3145 if ((name == (char *) NULL) || (*name == '\0'))
3146 name=BackgroundColor;
3147 while (isspace((int) ((unsigned char) *name)) != 0)
3167 (void) ResetMagickMemory(&pixel,0,sizeof(pixel));
3169 for (n=0; isxdigit((int) ((unsigned char) name[n])) != MagickFalse; n++) ;
3174 pixel.red=pixel.green;
3175 pixel.green=pixel.blue;
3177 for (i=(long) (n/3-1); i >= 0; i--)
3181 if ((c >= '0') && (c <= '9'))
3182 pixel.blue|=(int) (c-'0');
3184 if ((c >= 'A') && (c <= 'F'))
3185 pixel.blue|=(int) c-((int) 'A'-10);
3187 if ((c >= 'a') && (c <= 'f'))
3188 pixel.blue|=(int) c-((int) 'a'-10);
3190 return(MagickFalse);
3192 } while (isxdigit((int) ((unsigned char) *name)) != MagickFalse);
3199 (void) ThrowMagickException(exception,GetMagickModule(),
3200 OptionWarning,"UnrecognizedColor","`%s'",name);
3201 return(MagickFalse);
3205 pixel.red=pixel.green;
3206 pixel.green=pixel.blue;
3207 pixel.blue=pixel.opacity;
3209 for (i=(long) (n/4-1); i >= 0; i--)
3213 if ((c >= '0') && (c <= '9'))
3214 pixel.opacity|=(int) (c-'0');
3216 if ((c >= 'A') && (c <= 'F'))
3217 pixel.opacity|=(int) c-((int) 'A'-10);
3219 if ((c >= 'a') && (c <= 'f'))
3220 pixel.opacity|=(int) c-((int) 'a'-10);
3222 return(MagickFalse);
3224 } while (isxdigit((int) ((unsigned char) *name)) != MagickFalse);
3227 color->colorspace=RGBColorspace;
3228 color->matte=MagickFalse;
3229 range=GetQuantumRange(depth);
3230 color->red=(MagickRealType) ScaleAnyToQuantum(pixel.red,range);
3231 color->green=(MagickRealType) ScaleAnyToQuantum(pixel.green,range);
3232 color->blue=(MagickRealType) ScaleAnyToQuantum(pixel.blue,range);
3233 color->opacity=(MagickRealType) OpaqueOpacity;
3236 color->matte=MagickTrue;
3237 color->opacity=(MagickRealType) (QuantumRange-ScaleAnyToQuantum(
3238 pixel.opacity,range));
3243 if (strchr(name,'(') != (char *) NULL)
3246 colorspace[MaxTextExtent];
3249 Parse color of the form rgb(100,255,0).
3251 (void) CopyMagickString(colorspace,name,MaxTextExtent);
3252 for (i=0; colorspace[i] != '\0'; i++)
3253 if (colorspace[i] == '(')
3255 colorspace[i--]='\0';
3256 LocaleLower(colorspace);
3257 color->matte=MagickFalse;
3258 if ((i > 0) && (colorspace[i] == 'a'))
3261 color->matte=MagickTrue;
3263 type=ParseMagickOption(MagickColorspaceOptions,MagickFalse,colorspace);
3266 (void) ThrowMagickException(exception,GetMagickModule(),
3267 OptionWarning,"UnrecognizedColor","`%s'",name);
3268 return(MagickFalse);
3270 color->colorspace=(ColorspaceType) type;
3271 SetGeometryInfo(&geometry_info);
3272 flags=ParseGeometry(name+i+1,&geometry_info);
3273 scale=(MagickRealType) ScaleCharToQuantum(1);
3274 if ((flags & PercentValue) != 0)
3275 scale=(MagickRealType) (QuantumRange/100.0);
3276 if ((flags & RhoValue) != 0)
3277 color->red=(MagickRealType) RoundToQuantum(scale*geometry_info.rho);
3278 if ((flags & SigmaValue) != 0)
3279 color->green=(MagickRealType) RoundToQuantum(scale*geometry_info.sigma);
3280 if ((flags & XiValue) != 0)
3281 color->blue=(MagickRealType) RoundToQuantum(scale*geometry_info.xi);
3282 color->opacity=(MagickRealType) OpaqueOpacity;
3283 if ((flags & PsiValue) != 0)
3285 if (color->colorspace == CMYKColorspace)
3286 color->index=(MagickRealType) RoundToQuantum(scale*
3289 if (color->matte != MagickFalse)
3290 color->opacity=(MagickRealType) RoundToQuantum((MagickRealType)
3291 (QuantumRange-QuantumRange*geometry_info.psi));
3293 if (((flags & ChiValue) != 0) && (color->matte != MagickFalse))
3294 color->opacity=(MagickRealType) RoundToQuantum((MagickRealType)
3295 (QuantumRange-QuantumRange*geometry_info.chi));
3296 if (LocaleCompare(colorspace,"gray") == 0)
3298 color->green=color->red;
3299 color->blue=color->red;
3300 if (((flags & SigmaValue) != 0) && (color->matte != MagickFalse))
3301 color->opacity=(MagickRealType) RoundToQuantum((MagickRealType)
3302 (QuantumRange-QuantumRange*geometry_info.sigma));
3304 if ((LocaleCompare(colorspace,"HSB") == 0) ||
3305 (LocaleCompare(colorspace,"HSL") == 0) ||
3306 (LocaleCompare(colorspace,"HWB") == 0))
3312 if ((flags & PercentValue) != 0)
3314 geometry_info.rho*=360.0*scale;
3316 if ((flags & PercentValue) != 0)
3318 geometry_info.sigma*=scale;
3319 geometry_info.xi*=scale;
3320 if (LocaleCompare(colorspace,"HSB") == 0)
3321 ConvertHSBToRGB(fmod(fmod(geometry_info.rho,360.0)+360.0,360.0)/
3322 360.0,geometry_info.sigma,geometry_info.xi,&pixel.red,
3323 &pixel.green,&pixel.blue);
3325 if (LocaleCompare(colorspace,"HSL") == 0)
3326 ConvertHSLToRGB(fmod(fmod(geometry_info.rho,360.0)+360.0,360.0)/
3327 360.0,geometry_info.sigma,geometry_info.xi,&pixel.red,
3328 &pixel.green,&pixel.blue);
3330 ConvertHWBToRGB(fmod(fmod(geometry_info.rho,360.0)+360.0,360.0)/
3331 360.0,geometry_info.sigma,geometry_info.xi,&pixel.red,
3332 &pixel.green,&pixel.blue);
3333 color->colorspace=RGBColorspace;
3334 color->red=(MagickRealType) pixel.red;
3335 color->green=(MagickRealType) pixel.green;
3336 color->blue=(MagickRealType) pixel.blue;
3343 p=GetColorInfo(name,exception);
3344 if (p == (const ColorInfo *) NULL)
3345 return(MagickFalse);
3346 color->colorspace=RGBColorspace;
3347 color->matte=p->color.opacity != OpaqueOpacity ? MagickTrue : MagickFalse;
3348 color->red=(MagickRealType) p->color.red;
3349 color->green=(MagickRealType) p->color.green;
3350 color->blue=(MagickRealType) p->color.blue;
3351 color->opacity=(MagickRealType) p->color.opacity;
3357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3361 % Q u e r y M a g i c k C o l o r n a m e %
3365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3367 % QueryMagickColorname() returns a named color for the given color intensity.
3368 % If an exact match is not found, a hex value is returned instead. For
3369 % example an intensity of rgb:(0,0,0) returns black whereas rgb:(223,223,223)
3372 % The format of the QueryMagickColorname method is:
3374 % MagickBooleanType QueryMagickColorname(const Image *image,
3375 % const PixelPacket *color,const ComplianceType compliance,char *name,
3376 % ExceptionInfo *exception)
3378 % A description of each parameter follows.
3380 % o image: the image.
3382 % o color: the color intensities.
3384 % o Compliance: Adhere to this color standard: SVG, X11, or XPM.
3386 % o name: Return the color name or hex value.
3388 % o exception: return any errors or warnings in this structure.
3391 MagickExport MagickBooleanType QueryMagickColorname(const Image *image,
3392 const MagickPixelPacket *color,const ComplianceType compliance,
3393 char *name,ExceptionInfo *exception)
3401 register const ColorInfo
3406 if (compliance == XPMCompliance)
3408 pixel.matte=MagickFalse;
3409 pixel.depth=(unsigned long) MagickMin(1.0*image->depth,16.0);
3410 GetColorTuple(&pixel,MagickTrue,name);
3413 GetColorTuple(&pixel,compliance != SVGCompliance ? MagickTrue : MagickFalse,
3415 (void) GetColorInfo("*",exception);
3416 ResetLinkedListIterator(color_list);
3417 opacity=image->matte != MagickFalse ? color->opacity : OpaqueOpacity;
3418 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
3419 while (p != (const ColorInfo *) NULL)
3421 if (((p->compliance & compliance) != 0) && ((p->color.red == color->red)) &&
3422 (p->color.green == color->green) && (p->color.blue == color->blue) &&
3423 (p->color.opacity == opacity))
3425 (void) CopyMagickString(name,p->name,MaxTextExtent);
3428 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
3434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3438 % U n i q u e I m a g e C o l o r s %
3442 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3444 % UniqueImageColors() returns the unique colors of an image.
3446 % The format of the UniqueImageColors method is:
3448 % Image *UniqueImageColors(const Image *image,ExceptionInfo *exception)
3450 % A description of each parameter follows.
3452 % o image: the image.
3454 % o exception: return any errors or warnings in this structure.
3458 static void UniqueColorsToImage(Image *image,CubeInfo *cube_info,
3459 const NodeInfo *node_info,ExceptionInfo *exception)
3461 #define UniqueColorsImageTag "UniqueColors/Image"
3470 Traverse any children.
3472 number_children=image->matte == MagickFalse ? 8UL : 16UL;
3473 for (i=0; i < (long) number_children; i++)
3474 if (node_info->child[i] != (NodeInfo *) NULL)
3475 UniqueColorsToImage(image,cube_info,node_info->child[i],exception);
3476 if (node_info->level == (MaxTreeDepth-1))
3478 register ColorPacket
3481 register IndexPacket
3482 *__restrict indexes;
3484 register PixelPacket
3488 for (i=0; i < (long) node_info->number_unique; i++)
3490 q=QueueAuthenticPixels(image,cube_info->x,0,1,1,exception);
3491 if (q == (PixelPacket *) NULL)
3493 indexes=GetAuthenticIndexQueue(image);
3495 if (image->colorspace == CMYKColorspace)
3497 if (SyncAuthenticPixels(image,exception) == MagickFalse)
3502 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
3503 (QuantumTick(cube_info->progress,cube_info->colors) != MagickFalse))
3504 (void) image->progress_monitor(UniqueColorsImageTag,cube_info->progress,
3505 cube_info->colors,image->client_data);
3506 cube_info->progress++;
3510 MagickExport Image *UniqueImageColors(const Image *image,
3511 ExceptionInfo *exception)
3519 cube_info=ClassifyImageColors(image,exception);
3520 if (cube_info == (CubeInfo *) NULL)
3521 return((Image *) NULL);
3522 unique_image=CloneImage(image,cube_info->colors,1,MagickTrue,exception);
3523 if (unique_image == (Image *) NULL)
3524 return(unique_image);
3525 if (SetImageStorageClass(unique_image,DirectClass) == MagickFalse)
3527 InheritException(exception,&unique_image->exception);
3528 unique_image=DestroyImage(unique_image);
3529 return((Image *) NULL);
3531 UniqueColorsToImage(unique_image,cube_info,cube_info->root,exception);
3532 if (cube_info->colors < MaxColormapSize)
3537 quantize_info=AcquireQuantizeInfo((ImageInfo *) NULL);
3538 quantize_info->number_colors=MaxColormapSize;
3539 quantize_info->dither=MagickFalse;
3540 quantize_info->tree_depth=8;
3541 (void) QuantizeImage(quantize_info,unique_image);
3542 quantize_info=DestroyQuantizeInfo(quantize_info);
3544 cube_info=DestroyCubeInfo(image,cube_info);
3545 return(unique_image);