00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "magick/studio.h"
00044 #include "magick/blob.h"
00045 #include "magick/cache-view.h"
00046 #include "magick/cache.h"
00047 #include "magick/color.h"
00048 #include "magick/color-private.h"
00049 #include "magick/client.h"
00050 #include "magick/configure.h"
00051 #include "magick/exception.h"
00052 #include "magick/exception-private.h"
00053 #include "magick/gem.h"
00054 #include "magick/geometry.h"
00055 #include "magick/image-private.h"
00056 #include "magick/memory_.h"
00057 #include "magick/monitor.h"
00058 #include "magick/monitor-private.h"
00059 #include "magick/option.h"
00060 #include "magick/pixel-private.h"
00061 #include "magick/quantize.h"
00062 #include "magick/quantum.h"
00063 #include "magick/semaphore.h"
00064 #include "magick/string_.h"
00065 #include "magick/token.h"
00066 #include "magick/utility.h"
00067 #include "magick/xml-tree.h"
00068
00069
00070
00071
00072 #define ColorFilename "colors.xml"
00073 #define MaxTreeDepth 8
00074 #define NodesInAList 1536
00075
00076
00077
00078
00079 static const char
00080 *ColorMap = (const char *)
00081 "<?xml version=\"1.0\"?>"
00082 "<colormap>"
00083 " <color name=\"none\" color=\"rgba(0,0,0,0)\" compliance=\"SVG\" />"
00084 " <color name=\"black\" color=\"rgb(0,0,0)\" compliance=\"SVG, X11, XPM\" />"
00085 " <color name=\"red\" color=\"rgb(255,0,0)\" compliance=\"SVG, X11, XPM\" />"
00086 " <color name=\"magenta\" color=\"rgb(255,0,255)\" compliance=\"SVG, X11, XPM\" />"
00087 " <color name=\"green\" color=\"rgb(0,128,0)\" compliance=\"SVG\" />"
00088 " <color name=\"cyan\" color=\"rgb(0,255,255)\" compliance=\"SVG, X11, XPM\" />"
00089 " <color name=\"blue\" color=\"rgb(0,0,255)\" compliance=\"SVG, X11, XPM\" />"
00090 " <color name=\"yellow\" color=\"rgb(255,255,0)\" compliance=\"SVG, X11, XPM\" />"
00091 " <color name=\"white\" color=\"rgb(255,255,255)\" compliance=\"SVG, X11\" />"
00092 " <color name=\"AliceBlue\" color=\"rgb(240,248,255)\" compliance=\"SVG, X11, XPM\" />"
00093 " <color name=\"AntiqueWhite\" color=\"rgb(250,235,215)\" compliance=\"SVG, X11, XPM\" />"
00094 " <color name=\"aqua\" color=\"rgb(0,255,255)\" compliance=\"SVG\" />"
00095 " <color name=\"aquamarine\" color=\"rgb(127,255,212)\" compliance=\"SVG, X11, XPM\" />"
00096 " <color name=\"azure\" color=\"rgb(240,255,255)\" compliance=\"SVG, X11, XPM\" />"
00097 " <color name=\"beige\" color=\"rgb(245,245,220)\" compliance=\"SVG, X11, XPM\" />"
00098 " <color name=\"bisque\" color=\"rgb(255,228,196)\" compliance=\"SVG, X11, XPM\" />"
00099 " <color name=\"BlanchedAlmond\" color=\"rgb(255,235,205)\" compliance=\"SVG, X11, XPM\" />"
00100 " <color name=\"BlueViolet\" color=\"rgb(138,43,226)\" compliance=\"SVG, X11, XPM\" />"
00101 " <color name=\"brown\" color=\"rgb(165,42,42)\" compliance=\"SVG, X11, XPM\" />"
00102 " <color name=\"burlywood\" color=\"rgb(222,184,135)\" compliance=\"SVG, X11, XPM\" />"
00103 " <color name=\"CadetBlue\" color=\"rgb(95,158,160)\" compliance=\"SVG, X11, XPM\" />"
00104 " <color name=\"chartreuse\" color=\"rgb(127,255,0)\" compliance=\"SVG, X11, XPM\" />"
00105 " <color name=\"chocolate\" color=\"rgb(210,105,30)\" compliance=\"SVG, X11, XPM\" />"
00106 " <color name=\"coral\" color=\"rgb(255,127,80)\" compliance=\"SVG, X11, XPM\" />"
00107 " <color name=\"CornflowerBlue\" color=\"rgb(100,149,237)\" compliance=\"SVG, X11, XPM\" />"
00108 " <color name=\"cornsilk\" color=\"rgb(255,248,220)\" compliance=\"SVG, X11, XPM\" />"
00109 " <color name=\"crimson\" color=\"rgb(220,20,60)\" compliance=\"SVG\" />"
00110 " <color name=\"DarkBlue\" color=\"rgb(0,0,139)\" compliance=\"SVG, X11\" />"
00111 " <color name=\"DarkCyan\" color=\"rgb(0,139,139)\" compliance=\"SVG, X11\" />"
00112 " <color name=\"DarkGoldenrod\" color=\"rgb(184,134,11)\" compliance=\"SVG, X11, XPM\" />"
00113 " <color name=\"DarkGray\" color=\"rgb(169,169,169)\" compliance=\"SVG, X11\" />"
00114 " <color name=\"DarkGreen\" color=\"rgb(0,100,0)\" compliance=\"SVG, X11, XPM\" />"
00115 " <color name=\"DarkGrey\" color=\"rgb(169,169,169)\" compliance=\"SVG, X11\" />"
00116 " <color name=\"DarkKhaki\" color=\"rgb(189,183,107)\" compliance=\"SVG, X11, XPM\" />"
00117 " <color name=\"DarkMagenta\" color=\"rgb(139,0,139)\" compliance=\"SVG, X11\" />"
00118 " <color name=\"DarkOliveGreen\" color=\"rgb(85,107,47)\" compliance=\"SVG, X11, XPM\" />"
00119 " <color name=\"DarkOrange\" color=\"rgb(255,140,0)\" compliance=\"SVG, X11, XPM\" />"
00120 " <color name=\"DarkOrchid\" color=\"rgb(153,50,204)\" compliance=\"SVG, X11, XPM\" />"
00121 " <color name=\"DarkRed\" color=\"rgb(139,0,0)\" compliance=\"SVG, X11\" />"
00122 " <color name=\"DarkSalmon\" color=\"rgb(233,150,122)\" compliance=\"SVG, X11, XPM\" />"
00123 " <color name=\"DarkSeaGreen\" color=\"rgb(143,188,143)\" compliance=\"SVG, X11, XPM\" />"
00124 " <color name=\"DarkSlateBlue\" color=\"rgb(72,61,139)\" compliance=\"SVG, X11, XPM\" />"
00125 " <color name=\"DarkSlateGray\" color=\"rgb(47,79,79)\" compliance=\"SVG, X11, XPM\" />"
00126 " <color name=\"DarkSlateGrey\" color=\"rgb(47,79,79)\" compliance=\"SVG, X11\" />"
00127 " <color name=\"DarkTurquoise\" color=\"rgb(0,206,209)\" compliance=\"SVG, X11, XPM\" />"
00128 " <color name=\"DarkViolet\" color=\"rgb(148,0,211)\" compliance=\"SVG, X11, XPM\" />"
00129 " <color name=\"DeepPink\" color=\"rgb(255,20,147)\" compliance=\"SVG, X11, XPM\" />"
00130 " <color name=\"DeepSkyBlue\" color=\"rgb(0,191,255)\" compliance=\"SVG, X11, XPM\" />"
00131 " <color name=\"DimGray\" color=\"rgb(105,105,105)\" compliance=\"SVG, X11, XPM\" />"
00132 " <color name=\"DimGrey\" color=\"rgb(105,105,105)\" compliance=\"SVG, X11\" />"
00133 " <color name=\"DodgerBlue\" color=\"rgb(30,144,255)\" compliance=\"SVG, X11, XPM\" />"
00134 " <color name=\"firebrick\" color=\"rgb(178,34,34)\" compliance=\"SVG, X11, XPM\" />"
00135 " <color name=\"FloralWhite\" color=\"rgb(255,250,240)\" compliance=\"SVG, X11, XPM\" />"
00136 " <color name=\"ForestGreen\" color=\"rgb(34,139,34)\" compliance=\"SVG, X11, XPM\" />"
00137 " <color name=\"fractal\" color=\"rgb(128,128,128)\" compliance=\"SVG\" />"
00138 " <color name=\"fuchsia\" color=\"rgb(255,0,255)\" compliance=\"SVG\" />"
00139 " <color name=\"gainsboro\" color=\"rgb(220,220,220)\" compliance=\"SVG, X11, XPM\" />"
00140 " <color name=\"GhostWhite\" color=\"rgb(248,248,255)\" compliance=\"SVG, X11, XPM\" />"
00141 " <color name=\"gold\" color=\"rgb(255,215,0)\" compliance=\"X11, XPM\" />"
00142 " <color name=\"goldenrod\" color=\"rgb(218,165,32)\" compliance=\"SVG, X11, XPM\" />"
00143 " <color name=\"gray\" color=\"rgb(126,126,126)\" compliance=\"SVG\" />"
00144 " <color name=\"gray74\" color=\"rgb(189,189,189)\" compliance=\"SVG, X11\" />"
00145 " <color name=\"gray100\" color=\"rgb(255,255,255)\" compliance=\"SVG, X11\" />"
00146 " <color name=\"grey\" color=\"rgb(190,190,190)\" compliance=\"SVG, X11\" />"
00147 " <color name=\"grey0\" color=\"rgb(0,0,0)\" compliance=\"SVG, X11\" />"
00148 " <color name=\"grey1\" color=\"rgb(3,3,3)\" compliance=\"SVG, X11\" />"
00149 " <color name=\"grey10\" color=\"rgb(26,26,26)\" compliance=\"SVG, X11\" />"
00150 " <color name=\"grey100\" color=\"rgb(255,255,255)\" compliance=\"SVG, X11\" />"
00151 " <color name=\"grey11\" color=\"rgb(28,28,28)\" compliance=\"SVG, X11\" />"
00152 " <color name=\"grey12\" color=\"rgb(31,31,31)\" compliance=\"SVG, X11\" />"
00153 " <color name=\"grey13\" color=\"rgb(33,33,33)\" compliance=\"SVG, X11\" />"
00154 " <color name=\"grey14\" color=\"rgb(36,36,36)\" compliance=\"SVG, X11\" />"
00155 " <color name=\"grey15\" color=\"rgb(38,38,38)\" compliance=\"SVG, X11\" />"
00156 " <color name=\"grey16\" color=\"rgb(41,41,41)\" compliance=\"SVG, X11\" />"
00157 " <color name=\"grey17\" color=\"rgb(43,43,43)\" compliance=\"SVG, X11\" />"
00158 " <color name=\"grey18\" color=\"rgb(45,45,45)\" compliance=\"SVG, X11\" />"
00159 " <color name=\"grey19\" color=\"rgb(48,48,48)\" compliance=\"SVG, X11\" />"
00160 " <color name=\"grey2\" color=\"rgb(5,5,5)\" compliance=\"SVG, X11\" />"
00161 " <color name=\"grey20\" color=\"rgb(51,51,51)\" compliance=\"SVG, X11\" />"
00162 " <color name=\"grey21\" color=\"rgb(54,54,54)\" compliance=\"SVG, X11\" />"
00163 " <color name=\"grey22\" color=\"rgb(56,56,56)\" compliance=\"SVG, X11\" />"
00164 " <color name=\"grey23\" color=\"rgb(59,59,59)\" compliance=\"SVG, X11\" />"
00165 " <color name=\"grey24\" color=\"rgb(61,61,61)\" compliance=\"SVG, X11\" />"
00166 " <color name=\"grey25\" color=\"rgb(64,64,64)\" compliance=\"SVG, X11\" />"
00167 " <color name=\"grey26\" color=\"rgb(66,66,66)\" compliance=\"SVG, X11\" />"
00168 " <color name=\"grey27\" color=\"rgb(69,69,69)\" compliance=\"SVG, X11\" />"
00169 " <color name=\"grey28\" color=\"rgb(71,71,71)\" compliance=\"SVG, X11\" />"
00170 " <color name=\"grey29\" color=\"rgb(74,74,74)\" compliance=\"SVG, X11\" />"
00171 " <color name=\"grey3\" color=\"rgb(8,8,8)\" compliance=\"SVG, X11\" />"
00172 " <color name=\"grey30\" color=\"rgb(77,77,77)\" compliance=\"SVG, X11\" />"
00173 " <color name=\"grey31\" color=\"rgb(79,79,79)\" compliance=\"SVG, X11\" />"
00174 " <color name=\"grey32\" color=\"rgb(82,82,82)\" compliance=\"SVG, X11\" />"
00175 " <color name=\"grey33\" color=\"rgb(84,84,84)\" compliance=\"SVG, X11\" />"
00176 " <color name=\"grey34\" color=\"rgb(87,87,87)\" compliance=\"SVG, X11\" />"
00177 " <color name=\"grey35\" color=\"rgb(89,89,89)\" compliance=\"SVG, X11\" />"
00178 " <color name=\"grey36\" color=\"rgb(92,92,92)\" compliance=\"SVG, X11\" />"
00179 " <color name=\"grey37\" color=\"rgb(94,94,94)\" compliance=\"SVG, X11\" />"
00180 " <color name=\"grey38\" color=\"rgb(97,97,97)\" compliance=\"SVG, X11\" />"
00181 " <color name=\"grey39\" color=\"rgb(99,99,99)\" compliance=\"SVG, X11\" />"
00182 " <color name=\"grey4\" color=\"rgb(10,10,10)\" compliance=\"SVG, X11\" />"
00183 " <color name=\"grey40\" color=\"rgb(102,102,102)\" compliance=\"SVG, X11\" />"
00184 " <color name=\"grey41\" color=\"rgb(105,105,105)\" compliance=\"SVG, X11\" />"
00185 " <color name=\"grey42\" color=\"rgb(107,107,107)\" compliance=\"SVG, X11\" />"
00186 " <color name=\"grey43\" color=\"rgb(110,110,110)\" compliance=\"SVG, X11\" />"
00187 " <color name=\"grey44\" color=\"rgb(112,112,112)\" compliance=\"SVG, X11\" />"
00188 " <color name=\"grey45\" color=\"rgb(115,115,115)\" compliance=\"SVG, X11\" />"
00189 " <color name=\"grey45\" color=\"rgb(117,117,117)\" compliance=\"SVG, X11\" />"
00190 " <color name=\"grey47\" color=\"rgb(120,120,120)\" compliance=\"SVG, X11\" />"
00191 " <color name=\"grey48\" color=\"rgb(122,122,122)\" compliance=\"SVG, X11\" />"
00192 " <color name=\"grey49\" color=\"rgb(125,125,125)\" compliance=\"SVG, X11\" />"
00193 " <color name=\"grey5\" color=\"rgb(13,13,13)\" compliance=\"SVG, X11\" />"
00194 " <color name=\"grey50\" color=\"rgb(50%,50%,50%)\" compliance=\"SVG, X11\" />"
00195 " <color name=\"grey51\" color=\"rgb(130,130,130)\" compliance=\"SVG, X11\" />"
00196 " <color name=\"grey52\" color=\"rgb(133,133,133)\" compliance=\"SVG, X11\" />"
00197 " <color name=\"grey53\" color=\"rgb(135,135,135)\" compliance=\"SVG, X11\" />"
00198 " <color name=\"grey54\" color=\"rgb(138,138,138)\" compliance=\"SVG, X11\" />"
00199 " <color name=\"grey55\" color=\"rgb(140,140,140)\" compliance=\"SVG, X11\" />"
00200 " <color name=\"grey56\" color=\"rgb(143,143,143)\" compliance=\"SVG, X11\" />"
00201 " <color name=\"grey57\" color=\"rgb(145,145,145)\" compliance=\"SVG, X11\" />"
00202 " <color name=\"grey58\" color=\"rgb(148,148,148)\" compliance=\"SVG, X11\" />"
00203 " <color name=\"grey59\" color=\"rgb(150,150,150)\" compliance=\"SVG, X11\" />"
00204 " <color name=\"grey6\" color=\"rgb(15,15,15)\" compliance=\"SVG, X11\" />"
00205 " <color name=\"grey60\" color=\"rgb(153,153,153)\" compliance=\"SVG, X11\" />"
00206 " <color name=\"grey61\" color=\"rgb(156,156,156)\" compliance=\"SVG, X11\" />"
00207 " <color name=\"grey62\" color=\"rgb(158,158,158)\" compliance=\"SVG, X11\" />"
00208 " <color name=\"grey63\" color=\"rgb(161,161,161)\" compliance=\"SVG, X11\" />"
00209 " <color name=\"grey64\" color=\"rgb(163,163,163)\" compliance=\"SVG, X11\" />"
00210 " <color name=\"grey65\" color=\"rgb(166,166,166)\" compliance=\"SVG, X11\" />"
00211 " <color name=\"grey66\" color=\"rgb(168,168,168)\" compliance=\"SVG, X11\" />"
00212 " <color name=\"grey67\" color=\"rgb(171,171,171)\" compliance=\"SVG, X11\" />"
00213 " <color name=\"grey68\" color=\"rgb(173,173,173)\" compliance=\"SVG, X11\" />"
00214 " <color name=\"grey69\" color=\"rgb(176,176,176)\" compliance=\"SVG, X11\" />"
00215 " <color name=\"grey7\" color=\"rgb(18,18,18)\" compliance=\"SVG, X11\" />"
00216 " <color name=\"grey70\" color=\"rgb(179,179,179)\" compliance=\"SVG, X11\" />"
00217 " <color name=\"grey71\" color=\"rgb(181,181,181)\" compliance=\"SVG, X11\" />"
00218 " <color name=\"grey72\" color=\"rgb(184,184,184)\" compliance=\"SVG, X11\" />"
00219 " <color name=\"grey73\" color=\"rgb(186,186,186)\" compliance=\"SVG, X11\" />"
00220 " <color name=\"grey74\" color=\"rgb(189,189,189)\" compliance=\"SVG, X11\" />"
00221 " <color name=\"grey75\" color=\"rgb(191,191,191)\" compliance=\"SVG, X11\" />"
00222 " <color name=\"grey76\" color=\"rgb(194,194,194)\" compliance=\"SVG, X11\" />"
00223 " <color name=\"grey77\" color=\"rgb(196,196,196)\" compliance=\"SVG, X11\" />"
00224 " <color name=\"grey78\" color=\"rgb(199,199,199)\" compliance=\"SVG, X11\" />"
00225 " <color name=\"grey79\" color=\"rgb(201,201,201)\" compliance=\"SVG, X11\" />"
00226 " <color name=\"grey8\" color=\"rgb(20,20,20)\" compliance=\"SVG, X11\" />"
00227 " <color name=\"grey80\" color=\"rgb(204,204,204)\" compliance=\"SVG, X11\" />"
00228 " <color name=\"grey81\" color=\"rgb(207,207,207)\" compliance=\"SVG, X11\" />"
00229 " <color name=\"grey82\" color=\"rgb(209,209,209)\" compliance=\"SVG, X11\" />"
00230 " <color name=\"grey83\" color=\"rgb(212,212,212)\" compliance=\"SVG, X11\" />"
00231 " <color name=\"grey84\" color=\"rgb(214,214,214)\" compliance=\"SVG, X11\" />"
00232 " <color name=\"grey85\" color=\"rgb(217,217,217)\" compliance=\"SVG, X11\" />"
00233 " <color name=\"grey86\" color=\"rgb(219,219,219)\" compliance=\"SVG, X11\" />"
00234 " <color name=\"grey87\" color=\"rgb(222,222,222)\" compliance=\"SVG, X11\" />"
00235 " <color name=\"grey88\" color=\"rgb(224,224,224)\" compliance=\"SVG, X11\" />"
00236 " <color name=\"grey89\" color=\"rgb(227,227,227)\" compliance=\"SVG, X11\" />"
00237 " <color name=\"grey9\" color=\"rgb(23,23,23)\" compliance=\"SVG, X11\" />"
00238 " <color name=\"grey90\" color=\"rgb(229,229,229)\" compliance=\"SVG, X11\" />"
00239 " <color name=\"grey91\" color=\"rgb(232,232,232)\" compliance=\"SVG, X11\" />"
00240 " <color name=\"grey92\" color=\"rgb(235,235,235)\" compliance=\"SVG, X11\" />"
00241 " <color name=\"grey93\" color=\"rgb(237,237,237)\" compliance=\"SVG, X11\" />"
00242 " <color name=\"grey94\" color=\"rgb(240,240,240)\" compliance=\"SVG, X11\" />"
00243 " <color name=\"grey95\" color=\"rgb(242,242,242)\" compliance=\"SVG, X11\" />"
00244 " <color name=\"grey96\" color=\"rgb(245,245,245)\" compliance=\"SVG, X11\" />"
00245 " <color name=\"grey97\" color=\"rgb(247,247,247)\" compliance=\"SVG, X11\" />"
00246 " <color name=\"grey98\" color=\"rgb(250,250,250)\" compliance=\"SVG, X11\" />"
00247 " <color name=\"grey99\" color=\"rgb(252,252,252)\" compliance=\"SVG, X11\" />"
00248 " <color name=\"honeydew\" color=\"rgb(240,255,240)\" compliance=\"SVG, X11, XPM\" />"
00249 " <color name=\"HotPink\" color=\"rgb(255,105,180)\" compliance=\"SVG, X11, XPM\" />"
00250 " <color name=\"IndianRed\" color=\"rgb(205,92,92)\" compliance=\"SVG, X11, XPM\" />"
00251 " <color name=\"indigo\" color=\"rgb(75,0,130)\" compliance=\"SVG\" />"
00252 " <color name=\"ivory\" color=\"rgb(255,255,240)\" compliance=\"SVG, X11, XPM\" />"
00253 " <color name=\"khaki\" color=\"rgb(240,230,140)\" compliance=\"SVG, X11, XPM\" />"
00254 " <color name=\"lavender\" color=\"rgb(230,230,250)\" compliance=\"SVG, X11, XPM\" />"
00255 " <color name=\"LavenderBlush\" color=\"rgb(255,240,245)\" compliance=\"SVG, X11, XPM\" />"
00256 " <color name=\"LawnGreen\" color=\"rgb(124,252,0)\" compliance=\"SVG, X11, XPM\" />"
00257 " <color name=\"LemonChiffon\" color=\"rgb(255,250,205)\" compliance=\"SVG, X11, XPM\" />"
00258 " <color name=\"LightBlue\" color=\"rgb(173,216,230)\" compliance=\"SVG, X11, XPM\" />"
00259 " <color name=\"LightCoral\" color=\"rgb(240,128,128)\" compliance=\"SVG, X11, XPM\" />"
00260 " <color name=\"LightCyan\" color=\"rgb(224,255,255)\" compliance=\"SVG, X11, XPM\" />"
00261 " <color name=\"LightGoldenrodYellow\" color=\"rgb(250,250,210)\" compliance=\"SVG, X11, XPM\" />"
00262 " <color name=\"LightGray\" color=\"rgb(211,211,211)\" compliance=\"SVG, X11, XPM\" />"
00263 " <color name=\"LightGreen\" color=\"rgb(144,238,144)\" compliance=\"SVG, X11\" />"
00264 " <color name=\"LightGrey\" color=\"rgb(211,211,211)\" compliance=\"SVG, X11\" />"
00265 " <color name=\"LightPink\" color=\"rgb(255,182,193)\" compliance=\"SVG, X11, XPM\" />"
00266 " <color name=\"LightSalmon\" color=\"rgb(255,160,122)\" compliance=\"SVG, X11, XPM\" />"
00267 " <color name=\"LightSeaGreen\" color=\"rgb(32,178,170)\" compliance=\"SVG, X11, XPM\" />"
00268 " <color name=\"LightSkyBlue\" color=\"rgb(135,206,250)\" compliance=\"SVG, X11, XPM\" />"
00269 " <color name=\"LightSlateGray\" color=\"rgb(119,136,153)\" compliance=\"SVG, X11, XPM\" />"
00270 " <color name=\"LightSlateGrey\" color=\"rgb(119,136,153)\" compliance=\"SVG, X11\" />"
00271 " <color name=\"LightSteelBlue\" color=\"rgb(176,196,222)\" compliance=\"SVG, X11, XPM\" />"
00272 " <color name=\"LightYellow\" color=\"rgb(255,255,224)\" compliance=\"SVG, X11, XPM\" />"
00273 " <color name=\"lime\" color=\"rgb(0,255,0)\" compliance=\"SVG\" />"
00274 " <color name=\"LimeGreen\" color=\"rgb(50,205,50)\" compliance=\"SVG, X11, XPM\" />"
00275 " <color name=\"linen\" color=\"rgb(250,240,230)\" compliance=\"SVG, X11, XPM\" />"
00276 " <color name=\"maroon\" color=\"rgb(128,0,0)\" compliance=\"SVG\" />"
00277 " <color name=\"MediumAquamarine\" color=\"rgb(102,205,170)\" compliance=\"SVG, X11, XPM\" />"
00278 " <color name=\"MediumBlue\" color=\"rgb(0,0,205)\" compliance=\"SVG, X11, XPM\" />"
00279 " <color name=\"MediumOrchid\" color=\"rgb(186,85,211)\" compliance=\"SVG, X11, XPM\" />"
00280 " <color name=\"MediumPurple\" color=\"rgb(147,112,219)\" compliance=\"SVG, X11, XPM\" />"
00281 " <color name=\"MediumSeaGreen\" color=\"rgb(60,179,113)\" compliance=\"SVG, X11, XPM\" />"
00282 " <color name=\"MediumSlateBlue\" color=\"rgb(123,104,238)\" compliance=\"SVG, X11, XPM\" />"
00283 " <color name=\"MediumSpringGreen\" color=\"rgb(0,250,154)\" compliance=\"SVG, X11, XPM\" />"
00284 " <color name=\"MediumTurquoise\" color=\"rgb(72,209,204)\" compliance=\"SVG, X11, XPM\" />"
00285 " <color name=\"MediumVioletRed\" color=\"rgb(199,21,133)\" compliance=\"SVG, X11, XPM\" />"
00286 " <color name=\"MidnightBlue\" color=\"rgb(25,25,112)\" compliance=\"SVG, X11, XPM\" />"
00287 " <color name=\"MintCream\" color=\"rgb(245,255,250)\" compliance=\"SVG, X11, XPM\" />"
00288 " <color name=\"MistyRose\" color=\"rgb(255,228,225)\" compliance=\"SVG, X11, XPM\" />"
00289 " <color name=\"moccasin\" color=\"rgb(255,228,181)\" compliance=\"SVG, X11, XPM\" />"
00290 " <color name=\"NavajoWhite\" color=\"rgb(255,222,173)\" compliance=\"SVG, X11, XPM\" />"
00291 " <color name=\"navy\" color=\"rgb(0,0,128)\" compliance=\"SVG, X11, XPM\" />"
00292 " <color name=\"matte\" color=\"rgb(0,0,0,0)\" compliance=\"SVG\" />"
00293 " <color name=\"OldLace\" color=\"rgb(253,245,230)\" compliance=\"SVG, X11, XPM\" />"
00294 " <color name=\"olive\" color=\"rgb(128,128,0)\" compliance=\"SVG\" />"
00295 " <color name=\"OliveDrab\" color=\"rgb(107,142,35)\" compliance=\"SVG, X11, XPM\" />"
00296 " <color name=\"opaque\" color=\"rgb(0,0,0)\" compliance=\"SVG\" />"
00297 " <color name=\"orange\" color=\"rgb(255,165,0)\" compliance=\"SVG, X11, XPM\" />"
00298 " <color name=\"OrangeRed\" color=\"rgb(255,69,0)\" compliance=\"SVG, X11, XPM\" />"
00299 " <color name=\"orchid\" color=\"rgb(218,112,214)\" compliance=\"SVG, X11, XPM\" />"
00300 " <color name=\"PaleGoldenrod\" color=\"rgb(238,232,170)\" compliance=\"SVG, X11, XPM\" />"
00301 " <color name=\"PaleGreen\" color=\"rgb(152,251,152)\" compliance=\"SVG, X11, XPM\" />"
00302 " <color name=\"PaleTurquoise\" color=\"rgb(175,238,238)\" compliance=\"SVG, X11, XPM\" />"
00303 " <color name=\"PaleVioletRed\" color=\"rgb(219,112,147)\" compliance=\"SVG, X11, XPM\" />"
00304 " <color name=\"PapayaWhip\" color=\"rgb(255,239,213)\" compliance=\"SVG, X11, XPM\" />"
00305 " <color name=\"PeachPuff\" color=\"rgb(255,218,185)\" compliance=\"SVG, X11, XPM\" />"
00306 " <color name=\"peru\" color=\"rgb(205,133,63)\" compliance=\"SVG, X11, XPM\" />"
00307 " <color name=\"pink\" color=\"rgb(255,192,203)\" compliance=\"SVG, X11, XPM\" />"
00308 " <color name=\"plum\" color=\"rgb(221,160,221)\" compliance=\"SVG, X11, XPM\" />"
00309 " <color name=\"PowderBlue\" color=\"rgb(176,224,230)\" compliance=\"SVG, X11, XPM\" />"
00310 " <color name=\"purple\" color=\"rgb(128,0,128)\" compliance=\"SVG\" />"
00311 " <color name=\"RosyBrown\" color=\"rgb(188,143,143)\" compliance=\"SVG, X11, XPM\" />"
00312 " <color name=\"RoyalBlue\" color=\"rgb(65,105,225)\" compliance=\"SVG, X11, XPM\" />"
00313 " <color name=\"SaddleBrown\" color=\"rgb(139,69,19)\" compliance=\"SVG, X11, XPM\" />"
00314 " <color name=\"salmon\" color=\"rgb(250,128,114)\" compliance=\"SVG, X11, XPM\" />"
00315 " <color name=\"SandyBrown\" color=\"rgb(244,164,96)\" compliance=\"SVG, X11, XPM\" />"
00316 " <color name=\"SeaGreen\" color=\"rgb(45,139,87)\" compliance=\"SVG, X11, XPM\" />"
00317 " <color name=\"seashell\" color=\"rgb(255,245,238)\" compliance=\"SVG, X11, XPM\" />"
00318 " <color name=\"sienna\" color=\"rgb(160,82,45)\" compliance=\"SVG, X11, XPM\" />"
00319 " <color name=\"silver\" color=\"rgb(192,192,192)\" compliance=\"SVG\" />"
00320 " <color name=\"SkyBlue\" color=\"rgb(135,206,235)\" compliance=\"SVG, X11, XPM\" />"
00321 " <color name=\"SlateBlue\" color=\"rgb(106,90,205)\" compliance=\"SVG, X11, XPM\" />"
00322 " <color name=\"SlateGray\" color=\"rgb(112,128,144)\" compliance=\"SVG, X11, XPM\" />"
00323 " <color name=\"SlateGrey\" color=\"rgb(112,128,144)\" compliance=\"SVG, X11\" />"
00324 " <color name=\"snow\" color=\"rgb(255,250,250)\" compliance=\"SVG, X11, XPM\" />"
00325 " <color name=\"SpringGreen\" color=\"rgb(0,255,127)\" compliance=\"SVG, X11, XPM\" />"
00326 " <color name=\"SteelBlue\" color=\"rgb(70,130,180)\" compliance=\"SVG, X11, XPM\" />"
00327 " <color name=\"tan\" color=\"rgb(210,180,140)\" compliance=\"SVG, X11, XPM\" />"
00328 " <color name=\"teal\" color=\"rgb(0,128,128)\" compliance=\"SVG\" />"
00329 " <color name=\"thistle\" color=\"rgb(216,191,216)\" compliance=\"SVG, X11, XPM\" />"
00330 " <color name=\"tomato\" color=\"rgb(255,99,71)\" compliance=\"SVG, X11, XPM\" />"
00331 " <color name=\"transparent\" color=\"rgba(0,0,0,0)\" compliance=\"SVG\" />"
00332 " <color name=\"turquoise\" color=\"rgb(64,224,208)\" compliance=\"SVG, X11, XPM\" />"
00333 " <color name=\"violet\" color=\"rgb(238,130,238)\" compliance=\"SVG, X11, XPM\" />"
00334 " <color name=\"wheat\" color=\"rgb(245,222,179)\" compliance=\"SVG, X11, XPM\" />"
00335 " <color name=\"WhiteSmoke\" color=\"rgb(245,245,245)\" compliance=\"SVG, X11, XPM\" />"
00336 " <color name=\"YellowGreen\" color=\"rgb(154,205,50)\" compliance=\"SVG, X11, XPM\" />"
00337 "</colormap>";
00338
00339
00340
00341
00342 typedef struct _NodeInfo
00343 {
00344 struct _NodeInfo
00345 *child[16];
00346
00347 ColorPacket
00348 *list;
00349
00350 MagickSizeType
00351 number_unique;
00352
00353 unsigned long
00354 level;
00355 } NodeInfo;
00356
00357 typedef struct _Nodes
00358 {
00359 NodeInfo
00360 nodes[NodesInAList];
00361
00362 struct _Nodes
00363 *next;
00364 } Nodes;
00365
00366 typedef struct _CubeInfo
00367 {
00368 NodeInfo
00369 *root;
00370
00371 long
00372 x,
00373 progress;
00374
00375 unsigned long
00376 colors,
00377 free_nodes;
00378
00379 NodeInfo
00380 *node_info;
00381
00382 Nodes
00383 *node_queue;
00384 } CubeInfo;
00385
00386
00387
00388
00389 static LinkedListInfo
00390 *color_list = (LinkedListInfo *) NULL;
00391
00392 static SemaphoreInfo
00393 *color_semaphore = (SemaphoreInfo *) NULL;
00394
00395 static volatile MagickBooleanType
00396 instantiate_color = MagickFalse;
00397
00398
00399
00400
00401 static CubeInfo
00402 *GetCubeInfo(void);
00403
00404 static NodeInfo
00405 *GetNodeInfo(CubeInfo *,const unsigned long);
00406
00407 static MagickBooleanType
00408 InitializeColorList(ExceptionInfo *),
00409 LoadColorLists(const char *,ExceptionInfo *);
00410
00411 static void
00412 DestroyColorCube(const Image *,NodeInfo *);
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 static inline unsigned long ColorToNodeId(const Image *image,
00443 const MagickPixelPacket *pixel,unsigned long index)
00444 {
00445 unsigned long
00446 id;
00447
00448 id=(unsigned long) (
00449 ((ScaleQuantumToChar(RoundToQuantum(pixel->red)) >> index) & 0x01) |
00450 ((ScaleQuantumToChar(RoundToQuantum(pixel->green)) >> index) & 0x01) << 1 |
00451 ((ScaleQuantumToChar(RoundToQuantum(pixel->blue)) >> index) & 0x01) << 2);
00452 if (image->matte != MagickFalse)
00453 id|=((ScaleQuantumToChar(RoundToQuantum(pixel->opacity)) >> index) &
00454 0x01) << 3;
00455 return(id);
00456 }
00457
00458 static CubeInfo *ClassifyImageColors(const Image *image,
00459 ExceptionInfo *exception)
00460 {
00461 #define EvaluateImageTag " Compute image colors... "
00462
00463 CubeInfo
00464 *cube_info;
00465
00466 long
00467 y;
00468
00469 MagickBooleanType
00470 proceed;
00471
00472 MagickPixelPacket
00473 pixel,
00474 target;
00475
00476 NodeInfo
00477 *node_info;
00478
00479 register const IndexPacket
00480 *indexes;
00481
00482 register const PixelPacket
00483 *p;
00484
00485 register long
00486 i,
00487 x;
00488
00489 register unsigned long
00490 id,
00491 index,
00492 level;
00493
00494 ViewInfo
00495 *image_view;
00496
00497
00498
00499
00500 assert(image != (const Image *) NULL);
00501 assert(image->signature == MagickSignature);
00502 if (image->debug != MagickFalse)
00503 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00504 cube_info=GetCubeInfo();
00505 if (cube_info == (CubeInfo *) NULL)
00506 {
00507 (void) ThrowMagickException(exception,GetMagickModule(),
00508 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
00509 return(cube_info);
00510 }
00511 GetMagickPixelPacket(image,&pixel);
00512 GetMagickPixelPacket(image,&target);
00513 image_view=AcquireCacheView(image);
00514 for (y=0; y < (long) image->rows; y++)
00515 {
00516 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
00517 if (p == (const PixelPacket *) NULL)
00518 break;
00519 indexes=GetCacheViewVirtualIndexQueue(image_view);
00520 for (x=0; x < (long) image->columns; x++)
00521 {
00522
00523
00524
00525 node_info=cube_info->root;
00526 index=MaxTreeDepth-1;
00527 for (level=1; level < MaxTreeDepth; level++)
00528 {
00529 SetMagickPixelPacket(image,p,indexes+x,&pixel);
00530 id=ColorToNodeId(image,&pixel,index);
00531 if (node_info->child[id] == (NodeInfo *) NULL)
00532 {
00533 node_info->child[id]=GetNodeInfo(cube_info,level);
00534 if (node_info->child[id] == (NodeInfo *) NULL)
00535 {
00536 (void) ThrowMagickException(exception,GetMagickModule(),
00537 ResourceLimitError,"MemoryAllocationFailed","`%s'",
00538 image->filename);
00539 return(0);
00540 }
00541 }
00542 node_info=node_info->child[id];
00543 index--;
00544 }
00545 for (i=0; i < (long) node_info->number_unique; i++)
00546 {
00547 SetMagickPixelPacket(image,&node_info->list[i].pixel,
00548 &node_info->list[i].index,&target);
00549 if (IsMagickColorEqual(&pixel,&target) != MagickFalse)
00550 break;
00551 }
00552 if (i < (long) node_info->number_unique)
00553 node_info->list[i].count++;
00554 else
00555 {
00556 if (node_info->number_unique == 0)
00557 node_info->list=(ColorPacket *) AcquireMagickMemory(
00558 sizeof(*node_info->list));
00559 else
00560 node_info->list=(ColorPacket *) ResizeQuantumMemory(node_info->list,
00561 (size_t) (i+1),sizeof(*node_info->list));
00562 if (node_info->list == (ColorPacket *) NULL)
00563 {
00564 (void) ThrowMagickException(exception,GetMagickModule(),
00565 ResourceLimitError,"MemoryAllocationFailed","`%s'",
00566 image->filename);
00567 return(0);
00568 }
00569 node_info->list[i].pixel=(*p);
00570 if ((image->colorspace == CMYKColorspace) ||
00571 (image->storage_class == PseudoClass))
00572 node_info->list[i].index=indexes[x];
00573 node_info->list[i].count=1;
00574 node_info->number_unique++;
00575 cube_info->colors++;
00576 }
00577 p++;
00578 }
00579 proceed=SetImageProgress(image,EvaluateImageTag,y,image->rows);
00580 if (proceed == MagickFalse)
00581 break;
00582 }
00583 image_view=DestroyCacheView(image_view);
00584 return(cube_info);
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 MagickExport void ConcatenateColorComponent(const MagickPixelPacket *pixel,
00617 const ChannelType channel,const ComplianceType compliance,char *tuple)
00618 {
00619 char
00620 component[MaxTextExtent];
00621
00622 MagickRealType
00623 color;
00624
00625 color=0.0;
00626 switch (channel)
00627 {
00628 case RedChannel:
00629 {
00630 color=pixel->red;
00631 break;
00632 }
00633 case GreenChannel:
00634 {
00635 color=pixel->green;
00636 break;
00637 }
00638 case BlueChannel:
00639 {
00640 color=pixel->blue;
00641 break;
00642 }
00643 case AlphaChannel:
00644 {
00645 color=QuantumRange-pixel->opacity;
00646 break;
00647 }
00648 case IndexChannel:
00649 {
00650 color=pixel->index;
00651 break;
00652 }
00653 default:
00654 break;
00655 }
00656 if (compliance != SVGCompliance)
00657 {
00658 if (pixel->depth > 16)
00659 {
00660 (void) FormatMagickString(component,MaxTextExtent,"%10lu",
00661 (unsigned long) ScaleQuantumToLong(RoundToQuantum(color)));
00662 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
00663 return;
00664 }
00665 if (pixel->depth > 8)
00666 {
00667 (void) FormatMagickString(component,MaxTextExtent,"%5d",
00668 ScaleQuantumToShort(RoundToQuantum(color)));
00669 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
00670 return;
00671 }
00672 (void) FormatMagickString(component,MaxTextExtent,"%3d",
00673 ScaleQuantumToChar(RoundToQuantum(color)));
00674 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
00675 return;
00676 }
00677 if (channel == OpacityChannel)
00678 {
00679 (void) FormatMagickString(component,MaxTextExtent,"%g",
00680 (double) (QuantumScale*color));
00681 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
00682 return;
00683 }
00684 if (pixel->depth > 8)
00685 {
00686 (void) FormatMagickString(component,MaxTextExtent,"%g%%",
00687 (double) (100.0*QuantumScale*color));
00688 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
00689 return;
00690 }
00691 (void) FormatMagickString(component,MaxTextExtent,"%d",
00692 ScaleQuantumToChar(RoundToQuantum(color)));
00693 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726 static void DefineImageHistogram(const Image *image,NodeInfo *node_info,
00727 ColorPacket **histogram)
00728 {
00729 register long
00730 i;
00731
00732 unsigned long
00733 number_children;
00734
00735
00736
00737
00738 number_children=image->matte == MagickFalse ? 8UL : 16UL;
00739 for (i=0; i < (long) number_children; i++)
00740 if (node_info->child[i] != (NodeInfo *) NULL)
00741 DefineImageHistogram(image,node_info->child[i],histogram);
00742 if (node_info->level == (MaxTreeDepth-1))
00743 {
00744 register ColorPacket
00745 *p;
00746
00747 p=node_info->list;
00748 for (i=0; i < (long) node_info->number_unique; i++)
00749 {
00750 (*histogram)->pixel=p->pixel;
00751 (*histogram)->index=p->index;
00752 (*histogram)->count=p->count;
00753 (*histogram)++;
00754 p++;
00755 }
00756 }
00757 }
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778 static void *DestroyColorElement(void *color_info)
00779 {
00780 register ColorInfo
00781 *p;
00782
00783 p=(ColorInfo *) color_info;
00784 if (p->path != (char *) NULL)
00785 p->path=DestroyString(p->path);
00786 if (p->name != (char *) NULL)
00787 p->name=DestroyString(p->name);
00788 p=(ColorInfo *) RelinquishMagickMemory(p);
00789 return((void *) NULL);
00790 }
00791
00792 MagickExport void DestroyColorList(void)
00793 {
00794 AcquireSemaphoreInfo(&color_semaphore);
00795 if (color_list != (LinkedListInfo *) NULL)
00796 color_list=DestroyLinkedList(color_list,DestroyColorElement);
00797 instantiate_color=MagickFalse;
00798 RelinquishSemaphoreInfo(color_semaphore);
00799 DestroySemaphoreInfo(&color_semaphore);
00800 }
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826 static CubeInfo *DestroyCubeInfo(const Image *image,CubeInfo *cube_info)
00827 {
00828 register Nodes
00829 *nodes;
00830
00831
00832
00833
00834 DestroyColorCube(image,cube_info->root);
00835 do
00836 {
00837 nodes=cube_info->node_queue->next;
00838 cube_info->node_queue=(Nodes *)
00839 RelinquishMagickMemory(cube_info->node_queue);
00840 cube_info->node_queue=nodes;
00841 } while (cube_info->node_queue != (Nodes *) NULL);
00842 return((CubeInfo *) RelinquishMagickMemory(cube_info));
00843 }
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871 static void DestroyColorCube(const Image *image,NodeInfo *node_info)
00872 {
00873 register long
00874 i;
00875
00876 unsigned long
00877 number_children;
00878
00879
00880
00881
00882 number_children=image->matte == MagickFalse ? 8UL : 16UL;
00883 for (i=0; i < (long) number_children; i++)
00884 if (node_info->child[i] != (NodeInfo *) NULL)
00885 DestroyColorCube(image,node_info->child[i]);
00886 if (node_info->list != (ColorPacket *) NULL)
00887 node_info->list=(ColorPacket *) RelinquishMagickMemory(node_info->list);
00888 }
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919 MagickExport const ColorInfo *GetColorInfo(const char *name,
00920 ExceptionInfo *exception)
00921 {
00922 char
00923 colorname[MaxTextExtent];
00924
00925 register const ColorInfo
00926 *p;
00927
00928 register char
00929 *q;
00930
00931 assert(exception != (ExceptionInfo *) NULL);
00932 if ((color_list == (LinkedListInfo *) NULL) ||
00933 (instantiate_color == MagickFalse))
00934 if (InitializeColorList(exception) == MagickFalse)
00935 return((const ColorInfo *) NULL);
00936 if ((color_list == (LinkedListInfo *) NULL) ||
00937 (IsLinkedListEmpty(color_list) != MagickFalse))
00938 return((const ColorInfo *) NULL);
00939 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
00940 return((const ColorInfo *) GetValueFromLinkedList(color_list,0));
00941
00942
00943
00944 (void) CopyMagickString(colorname,name,MaxTextExtent);
00945 for (q=colorname; *q != '\0'; q++)
00946 {
00947 if (isspace((int) ((unsigned char) *q)) == 0)
00948 continue;
00949 (void) CopyMagickString(q,q+1,MaxTextExtent);
00950 q--;
00951 }
00952
00953
00954
00955 AcquireSemaphoreInfo(&color_semaphore);
00956 ResetLinkedListIterator(color_list);
00957 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
00958 while (p != (const ColorInfo *) NULL)
00959 {
00960 if (LocaleCompare(colorname,p->name) == 0)
00961 break;
00962 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
00963 }
00964 if (p == (ColorInfo *) NULL)
00965 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
00966 "UnrecognizedColor","`%s'",name);
00967 else
00968 (void) InsertValueInLinkedList(color_list,0,
00969 RemoveElementByValueFromLinkedList(color_list,p));
00970 RelinquishSemaphoreInfo(color_semaphore);
00971 return(p);
00972 }
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002 #if defined(__cplusplus) || defined(c_plusplus)
01003 extern "C" {
01004 #endif
01005
01006 static int ColorInfoCompare(const void *x,const void *y)
01007 {
01008 const ColorInfo
01009 **p,
01010 **q;
01011
01012 p=(const ColorInfo **) x,
01013 q=(const ColorInfo **) y;
01014 if (LocaleCompare((*p)->path,(*q)->path) == 0)
01015 return(LocaleCompare((*p)->name,(*q)->name));
01016 return(LocaleCompare((*p)->path,(*q)->path));
01017 }
01018
01019 #if defined(__cplusplus) || defined(c_plusplus)
01020 }
01021 #endif
01022
01023 MagickExport const ColorInfo **GetColorInfoList(const char *pattern,
01024 unsigned long *number_colors,ExceptionInfo *exception)
01025 {
01026 const ColorInfo
01027 **colors;
01028
01029 register const ColorInfo
01030 *p;
01031
01032 register long
01033 i;
01034
01035
01036
01037
01038 assert(pattern != (char *) NULL);
01039 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
01040 assert(number_colors != (unsigned long *) NULL);
01041 *number_colors=0;
01042 p=GetColorInfo("*",exception);
01043 if (p == (const ColorInfo *) NULL)
01044 return((const ColorInfo **) NULL);
01045 colors=(const ColorInfo **) AcquireQuantumMemory((size_t)
01046 GetNumberOfElementsInLinkedList(color_list)+1UL,sizeof(*colors));
01047 if (colors == (const ColorInfo **) NULL)
01048 return((const ColorInfo **) NULL);
01049
01050
01051
01052 AcquireSemaphoreInfo(&color_semaphore);
01053 ResetLinkedListIterator(color_list);
01054 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
01055 for (i=0; p != (const ColorInfo *) NULL; )
01056 {
01057 if ((p->stealth == MagickFalse) &&
01058 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
01059 colors[i++]=p;
01060 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
01061 }
01062 RelinquishSemaphoreInfo(color_semaphore);
01063 qsort((void *) colors,(size_t) i,sizeof(*colors),ColorInfoCompare);
01064 colors[i]=(ColorInfo *) NULL;
01065 *number_colors=(unsigned long) i;
01066 return(colors);
01067 }
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097 #if defined(__cplusplus) || defined(c_plusplus)
01098 extern "C" {
01099 #endif
01100
01101 static int ColorCompare(const void *x,const void *y)
01102 {
01103 register const char
01104 **p,
01105 **q;
01106
01107 p=(const char **) x;
01108 q=(const char **) y;
01109 return(LocaleCompare(*p,*q));
01110 }
01111
01112 #if defined(__cplusplus) || defined(c_plusplus)
01113 }
01114 #endif
01115
01116 MagickExport char **GetColorList(const char *pattern,
01117 unsigned long *number_colors,ExceptionInfo *exception)
01118 {
01119 char
01120 **colors;
01121
01122 register const ColorInfo
01123 *p;
01124
01125 register long
01126 i;
01127
01128
01129
01130
01131 assert(pattern != (char *) NULL);
01132 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
01133 assert(number_colors != (unsigned long *) NULL);
01134 *number_colors=0;
01135 p=GetColorInfo("*",exception);
01136 if (p == (const ColorInfo *) NULL)
01137 return((char **) NULL);
01138 colors=(char **) AcquireQuantumMemory((size_t)
01139 GetNumberOfElementsInLinkedList(color_list)+1UL,sizeof(*colors));
01140 if (colors == (char **) NULL)
01141 return((char **) NULL);
01142
01143
01144
01145 AcquireSemaphoreInfo(&color_semaphore);
01146 ResetLinkedListIterator(color_list);
01147 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
01148 for (i=0; p != (const ColorInfo *) NULL; )
01149 {
01150 if ((p->stealth == MagickFalse) &&
01151 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
01152 colors[i++]=ConstantString(p->name);
01153 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
01154 }
01155 RelinquishSemaphoreInfo(color_semaphore);
01156 qsort((void *) colors,(size_t) i,sizeof(*colors),ColorCompare);
01157 colors[i]=(char *) NULL;
01158 *number_colors=(unsigned long) i;
01159 return(colors);
01160 }
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191 static void ConcatentateHexColorComponent(const MagickPixelPacket *pixel,
01192 const ChannelType channel,char *tuple)
01193 {
01194 char
01195 component[MaxTextExtent];
01196
01197 MagickRealType
01198 color;
01199
01200 color=0.0;
01201 switch (channel)
01202 {
01203 case RedChannel:
01204 {
01205 color=pixel->red;
01206 break;
01207 }
01208 case GreenChannel:
01209 {
01210 color=pixel->green;
01211 break;
01212 }
01213 case BlueChannel:
01214 {
01215 color=pixel->blue;
01216 break;
01217 }
01218 case OpacityChannel:
01219 {
01220 color=(MagickRealType) QuantumRange-pixel->opacity;
01221 break;
01222 }
01223 case IndexChannel:
01224 {
01225 color=pixel->index;
01226 break;
01227 }
01228 default:
01229 break;
01230 }
01231 if (pixel->depth > 32)
01232 {
01233 (void) FormatMagickString(component,MaxTextExtent,"%08lX",
01234 ScaleQuantumToLong(RoundToQuantum(color)));
01235 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
01236 return;
01237 }
01238 if (pixel->depth > 16)
01239 {
01240 (void) FormatMagickString(component,MaxTextExtent,"%08X",
01241 (unsigned int) ScaleQuantumToLong(RoundToQuantum(color)));
01242 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
01243 return;
01244 }
01245 if (pixel->depth > 8)
01246 {
01247 (void) FormatMagickString(component,MaxTextExtent,"%04X",
01248 ScaleQuantumToShort(RoundToQuantum(color)));
01249 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
01250 return;
01251 }
01252 (void) FormatMagickString(component,MaxTextExtent,"%02X",
01253 ScaleQuantumToChar(RoundToQuantum(color)));
01254 (void) ConcatenateMagickString(tuple,component,MaxTextExtent);
01255 return;
01256 }
01257
01258 MagickExport void GetColorTuple(const MagickPixelPacket *pixel,
01259 const MagickBooleanType hex,char *tuple)
01260 {
01261 MagickPixelPacket
01262 color;
01263
01264 assert(pixel != (const MagickPixelPacket *) NULL);
01265 assert(tuple != (char *) NULL);
01266 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tuple);
01267 *tuple='\0';
01268 if (hex != MagickFalse)
01269 {
01270
01271
01272
01273 (void) ConcatenateMagickString(tuple,"#",MaxTextExtent);
01274 ConcatentateHexColorComponent(pixel,RedChannel,tuple);
01275 ConcatentateHexColorComponent(pixel,GreenChannel,tuple);
01276 ConcatentateHexColorComponent(pixel,BlueChannel,tuple);
01277 if (pixel->colorspace == CMYKColorspace)
01278 ConcatentateHexColorComponent(pixel,IndexChannel,tuple);
01279 if ((pixel->matte != MagickFalse) && (pixel->opacity != OpaqueOpacity))
01280 ConcatentateHexColorComponent(pixel,OpacityChannel,tuple);
01281 return;
01282 }
01283
01284
01285
01286 color=(*pixel);
01287 if (color.depth > 8)
01288 {
01289 #define SVGCompliant(component) ((MagickRealType) \
01290 ScaleCharToQuantum(ScaleQuantumToChar(RoundToQuantum(component))));
01291
01292 MagickStatusType
01293 status;
01294
01295
01296
01297
01298 status=color.red == SVGCompliant(color.red);
01299 status&=color.green == SVGCompliant(color.green);
01300 status&=color.blue == SVGCompliant(color.blue);
01301 if (color.colorspace != CMYKColorspace)
01302 status&=color.index == SVGCompliant(color.index);
01303 if (color.matte != MagickFalse)
01304 status&=color.opacity == SVGCompliant(color.opacity);
01305 if (status != MagickFalse)
01306 color.depth=8;
01307 }
01308 (void) ConcatenateMagickString(tuple,MagickOptionToMnemonic(
01309 MagickColorspaceOptions,(long) color.colorspace),MaxTextExtent);
01310 if (color.matte != MagickFalse)
01311 (void) ConcatenateMagickString(tuple,"a",MaxTextExtent);
01312 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
01313 ConcatenateColorComponent(&color,RedChannel,SVGCompliance,tuple);
01314 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
01315 ConcatenateColorComponent(&color,GreenChannel,SVGCompliance,tuple);
01316 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
01317 ConcatenateColorComponent(&color,BlueChannel,SVGCompliance,tuple);
01318 if (color.colorspace == CMYKColorspace)
01319 {
01320 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
01321 ConcatenateColorComponent(&color,IndexChannel,SVGCompliance,tuple);
01322 }
01323 if (color.matte != MagickFalse)
01324 {
01325 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
01326 ConcatenateColorComponent(&color,AlphaChannel,SVGCompliance,tuple);
01327 }
01328 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
01329 LocaleLower(tuple);
01330 return;
01331 }
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355 static CubeInfo *GetCubeInfo(void)
01356 {
01357 CubeInfo
01358 *cube_info;
01359
01360
01361
01362
01363 cube_info=(CubeInfo *) AcquireMagickMemory(sizeof(*cube_info));
01364 if (cube_info == (CubeInfo *) NULL)
01365 return((CubeInfo *) NULL);
01366 (void) ResetMagickMemory(cube_info,0,sizeof(*cube_info));
01367
01368
01369
01370 cube_info->root=GetNodeInfo(cube_info,0);
01371 if (cube_info->root == (NodeInfo *) NULL)
01372 return((CubeInfo *) NULL);
01373 return(cube_info);
01374 }
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403 MagickExport ColorPacket *GetImageHistogram(const Image *image,
01404 unsigned long *number_colors,ExceptionInfo *exception)
01405 {
01406 ColorPacket
01407 *histogram;
01408
01409 CubeInfo
01410 *cube_info;
01411
01412 *number_colors=0;
01413 histogram=(ColorPacket *) NULL;
01414 cube_info=ClassifyImageColors(image,exception);
01415 if (cube_info != (CubeInfo *) NULL)
01416 {
01417 histogram=(ColorPacket *) AcquireQuantumMemory((size_t) cube_info->colors,
01418 sizeof(*histogram));
01419 if (histogram == (ColorPacket *) NULL)
01420 (void) ThrowMagickException(exception,GetMagickModule(),
01421 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
01422 else
01423 {
01424 ColorPacket
01425 *root;
01426
01427 *number_colors=cube_info->colors;
01428 root=histogram;
01429 DefineImageHistogram(image,cube_info->root,&root);
01430 }
01431 }
01432 cube_info=DestroyCubeInfo(image,cube_info);
01433 return(histogram);
01434 }
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461 static NodeInfo *GetNodeInfo(CubeInfo *cube_info,const unsigned long level)
01462 {
01463 NodeInfo
01464 *node_info;
01465
01466 if (cube_info->free_nodes == 0)
01467 {
01468 Nodes
01469 *nodes;
01470
01471
01472
01473
01474 nodes=(Nodes *) AcquireMagickMemory(sizeof(*nodes));
01475 if (nodes == (Nodes *) NULL)
01476 return((NodeInfo *) NULL);
01477 nodes->next=cube_info->node_queue;
01478 cube_info->node_queue=nodes;
01479 cube_info->node_info=nodes->nodes;
01480 cube_info->free_nodes=NodesInAList;
01481 }
01482 cube_info->free_nodes--;
01483 node_info=cube_info->node_info++;
01484 (void) ResetMagickMemory(node_info,0,sizeof(*node_info));
01485 node_info->level=level;
01486 return(node_info);
01487 }
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517 #if defined(__cplusplus) || defined(c_plusplus)
01518 extern "C" {
01519 #endif
01520
01521 static int HistogramCompare(const void *x,const void *y)
01522 {
01523 const ColorPacket
01524 *color_1,
01525 *color_2;
01526
01527 color_1=(const ColorPacket *) x;
01528 color_2=(const ColorPacket *) y;
01529 if (color_2->count != color_1->count)
01530 return((int) color_2->count-(int) color_1->count);
01531 if (color_2->pixel.red != color_1->pixel.red)
01532 return((int) color_1->pixel.red-(int) color_2->pixel.red);
01533 if (color_2->pixel.green != color_1->pixel.green)
01534 return((int) color_1->pixel.green-(int) color_2->pixel.green);
01535 return((int) color_1->pixel.blue-(int) color_2->pixel.blue);
01536 }
01537
01538 #if defined(__cplusplus) || defined(c_plusplus)
01539 }
01540 #endif
01541
01542 MagickExport unsigned long GetNumberColors(const Image *image,FILE *file,
01543 ExceptionInfo *exception)
01544 {
01545 #define HistogramImageTag "Histogram/Image"
01546
01547 char
01548 color[MaxTextExtent],
01549 hex[MaxTextExtent],
01550 tuple[MaxTextExtent];
01551
01552 ColorPacket
01553 *histogram;
01554
01555 MagickPixelPacket
01556 pixel;
01557
01558 register ColorPacket
01559 *p;
01560
01561 register long
01562 i;
01563
01564 unsigned long
01565 number_colors;
01566
01567 number_colors=0;
01568 if (file == (FILE *) NULL)
01569 {
01570 CubeInfo
01571 *cube_info;
01572
01573 cube_info=ClassifyImageColors(image,exception);
01574 if (cube_info != (CubeInfo *) NULL)
01575 number_colors=cube_info->colors;
01576 cube_info=DestroyCubeInfo(image,cube_info);
01577 return(number_colors);
01578 }
01579 histogram=GetImageHistogram(image,&number_colors,exception);
01580 if (histogram == (ColorPacket *) NULL)
01581 return(number_colors);
01582 qsort((void *) histogram,(size_t) number_colors,sizeof(*histogram),
01583 HistogramCompare);
01584 GetMagickPixelPacket(image,&pixel);
01585 p=histogram;
01586 for (i=0; i < (long) number_colors; i++)
01587 {
01588 SetMagickPixelPacket(image,&p->pixel,&p->index,&pixel);
01589 (void) CopyMagickString(tuple,"(",MaxTextExtent);
01590 ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
01591 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
01592 ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
01593 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
01594 ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
01595 if (pixel.colorspace == CMYKColorspace)
01596 {
01597 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
01598 ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
01599 }
01600 if (pixel.matte != MagickFalse)
01601 {
01602 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
01603 ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
01604 }
01605 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
01606 (void) QueryMagickColorname(image,&pixel,SVGCompliance,color,exception);
01607 GetColorTuple(&pixel,MagickTrue,hex);
01608 (void) fprintf(file,MagickSizeFormat,p->count);
01609 (void) fprintf(file,": %s %s %s\n",tuple,hex,color);
01610 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
01611 (QuantumTick(i,number_colors) != MagickFalse))
01612 (void) image->progress_monitor(HistogramImageTag,i,number_colors,
01613 image->client_data);
01614 p++;
01615 }
01616 (void) fflush(file);
01617 histogram=(ColorPacket *) RelinquishMagickMemory(histogram);
01618 return(number_colors);
01619 }
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643 static MagickBooleanType InitializeColorList(ExceptionInfo *exception)
01644 {
01645 if ((color_list == (LinkedListInfo *) NULL) &&
01646 (instantiate_color == MagickFalse))
01647 {
01648 AcquireSemaphoreInfo(&color_semaphore);
01649 if ((color_list == (LinkedListInfo *) NULL) &&
01650 (instantiate_color == MagickFalse))
01651 {
01652 (void) LoadColorLists(ColorFilename,exception);
01653 instantiate_color=MagickTrue;
01654 }
01655 RelinquishSemaphoreInfo(color_semaphore);
01656 }
01657 return(color_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
01658 }
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691 static inline double MagickMax(const double x,const double y)
01692 {
01693 if (x > y)
01694 return(x);
01695 return(y);
01696 }
01697
01698 MagickExport MagickBooleanType IsColorSimilar(const Image *image,
01699 const PixelPacket *p,const PixelPacket *q)
01700 {
01701 MagickRealType
01702 fuzz,
01703 pixel;
01704
01705 register MagickRealType
01706 alpha,
01707 beta,
01708 distance;
01709
01710 if ((image->fuzz == 0.0) && (image->matte == MagickFalse))
01711 return(IsColorEqual(p,q));
01712 fuzz=3.0*MagickMax(image->fuzz,MagickSQ1_2)*MagickMax(image->fuzz,
01713 MagickSQ1_2);
01714 alpha=1.0;
01715 beta=1.0;
01716 if (image->matte != MagickFalse)
01717 {
01718 alpha=(MagickRealType) (QuantumScale*(QuantumRange-p->opacity));
01719 beta=(MagickRealType) (QuantumScale*(QuantumRange-q->opacity));
01720 }
01721 pixel=alpha*p->red-beta*q->red;
01722 distance=pixel*pixel;
01723 if (distance > fuzz)
01724 return(MagickFalse);
01725 pixel=alpha*p->green-beta*q->green;
01726 distance+=pixel*pixel;
01727 if (distance > fuzz)
01728 return(MagickFalse);
01729 pixel=alpha*p->blue-beta*q->blue;
01730 distance+=pixel*pixel;
01731 if (distance > fuzz)
01732 return(MagickFalse);
01733 return(MagickTrue);
01734 }
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762 MagickExport MagickBooleanType IsGrayImage(const Image *image,
01763 ExceptionInfo *exception)
01764 {
01765 ImageType
01766 type;
01767
01768 register const PixelPacket
01769 *p;
01770
01771 assert(image != (Image *) NULL);
01772 assert(image->signature == MagickSignature);
01773 if (image->debug != MagickFalse)
01774 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01775 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
01776 (image->type == GrayscaleMatteType))
01777 return(MagickTrue);
01778 if (image->colorspace == CMYKColorspace)
01779 return(MagickFalse);
01780 type=BilevelType;
01781 switch (image->storage_class)
01782 {
01783 case DirectClass:
01784 case UndefinedClass:
01785 {
01786 long
01787 y;
01788
01789 register long
01790 x;
01791
01792 ViewInfo
01793 *image_view;
01794
01795 image_view=AcquireCacheView(image);
01796 for (y=0; y < (long) image->rows; y++)
01797 {
01798 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
01799 if (p == (const PixelPacket *) NULL)
01800 break;
01801 for (x=0; x < (long) image->columns; x++)
01802 {
01803 if (IsGrayPixel(p) == MagickFalse)
01804 {
01805 type=UndefinedType;
01806 break;
01807 }
01808 if ((type == BilevelType) && (IsMonochromePixel(p) == MagickFalse))
01809 type=GrayscaleType;
01810 p++;
01811 }
01812 if (type == UndefinedType)
01813 break;
01814 }
01815 image_view=DestroyCacheView(image_view);
01816 break;
01817 }
01818 case PseudoClass:
01819 {
01820 register long
01821 i;
01822
01823 p=image->colormap;
01824 for (i=0; i < (long) image->colors; i++)
01825 {
01826 if (IsGrayPixel(p) == MagickFalse)
01827 {
01828 type=UndefinedType;
01829 break;
01830 }
01831 if ((type == BilevelType) && (IsMonochromePixel(p) == MagickFalse))
01832 type=GrayscaleType;
01833 p++;
01834 }
01835 break;
01836 }
01837 }
01838 if (type == UndefinedType)
01839 return(MagickFalse);
01840 ((Image *) image)->type=type;
01841 if ((type == GrayscaleType) && (image->matte != MagickFalse))
01842 ((Image *) image)->type=GrayscaleMatteType;
01843 return(MagickTrue);
01844 }
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872 MagickExport MagickBooleanType IsHistogramImage(const Image *image,
01873 ExceptionInfo *exception)
01874 {
01875 #define MaximumUniqueColors 1024
01876
01877 CubeInfo
01878 *cube_info;
01879
01880 long
01881 y;
01882
01883 MagickPixelPacket
01884 pixel,
01885 target;
01886
01887 register const IndexPacket
01888 *indexes;
01889
01890 register const PixelPacket
01891 *p;
01892
01893 register long
01894 x;
01895
01896 register NodeInfo
01897 *node_info;
01898
01899 register long
01900 i;
01901
01902 unsigned long
01903 id,
01904 index,
01905 level;
01906
01907 ViewInfo
01908 *image_view;
01909
01910 assert(image != (Image *) NULL);
01911 assert(image->signature == MagickSignature);
01912 if (image->debug != MagickFalse)
01913 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01914 if ((image->storage_class == PseudoClass) && (image->colors <= 256))
01915 return(MagickTrue);
01916 if (image->storage_class == PseudoClass)
01917 return(MagickFalse);
01918
01919
01920
01921 cube_info=GetCubeInfo();
01922 if (cube_info == (CubeInfo *) NULL)
01923 {
01924 (void) ThrowMagickException(exception,GetMagickModule(),
01925 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
01926 return(MagickFalse);
01927 }
01928 GetMagickPixelPacket(image,&pixel);
01929 GetMagickPixelPacket(image,&target);
01930 image_view=AcquireCacheView(image);
01931 for (y=0; y < (long) image->rows; y++)
01932 {
01933 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
01934 if (p == (const PixelPacket *) NULL)
01935 break;
01936 indexes=GetCacheViewVirtualIndexQueue(image_view);
01937 for (x=0; x < (long) image->columns; x++)
01938 {
01939
01940
01941
01942 node_info=cube_info->root;
01943 index=MaxTreeDepth-1;
01944 for (level=1; level < MaxTreeDepth; level++)
01945 {
01946 SetMagickPixelPacket(image,p,indexes+x,&pixel);
01947 id=ColorToNodeId(image,&pixel,index);
01948 if (node_info->child[id] == (NodeInfo *) NULL)
01949 {
01950 node_info->child[id]=GetNodeInfo(cube_info,level);
01951 if (node_info->child[id] == (NodeInfo *) NULL)
01952 {
01953 (void) ThrowMagickException(exception,GetMagickModule(),
01954 ResourceLimitError,"MemoryAllocationFailed","`%s'",
01955 image->filename);
01956 break;
01957 }
01958 }
01959 node_info=node_info->child[id];
01960 index--;
01961 }
01962 if (level < MaxTreeDepth)
01963 break;
01964 for (i=0; i < (long) node_info->number_unique; i++)
01965 {
01966 SetMagickPixelPacket(image,&node_info->list[i].pixel,
01967 &node_info->list[i].index,&target);
01968 if (IsMagickColorEqual(&pixel,&target) != MagickFalse)
01969 break;
01970 }
01971 if (i < (long) node_info->number_unique)
01972 node_info->list[i].count++;
01973 else
01974 {
01975
01976
01977
01978 if (node_info->number_unique == 0)
01979 node_info->list=(ColorPacket *) AcquireMagickMemory(
01980 sizeof(*node_info->list));
01981 else
01982 node_info->list=(ColorPacket *) ResizeQuantumMemory(node_info->list,
01983 (size_t) (i+1),sizeof(*node_info->list));
01984 if (node_info->list == (ColorPacket *) NULL)
01985 {
01986 (void) ThrowMagickException(exception,GetMagickModule(),
01987 ResourceLimitError,"MemoryAllocationFailed","`%s'",
01988 image->filename);
01989 break;
01990 }
01991 node_info->list[i].pixel=(*p);
01992 if ((image->colorspace == CMYKColorspace) ||
01993 (image->storage_class == PseudoClass))
01994 node_info->list[i].index=indexes[x];
01995 node_info->list[i].count=1;
01996 node_info->number_unique++;
01997 cube_info->colors++;
01998 if (cube_info->colors > MaximumUniqueColors)
01999 break;
02000 }
02001 p++;
02002 }
02003 if (x < (long) image->columns)
02004 break;
02005 }
02006 image_view=DestroyCacheView(image_view);
02007 cube_info=DestroyCubeInfo(image,cube_info);
02008 return(y < (long) image->rows ? MagickFalse : MagickTrue);
02009 }
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046 MagickExport MagickBooleanType IsImageSimilar(const Image *image,
02047 const Image *target_image,long *x_offset,long *y_offset,
02048 ExceptionInfo *exception)
02049 {
02050 #define SearchImageText " Searching image... "
02051
02052 long
02053 j,
02054 y;
02055
02056 MagickBooleanType
02057 status;
02058
02059 MagickPixelPacket
02060 target,
02061 pixel;
02062
02063 register const PixelPacket
02064 *p,
02065 *q;
02066
02067 register const IndexPacket
02068 *indexes,
02069 *target_indexes;
02070
02071 register long
02072 i,
02073 x;
02074
02075 ViewInfo
02076 *image_view,
02077 *target_view;
02078
02079 assert(image != (Image *) NULL);
02080 assert(image->signature == MagickSignature);
02081 if (image->debug != MagickFalse)
02082 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02083 assert(target_image != (Image *) NULL);
02084 assert(target_image->signature == MagickSignature);
02085 assert(x_offset != (long *) NULL);
02086 assert(y_offset != (long *) NULL);
02087 assert(exception != (ExceptionInfo *) NULL);
02088 x=0;
02089 GetMagickPixelPacket(image,&pixel);
02090 GetMagickPixelPacket(image,&target);
02091 image_view=AcquireCacheView(image);
02092 target_view=AcquireCacheView(target_image);
02093 for (y=(*y_offset); y < (long) image->rows; y++)
02094 {
02095 for (x=y == 0 ? *x_offset : 0; x < (long) image->columns; x++)
02096 {
02097 for (j=0; j < (long) target_image->rows; j++)
02098 {
02099 for (i=0; i < (long) target_image->columns; i++)
02100 {
02101 p=GetCacheViewVirtualPixels(image_view,x+i,y+j,1,1,exception);
02102 indexes=GetCacheViewVirtualIndexQueue(image_view);
02103 SetMagickPixelPacket(image,p,indexes,&pixel);
02104 q=GetCacheViewVirtualPixels(target_view,i,j,1,1,exception);
02105 target_indexes=GetCacheViewVirtualIndexQueue(target_view);
02106 SetMagickPixelPacket(image,q,target_indexes,&target);
02107 if (IsMagickColorSimilar(&pixel,&target) == MagickFalse)
02108 break;
02109 }
02110 if (i < (long) target_image->columns)
02111 break;
02112 }
02113 if (j == (long) target_image->rows)
02114 break;
02115 }
02116 if (x < (long) image->columns)
02117 break;
02118 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
02119 (QuantumTick(y,image->rows) != MagickFalse))
02120 {
02121 status=image->progress_monitor(SearchImageText,y,image->rows,
02122 image->client_data);
02123 if (status == MagickFalse)
02124 break;
02125 }
02126 }
02127 target_view=DestroyCacheView(target_view);
02128 image_view=DestroyCacheView(image_view);
02129 *x_offset=x;
02130 *y_offset=y;
02131 return(y < (long) image->rows ? MagickTrue : MagickFalse);
02132 }
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162 MagickExport MagickBooleanType IsMagickColorSimilar(const MagickPixelPacket *p,
02163 const MagickPixelPacket *q)
02164 {
02165 MagickRealType
02166 fuzz,
02167 pixel;
02168
02169 register MagickRealType
02170 alpha,
02171 beta,
02172 distance;
02173
02174 if ((p->fuzz == 0.0) && (q->fuzz == 0.0))
02175 return(IsMagickColorEqual(p,q));
02176 if (p->fuzz == 0.0)
02177 fuzz=MagickMax(q->fuzz,MagickSQ1_2)*MagickMax(q->fuzz,MagickSQ1_2);
02178 else
02179 if (q->fuzz == 0.0)
02180 fuzz=3.0*MagickMax(p->fuzz,MagickSQ1_2)*MagickMax(p->fuzz,MagickSQ1_2);
02181 else
02182 fuzz=3.0*MagickMax(p->fuzz,MagickSQ1_2)*MagickMax(q->fuzz,MagickSQ1_2);
02183 alpha=1.0;
02184 if (p->matte != MagickFalse)
02185 alpha=(MagickRealType) (QuantumScale*(QuantumRange-p->opacity));
02186 beta=1.0;
02187 if (q->matte != MagickFalse)
02188 beta=(MagickRealType) (QuantumScale*(QuantumRange-q->opacity));
02189 if (p->colorspace == CMYKColorspace)
02190 {
02191 alpha*=(MagickRealType) (QuantumScale*(QuantumRange-p->index));
02192 beta*=(MagickRealType) (QuantumScale*(QuantumRange-q->index));
02193 }
02194 pixel=alpha*p->red-beta*q->red;
02195 if ((p->colorspace == HSLColorspace) || (p->colorspace == HSBColorspace) ||
02196 (p->colorspace == HWBColorspace))
02197 {
02198 if (fabs(p->red-q->red) > (QuantumRange/2))
02199 {
02200 if (p->red > (QuantumRange/2))
02201 pixel=alpha*(p->red-QuantumRange)-beta*q->red;
02202 else
02203 pixel=alpha*p->red-beta*(q->red-QuantumRange);
02204 }
02205 pixel*=2;
02206 }
02207 distance=pixel*pixel;
02208 if (distance > fuzz)
02209 return(MagickFalse);
02210 pixel=alpha*p->green-beta*q->green;
02211 distance+=pixel*pixel;
02212 if (distance > fuzz)
02213 return(MagickFalse);
02214 pixel=alpha*p->blue-beta*q->blue;
02215 distance+=pixel*pixel;
02216 if (distance > fuzz)
02217 return(MagickFalse);
02218 pixel=p->opacity-q->opacity;
02219 distance+=pixel*pixel;
02220 if (distance > fuzz)
02221 return(MagickFalse);
02222 return(MagickTrue);
02223 }
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252 MagickExport MagickBooleanType IsMonochromeImage(const Image *image,
02253 ExceptionInfo *exception)
02254 {
02255 ImageType
02256 type;
02257
02258 register const PixelPacket
02259 *p;
02260
02261 assert(image != (Image *) NULL);
02262 assert(image->signature == MagickSignature);
02263 if (image->debug != MagickFalse)
02264 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02265 if (image->type == BilevelType)
02266 return(MagickTrue);
02267 if (image->colorspace == CMYKColorspace)
02268 return(MagickFalse);
02269 type=BilevelType;
02270 switch (image->storage_class)
02271 {
02272 case DirectClass:
02273 case UndefinedClass:
02274 {
02275 long
02276 y;
02277
02278 register long
02279 x;
02280
02281 ViewInfo
02282 *image_view;
02283
02284 image_view=AcquireCacheView(image);
02285 for (y=0; y < (long) image->rows; y++)
02286 {
02287 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
02288 if (p == (const PixelPacket *) NULL)
02289 break;
02290 for (x=0; x < (long) image->columns; x++)
02291 {
02292 if (IsMonochromePixel(p) == MagickFalse)
02293 {
02294 type=UndefinedType;
02295 break;
02296 }
02297 p++;
02298 }
02299 if (type == UndefinedType)
02300 break;
02301 }
02302 image_view=DestroyCacheView(image_view);
02303 if (y == (long) image->rows)
02304 ((Image *) image)->type=BilevelType;
02305 break;
02306 }
02307 case PseudoClass:
02308 {
02309 register long
02310 i;
02311
02312 p=image->colormap;
02313 for (i=0; i < (long) image->colors; i++)
02314 {
02315 if (IsMonochromePixel(p) == MagickFalse)
02316 {
02317 type=UndefinedType;
02318 break;
02319 }
02320 p++;
02321 }
02322 break;
02323 }
02324 }
02325 if (type == UndefinedType)
02326 return(MagickFalse);
02327 ((Image *) image)->type=type;
02328 return(MagickTrue);
02329 }
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361 MagickExport MagickBooleanType IsOpacitySimilar(const Image *image,
02362 const PixelPacket *p,const PixelPacket *q)
02363 {
02364 MagickRealType
02365 fuzz,
02366 pixel;
02367
02368 register MagickRealType
02369 distance;
02370
02371 if (image->matte == MagickFalse)
02372 return(MagickTrue);
02373 if (p->opacity == q->opacity)
02374 return(MagickTrue);
02375 fuzz=MagickMax(image->fuzz,MagickSQ1_2)*MagickMax(image->fuzz,MagickSQ1_2);
02376 pixel=(MagickRealType) p->opacity-(MagickRealType) q->opacity;
02377 distance=pixel*pixel;
02378 if (distance > fuzz)
02379 return(MagickFalse);
02380 return(MagickTrue);
02381 }
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409 MagickExport MagickBooleanType IsOpaqueImage(const Image *image,
02410 ExceptionInfo *exception)
02411 {
02412 long
02413 y;
02414
02415 register const PixelPacket
02416 *p;
02417
02418 register long
02419 x;
02420
02421 ViewInfo
02422 *image_view;
02423
02424
02425
02426
02427 assert(image != (Image *) NULL);
02428 assert(image->signature == MagickSignature);
02429 if (image->debug != MagickFalse)
02430 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02431 if (image->matte == MagickFalse)
02432 return(MagickTrue);
02433 image_view=AcquireCacheView(image);
02434 for (y=0; y < (long) image->rows; y++)
02435 {
02436 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
02437 if (p == (const PixelPacket *) NULL)
02438 break;
02439 for (x=0; x < (long) image->columns; x++)
02440 {
02441 if (p->opacity != OpaqueOpacity)
02442 break;
02443 p++;
02444 }
02445 if (x < (long) image->columns)
02446 break;
02447 }
02448 image_view=DestroyCacheView(image_view);
02449 return(y < (long) image->rows ? MagickFalse : MagickTrue);
02450 }
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478 MagickExport MagickBooleanType IsPaletteImage(const Image *image,
02479 ExceptionInfo *exception)
02480 {
02481 CubeInfo
02482 *cube_info;
02483
02484 long
02485 y;
02486
02487 MagickPixelPacket
02488 pixel,
02489 target;
02490
02491 register const IndexPacket
02492 *indexes;
02493
02494 register const PixelPacket
02495 *p;
02496
02497 register long
02498 x;
02499
02500 register NodeInfo
02501 *node_info;
02502
02503 register long
02504 i;
02505
02506 unsigned long
02507 id,
02508 index,
02509 level;
02510
02511 ViewInfo
02512 *image_view;
02513
02514 assert(image != (Image *) NULL);
02515 assert(image->signature == MagickSignature);
02516 if (image->debug != MagickFalse)
02517 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02518 if ((image->storage_class == PseudoClass) && (image->colors <= 256))
02519 return(MagickTrue);
02520 if (image->storage_class == PseudoClass)
02521 return(MagickFalse);
02522
02523
02524
02525 cube_info=GetCubeInfo();
02526 if (cube_info == (CubeInfo *) NULL)
02527 {
02528 (void) ThrowMagickException(exception,GetMagickModule(),
02529 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
02530 return(MagickFalse);
02531 }
02532 GetMagickPixelPacket(image,&pixel);
02533 GetMagickPixelPacket(image,&target);
02534 image_view=AcquireCacheView(image);
02535 for (y=0; y < (long) image->rows; y++)
02536 {
02537 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
02538 if (p == (const PixelPacket *) NULL)
02539 break;
02540 indexes=GetCacheViewVirtualIndexQueue(image_view);
02541 for (x=0; x < (long) image->columns; x++)
02542 {
02543
02544
02545
02546 node_info=cube_info->root;
02547 index=MaxTreeDepth-1;
02548 for (level=1; level < MaxTreeDepth; level++)
02549 {
02550 SetMagickPixelPacket(image,p,indexes+x,&pixel);
02551 id=ColorToNodeId(image,&pixel,index);
02552 if (node_info->child[id] == (NodeInfo *) NULL)
02553 {
02554 node_info->child[id]=GetNodeInfo(cube_info,level);
02555 if (node_info->child[id] == (NodeInfo *) NULL)
02556 {
02557 (void) ThrowMagickException(exception,GetMagickModule(),
02558 ResourceLimitError,"MemoryAllocationFailed","`%s'",
02559 image->filename);
02560 break;
02561 }
02562 }
02563 node_info=node_info->child[id];
02564 index--;
02565 }
02566 if (level < MaxTreeDepth)
02567 break;
02568 for (i=0; i < (long) node_info->number_unique; i++)
02569 {
02570 SetMagickPixelPacket(image,&node_info->list[i].pixel,
02571 &node_info->list[i].index,&target);
02572 if (IsMagickColorEqual(&pixel,&target) != MagickFalse)
02573 break;
02574 }
02575 if (i < (long) node_info->number_unique)
02576 node_info->list[i].count++;
02577 else
02578 {
02579
02580
02581
02582 if (node_info->number_unique == 0)
02583 node_info->list=(ColorPacket *) AcquireMagickMemory(
02584 sizeof(*node_info->list));
02585 else
02586 node_info->list=(ColorPacket *) ResizeQuantumMemory(node_info->list,
02587 (size_t) (i+1),sizeof(*node_info->list));
02588 if (node_info->list == (ColorPacket *) NULL)
02589 {
02590 (void) ThrowMagickException(exception,GetMagickModule(),
02591 ResourceLimitError,"MemoryAllocationFailed","`%s'",
02592 image->filename);
02593 break;
02594 }
02595 node_info->list[i].pixel=(*p);
02596 if ((image->colorspace == CMYKColorspace) ||
02597 (image->storage_class == PseudoClass))
02598 node_info->list[i].index=indexes[x];
02599 node_info->list[i].count=1;
02600 node_info->number_unique++;
02601 cube_info->colors++;
02602 if (cube_info->colors > 256)
02603 break;
02604 }
02605 p++;
02606 }
02607 if (x < (long) image->columns)
02608 break;
02609 }
02610 image_view=DestroyCacheView(image_view);
02611 cube_info=DestroyCubeInfo(image,cube_info);
02612 return(y < (long) image->rows ? MagickFalse : MagickTrue);
02613 }
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641 MagickExport MagickBooleanType ListColorInfo(FILE *file,
02642 ExceptionInfo *exception)
02643 {
02644 char
02645 tuple[MaxTextExtent];
02646
02647 const char
02648 *path;
02649
02650 const ColorInfo
02651 **color_info;
02652
02653 register long
02654 i;
02655
02656 unsigned long
02657 number_colors;
02658
02659
02660
02661
02662 if (file == (const FILE *) NULL)
02663 file=stdout;
02664 color_info=GetColorInfoList("*",&number_colors,exception);
02665 if (color_info == (const ColorInfo **) NULL)
02666 return(MagickFalse);
02667 path=(const char *) NULL;
02668 for (i=0; i < (long) number_colors; i++)
02669 {
02670 if (color_info[i]->stealth != MagickFalse)
02671 continue;
02672 if ((path == (const char *) NULL) ||
02673 (LocaleCompare(path,color_info[i]->path) != 0))
02674 {
02675 if (color_info[i]->path != (char *) NULL)
02676 (void) fprintf(file,"\nPath: %s\n\n",color_info[i]->path);
02677 (void) fprintf(file,"Name Color "
02678 " Compliance\n");
02679 (void) fprintf(file,"-------------------------------------------------"
02680 "------------------------------\n");
02681 }
02682 path=color_info[i]->path;
02683 (void) fprintf(file,"%-21.21s ",color_info[i]->name);
02684 GetColorTuple(&color_info[i]->color,MagickFalse,tuple);
02685 (void) fprintf(file,"%-45.45s ",tuple);
02686 if ((color_info[i]->compliance & SVGCompliance) != 0)
02687 (void) fprintf(file,"SVG ");
02688 if ((color_info[i]->compliance & X11Compliance) != 0)
02689 (void) fprintf(file,"X11 ");
02690 if ((color_info[i]->compliance & XPMCompliance) != 0)
02691 (void) fprintf(file,"XPM ");
02692 (void) fprintf(file,"\n");
02693 }
02694 color_info=(const ColorInfo **) RelinquishMagickMemory((void *) color_info);
02695 (void) fflush(file);
02696 return(MagickTrue);
02697 }
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729 static MagickBooleanType LoadColorList(const char *xml,const char *filename,
02730 const unsigned long depth,ExceptionInfo *exception)
02731 {
02732 char
02733 keyword[MaxTextExtent],
02734 *token;
02735
02736 ColorInfo
02737 *color_info;
02738
02739 const char
02740 *q;
02741
02742 MagickBooleanType
02743 status;
02744
02745
02746
02747
02748 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
02749 "Loading color file \"%s\" ...",filename);
02750 if (xml == (char *) NULL)
02751 return(MagickFalse);
02752 if (color_list == (LinkedListInfo *) NULL)
02753 {
02754 color_list=NewLinkedList(0);
02755 if (color_list == (LinkedListInfo *) NULL)
02756 {
02757 ThrowFileException(exception,ResourceLimitError,
02758 "MemoryAllocationFailed",filename);
02759 return(MagickFalse);
02760 }
02761 }
02762 status=MagickTrue;
02763 color_info=(ColorInfo *) NULL;
02764 token=AcquireString(xml);
02765 for (q=(char *) xml; *q != '\0'; )
02766 {
02767
02768
02769
02770 GetMagickToken(q,&q,token);
02771 if (*token == '\0')
02772 break;
02773 (void) CopyMagickString(keyword,token,MaxTextExtent);
02774 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
02775 {
02776
02777
02778
02779 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
02780 GetMagickToken(q,&q,token);
02781 continue;
02782 }
02783 if (LocaleNCompare(keyword,"<!--",4) == 0)
02784 {
02785
02786
02787
02788 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
02789 GetMagickToken(q,&q,token);
02790 continue;
02791 }
02792 if (LocaleCompare(keyword,"<include") == 0)
02793 {
02794
02795
02796
02797 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
02798 {
02799 (void) CopyMagickString(keyword,token,MaxTextExtent);
02800 GetMagickToken(q,&q,token);
02801 if (*token != '=')
02802 continue;
02803 GetMagickToken(q,&q,token);
02804 if (LocaleCompare(keyword,"file") == 0)
02805 {
02806 if (depth > 200)
02807 (void) ThrowMagickException(exception,GetMagickModule(),
02808 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
02809 else
02810 {
02811 char
02812 path[MaxTextExtent],
02813 *xml;
02814
02815 GetPathComponent(filename,HeadPath,path);
02816 if (*path != '\0')
02817 (void) ConcatenateMagickString(path,DirectorySeparator,
02818 MaxTextExtent);
02819 if (*token == *DirectorySeparator)
02820 (void) CopyMagickString(path,token,MaxTextExtent);
02821 else
02822 (void) ConcatenateMagickString(path,token,MaxTextExtent);
02823 xml=FileToString(path,~0,exception);
02824 if (xml != (char *) NULL)
02825 {
02826 status=LoadColorList(xml,path,depth+1,exception);
02827 xml=(char *) RelinquishMagickMemory(xml);
02828 }
02829 }
02830 }
02831 }
02832 continue;
02833 }
02834 if (LocaleCompare(keyword,"<color") == 0)
02835 {
02836
02837
02838
02839 color_info=(ColorInfo *) AcquireMagickMemory(sizeof(*color_info));
02840 if (color_info == (ColorInfo *) NULL)
02841 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
02842 (void) ResetMagickMemory(color_info,0,sizeof(*color_info));
02843 color_info->path=ConstantString(filename);
02844 color_info->signature=MagickSignature;
02845 continue;
02846 }
02847 if (color_info == (ColorInfo *) NULL)
02848 continue;
02849 if (LocaleCompare(keyword,"/>") == 0)
02850 {
02851 status=AppendValueToLinkedList(color_list,color_info);
02852 if (status == MagickFalse)
02853 (void) ThrowMagickException(exception,GetMagickModule(),
02854 ResourceLimitError,"MemoryAllocationFailed","`%s'",
02855 color_info->name);
02856 color_info=(ColorInfo *) NULL;
02857 }
02858 GetMagickToken(q,(const char **) NULL,token);
02859 if (*token != '=')
02860 continue;
02861 GetMagickToken(q,&q,token);
02862 GetMagickToken(q,&q,token);
02863 switch (*keyword)
02864 {
02865 case 'C':
02866 case 'c':
02867 {
02868 if (LocaleCompare((char *) keyword,"color") == 0)
02869 {
02870 (void) QueryMagickColor(token,&color_info->color,exception);
02871 break;
02872 }
02873 if (LocaleCompare((char *) keyword,"compliance") == 0)
02874 {
02875 long
02876 compliance;
02877
02878 compliance=color_info->compliance;
02879 if (GlobExpression(token,"*SVG*",MagickTrue) != MagickFalse)
02880 compliance|=SVGCompliance;
02881 if (GlobExpression(token,"*X11*",MagickTrue) != MagickFalse)
02882 compliance|=X11Compliance;
02883 if (GlobExpression(token,"*XPM*",MagickTrue) != MagickFalse)
02884 compliance|=XPMCompliance;
02885 color_info->compliance=(ComplianceType) compliance;
02886 break;
02887 }
02888 break;
02889 }
02890 case 'N':
02891 case 'n':
02892 {
02893 if (LocaleCompare((char *) keyword,"name") == 0)
02894 {
02895 color_info->name=ConstantString(token);
02896 break;
02897 }
02898 break;
02899 }
02900 case 'S':
02901 case 's':
02902 {
02903 if (LocaleCompare((char *) keyword,"stealth") == 0)
02904 {
02905 color_info->stealth=IsMagickTrue(token);
02906 break;
02907 }
02908 break;
02909 }
02910 default:
02911 break;
02912 }
02913 }
02914 token=(char *) RelinquishMagickMemory(token);
02915 return(status);
02916 }
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944 static MagickBooleanType LoadColorLists(const char *filename,
02945 ExceptionInfo *exception)
02946 {
02947 #if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
02948 return(LoadColorList(ColorMap,"built-in",0,exception));
02949 #else
02950 const StringInfo
02951 *option;
02952
02953 LinkedListInfo
02954 *options;
02955
02956 MagickStatusType
02957 status;
02958
02959 status=MagickFalse;
02960 options=GetConfigureOptions(filename,exception);
02961 option=(const StringInfo *) GetNextValueInLinkedList(options);
02962 while (option != (const StringInfo *) NULL)
02963 {
02964 status|=LoadColorList((const char *) GetStringInfoDatum(option),
02965 GetStringInfoPath(option),0,exception);
02966 option=(const StringInfo *) GetNextValueInLinkedList(options);
02967 }
02968 options=DestroyConfigureOptions(options);
02969 if ((color_list == (LinkedListInfo *) NULL) ||
02970 (IsLinkedListEmpty(color_list) != MagickFalse))
02971 status|=LoadColorList(ColorMap,"built-in",0,exception);
02972 return(status != 0 ? MagickTrue : MagickFalse);
02973 #endif
02974 }
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006 static inline double MagickMin(const double x,const double y)
03007 {
03008 if (x < y)
03009 return(x);
03010 return(y);
03011 }
03012
03013 MagickExport MagickBooleanType QueryColorDatabase(const char *name,
03014 PixelPacket *color,ExceptionInfo *exception)
03015 {
03016 MagickBooleanType
03017 status;
03018
03019 MagickPixelPacket
03020 pixel;
03021
03022 status=QueryMagickColor(name,&pixel,exception);
03023 color->opacity=RoundToQuantum(pixel.opacity);
03024 if (pixel.colorspace == CMYKColorspace)
03025 {
03026 color->red=RoundToQuantum((MagickRealType) (QuantumRange-MagickMin(
03027 QuantumRange,(MagickRealType) (QuantumScale*pixel.red*(QuantumRange-
03028 pixel.index)+pixel.index))));
03029 color->green=RoundToQuantum((MagickRealType) (QuantumRange-MagickMin(
03030 QuantumRange,(MagickRealType) (QuantumScale*pixel.green*(QuantumRange-
03031 pixel.index)+pixel.index))));
03032 color->blue=RoundToQuantum((MagickRealType) (QuantumRange-MagickMin(
03033 QuantumRange,(MagickRealType) (QuantumScale*pixel.blue*(QuantumRange-
03034 pixel.index)+pixel.index))));
03035 return(status);
03036 }
03037 color->red=RoundToQuantum(pixel.red);
03038 color->green=RoundToQuantum(pixel.green);
03039 color->blue=RoundToQuantum(pixel.blue);
03040 return(status);
03041 }
03042
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075
03076 MagickExport MagickBooleanType QueryColorname(const Image *image,
03077 const PixelPacket *color,const ComplianceType compliance,char *name,
03078 ExceptionInfo *exception)
03079 {
03080 MagickPixelPacket
03081 pixel;
03082
03083 GetMagickPixelPacket(image,&pixel);
03084 SetMagickPixelPacket(image,color,(IndexPacket *) NULL,&pixel);
03085 return(QueryMagickColorname(image,&pixel,compliance,name,exception));
03086 }
03087
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117 MagickExport MagickBooleanType QueryMagickColor(const char *name,
03118 MagickPixelPacket *color,ExceptionInfo *exception)
03119 {
03120 GeometryInfo
03121 geometry_info;
03122
03123 long
03124 type;
03125
03126 MagickRealType
03127 scale;
03128
03129 MagickStatusType
03130 flags;
03131
03132 register const ColorInfo
03133 *p;
03134
03135 register long
03136 i;
03137
03138
03139
03140
03141 assert(name != (const char *) NULL);
03142 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
03143 assert(color != (MagickPixelPacket *) NULL);
03144 GetMagickPixelPacket((Image *) NULL,color);
03145 if ((name == (char *) NULL) || (*name == '\0'))
03146 name=BackgroundColor;
03147 while (isspace((int) ((unsigned char) *name)) != 0)
03148 name++;
03149 if (*name == '#')
03150 {
03151 char
03152 c;
03153
03154 LongPixelPacket
03155 pixel;
03156
03157 QuantumAny
03158 range;
03159
03160 unsigned long
03161 depth,
03162 n;
03163
03164
03165
03166
03167 (void) ResetMagickMemory(&pixel,0,sizeof(pixel));
03168 name++;
03169 for (n=0; isxdigit((int) ((unsigned char) name[n])) != MagickFalse; n++) ;
03170 if ((n % 3) == 0)
03171 {
03172 do
03173 {
03174 pixel.red=pixel.green;
03175 pixel.green=pixel.blue;
03176 pixel.blue=0;
03177 for (i=(long) (n/3-1); i >= 0; i--)
03178 {
03179 c=(*name++);
03180 pixel.blue<<=4;
03181 if ((c >= '0') && (c <= '9'))
03182 pixel.blue|=(int) (c-'0');
03183 else
03184 if ((c >= 'A') && (c <= 'F'))
03185 pixel.blue|=(int) c-((int) 'A'-10);
03186 else
03187 if ((c >= 'a') && (c <= 'f'))
03188 pixel.blue|=(int) c-((int) 'a'-10);
03189 else
03190 return(MagickFalse);
03191 }
03192 } while (isxdigit((int) ((unsigned char) *name)) != MagickFalse);
03193 depth=4*(n/3);
03194 }
03195 else
03196 {
03197 if ((n % 4) != 0)
03198 {
03199 (void) ThrowMagickException(exception,GetMagickModule(),
03200 OptionWarning,"UnrecognizedColor","`%s'",name);
03201 return(MagickFalse);
03202 }
03203 do
03204 {
03205 pixel.red=pixel.green;
03206 pixel.green=pixel.blue;
03207 pixel.blue=pixel.opacity;
03208 pixel.opacity=0;
03209 for (i=(long) (n/4-1); i >= 0; i--)
03210 {
03211 c=(*name++);
03212 pixel.opacity<<=4;
03213 if ((c >= '0') && (c <= '9'))
03214 pixel.opacity|=(int) (c-'0');
03215 else
03216 if ((c >= 'A') && (c <= 'F'))
03217 pixel.opacity|=(int) c-((int) 'A'-10);
03218 else
03219 if ((c >= 'a') && (c <= 'f'))
03220 pixel.opacity|=(int) c-((int) 'a'-10);
03221 else
03222 return(MagickFalse);
03223 }
03224 } while (isxdigit((int) ((unsigned char) *name)) != MagickFalse);
03225 depth=4*(n/4);
03226 }
03227 color->colorspace=RGBColorspace;
03228 color->matte=MagickFalse;
03229 range=GetQuantumRange(depth);
03230 color->red=(MagickRealType) ScaleAnyToQuantum(pixel.red,range);
03231 color->green=(MagickRealType) ScaleAnyToQuantum(pixel.green,range);
03232 color->blue=(MagickRealType) ScaleAnyToQuantum(pixel.blue,range);
03233 color->opacity=(MagickRealType) OpaqueOpacity;
03234 if ((n % 3) != 0)
03235 {
03236 color->matte=MagickTrue;
03237 color->opacity=(MagickRealType) (QuantumRange-ScaleAnyToQuantum(
03238 pixel.opacity,range));
03239 }
03240 color->index=0.0;
03241 return(MagickTrue);
03242 }
03243 if (strchr(name,'(') != (char *) NULL)
03244 {
03245 char
03246 colorspace[MaxTextExtent];
03247
03248
03249
03250
03251 (void) CopyMagickString(colorspace,name,MaxTextExtent);
03252 for (i=0; colorspace[i] != '\0'; i++)
03253 if (colorspace[i] == '(')
03254 break;
03255 colorspace[i--]='\0';
03256 LocaleLower(colorspace);
03257 color->matte=MagickFalse;
03258 if ((i > 0) && (colorspace[i] == 'a'))
03259 {
03260 colorspace[i]='\0';
03261 color->matte=MagickTrue;
03262 }
03263 type=ParseMagickOption(MagickColorspaceOptions,MagickFalse,colorspace);
03264 if (type < 0)
03265 {
03266 (void) ThrowMagickException(exception,GetMagickModule(),
03267 OptionWarning,"UnrecognizedColor","`%s'",name);
03268 return(MagickFalse);
03269 }
03270 color->colorspace=(ColorspaceType) type;
03271 SetGeometryInfo(&geometry_info);
03272 flags=ParseGeometry(name+i+1,&geometry_info);
03273 scale=(MagickRealType) ScaleCharToQuantum(1);
03274 if ((flags & PercentValue) != 0)
03275 scale=(MagickRealType) (QuantumRange/100.0);
03276 if ((flags & RhoValue) != 0)
03277 color->red=(MagickRealType) RoundToQuantum(scale*geometry_info.rho);
03278 if ((flags & SigmaValue) != 0)
03279 color->green=(MagickRealType) RoundToQuantum(scale*geometry_info.sigma);
03280 if ((flags & XiValue) != 0)
03281 color->blue=(MagickRealType) RoundToQuantum(scale*geometry_info.xi);
03282 color->opacity=OpaqueOpacity;
03283 if ((flags & PsiValue) != 0)
03284 {
03285 if (color->colorspace == CMYKColorspace)
03286 color->index=(MagickRealType) RoundToQuantum(scale*
03287 geometry_info.psi);
03288 else
03289 if (color->matte != MagickFalse)
03290 color->opacity=(MagickRealType) RoundToQuantum((MagickRealType)
03291 (QuantumRange-QuantumRange*geometry_info.psi));
03292 }
03293 if (((flags & ChiValue) != 0) && (color->matte != MagickFalse))
03294 color->opacity=(MagickRealType) RoundToQuantum((MagickRealType)
03295 (QuantumRange-QuantumRange*geometry_info.chi));
03296 if (LocaleCompare(colorspace,"gray") == 0)
03297 {
03298 color->green=color->red;
03299 color->blue=color->red;
03300 if (((flags & SigmaValue) != 0) && (color->matte != MagickFalse))
03301 color->opacity=(MagickRealType) RoundToQuantum((MagickRealType)
03302 (QuantumRange-QuantumRange*geometry_info.sigma));
03303 }
03304 if (LocaleCompare(colorspace,"HSL") == 0)
03305 {
03306 PixelPacket
03307 pixel;
03308
03309 geometry_info.rho=fmod(fmod(geometry_info.rho,360.0)+360.0,360.0)/
03310 360.0;
03311 geometry_info.sigma/=100.0;
03312 geometry_info.xi/=100.0;
03313 ConvertHSLToRGB(geometry_info.rho,geometry_info.sigma,
03314 geometry_info.xi,&pixel.red,&pixel.green,&pixel.blue);
03315 color->colorspace=RGBColorspace;
03316 color->red=(MagickRealType) pixel.red;
03317 color->green=(MagickRealType) pixel.green;
03318 color->blue=(MagickRealType) pixel.blue;
03319 }
03320 return(MagickTrue);
03321 }
03322
03323
03324
03325 p=GetColorInfo(name,exception);
03326 if (p == (const ColorInfo *) NULL)
03327 return(MagickFalse);
03328 color->colorspace=RGBColorspace;
03329 color->matte=p->color.opacity != OpaqueOpacity ? MagickTrue : MagickFalse;
03330 color->red=(MagickRealType) p->color.red;
03331 color->green=(MagickRealType) p->color.green;
03332 color->blue=(MagickRealType) p->color.blue;
03333 color->opacity=(MagickRealType) p->color.opacity;
03334 color->index=0.0;
03335 return(MagickTrue);
03336 }
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366
03367
03368
03369
03370
03371
03372
03373 MagickExport MagickBooleanType QueryMagickColorname(const Image *image,
03374 const MagickPixelPacket *color,const ComplianceType compliance,
03375 char *name,ExceptionInfo *exception)
03376 {
03377 MagickPixelPacket
03378 pixel;
03379
03380 MagickRealType
03381 opacity;
03382
03383 register const ColorInfo
03384 *p;
03385
03386 *name='\0';
03387 pixel=(*color);
03388 if (compliance == XPMCompliance)
03389 {
03390 pixel.matte=MagickFalse;
03391 pixel.depth=(unsigned long) MagickMin(1.0*image->depth,16.0);
03392 GetColorTuple(&pixel,MagickTrue,name);
03393 return(MagickTrue);
03394 }
03395 GetColorTuple(&pixel,compliance != SVGCompliance ? MagickTrue : MagickFalse,
03396 name);
03397 (void) GetColorInfo("*",exception);
03398 ResetLinkedListIterator(color_list);
03399 opacity=image->matte != MagickFalse ? color->opacity : OpaqueOpacity;
03400 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
03401 while (p != (const ColorInfo *) NULL)
03402 {
03403 if (((p->compliance & compliance) != 0) && ((p->color.red == color->red)) &&
03404 (p->color.green == color->green) && (p->color.blue == color->blue) &&
03405 (p->color.opacity == opacity))
03406 {
03407 (void) CopyMagickString(name,p->name,MaxTextExtent);
03408 break;
03409 }
03410 p=(const ColorInfo *) GetNextValueInLinkedList(color_list);
03411 }
03412 return(MagickTrue);
03413 }
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440 static void UniqueColorsToImage(Image *image,CubeInfo *cube_info,
03441 const NodeInfo *node_info,ExceptionInfo *exception)
03442 {
03443 #define UniqueColorsImageTag "UniqueColors/Image"
03444
03445 register long
03446 i;
03447
03448 unsigned long
03449 number_children;
03450
03451
03452
03453
03454 number_children=image->matte == MagickFalse ? 8UL : 16UL;
03455 for (i=0; i < (long) number_children; i++)
03456 if (node_info->child[i] != (NodeInfo *) NULL)
03457 UniqueColorsToImage(image,cube_info,node_info->child[i],exception);
03458 if (node_info->level == (MaxTreeDepth-1))
03459 {
03460 register ColorPacket
03461 *p;
03462
03463 register IndexPacket
03464 *__restrict indexes;
03465
03466 register PixelPacket
03467 *__restrict q;
03468
03469 p=node_info->list;
03470 for (i=0; i < (long) node_info->number_unique; i++)
03471 {
03472 q=QueueAuthenticPixels(image,cube_info->x,0,1,1,exception);
03473 if (q == (PixelPacket *) NULL)
03474 continue;
03475 indexes=GetAuthenticIndexQueue(image);
03476 *q=p->pixel;
03477 if (image->colorspace == CMYKColorspace)
03478 *indexes=p->index;
03479 if (SyncAuthenticPixels(image,exception) == MagickFalse)
03480 break;
03481 cube_info->x++;
03482 p++;
03483 }
03484 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
03485 (QuantumTick(cube_info->progress,cube_info->colors) != MagickFalse))
03486 (void) image->progress_monitor(UniqueColorsImageTag,cube_info->progress,
03487 cube_info->colors,image->client_data);
03488 cube_info->progress++;
03489 }
03490 }
03491
03492 MagickExport Image *UniqueImageColors(const Image *image,
03493 ExceptionInfo *exception)
03494 {
03495 CubeInfo
03496 *cube_info;
03497
03498 Image
03499 *unique_image;
03500
03501 cube_info=ClassifyImageColors(image,exception);
03502 if (cube_info == (CubeInfo *) NULL)
03503 return((Image *) NULL);
03504 unique_image=CloneImage(image,cube_info->colors,1,MagickTrue,exception);
03505 if (unique_image == (Image *) NULL)
03506 return(unique_image);
03507 if (SetImageStorageClass(unique_image,DirectClass) == MagickFalse)
03508 {
03509 InheritException(exception,&unique_image->exception);
03510 unique_image=DestroyImage(unique_image);
03511 return((Image *) NULL);
03512 }
03513 UniqueColorsToImage(unique_image,cube_info,cube_info->root,exception);
03514 if (cube_info->colors < MaxColormapSize)
03515 {
03516 QuantizeInfo
03517 *quantize_info;
03518
03519 quantize_info=AcquireQuantizeInfo((ImageInfo *) NULL);
03520 quantize_info->number_colors=MaxColormapSize;
03521 quantize_info->dither=MagickFalse;
03522 quantize_info->tree_depth=8;
03523 (void) QuantizeImage(quantize_info,unique_image);
03524 quantize_info=DestroyQuantizeInfo(quantize_info);
03525 }
03526 cube_info=DestroyCubeInfo(image,cube_info);
03527 return(unique_image);
03528 }