]> granicus.if.org Git - imagemagick/blob - magick/coder.c
(no commit message)
[imagemagick] / magick / coder.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                   CCCC   OOO   DDDD    EEEEE  RRRR                          %
7 %                  C      O   O  D   D   E      R   R                         %
8 %                  C      O   O  D   D   EEE    RRRR                          %
9 %                  C      O   O  D   D   E      R R                           %
10 %                   CCCC   OOO   DDDD    EEEEE  R  R                          %
11 %                                                                             %
12 %                                                                             %
13 %                     MagickCore Image Coder Methods                          %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                John Cristy                                  %
17 %                                 May 2001                                    %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
42 #include "magick/studio.h"
43 #include "magick/blob.h"
44 #include "magick/client.h"
45 #include "magick/coder.h"
46 #include "magick/configure.h"
47 #include "magick/draw.h"
48 #include "magick/exception.h"
49 #include "magick/exception-private.h"
50 #include "magick/hashmap.h"
51 #include "magick/log.h"
52 #include "magick/memory_.h"
53 #include "magick/option.h"
54 #include "magick/semaphore.h"
55 #include "magick/string_.h"
56 #include "magick/splay-tree.h"
57 #include "magick/token.h"
58 #include "magick/utility.h"
59 #include "magick/xml-tree.h"
60 \f
61 /*
62   Define declarations.
63 */
64 #define MagickCoderFilename  "coder.xml"
65 \f
66 /*
67   Declare coder map.
68 */
69 static const char
70   *CoderMap = (const char *)
71     "<?xml version=\"1.0\"?>"
72     "<codermap>"
73     "  <coder magick=\"8BIM\" name=\"META\" />"
74     "  <coder magick=\"8BIMTEXT\" name=\"META\" />"
75     "  <coder magick=\"8BIMWTEXT\" name=\"META\" />"
76     "  <coder magick=\"A\" name=\"RAW\" />"
77     "  <coder magick=\"AI\" name=\"PDF\" />"
78     "  <coder magick=\"AFM\" name=\"TTF\" />"
79     "  <coder magick=\"APP1JPEG\" name=\"META\" />"
80     "  <coder magick=\"APP1\" name=\"META\" />"
81     "  <coder magick=\"ARW\" name=\"DNG\" />"
82     "  <coder magick=\"BIE\" name=\"JBIG\" />"
83     "  <coder magick=\"BMP2\" name=\"BMP\" />"
84     "  <coder magick=\"BMP3\" name=\"BMP\" />"
85     "  <coder magick=\"B\" name=\"GRAY\" />"
86     "  <coder magick=\"BRF\" name=\"BRAILLE\" />"
87     "  <coder magick=\"CMYKA\" name=\"CMYK\" />"
88     "  <coder magick=\"C\" name=\"GRAY\" />"
89     "  <coder magick=\"CR2\" name=\"DNG\" />"
90     "  <coder magick=\"CRW\" name=\"DNG\" />"
91     "  <coder magick=\"CUR\" name=\"ICON\" />"
92     "  <coder magick=\"DCR\" name=\"DNG\" />"
93     "  <coder magick=\"DCX\" name=\"PCX\" />"
94     "  <coder magick=\"DFONT\" name=\"TTF\" />"
95     "  <coder magick=\"EMF\" name=\"EMF\" />"
96     "  <coder magick=\"EPDF\" name=\"PDF\" />"
97     "  <coder magick=\"EPI\" name=\"PS\" />"
98     "  <coder magick=\"EPS2\" name=\"PS2\" />"
99     "  <coder magick=\"EPS3\" name=\"PS3\" />"
100     "  <coder magick=\"EPSF\" name=\"PS\" />"
101     "  <coder magick=\"EPSI\" name=\"PS\" />"
102     "  <coder magick=\"EPS\" name=\"PS\" />"
103     "  <coder magick=\"EPT2\" name=\"EPT\" />"
104     "  <coder magick=\"EPT3\" name=\"EPT\" />"
105     "  <coder magick=\"EXIF\" name=\"META\" />"
106     "  <coder magick=\"FILE\" name=\"URL\" />"
107     "  <coder magick=\"FRACTAL\" name=\"PLASMA\" />"
108     "  <coder magick=\"FTP\" name=\"URL\" />"
109     "  <coder magick=\"FTS\" name=\"FITS\" />"
110     "  <coder magick=\"G3\" name=\"FAX\" />"
111     "  <coder magick=\"GIF87\" name=\"GIF\" />"
112     "  <coder magick=\"G\" name=\"GRAY\" />"
113     "  <coder magick=\"GRANITE\" name=\"MAGICK\" />"
114     "  <coder magick=\"H\" name=\"MAGICK\" />"
115     "  <coder magick=\"HTM\" name=\"HTML\" />"
116     "  <coder magick=\"HTTP\" name=\"URL\" />"
117     "  <coder magick=\"ICB\" name=\"TGA\" />"
118     "  <coder magick=\"ICC\" name=\"META\" />"
119     "  <coder magick=\"ICM\" name=\"META\" />"
120     "  <coder magick=\"ICO\" name=\"ICON\" />"
121     "  <coder magick=\"IMPLICIT\" name=\"***\" />"
122     "  <coder magick=\"IPTC\" name=\"META\" />"
123     "  <coder magick=\"IPTCTEXT\" name=\"META\" />"
124     "  <coder magick=\"IPTCWTEXT\" name=\"META\" />"
125     "  <coder magick=\"ISOBRL\" name=\"BRAILLE\" />"
126     "  <coder magick=\"JBG\" name=\"JBIG\" />"
127     "  <coder magick=\"JNG\" name=\"PNG\" />"
128     "  <coder magick=\"JPC\" name=\"JP2\" />"
129     "  <coder magick=\"JPG\" name=\"JPEG\" />"
130     "  <coder magick=\"JPX\" name=\"JP2\" />"
131     "  <coder magick=\"K\" name=\"GRAY\" />"
132     "  <coder magick=\"LOGO\" name=\"MAGICK\" />"
133     "  <coder magick=\"M2V\" name=\"MPEG\" />"
134     "  <coder magick=\"M4V\" name=\"MPEG\" />"
135     "  <coder magick=\"M\" name=\"GRAY\" />"
136     "  <coder magick=\"MNG\" name=\"PNG\" />"
137     "  <coder magick=\"MOV\" name=\"MPEG\" />"
138     "  <coder magick=\"MPG\" name=\"MPEG\" />"
139     "  <coder magick=\"MP4\" name=\"MPEG\" />"
140     "  <coder magick=\"MPRI\" name=\"MPR\" />"
141     "  <coder magick=\"MRW\" name=\"DNG\" />"
142     "  <coder magick=\"MSVG\" name=\"SVG\" />"
143     "  <coder magick=\"NEF\" name=\"DNG\" />"
144     "  <coder magick=\"NETSCAPE\" name=\"MAGICK\" />"
145     "  <coder magick=\"O\" name=\"GRAY\" />"
146     "  <coder magick=\"ORF\" name=\"DNG\" />"
147     "  <coder magick=\"OTF\" name=\"TTF\" />"
148     "  <coder magick=\"P7\" name=\"PNM\" />"
149     "  <coder magick=\"PAL\" name=\"UYVY\" />"
150     "  <coder magick=\"PAM\" name=\"PNM\" />"
151     "  <coder magick=\"PBM\" name=\"PNM\" />"
152     "  <coder magick=\"PCDS\" name=\"PCD\" />"
153     "  <coder magick=\"PCT\" name=\"PICT\" />"
154     "  <coder magick=\"PDFA\" name=\"PDF\" />"
155     "  <coder magick=\"PEF\" name=\"DNG\" />"
156     "  <coder magick=\"PFA\" name=\"TTF\" />"
157     "  <coder magick=\"PFB\" name=\"TTF\" />"
158     "  <coder magick=\"PFM\" name=\"PNM\" />"
159     "  <coder magick=\"PGM\" name=\"PNM\" />"
160     "  <coder magick=\"PGX\" name=\"JP2\" />"
161     "  <coder magick=\"PICON\" name=\"XPM\" />"
162     "  <coder magick=\"PJPEG\" name=\"JPEG\" />"
163     "  <coder magick=\"PM\" name=\"XPM\" />"
164     "  <coder magick=\"PNG24\" name=\"PNG\" />"
165     "  <coder magick=\"PNG32\" name=\"PNG\" />"
166     "  <coder magick=\"PNG8\" name=\"PNG\" />"
167     "  <coder magick=\"PPM\" name=\"PNM\" />"
168     "  <coder magick=\"PTIF\" name=\"TIFF\" />"
169     "  <coder magick=\"RADIAL-GRADIENT\" name=\"GRADIENT\" />"
170     "  <coder magick=\"RAF\" name=\"DNG\" />"
171     "  <coder magick=\"RAS\" name=\"SUN\" />"
172     "  <coder magick=\"RGBA\" name=\"RGB\" />"
173     "  <coder magick=\"RGBO\" name=\"RGB\" />"
174     "  <coder magick=\"R\" name=\"GRAY\" />"
175     "  <coder magick=\"ROSE\" name=\"MAGICK\" />"
176     "  <coder magick=\"SHTML\" name=\"HTML\" />"
177     "  <coder magick=\"SVGZ\" name=\"SVG\" />"
178     "  <coder magick=\"TEXT\" name=\"TXT\" />"
179     "  <coder magick=\"TIFF64\" name=\"TIFF\" />"
180     "  <coder magick=\"TIF\" name=\"TIFF\" />"
181     "  <coder magick=\"TTC\" name=\"TTF\" />"
182     "  <coder magick=\"UBRL\" name=\"BRAILLE\" />"
183     "  <coder magick=\"VDA\" name=\"TGA\" />"
184     "  <coder magick=\"VST\" name=\"TGA\" />"
185     "  <coder magick=\"WMFWIN32\" name=\"EMF\" />"
186     "  <coder magick=\"WMV\" name=\"MPEG\" />"
187     "  <coder magick=\"X3F\" name=\"DNG\" />"
188     "  <coder magick=\"XTRNARRAY\" name=\"XTRN\" />"
189     "  <coder magick=\"XTRNBLOB\" name=\"XTRN\" />"
190     "  <coder magick=\"XTRNBSTR\" name=\"XTRN\" />"
191     "  <coder magick=\"XTRNFILE\" name=\"XTRN\" />"
192     "  <coder magick=\"XTRNIMAGE\" name=\"XTRN\" />"
193     "  <coder magick=\"XTRNSTREAM\" name=\"XTRN\" />"
194     "  <coder magick=\"XV\" name=\"VIFF\" />"
195     "  <coder magick=\"Y\" name=\"GRAY\" />"
196     "  <coder magick=\"YCbCrA\" name=\"YCbCr\" />"
197     "</codermap>";
198 \f
199 /*
200   Static declarations.
201 */
202 static SemaphoreInfo
203   *coder_semaphore = (SemaphoreInfo *) NULL;
204
205 static SplayTreeInfo
206   *coder_list = (SplayTreeInfo *) NULL;
207
208 static volatile MagickBooleanType
209   instantiate_coder = MagickFalse;
210 \f
211 /*
212   Forward declarations.
213 */
214 static MagickBooleanType
215   InitializeCoderList(ExceptionInfo *),
216   LoadCoderLists(const char *,ExceptionInfo *);
217 \f
218 /*
219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
220 %                                                                             %
221 %                                                                             %
222 %                                                                             %
223 +   D e s t r o y C o d e r L i s t                                           %
224 %                                                                             %
225 %                                                                             %
226 %                                                                             %
227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228 %
229 %  DestroyCoderList() deallocates memory associated with the font list.
230 %
231 %  The format of the DestroyCoderList method is:
232 %
233 %      DestroyCoderList(void)
234 %
235 */
236 MagickExport void DestroyCoderList(void)
237 {
238   AcquireSemaphoreInfo(&coder_semaphore);
239   if (coder_list != (SplayTreeInfo *) NULL)
240     coder_list=DestroySplayTree(coder_list);
241   instantiate_coder=MagickFalse;
242   RelinquishSemaphoreInfo(coder_semaphore);
243   DestroySemaphoreInfo(&coder_semaphore);
244 }
245 \f
246 /*
247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
248 %                                                                             %
249 %                                                                             %
250 %                                                                             %
251 +   G e t C o d e r I n f o                                                   %
252 %                                                                             %
253 %                                                                             %
254 %                                                                             %
255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256 %
257 %  GetCoderInfo searches the coder list for the specified name and if found
258 %  returns attributes for that coder.
259 %
260 %  The format of the GetCoderInfo method is:
261 %
262 %      const CoderInfo *GetCoderInfo(const char *name,ExceptionInfo *exception)
263 %
264 %  A description of each parameter follows:
265 %
266 %    o name: the coder name.
267 %
268 %    o exception: return any errors or warnings in this structure.
269 %
270 */
271 MagickExport const CoderInfo *GetCoderInfo(const char *name,
272   ExceptionInfo *exception)
273 {
274   assert(exception != (ExceptionInfo *) NULL);
275   if ((coder_list == (SplayTreeInfo *) NULL) ||
276       (instantiate_coder == MagickFalse))
277     if (InitializeCoderList(exception) == MagickFalse)
278       return((const CoderInfo *) NULL);
279   if ((coder_list == (SplayTreeInfo *) NULL) ||
280       (GetNumberOfNodesInSplayTree(coder_list) == 0))
281     return((const CoderInfo *) NULL);
282   if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
283     {
284       ResetSplayTreeIterator(coder_list);
285       return((const CoderInfo *) GetNextValueInSplayTree(coder_list));
286     }
287   return((const CoderInfo *) GetValueFromSplayTree(coder_list,name));
288 }
289 \f
290 /*
291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
292 %                                                                             %
293 %                                                                             %
294 %                                                                             %
295 %   G e t C o d e r I n f o L i s t                                           %
296 %                                                                             %
297 %                                                                             %
298 %                                                                             %
299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
300 %
301 %  GetCoderInfoList() returns any coder_map that match the specified pattern.
302 %  The format of the GetCoderInfoList function is:
303 %
304 %      const CoderInfo **GetCoderInfoList(const char *pattern,
305 %        unsigned long *number_coders,ExceptionInfo *exception)
306 %
307 %  A description of each parameter follows:
308 %
309 %    o pattern: Specifies a pointer to a text string containing a pattern.
310 %
311 %    o number_coders:  This integer returns the number of coders in the list.
312 %
313 %    o exception: return any errors or warnings in this structure.
314 %
315 */
316
317 static int CoderInfoCompare(const void *x,const void *y)
318 {
319   const CoderInfo
320     **p,
321     **q;
322
323   p=(const CoderInfo **) x,
324   q=(const CoderInfo **) y;
325   if (LocaleCompare((*p)->path,(*q)->path) == 0)
326     return(LocaleCompare((*p)->name,(*q)->name));
327   return(LocaleCompare((*p)->path,(*q)->path));
328 }
329
330 MagickExport const CoderInfo **GetCoderInfoList(const char *pattern,
331   unsigned long *number_coders,ExceptionInfo *exception)
332 {
333   const CoderInfo
334     **coder_map;
335
336   register const CoderInfo
337     *p;
338
339   register long
340     i;
341
342   /*
343     Allocate coder list.
344   */
345   assert(pattern != (char *) NULL);
346   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
347   assert(number_coders != (unsigned long *) NULL);
348   *number_coders=0;
349   p=GetCoderInfo("*",exception);
350   if (p == (const CoderInfo *) NULL)
351     return((const CoderInfo **) NULL);
352   coder_map=(const CoderInfo **) AcquireQuantumMemory((size_t)
353     GetNumberOfNodesInSplayTree(coder_list)+1UL,sizeof(*coder_map));
354   if (coder_map == (const CoderInfo **) NULL)
355     return((const CoderInfo **) NULL);
356   /*
357     Generate coder list.
358   */
359   AcquireSemaphoreInfo(&coder_semaphore);
360   ResetSplayTreeIterator(coder_list);
361   p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
362   for (i=0; p != (const CoderInfo *) NULL; )
363   {
364     if ((p->stealth == MagickFalse) &&
365         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
366       coder_map[i++]=p;
367     p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
368   }
369   RelinquishSemaphoreInfo(coder_semaphore);
370   qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderInfoCompare);
371   coder_map[i]=(CoderInfo *) NULL;
372   *number_coders=(unsigned long) i;
373   return(coder_map);
374 }
375 \f
376 /*
377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
378 %                                                                             %
379 %                                                                             %
380 %                                                                             %
381 %   G e t C o d e r L i s t                                                   %
382 %                                                                             %
383 %                                                                             %
384 %                                                                             %
385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
386 %
387 %  GetCoderList() returns any coder_map that match the specified pattern.
388 %
389 %  The format of the GetCoderList function is:
390 %
391 %      char **GetCoderList(const char *pattern,unsigned long *number_coders,
392 %        ExceptionInfo *exception)
393 %
394 %  A description of each parameter follows:
395 %
396 %    o pattern: Specifies a pointer to a text string containing a pattern.
397 %
398 %    o number_coders:  This integer returns the number of coders in the list.
399 %
400 %    o exception: return any errors or warnings in this structure.
401 %
402 */
403
404 static int CoderCompare(const void *x,const void *y)
405 {
406   register const char
407     **p,
408     **q;
409
410   p=(const char **) x;
411   q=(const char **) y;
412   return(LocaleCompare(*p,*q));
413 }
414
415 MagickExport char **GetCoderList(const char *pattern,
416   unsigned long *number_coders,ExceptionInfo *exception)
417 {
418   char
419     **coder_map;
420
421   register const CoderInfo
422     *p;
423
424   register long
425     i;
426
427   /*
428     Allocate coder list.
429   */
430   assert(pattern != (char *) NULL);
431   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
432   assert(number_coders != (unsigned long *) NULL);
433   *number_coders=0;
434   p=GetCoderInfo("*",exception);
435   if (p == (const CoderInfo *) NULL)
436     return((char **) NULL);
437   coder_map=(char **) AcquireQuantumMemory((size_t)
438     GetNumberOfNodesInSplayTree(coder_list)+1UL,sizeof(*coder_map));
439   if (coder_map == (char **) NULL)
440     return((char **) NULL);
441   /*
442     Generate coder list.
443   */
444   AcquireSemaphoreInfo(&coder_semaphore);
445   ResetSplayTreeIterator(coder_list);
446   p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
447   for (i=0; p != (const CoderInfo *) NULL; )
448   {
449     if ((p->stealth == MagickFalse) &&
450         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
451       coder_map[i++]=ConstantString(p->name);
452     p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
453   }
454   RelinquishSemaphoreInfo(coder_semaphore);
455   qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderCompare);
456   coder_map[i]=(char *) NULL;
457   *number_coders=(unsigned long) i;
458   return(coder_map);
459 }
460 \f
461 /*
462 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
463 %                                                                             %
464 %                                                                             %
465 %                                                                             %
466 +   I n i t i a l i z e C o d e r L i s t                                     %
467 %                                                                             %
468 %                                                                             %
469 %                                                                             %
470 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
471 %
472 %  InitializeCoderList() initializes the coder list.
473 %
474 %  The format of the InitializeCoderList method is:
475 %
476 %      MagickBooleanType InitializeCoderList(ExceptionInfo *exception)
477 %
478 %  A description of each parameter follows.
479 %
480 %    o exception: return any errors or warnings in this structure.
481 %
482 */
483 static MagickBooleanType InitializeCoderList(ExceptionInfo *exception)
484 {
485   if ((coder_list == (SplayTreeInfo *) NULL) &&
486       (instantiate_coder == MagickFalse))
487     {
488       AcquireSemaphoreInfo(&coder_semaphore);
489       if ((coder_list == (SplayTreeInfo *) NULL) &&
490           (instantiate_coder == MagickFalse))
491         {
492           (void) LoadCoderLists(MagickCoderFilename,exception);
493           instantiate_coder=MagickTrue;
494         }
495       RelinquishSemaphoreInfo(coder_semaphore);
496     }
497   return(coder_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
498 }
499 \f
500 /*
501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
502 %                                                                             %
503 %                                                                             %
504 %                                                                             %
505 %  L i s t C o d e r I n f o                                                  %
506 %                                                                             %
507 %                                                                             %
508 %                                                                             %
509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510 %
511 %  ListCoderInfo() lists the coder info to a file.
512 %
513 %  The format of the ListCoderInfo coder is:
514 %
515 %      MagickBooleanType ListCoderInfo(FILE *file,ExceptionInfo *exception)
516 %
517 %  A description of each parameter follows.
518 %
519 %    o file:  An pointer to a FILE.
520 %
521 %    o exception: return any errors or warnings in this structure.
522 %
523 */
524 MagickExport MagickBooleanType ListCoderInfo(FILE *file,
525   ExceptionInfo *exception)
526 {
527   const char
528     *path;
529
530   const CoderInfo
531     **coder_info;
532
533   long
534     j;
535
536   register long
537     i;
538
539   unsigned long
540     number_coders;
541
542   if (file == (const FILE *) NULL)
543     file=stdout;
544   coder_info=GetCoderInfoList("*",&number_coders,exception);
545   if (coder_info == (const CoderInfo **) NULL)
546     return(MagickFalse);
547   path=(const char *) NULL;
548   for (i=0; i < (long) number_coders; i++)
549   {
550     if (coder_info[i]->stealth != MagickFalse)
551       continue;
552     if ((path == (const char *) NULL) ||
553         (LocaleCompare(path,coder_info[i]->path) != 0))
554       {
555         if (coder_info[i]->path != (char *) NULL)
556           (void) fprintf(file,"\nPath: %s\n\n",coder_info[i]->path);
557         (void) fprintf(file,"Magick      Coder\n");
558         (void) fprintf(file,"-------------------------------------------------"
559           "------------------------------\n");
560       }
561     path=coder_info[i]->path;
562     (void) fprintf(file,"%s",coder_info[i]->magick);
563     for (j=(long) strlen(coder_info[i]->magick); j <= 11; j++)
564       (void) fprintf(file," ");
565     if (coder_info[i]->name != (char *) NULL)
566       (void) fprintf(file,"%s",coder_info[i]->name);
567     (void) fprintf(file,"\n");
568   }
569   coder_info=(const CoderInfo **) RelinquishMagickMemory((void *) coder_info);
570   (void) fflush(file);
571   return(MagickTrue);
572 }
573 \f
574 /*
575 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
576 %                                                                             %
577 %                                                                             %
578 %                                                                             %
579 +   L o a d C o d e r L i s t                                                 %
580 %                                                                             %
581 %                                                                             %
582 %                                                                             %
583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
584 %
585 %  LoadCoderList() loads the coder configuration file which provides a
586 %  mapping between coder attributes and a coder name.
587 %
588 %  The format of the LoadCoderList coder is:
589 %
590 %      MagickBooleanType LoadCoderList(const char *xml,const char *filename,
591 %        const unsigned long depth,ExceptionInfo *exception)
592 %
593 %  A description of each parameter follows:
594 %
595 %    o xml:  The coder list in XML format.
596 %
597 %    o filename:  The coder list filename.
598 %
599 %    o depth: depth of <include /> statements.
600 %
601 %    o exception: return any errors or warnings in this structure.
602 %
603 */
604
605 static void *DestroyCoderNode(void *coder_info)
606 {
607   register CoderInfo
608     *p;
609
610   p=(CoderInfo *) coder_info;
611   if (p->path != (char *) NULL)
612     p->path=DestroyString(p->path);
613   if (p->name != (char *) NULL)
614     p->name=DestroyString(p->name);
615   if (p->magick != (char *) NULL)
616     p->magick=DestroyString(p->magick);
617   return(RelinquishMagickMemory(p));
618 }
619
620 static MagickBooleanType LoadCoderList(const char *xml,const char *filename,
621   const unsigned long depth,ExceptionInfo *exception)
622 {
623   char
624     keyword[MaxTextExtent],
625     *token;
626
627   const char
628     *q;
629
630   CoderInfo
631     *coder_info;
632
633   MagickBooleanType
634     status;
635
636   /*
637     Load the coder map file.
638   */
639   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
640     "Loading coder configuration file \"%s\" ...",filename);
641   if (xml == (const char *) NULL)
642     return(MagickFalse);
643   if (coder_list == (SplayTreeInfo *) NULL)
644     {
645       coder_list=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
646         DestroyCoderNode);
647       if (coder_list == (SplayTreeInfo *) NULL)
648         {
649           ThrowFileException(exception,ResourceLimitError,
650             "MemoryAllocationFailed",filename);
651           return(MagickFalse);
652         }
653     }
654   status=MagickTrue;
655   coder_info=(CoderInfo *) NULL;
656   token=AcquireString(xml);
657   for (q=(char *) xml; *q != '\0'; )
658   {
659     /*
660       Interpret XML.
661     */
662     GetMagickToken(q,&q,token);
663     if (*token == '\0')
664       break;
665     (void) CopyMagickString(keyword,token,MaxTextExtent);
666     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
667       {
668         /*
669           Doctype element.
670         */
671         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
672           GetMagickToken(q,&q,token);
673         continue;
674       }
675     if (LocaleNCompare(keyword,"<!--",4) == 0)
676       {
677         /*
678           Comment element.
679         */
680         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
681           GetMagickToken(q,&q,token);
682         continue;
683       }
684     if (LocaleCompare(keyword,"<include") == 0)
685       {
686         /*
687           Include element.
688         */
689         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
690         {
691           (void) CopyMagickString(keyword,token,MaxTextExtent);
692           GetMagickToken(q,&q,token);
693           if (*token != '=')
694             continue;
695           GetMagickToken(q,&q,token);
696           if (LocaleCompare(keyword,"file") == 0)
697             {
698               if (depth > 200)
699                 (void) ThrowMagickException(exception,GetMagickModule(),
700                   ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token);
701               else
702                 {
703                   char
704                     path[MaxTextExtent],
705                     *xml;
706
707                   GetPathComponent(filename,HeadPath,path);
708                   if (*path != '\0')
709                     (void) ConcatenateMagickString(path,DirectorySeparator,
710                       MaxTextExtent);
711                   if (*token == *DirectorySeparator)
712                     (void) CopyMagickString(path,token,MaxTextExtent);
713                   else
714                     (void) ConcatenateMagickString(path,token,MaxTextExtent);
715                   xml=FileToString(path,~0,exception);
716                   if (xml != (char *) NULL)
717                     {
718                       status=LoadCoderList(xml,path,depth+1,exception);
719                       xml=(char *) RelinquishMagickMemory(xml);
720                     }
721                 }
722             }
723         }
724         continue;
725       }
726     if (LocaleCompare(keyword,"<coder") == 0)
727       {
728         /*
729           Coder element.
730         */
731         coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info));
732         if (coder_info == (CoderInfo *) NULL)
733           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
734         (void) ResetMagickMemory(coder_info,0,sizeof(*coder_info));
735         coder_info->path=ConstantString(filename);
736         coder_info->signature=MagickSignature;
737         continue;
738       }
739     if (coder_info == (CoderInfo *) NULL)
740       continue;
741     if (LocaleCompare(keyword,"/>") == 0)
742       {
743         status=AddValueToSplayTree(coder_list,ConstantString(
744           coder_info->magick),coder_info);
745         if (status == MagickFalse)
746           (void) ThrowMagickException(exception,GetMagickModule(),
747             ResourceLimitError,"MemoryAllocationFailed","`%s'",
748             coder_info->magick);
749         coder_info=(CoderInfo *) NULL;
750       }
751     GetMagickToken(q,(const char **) NULL,token);
752     if (*token != '=')
753       continue;
754     GetMagickToken(q,&q,token);
755     GetMagickToken(q,&q,token);
756     switch (*keyword)
757     {
758       case 'M':
759       case 'm':
760       {
761         if (LocaleCompare((char *) keyword,"magick") == 0)
762           {
763             coder_info->magick=ConstantString(token);
764             break;
765           }
766         break;
767       }
768       case 'N':
769       case 'n':
770       {
771         if (LocaleCompare((char *) keyword,"name") == 0)
772           {
773             coder_info->name=ConstantString(token);
774             break;
775           }
776         break;
777       }
778       case 'S':
779       case 's':
780       {
781         if (LocaleCompare((char *) keyword,"stealth") == 0)
782           {
783             coder_info->stealth=IsMagickTrue(token);
784             break;
785           }
786         break;
787       }
788       default:
789         break;
790     }
791   }
792   token=(char *) RelinquishMagickMemory(token);
793   return(status);
794 }
795 \f
796 /*
797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
798 %                                                                             %
799 %                                                                             %
800 %                                                                             %
801 %  L o a d C o d e r L i s t s                                                %
802 %                                                                             %
803 %                                                                             %
804 %                                                                             %
805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
806 %
807 %  LoadCoderLists() loads one or more coder configuration file which
808 %  provides a mapping between coder attributes and a coder name.
809 %
810 %  The format of the LoadCoderLists coder is:
811 %
812 %      MagickBooleanType LoadCoderLists(const char *filename,
813 %        ExceptionInfo *exception)
814 %
815 %  A description of each parameter follows:
816 %
817 %    o filename: the font file name.
818 %
819 %    o exception: return any errors or warnings in this structure.
820 %
821 */
822 static MagickBooleanType LoadCoderLists(const char *filename,
823   ExceptionInfo *exception)
824 {
825 #if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
826   return(LoadCoderList(CoderMap,"built-in",0,exception));
827 #else
828   const StringInfo
829     *option;
830
831   LinkedListInfo
832     *options;
833
834   MagickStatusType
835     status;
836
837   status=MagickFalse;
838   options=GetConfigureOptions(filename,exception);
839   option=(const StringInfo *) GetNextValueInLinkedList(options);
840   while (option != (const StringInfo *) NULL)
841   {
842     status|=LoadCoderList((const char *) GetStringInfoDatum(option),
843       GetStringInfoPath(option),0,exception);
844     option=(const StringInfo *) GetNextValueInLinkedList(options);
845   }
846   options=DestroyConfigureOptions(options);
847   if ((coder_list == (SplayTreeInfo *) NULL) || 
848       (GetNumberOfNodesInSplayTree(coder_list) == 0))
849     status|=LoadCoderList(CoderMap,"built-in",0,exception);
850   return(status != 0 ? MagickTrue : MagickFalse);
851 #endif
852 }