MagickCore  6.7.5
coder.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %                   CCCC   OOO   DDDD    EEEEE  RRRR                          %
00007 %                  C      O   O  D   D   E      R   R                         %
00008 %                  C      O   O  D   D   EEE    RRRR                          %
00009 %                  C      O   O  D   D   E      R R                           %
00010 %                   CCCC   OOO   DDDD    EEEEE  R  R                          %
00011 %                                                                             %
00012 %                                                                             %
00013 %                     MagickCore Image Coder Methods                          %
00014 %                                                                             %
00015 %                              Software Design                                %
00016 %                                John Cristy                                  %
00017 %                                 May 2001                                    %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 */
00038 
00039 /*
00040   Include declarations.
00041 */
00042 #include "MagickCore/studio.h"
00043 #include "MagickCore/blob.h"
00044 #include "MagickCore/client.h"
00045 #include "MagickCore/coder.h"
00046 #include "MagickCore/coder-private.h"
00047 #include "MagickCore/configure.h"
00048 #include "MagickCore/draw.h"
00049 #include "MagickCore/exception.h"
00050 #include "MagickCore/exception-private.h"
00051 #include "MagickCore/hashmap.h"
00052 #include "MagickCore/log.h"
00053 #include "MagickCore/memory_.h"
00054 #include "MagickCore/option.h"
00055 #include "MagickCore/semaphore.h"
00056 #include "MagickCore/string_.h"
00057 #include "MagickCore/splay-tree.h"
00058 #include "MagickCore/token.h"
00059 #include "MagickCore/utility.h"
00060 #include "MagickCore/utility-private.h"
00061 #include "MagickCore/xml-tree.h"
00062 
00063 /*
00064   Define declarations.
00065 */
00066 #define MagickCoderFilename  "coder.xml"
00067 
00068 /*
00069   Typedef declarations.
00070 */
00071 typedef struct _CoderMapInfo
00072 {
00073   const char
00074     *magick,
00075     *name;
00076 } CoderMapInfo;
00077 
00078 /*
00079   Static declarations.
00080 */
00081 static const CoderMapInfo
00082   CoderMap[] =
00083   {
00084     { "3FR", "DNG" },
00085     { "8BIM", "META" },
00086     { "8BIMTEXT", "META" },
00087     { "8BIMWTEXT", "META" },
00088     { "AFM", "TTF" },
00089     { "A", "RAW" },
00090     { "AI", "PDF" },
00091     { "APP1JPEG", "META" },
00092     { "APP1", "META" },
00093     { "ARW", "DNG" },
00094     { "AVI", "MPEG" },
00095     { "BIE", "JBIG" },
00096     { "BMP2", "BMP" },
00097     { "BMP3", "BMP" },
00098     { "B", "RAW" },
00099     { "BRF", "BRAILLE" },
00100     { "BGRA", "BGR" },
00101     { "CMYKA", "CMYK" },
00102     { "C", "RAW" },
00103     { "CAL", "CALS" },
00104     { "CANVAS", "XC" },
00105     { "CR2", "DNG" },
00106     { "CRW", "DNG" },
00107     { "CUR", "ICON" },
00108     { "DCR", "DNG" },
00109     { "DCX", "PCX" },
00110     { "DFONT", "TTF" },
00111     { "EPDF", "PDF" },
00112     { "EPI", "PS" },
00113     { "EPS2", "PS2" },
00114     { "EPS3", "PS3" },
00115     { "EPSF", "PS" },
00116     { "EPSI", "PS" },
00117     { "EPS", "PS" },
00118     { "EPT2", "EPT" },
00119     { "EPT3", "EPT" },
00120     { "ERF", "DNG" },
00121     { "EXIF", "META" },
00122     { "FILE", "URL" },
00123     { "FRACTAL", "PLASMA" },
00124     { "FTP", "URL" },
00125     { "FTS", "FITS" },
00126     { "G3", "FAX" },
00127     { "GIF87", "GIF" },
00128     { "G", "RAW" },
00129     { "GRANITE", "MAGICK" },
00130     { "GROUP4", "TIFF" },
00131     { "K25", "DNG" },
00132     { "KDC", "DNG" },
00133     { "H", "MAGICK" },
00134     { "HTM", "HTML" },
00135     { "HTTP", "URL" },
00136     { "ICB", "TGA" },
00137     { "ICC", "META" },
00138     { "ICM", "META" },
00139     { "ICO", "ICON" },
00140     { "IMPLICIT", "***" },
00141     { "IPTC", "META" },
00142     { "IPTCTEXT", "META" },
00143     { "IPTCWTEXT", "META" },
00144     { "ISOBRL", "BRAILLE" },
00145     { "JBG", "JBIG" },
00146     { "JNG", "PNG" },
00147     { "JPC", "JP2" },
00148     { "J2C", "JP2" },
00149     { "JPG", "JPEG" },
00150     { "JPX", "JP2" },
00151     { "K", "RAW" },
00152     { "LOGO", "MAGICK" },
00153     { "M2V", "MPEG" },
00154     { "M4V", "MPEG" },
00155     { "M", "RAW" },
00156     { "MNG", "PNG" },
00157     { "MOV", "MPEG" },
00158     { "MP4", "MPEG" },
00159     { "MPG", "MPEG" },
00160     { "MPRI", "MPR" },
00161     { "MEF", "DNG" },
00162     { "MRW", "DNG" },
00163     { "MSVG", "SVG" },
00164     { "NEF", "DNG" },
00165     { "NETSCAPE", "MAGICK" },
00166     { "O", "RAW" },
00167     { "ORF", "DNG" },
00168     { "OTF", "TTF" },
00169     { "P7", "PNM" },
00170     { "PAL", "UYVY" },
00171     { "PAM", "PNM" },
00172     { "PBM", "PNM" },
00173     { "PCDS", "PCD" },
00174     { "PDFA", "PDF" },
00175     { "PEF", "DNG" },
00176     { "PEF", "DNG" },
00177     { "PFA", "TTF" },
00178     { "PFB", "TTF" },
00179     { "PFM", "PNM" },
00180     { "PGM", "PNM" },
00181     { "PGX", "JP2" },
00182     { "PICON", "XPM" },
00183     { "PJPEG", "JPEG" },
00184     { "PM", "XPM" },
00185     { "PNG24", "PNG" },
00186     { "PNG32", "PNG" },
00187     { "PNG8", "PNG" },
00188     { "PPM", "PNM" },
00189     { "PSB", "PSD" },
00190     { "PTIF", "TIFF" },
00191     { "RADIAL-GRADIENT", "GRADIENT" },
00192     { "RAF", "DNG" },
00193     { "RAS", "SUN" },
00194     { "RGBA", "RGB" },
00195     { "RGBO", "RGB" },
00196     { "R", "RAW" },
00197     { "ROSE", "MAGICK" },
00198     { "SHTML", "HTML" },
00199     { "SR2", "DNG" },
00200     { "SRF", "DNG" },
00201     { "SVGZ", "SVG" },
00202     { "TEXT", "TXT" },
00203     { "TIFF64", "TIFF" },
00204     { "TIF", "TIFF" },
00205     { "TTC", "TTF" },
00206     { "UBRL", "BRAILLE" },
00207     { "VDA", "TGA" },
00208     { "VST", "TGA" },
00209     { "WIZARD", "MAGICK" },
00210     { "WMV", "MPEG" },
00211     { "WMFWIN32", "EMF" },
00212     { "WMZ", "WMF" },
00213     { "X3f", "DNG" },
00214     { "XMP", "META" },
00215     { "XTRNARRAY", "XTRN" },
00216     { "XTRNBLOB", "XTRN" },
00217     { "XTRNFILE", "XTRN" },
00218     { "XTRNIMAGE", "XTRN" },
00219     { "XV", "VIFF" },
00220     { "Y", "RAW" },
00221     { "YCbCrA", "YCbCr" }
00222  };
00223 
00224 static SemaphoreInfo
00225   *coder_semaphore = (SemaphoreInfo *) NULL;
00226 
00227 static SplayTreeInfo
00228   *coder_list = (SplayTreeInfo *) NULL;
00229 
00230 static volatile MagickBooleanType
00231   instantiate_coder = MagickFalse;
00232 
00233 /*
00234   Forward declarations.
00235 */
00236 static MagickBooleanType
00237   InitializeCoderList(ExceptionInfo *),
00238   LoadCoderLists(const char *,ExceptionInfo *);
00239 
00240 /*
00241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00242 %                                                                             %
00243 %                                                                             %
00244 %                                                                             %
00245 +   C o d e r C o m p o n e n t G e n e s i s                                 %
00246 %                                                                             %
00247 %                                                                             %
00248 %                                                                             %
00249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00250 %
00251 %  CoderComponentGenesis() instantiates the coder component.
00252 %
00253 %  The format of the CoderComponentGenesis method is:
00254 %
00255 %      MagickBooleanType CoderComponentGenesis(void)
00256 %
00257 */
00258 MagickPrivate MagickBooleanType CoderComponentGenesis(void)
00259 {
00260   AcquireSemaphoreInfo(&coder_semaphore);
00261   return(MagickTrue);
00262 }
00263 
00264 /*
00265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00266 %                                                                             %
00267 %                                                                             %
00268 %                                                                             %
00269 +   C o d e r C o m p o n e n t T e r m i n u s                               %
00270 %                                                                             %
00271 %                                                                             %
00272 %                                                                             %
00273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00274 %
00275 %  CoderComponentTerminus() destroys the coder component.
00276 %
00277 %  The format of the CoderComponentTerminus method is:
00278 %
00279 %      CoderComponentTerminus(void)
00280 %
00281 */
00282 MagickPrivate void CoderComponentTerminus(void)
00283 {
00284   if (coder_semaphore == (SemaphoreInfo *) NULL)
00285     AcquireSemaphoreInfo(&coder_semaphore);
00286   LockSemaphoreInfo(coder_semaphore);
00287   if (coder_list != (SplayTreeInfo *) NULL)
00288     coder_list=DestroySplayTree(coder_list);
00289   instantiate_coder=MagickFalse;
00290   UnlockSemaphoreInfo(coder_semaphore);
00291   DestroySemaphoreInfo(&coder_semaphore);
00292 }
00293 
00294 /*
00295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00296 %                                                                             %
00297 %                                                                             %
00298 %                                                                             %
00299 +   G e t C o d e r I n f o                                                   %
00300 %                                                                             %
00301 %                                                                             %
00302 %                                                                             %
00303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00304 %
00305 %  GetCoderInfo searches the coder list for the specified name and if found
00306 %  returns attributes for that coder.
00307 %
00308 %  The format of the GetCoderInfo method is:
00309 %
00310 %      const CoderInfo *GetCoderInfo(const char *name,ExceptionInfo *exception)
00311 %
00312 %  A description of each parameter follows:
00313 %
00314 %    o name: the coder name.
00315 %
00316 %    o exception: return any errors or warnings in this structure.
00317 %
00318 */
00319 MagickExport const CoderInfo *GetCoderInfo(const char *name,
00320   ExceptionInfo *exception)
00321 {
00322   assert(exception != (ExceptionInfo *) NULL);
00323   if ((coder_list == (SplayTreeInfo *) NULL) ||
00324       (instantiate_coder == MagickFalse))
00325     if (InitializeCoderList(exception) == MagickFalse)
00326       return((const CoderInfo *) NULL);
00327   if ((coder_list == (SplayTreeInfo *) NULL) ||
00328       (GetNumberOfNodesInSplayTree(coder_list) == 0))
00329     return((const CoderInfo *) NULL);
00330   if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
00331     {
00332       ResetSplayTreeIterator(coder_list);
00333       return((const CoderInfo *) GetNextValueInSplayTree(coder_list));
00334     }
00335   return((const CoderInfo *) GetValueFromSplayTree(coder_list,name));
00336 }
00337 
00338 /*
00339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00340 %                                                                             %
00341 %                                                                             %
00342 %                                                                             %
00343 %   G e t C o d e r I n f o L i s t                                           %
00344 %                                                                             %
00345 %                                                                             %
00346 %                                                                             %
00347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00348 %
00349 %  GetCoderInfoList() returns any coder_map that match the specified pattern.
00350 %  The format of the GetCoderInfoList function is:
00351 %
00352 %      const CoderInfo **GetCoderInfoList(const char *pattern,
00353 %        size_t *number_coders,ExceptionInfo *exception)
00354 %
00355 %  A description of each parameter follows:
00356 %
00357 %    o pattern: Specifies a pointer to a text string containing a pattern.
00358 %
00359 %    o number_coders:  This integer returns the number of coders in the list.
00360 %
00361 %    o exception: return any errors or warnings in this structure.
00362 %
00363 */
00364 
00365 static int CoderInfoCompare(const void *x,const void *y)
00366 {
00367   const CoderInfo
00368     **p,
00369     **q;
00370 
00371   p=(const CoderInfo **) x,
00372   q=(const CoderInfo **) y;
00373   if (LocaleCompare((*p)->path,(*q)->path) == 0)
00374     return(LocaleCompare((*p)->name,(*q)->name));
00375   return(LocaleCompare((*p)->path,(*q)->path));
00376 }
00377 
00378 MagickExport const CoderInfo **GetCoderInfoList(const char *pattern,
00379   size_t *number_coders,ExceptionInfo *exception)
00380 {
00381   const CoderInfo
00382     **coder_map;
00383 
00384   register const CoderInfo
00385     *p;
00386 
00387   register ssize_t
00388     i;
00389 
00390   /*
00391     Allocate coder list.
00392   */
00393   assert(pattern != (char *) NULL);
00394   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00395   assert(number_coders != (size_t *) NULL);
00396   *number_coders=0;
00397   p=GetCoderInfo("*",exception);
00398   if (p == (const CoderInfo *) NULL)
00399     return((const CoderInfo **) NULL);
00400   coder_map=(const CoderInfo **) AcquireQuantumMemory((size_t)
00401     GetNumberOfNodesInSplayTree(coder_list)+1UL,sizeof(*coder_map));
00402   if (coder_map == (const CoderInfo **) NULL)
00403     return((const CoderInfo **) NULL);
00404   /*
00405     Generate coder list.
00406   */
00407   LockSemaphoreInfo(coder_semaphore);
00408   ResetSplayTreeIterator(coder_list);
00409   p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
00410   for (i=0; p != (const CoderInfo *) NULL; )
00411   {
00412     if ((p->stealth == MagickFalse) &&
00413         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
00414       coder_map[i++]=p;
00415     p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
00416   }
00417   UnlockSemaphoreInfo(coder_semaphore);
00418   qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderInfoCompare);
00419   coder_map[i]=(CoderInfo *) NULL;
00420   *number_coders=(size_t) i;
00421   return(coder_map);
00422 }
00423 
00424 /*
00425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00426 %                                                                             %
00427 %                                                                             %
00428 %                                                                             %
00429 %   G e t C o d e r L i s t                                                   %
00430 %                                                                             %
00431 %                                                                             %
00432 %                                                                             %
00433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00434 %
00435 %  GetCoderList() returns any coder_map that match the specified pattern.
00436 %
00437 %  The format of the GetCoderList function is:
00438 %
00439 %      char **GetCoderList(const char *pattern,size_t *number_coders,
00440 %        ExceptionInfo *exception)
00441 %
00442 %  A description of each parameter follows:
00443 %
00444 %    o pattern: Specifies a pointer to a text string containing a pattern.
00445 %
00446 %    o number_coders:  This integer returns the number of coders in the list.
00447 %
00448 %    o exception: return any errors or warnings in this structure.
00449 %
00450 */
00451 
00452 static int CoderCompare(const void *x,const void *y)
00453 {
00454   register const char
00455     **p,
00456     **q;
00457 
00458   p=(const char **) x;
00459   q=(const char **) y;
00460   return(LocaleCompare(*p,*q));
00461 }
00462 
00463 MagickExport char **GetCoderList(const char *pattern,
00464   size_t *number_coders,ExceptionInfo *exception)
00465 {
00466   char
00467     **coder_map;
00468 
00469   register const CoderInfo
00470     *p;
00471 
00472   register ssize_t
00473     i;
00474 
00475   /*
00476     Allocate coder list.
00477   */
00478   assert(pattern != (char *) NULL);
00479   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00480   assert(number_coders != (size_t *) NULL);
00481   *number_coders=0;
00482   p=GetCoderInfo("*",exception);
00483   if (p == (const CoderInfo *) NULL)
00484     return((char **) NULL);
00485   coder_map=(char **) AcquireQuantumMemory((size_t)
00486     GetNumberOfNodesInSplayTree(coder_list)+1UL,sizeof(*coder_map));
00487   if (coder_map == (char **) NULL)
00488     return((char **) NULL);
00489   /*
00490     Generate coder list.
00491   */
00492   LockSemaphoreInfo(coder_semaphore);
00493   ResetSplayTreeIterator(coder_list);
00494   p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
00495   for (i=0; p != (const CoderInfo *) NULL; )
00496   {
00497     if ((p->stealth == MagickFalse) &&
00498         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
00499       coder_map[i++]=ConstantString(p->name);
00500     p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
00501   }
00502   UnlockSemaphoreInfo(coder_semaphore);
00503   qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderCompare);
00504   coder_map[i]=(char *) NULL;
00505   *number_coders=(size_t) i;
00506   return(coder_map);
00507 }
00508 
00509 /*
00510 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00511 %                                                                             %
00512 %                                                                             %
00513 %                                                                             %
00514 +   I n i t i a l i z e C o d e r L i s t                                     %
00515 %                                                                             %
00516 %                                                                             %
00517 %                                                                             %
00518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00519 %
00520 %  InitializeCoderList() initializes the coder list.
00521 %
00522 %  The format of the InitializeCoderList method is:
00523 %
00524 %      MagickBooleanType InitializeCoderList(ExceptionInfo *exception)
00525 %
00526 %  A description of each parameter follows.
00527 %
00528 %    o exception: return any errors or warnings in this structure.
00529 %
00530 */
00531 static MagickBooleanType InitializeCoderList(ExceptionInfo *exception)
00532 {
00533   if ((coder_list == (SplayTreeInfo *) NULL) &&
00534       (instantiate_coder == MagickFalse))
00535     {
00536       if (coder_semaphore == (SemaphoreInfo *) NULL)
00537         AcquireSemaphoreInfo(&coder_semaphore);
00538       LockSemaphoreInfo(coder_semaphore);
00539       if ((coder_list == (SplayTreeInfo *) NULL) &&
00540           (instantiate_coder == MagickFalse))
00541         {
00542           (void) LoadCoderLists(MagickCoderFilename,exception);
00543           instantiate_coder=MagickTrue;
00544         }
00545       UnlockSemaphoreInfo(coder_semaphore);
00546     }
00547   return(coder_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
00548 }
00549 
00550 /*
00551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00552 %                                                                             %
00553 %                                                                             %
00554 %                                                                             %
00555 %  L i s t C o d e r I n f o                                                  %
00556 %                                                                             %
00557 %                                                                             %
00558 %                                                                             %
00559 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00560 %
00561 %  ListCoderInfo() lists the coder info to a file.
00562 %
00563 %  The format of the ListCoderInfo coder is:
00564 %
00565 %      MagickBooleanType ListCoderInfo(FILE *file,ExceptionInfo *exception)
00566 %
00567 %  A description of each parameter follows.
00568 %
00569 %    o file:  An pointer to a FILE.
00570 %
00571 %    o exception: return any errors or warnings in this structure.
00572 %
00573 */
00574 MagickExport MagickBooleanType ListCoderInfo(FILE *file,
00575   ExceptionInfo *exception)
00576 {
00577   const char
00578     *path;
00579 
00580   const CoderInfo
00581     **coder_info;
00582 
00583   register ssize_t
00584     i;
00585 
00586   size_t
00587     number_coders;
00588 
00589   ssize_t
00590     j;
00591 
00592   if (file == (const FILE *) NULL)
00593     file=stdout;
00594   coder_info=GetCoderInfoList("*",&number_coders,exception);
00595   if (coder_info == (const CoderInfo **) NULL)
00596     return(MagickFalse);
00597   path=(const char *) NULL;
00598   for (i=0; i < (ssize_t) number_coders; i++)
00599   {
00600     if (coder_info[i]->stealth != MagickFalse)
00601       continue;
00602     if ((path == (const char *) NULL) ||
00603         (LocaleCompare(path,coder_info[i]->path) != 0))
00604       {
00605         if (coder_info[i]->path != (char *) NULL)
00606           (void) FormatLocaleFile(file,"\nPath: %s\n\n",coder_info[i]->path);
00607         (void) FormatLocaleFile(file,"Magick      Coder\n");
00608         (void) FormatLocaleFile(file,
00609           "-------------------------------------------------"
00610           "------------------------------\n");
00611       }
00612     path=coder_info[i]->path;
00613     (void) FormatLocaleFile(file,"%s",coder_info[i]->magick);
00614     for (j=(ssize_t) strlen(coder_info[i]->magick); j <= 11; j++)
00615       (void) FormatLocaleFile(file," ");
00616     if (coder_info[i]->name != (char *) NULL)
00617       (void) FormatLocaleFile(file,"%s",coder_info[i]->name);
00618     (void) FormatLocaleFile(file,"\n");
00619   }
00620   coder_info=(const CoderInfo **) RelinquishMagickMemory((void *) coder_info);
00621   (void) fflush(file);
00622   return(MagickTrue);
00623 }
00624 
00625 /*
00626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00627 %                                                                             %
00628 %                                                                             %
00629 %                                                                             %
00630 +   L o a d C o d e r L i s t                                                 %
00631 %                                                                             %
00632 %                                                                             %
00633 %                                                                             %
00634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00635 %
00636 %  LoadCoderList() loads the coder configuration file which provides a
00637 %  mapping between coder attributes and a coder name.
00638 %
00639 %  The format of the LoadCoderList coder is:
00640 %
00641 %      MagickBooleanType LoadCoderList(const char *xml,const char *filename,
00642 %        const size_t depth,ExceptionInfo *exception)
00643 %
00644 %  A description of each parameter follows:
00645 %
00646 %    o xml:  The coder list in XML format.
00647 %
00648 %    o filename:  The coder list filename.
00649 %
00650 %    o depth: depth of <include /> statements.
00651 %
00652 %    o exception: return any errors or warnings in this structure.
00653 %
00654 */
00655 
00656 static void *DestroyCoderNode(void *coder_info)
00657 {
00658   register CoderInfo
00659     *p;
00660 
00661   p=(CoderInfo *) coder_info;
00662   if (p->exempt == MagickFalse)
00663     {
00664       if (p->path != (char *) NULL)
00665         p->path=DestroyString(p->path);
00666       if (p->name != (char *) NULL)
00667         p->name=DestroyString(p->name);
00668       if (p->magick != (char *) NULL)
00669         p->magick=DestroyString(p->magick);
00670     }
00671   return(RelinquishMagickMemory(p));
00672 }
00673 
00674 static MagickBooleanType LoadCoderList(const char *xml,const char *filename,
00675   const size_t depth,ExceptionInfo *exception)
00676 {
00677   char
00678     keyword[MaxTextExtent],
00679     *token;
00680 
00681   const char
00682     *q;
00683 
00684   CoderInfo
00685     *coder_info;
00686 
00687   MagickBooleanType
00688     status;
00689 
00690   /*
00691     Load the coder map file.
00692   */
00693   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
00694     "Loading coder configuration file \"%s\" ...",filename);
00695   if (xml == (const char *) NULL)
00696     return(MagickFalse);
00697   if (coder_list == (SplayTreeInfo *) NULL)
00698     {
00699       coder_list=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
00700         DestroyCoderNode);
00701       if (coder_list == (SplayTreeInfo *) NULL)
00702         {
00703           ThrowFileException(exception,ResourceLimitError,
00704             "MemoryAllocationFailed",filename);
00705           return(MagickFalse);
00706         }
00707     }
00708   status=MagickTrue;
00709   coder_info=(CoderInfo *) NULL;
00710   token=AcquireString(xml);
00711   for (q=(char *) xml; *q != '\0'; )
00712   {
00713     /*
00714       Interpret XML.
00715     */
00716     GetMagickToken(q,&q,token);
00717     if (*token == '\0')
00718       break;
00719     (void) CopyMagickString(keyword,token,MaxTextExtent);
00720     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
00721       {
00722         /*
00723           Doctype element.
00724         */
00725         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
00726           GetMagickToken(q,&q,token);
00727         continue;
00728       }
00729     if (LocaleNCompare(keyword,"<!--",4) == 0)
00730       {
00731         /*
00732           Comment element.
00733         */
00734         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
00735           GetMagickToken(q,&q,token);
00736         continue;
00737       }
00738     if (LocaleCompare(keyword,"<include") == 0)
00739       {
00740         /*
00741           Include element.
00742         */
00743         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
00744         {
00745           (void) CopyMagickString(keyword,token,MaxTextExtent);
00746           GetMagickToken(q,&q,token);
00747           if (*token != '=')
00748             continue;
00749           GetMagickToken(q,&q,token);
00750           if (LocaleCompare(keyword,"file") == 0)
00751             {
00752               if (depth > 200)
00753                 (void) ThrowMagickException(exception,GetMagickModule(),
00754                   ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token);
00755               else
00756                 {
00757                   char
00758                     path[MaxTextExtent],
00759                     *xml;
00760 
00761                   GetPathComponent(filename,HeadPath,path);
00762                   if (*path != '\0')
00763                     (void) ConcatenateMagickString(path,DirectorySeparator,
00764                       MaxTextExtent);
00765                   if (*token == *DirectorySeparator)
00766                     (void) CopyMagickString(path,token,MaxTextExtent);
00767                   else
00768                     (void) ConcatenateMagickString(path,token,MaxTextExtent);
00769                   xml=FileToString(path,~0,exception);
00770                   if (xml != (char *) NULL)
00771                     {
00772                       status=LoadCoderList(xml,path,depth+1,exception);
00773                       xml=(char *) RelinquishMagickMemory(xml);
00774                     }
00775                 }
00776             }
00777         }
00778         continue;
00779       }
00780     if (LocaleCompare(keyword,"<coder") == 0)
00781       {
00782         /*
00783           Coder element.
00784         */
00785         coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info));
00786         if (coder_info == (CoderInfo *) NULL)
00787           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00788         (void) ResetMagickMemory(coder_info,0,sizeof(*coder_info));
00789         coder_info->path=ConstantString(filename);
00790         coder_info->exempt=MagickFalse;
00791         coder_info->signature=MagickSignature;
00792         continue;
00793       }
00794     if (coder_info == (CoderInfo *) NULL)
00795       continue;
00796     if (LocaleCompare(keyword,"/>") == 0)
00797       {
00798         status=AddValueToSplayTree(coder_list,ConstantString(
00799           coder_info->magick),coder_info);
00800         if (status == MagickFalse)
00801           (void) ThrowMagickException(exception,GetMagickModule(),
00802             ResourceLimitError,"MemoryAllocationFailed","`%s'",
00803             coder_info->magick);
00804         coder_info=(CoderInfo *) NULL;
00805       }
00806     GetMagickToken(q,(const char **) NULL,token);
00807     if (*token != '=')
00808       continue;
00809     GetMagickToken(q,&q,token);
00810     GetMagickToken(q,&q,token);
00811     switch (*keyword)
00812     {
00813       case 'M':
00814       case 'm':
00815       {
00816         if (LocaleCompare((char *) keyword,"magick") == 0)
00817           {
00818             coder_info->magick=ConstantString(token);
00819             break;
00820           }
00821         break;
00822       }
00823       case 'N':
00824       case 'n':
00825       {
00826         if (LocaleCompare((char *) keyword,"name") == 0)
00827           {
00828             coder_info->name=ConstantString(token);
00829             break;
00830           }
00831         break;
00832       }
00833       case 'S':
00834       case 's':
00835       {
00836         if (LocaleCompare((char *) keyword,"stealth") == 0)
00837           {
00838             coder_info->stealth=IsMagickTrue(token);
00839             break;
00840           }
00841         break;
00842       }
00843       default:
00844         break;
00845     }
00846   }
00847   token=(char *) RelinquishMagickMemory(token);
00848   return(status);
00849 }
00850 
00851 /*
00852 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00853 %                                                                             %
00854 %                                                                             %
00855 %                                                                             %
00856 %  L o a d C o d e r L i s t s                                                %
00857 %                                                                             %
00858 %                                                                             %
00859 %                                                                             %
00860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00861 %
00862 %  LoadCoderLists() loads one or more coder configuration file which
00863 %  provides a mapping between coder attributes and a coder name.
00864 %
00865 %  The format of the LoadCoderLists coder is:
00866 %
00867 %      MagickBooleanType LoadCoderLists(const char *filename,
00868 %        ExceptionInfo *exception)
00869 %
00870 %  A description of each parameter follows:
00871 %
00872 %    o filename: the font file name.
00873 %
00874 %    o exception: return any errors or warnings in this structure.
00875 %
00876 */
00877 static MagickBooleanType LoadCoderLists(const char *filename,
00878   ExceptionInfo *exception)
00879 {
00880   const StringInfo
00881     *option;
00882 
00883   LinkedListInfo
00884     *options;
00885 
00886   MagickStatusType
00887     status;
00888 
00889   register ssize_t
00890     i;
00891 
00892   /*
00893     Load built-in coder map.
00894   */
00895   status=MagickFalse;
00896   if (coder_list == (SplayTreeInfo *) NULL)
00897     {
00898       coder_list=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
00899         DestroyCoderNode);
00900       if (coder_list == (SplayTreeInfo *) NULL)
00901         {
00902           ThrowFileException(exception,ResourceLimitError,
00903             "MemoryAllocationFailed",filename);
00904           return(MagickFalse);
00905         }
00906     }
00907   for (i=0; i < (ssize_t) (sizeof(CoderMap)/sizeof(*CoderMap)); i++)
00908   {
00909     CoderInfo
00910       *coder_info;
00911 
00912     register const CoderMapInfo
00913       *p;
00914 
00915     p=CoderMap+i;
00916     coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info));
00917     if (coder_info == (CoderInfo *) NULL)
00918       {
00919         (void) ThrowMagickException(exception,GetMagickModule(),
00920           ResourceLimitError,"MemoryAllocationFailed","`%s'",coder_info->name);
00921         continue;
00922       }
00923     (void) ResetMagickMemory(coder_info,0,sizeof(*coder_info));
00924     coder_info->path=(char *) "[built-in]";
00925     coder_info->magick=(char *) p->magick;
00926     coder_info->name=(char *) p->name;
00927     coder_info->exempt=MagickTrue;
00928     coder_info->signature=MagickSignature;
00929     status=AddValueToSplayTree(coder_list,ConstantString(coder_info->magick),
00930       coder_info);
00931     if (status == MagickFalse)
00932       (void) ThrowMagickException(exception,GetMagickModule(),
00933         ResourceLimitError,"MemoryAllocationFailed","`%s'",coder_info->name);
00934   }
00935   /*
00936     Load external coder map.
00937   */
00938   options=GetConfigureOptions(filename,exception);
00939   option=(const StringInfo *) GetNextValueInLinkedList(options);
00940   while (option != (const StringInfo *) NULL)
00941   {
00942     status|=LoadCoderList((const char *) GetStringInfoDatum(option),
00943       GetStringInfoPath(option),0,exception);
00944     option=(const StringInfo *) GetNextValueInLinkedList(options);
00945   }
00946   options=DestroyConfigureOptions(options);
00947   return(status != 0 ? MagickTrue : MagickFalse);
00948 }