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% Cristy % 17% May 2001 % 18% % 19% % 20% Copyright 1999-2016 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 39/* 40 Include declarations. 41*/ 42#include "MagickCore/studio.h" 43#include "MagickCore/blob.h" 44#include "MagickCore/client.h" 45#include "MagickCore/coder.h" 46#include "MagickCore/coder-private.h" 47#include "MagickCore/configure.h" 48#include "MagickCore/draw.h" 49#include "MagickCore/exception.h" 50#include "MagickCore/exception-private.h" 51#include "MagickCore/linked-list.h" 52#include "MagickCore/log.h" 53#include "MagickCore/memory_.h" 54#include "MagickCore/option.h" 55#include "MagickCore/semaphore.h" 56#include "MagickCore/string_.h" 57#include "MagickCore/splay-tree.h" 58#include "MagickCore/token.h" 59#include "MagickCore/utility.h" 60#include "MagickCore/utility-private.h" 61#include "MagickCore/xml-tree.h" 62#include "MagickCore/xml-tree-private.h" 63 64/* 65 Define declarations. 66*/ 67#define MagickCoderFilename "coder.xml" 68 69/* 70 Typedef declarations. 71*/ 72typedef struct _CoderMapInfo 73{ 74 const char 75 *magick, 76 *name; 77} CoderMapInfo; 78 79/* 80 Static declarations. 81*/ 82static const CoderMapInfo 83 CoderMap[] = 84 { 85 { "3FR", "DNG" }, 86 { "8BIM", "META" }, 87 { "8BIMTEXT", "META" }, 88 { "8BIMWTEXT", "META" }, 89 { "AFM", "TTF" }, 90 { "A", "RAW" }, 91 { "AI", "PDF" }, 92 { "APP1JPEG", "META" }, 93 { "APP1", "META" }, 94 { "ARW", "DNG" }, 95 { "AVI", "MPEG" }, 96 { "BIE", "JBIG" }, 97 { "BMP2", "BMP" }, 98 { "BMP3", "BMP" }, 99 { "B", "RAW" }, 100 { "BRF", "BRAILLE" }, 101 { "BGRA", "BGR" }, 102 { "BGRO", "BGR" }, 103 { "CMYKA", "CMYK" }, 104 { "C", "RAW" }, 105 { "CAL", "CALS" }, 106 { "CANVAS", "XC" }, 107 { "CMYKA", "CMYK" }, 108 { "CR2", "DNG" }, 109 { "CRW", "DNG" }, 110 { "CUR", "ICON" }, 111 { "DATA", "INLINE" }, 112 { "DCR", "DNG" }, 113 { "DCX", "PCX" }, 114 { "DFONT", "TTF" }, 115 { "DXT1", "DDS" }, 116 { "DXT5", "DDS" }, 117 { "EPDF", "PDF" }, 118 { "EPI", "PS" }, 119 { "EPS2", "PS2" }, 120 { "EPS3", "PS3" }, 121 { "EPSF", "PS" }, 122 { "EPSI", "PS" }, 123 { "EPS", "PS" }, 124 { "EPT2", "EPT" }, 125 { "EPT3", "EPT" }, 126 { "ERF", "DNG" }, 127 { "EXIF", "META" }, 128 { "FILE", "URL" }, 129 { "FRACTAL", "PLASMA" }, 130 { "FTP", "URL" }, 131 { "FTS", "FITS" }, 132 { "G3", "FAX" }, 133 { "G4", "FAX" }, 134 { "GIF87", "GIF" }, 135 { "G", "RAW" }, 136 { "GRANITE", "MAGICK" }, 137 { "GROUP4", "TIFF" }, 138 { "GV", "DOT" }, 139 { "HTM", "HTML" }, 140 { "ICB", "TGA" }, 141 { "ICO", "ICON" }, 142 { "IIQ", "DNG" }, 143 { "K25", "DNG" }, 144 { "KDC", "DNG" }, 145 { "H", "MAGICK" }, 146 { "HTM", "HTML" }, 147 { "HTTP", "URL" }, 148 { "HTTPS", "URL" }, 149 { "ICB", "TGA" }, 150 { "ICC", "META" }, 151 { "ICM", "META" }, 152 { "ICO", "ICON" }, 153 { "IMPLICIT", "***" }, 154 { "IPTC", "META" }, 155 { "IPTCTEXT", "META" }, 156 { "IPTCWTEXT", "META" }, 157 { "ISOBRL", "BRAILLE" }, 158 { "ISOBRL6", "BRAILLE" }, 159 { "JBG", "JBIG" }, 160 { "JNG", "PNG" }, 161 { "JPC", "JP2" }, 162 { "JPT", "JP2" }, 163 { "JPM", "JP2" }, 164 { "J2C", "JP2" }, 165 { "J2K", "JP2" }, 166 { "JNG", "PNG" }, 167 { "JPE", "JPEG" }, 168 { "JPG", "JPEG" }, 169 { "JPM", "JP2" }, 170 { "JPS", "JPEG" }, 171 { "JPT", "JP2" }, 172 { "JPX", "JP2" }, 173 { "K", "RAW" }, 174 { "K25", "DNG" }, 175 { "KDC", "DNG" }, 176 { "LOGO", "MAGICK" }, 177 { "M", "RAW" }, 178 { "M2V", "MPEG" }, 179 { "M4V", "MPEG" }, 180 { "MEF", "DNG" }, 181 { "MKV", "MPEG" }, 182 { "MNG", "PNG" }, 183 { "MOV", "MPEG" }, 184 { "MP4", "MPEG" }, 185 { "MPG", "MPEG" }, 186 { "MPRI", "MPR" }, 187 { "MEF", "DNG" }, 188 { "MRW", "DNG" }, 189 { "MSVG", "SVG" }, 190 { "NEF", "DNG" }, 191 { "NETSCAPE", "MAGICK" }, 192 { "NRW", "DNG" }, 193 { "O", "RAW" }, 194 { "ORF", "DNG" }, 195 { "OTF", "TTF" }, 196 { "P7", "PNM" }, 197 { "PAL", "UYVY" }, 198 { "PAM", "PNM" }, 199 { "PBM", "PNM" }, 200 { "PCDS", "PCD" }, 201 { "PCT", "PICT" }, 202 { "PDFA", "PDF" }, 203 { "PEF", "DNG" }, 204 { "PEF", "DNG" }, 205 { "PFA", "TTF" }, 206 { "PFB", "TTF" }, 207 { "PFM", "PNM" }, 208 { "PGM", "PNM" }, 209 { "PGX", "JP2" }, 210 { "PICON", "XPM" }, 211 { "PJPEG", "JPEG" }, 212 { "PM", "XPM" }, 213 { "PNG00", "PNG" }, 214 { "PNG24", "PNG" }, 215 { "PNG32", "PNG" }, 216 { "PNG48", "PNG" }, 217 { "PNG64", "PNG" }, 218 { "PNG8", "PNG" }, 219 { "PPM", "PNM" }, 220 { "PSB", "PSD" }, 221 { "PTIF", "TIFF" }, 222 { "R", "RAW" }, 223 { "RADIAL-GRADIENT", "GRADIENT" }, 224 { "RAF", "DNG" }, 225 { "RAS", "SUN" }, 226 { "RAW", "DNG" }, 227 { "RGBA", "RGB" }, 228 { "RGBO", "RGB" }, 229 { "RMF", "DNG" }, 230 { "ROSE", "MAGICK" }, 231 { "RW2", "DNG" }, 232 { "SHTML", "HTML" }, 233 { "SIX", "SIXEL" }, 234 { "SPARSE-COLOR", "TXT" }, 235 { "SR2", "DNG" }, 236 { "SRF", "DNG" }, 237 { "SVGZ", "SVG" }, 238 { "TEXT", "TXT" }, 239 { "TIFF64", "TIFF" }, 240 { "TIF", "TIFF" }, 241 { "TTC", "TTF" }, 242 { "UBRL", "BRAILLE" }, 243 { "UBRL6", "BRAILLE" }, 244 { "VDA", "TGA" }, 245 { "VST", "TGA" }, 246 { "WIZARD", "MAGICK" }, 247#if defined(MAGICKCORE_WINGDI32_DELEGATE) 248 { "WMF", "EMF" }, 249#endif 250 { "WMV", "MPEG" }, 251 { "WMZ", "WMF" }, 252 { "X3f", "DNG" }, 253 { "XMP", "META" }, 254 { "XTRNARRAY", "XTRN" }, 255 { "XTRNBLOB", "XTRN" }, 256 { "XTRNFILE", "XTRN" }, 257 { "XTRNIMAGE", "XTRN" }, 258 { "XV", "VIFF" }, 259 { "Y", "RAW" }, 260 { "YCbCrA", "YCbCr" } 261 }; 262 263static SemaphoreInfo 264 *coder_semaphore = (SemaphoreInfo *) NULL; 265 266static SplayTreeInfo 267 *coder_cache = (SplayTreeInfo *) NULL; 268 269/* 270 Forward declarations. 271*/ 272static MagickBooleanType 273 IsCoderTreeInstantiated(ExceptionInfo *), 274 LoadCoderCache(SplayTreeInfo *,const char *,const char *,const size_t, 275 ExceptionInfo *); 276 277/* 278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 279% % 280% % 281% % 282+ A c q u i r e C o d e r C a c h e % 283% % 284% % 285% % 286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 287% 288% AcquireCoderCache() caches one or more coder configurations which provides a 289% mapping between coder attributes and a coder name. 290% 291% The format of the AcquireCoderCache coder is: 292% 293% SplayTreeInfo *AcquireCoderCache(const char *filename, 294% ExceptionInfo *exception) 295% 296% A description of each parameter follows: 297% 298% o filename: the font file name. 299% 300% o exception: return any errors or warnings in this structure. 301% 302*/ 303 304static void *DestroyCoderNode(void *coder_info) 305{ 306 register CoderInfo 307 *p; 308 309 p=(CoderInfo *) coder_info; 310 if (p->exempt == MagickFalse) 311 { 312 if (p->path != (char *) NULL) 313 p->path=DestroyString(p->path); 314 if (p->name != (char *) NULL) 315 p->name=DestroyString(p->name); 316 if (p->magick != (char *) NULL) 317 p->magick=DestroyString(p->magick); 318 } 319 return(RelinquishMagickMemory(p)); 320} 321 322static SplayTreeInfo *AcquireCoderCache(const char *filename, 323 ExceptionInfo *exception) 324{ 325 MagickStatusType 326 status; 327 328 register ssize_t 329 i; 330 331 SplayTreeInfo 332 *cache; 333 334 /* 335 Load external coder map. 336 */ 337 cache=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory, 338 DestroyCoderNode); 339 if (cache == (SplayTreeInfo *) NULL) 340 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 341 status=MagickTrue; 342#if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT) 343 { 344 const StringInfo 345 *option; 346 347 LinkedListInfo 348 *options; 349 350 options=GetConfigureOptions(filename,exception); 351 option=(const StringInfo *) GetNextValueInLinkedList(options); 352 while (option != (const StringInfo *) NULL) 353 { 354 status&=LoadCoderCache(cache,(const char *) GetStringInfoDatum(option), 355 GetStringInfoPath(option),0,exception); 356 option=(const StringInfo *) GetNextValueInLinkedList(options); 357 } 358 options=DestroyConfigureOptions(options); 359 } 360#endif 361 /* 362 Load built-in coder map. 363 */ 364 for (i=0; i < (ssize_t) (sizeof(CoderMap)/sizeof(*CoderMap)); i++) 365 { 366 CoderInfo 367 *coder_info; 368 369 register const CoderMapInfo 370 *p; 371 372 p=CoderMap+i; 373 coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info)); 374 if (coder_info == (CoderInfo *) NULL) 375 { 376 (void) ThrowMagickException(exception,GetMagickModule(), 377 ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name); 378 continue; 379 } 380 (void) ResetMagickMemory(coder_info,0,sizeof(*coder_info)); 381 coder_info->path=(char *) "[built-in]"; 382 coder_info->magick=(char *) p->magick; 383 coder_info->name=(char *) p->name; 384 coder_info->exempt=MagickTrue; 385 coder_info->signature=MagickCoreSignature; 386 status&=AddValueToSplayTree(cache,ConstantString(coder_info->magick), 387 coder_info); 388 if (status == MagickFalse) 389 (void) ThrowMagickException(exception,GetMagickModule(), 390 ResourceLimitError,"MemoryAllocationFailed","`%s'",coder_info->name); 391 } 392 return(cache); 393} 394 395/* 396%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 397% % 398% % 399% % 400+ C o d e r C o m p o n e n t G e n e s i s % 401% % 402% % 403% % 404%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 405% 406% CoderComponentGenesis() instantiates the coder component. 407% 408% The format of the CoderComponentGenesis method is: 409% 410% MagickBooleanType CoderComponentGenesis(void) 411% 412*/ 413MagickPrivate MagickBooleanType CoderComponentGenesis(void) 414{ 415 if (coder_semaphore == (SemaphoreInfo *) NULL) 416 coder_semaphore=AcquireSemaphoreInfo(); 417 return(MagickTrue); 418} 419 420/* 421%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 422% % 423% % 424% % 425+ C o d e r C o m p o n e n t T e r m i n u s % 426% % 427% % 428% % 429%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 430% 431% CoderComponentTerminus() destroys the coder component. 432% 433% The format of the CoderComponentTerminus method is: 434% 435% CoderComponentTerminus(void) 436% 437*/ 438MagickPrivate void CoderComponentTerminus(void) 439{ 440 if (coder_semaphore == (SemaphoreInfo *) NULL) 441 ActivateSemaphoreInfo(&coder_semaphore); 442 LockSemaphoreInfo(coder_semaphore); 443 if (coder_cache != (SplayTreeInfo *) NULL) 444 coder_cache=DestroySplayTree(coder_cache); 445 UnlockSemaphoreInfo(coder_semaphore); 446 RelinquishSemaphoreInfo(&coder_semaphore); 447} 448 449/* 450%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 451% % 452% % 453% % 454+ G e t C o d e r I n f o % 455% % 456% % 457% % 458%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 459% 460% GetCoderInfo searches the coder list for the specified name and if found 461% returns attributes for that coder. 462% 463% The format of the GetCoderInfo method is: 464% 465% const CoderInfo *GetCoderInfo(const char *name,ExceptionInfo *exception) 466% 467% A description of each parameter follows: 468% 469% o name: the coder name. 470% 471% o exception: return any errors or warnings in this structure. 472% 473*/ 474MagickExport const CoderInfo *GetCoderInfo(const char *name, 475 ExceptionInfo *exception) 476{ 477 const CoderInfo 478 *coder_info; 479 480 assert(exception != (ExceptionInfo *) NULL); 481 if (IsCoderTreeInstantiated(exception) == MagickFalse) 482 return((const CoderInfo *) NULL); 483 LockSemaphoreInfo(coder_semaphore); 484 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0)) 485 { 486 ResetSplayTreeIterator(coder_cache); 487 coder_info=(const CoderInfo *) GetNextValueInSplayTree(coder_cache); 488 UnlockSemaphoreInfo(coder_semaphore); 489 return(coder_info); 490 } 491 coder_info=(const CoderInfo *) GetValueFromSplayTree(coder_cache,name); 492 UnlockSemaphoreInfo(coder_semaphore); 493 return(coder_info); 494} 495 496/* 497%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 498% % 499% % 500% % 501% G e t C o d e r I n f o L i s t % 502% % 503% % 504% % 505%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 506% 507% GetCoderInfoList() returns any coder_map that match the specified pattern. 508% The format of the GetCoderInfoList function is: 509% 510% const CoderInfo **GetCoderInfoList(const char *pattern, 511% size_t *number_coders,ExceptionInfo *exception) 512% 513% A description of each parameter follows: 514% 515% o pattern: Specifies a pointer to a text string containing a pattern. 516% 517% o number_coders: This integer returns the number of coders in the list. 518% 519% o exception: return any errors or warnings in this structure. 520% 521*/ 522 523static int CoderInfoCompare(const void *x,const void *y) 524{ 525 const CoderInfo 526 **p, 527 **q; 528 529 p=(const CoderInfo **) x, 530 q=(const CoderInfo **) y; 531 if (LocaleCompare((*p)->path,(*q)->path) == 0) 532 return(LocaleCompare((*p)->name,(*q)->name)); 533 return(LocaleCompare((*p)->path,(*q)->path)); 534} 535 536MagickExport const CoderInfo **GetCoderInfoList(const char *pattern, 537 size_t *number_coders,ExceptionInfo *exception) 538{ 539 const CoderInfo 540 **coder_map; 541 542 register const CoderInfo 543 *p; 544 545 register ssize_t 546 i; 547 548 /* 549 Allocate coder list. 550 */ 551 assert(pattern != (char *) NULL); 552 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern); 553 assert(number_coders != (size_t *) NULL); 554 *number_coders=0; 555 p=GetCoderInfo("*",exception); 556 if (p == (const CoderInfo *) NULL) 557 return((const CoderInfo **) NULL); 558 coder_map=(const CoderInfo **) AcquireQuantumMemory((size_t) 559 GetNumberOfNodesInSplayTree(coder_cache)+1UL,sizeof(*coder_map)); 560 if (coder_map == (const CoderInfo **) NULL) 561 return((const CoderInfo **) NULL); 562 /* 563 Generate coder list. 564 */ 565 LockSemaphoreInfo(coder_semaphore); 566 ResetSplayTreeIterator(coder_cache); 567 p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache); 568 for (i=0; p != (const CoderInfo *) NULL; ) 569 { 570 if ((p->stealth == MagickFalse) && 571 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse)) 572 coder_map[i++]=p; 573 p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache); 574 } 575 UnlockSemaphoreInfo(coder_semaphore); 576 qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderInfoCompare); 577 coder_map[i]=(CoderInfo *) NULL; 578 *number_coders=(size_t) i; 579 return(coder_map); 580} 581 582/* 583%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 584% % 585% % 586% % 587% G e t C o d e r L i s t % 588% % 589% % 590% % 591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 592% 593% GetCoderList() returns any coder_map that match the specified pattern. 594% 595% The format of the GetCoderList function is: 596% 597% char **GetCoderList(const char *pattern,size_t *number_coders, 598% ExceptionInfo *exception) 599% 600% A description of each parameter follows: 601% 602% o pattern: Specifies a pointer to a text string containing a pattern. 603% 604% o number_coders: This integer returns the number of coders in the list. 605% 606% o exception: return any errors or warnings in this structure. 607% 608*/ 609 610static int CoderCompare(const void *x,const void *y) 611{ 612 register const char 613 **p, 614 **q; 615 616 p=(const char **) x; 617 q=(const char **) y; 618 return(LocaleCompare(*p,*q)); 619} 620 621MagickExport char **GetCoderList(const char *pattern, 622 size_t *number_coders,ExceptionInfo *exception) 623{ 624 char 625 **coder_map; 626 627 register const CoderInfo 628 *p; 629 630 register ssize_t 631 i; 632 633 /* 634 Allocate coder list. 635 */ 636 assert(pattern != (char *) NULL); 637 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern); 638 assert(number_coders != (size_t *) NULL); 639 *number_coders=0; 640 p=GetCoderInfo("*",exception); 641 if (p == (const CoderInfo *) NULL) 642 return((char **) NULL); 643 coder_map=(char **) AcquireQuantumMemory((size_t) 644 GetNumberOfNodesInSplayTree(coder_cache)+1UL,sizeof(*coder_map)); 645 if (coder_map == (char **) NULL) 646 return((char **) NULL); 647 /* 648 Generate coder list. 649 */ 650 LockSemaphoreInfo(coder_semaphore); 651 ResetSplayTreeIterator(coder_cache); 652 p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache); 653 for (i=0; p != (const CoderInfo *) NULL; ) 654 { 655 if ((p->stealth == MagickFalse) && 656 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse)) 657 coder_map[i++]=ConstantString(p->name); 658 p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache); 659 } 660 UnlockSemaphoreInfo(coder_semaphore); 661 qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderCompare); 662 coder_map[i]=(char *) NULL; 663 *number_coders=(size_t) i; 664 return(coder_map); 665} 666 667/* 668%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 669% % 670% % 671% % 672+ I s C o d e r T r e e I n s t a n t i a t e d % 673% % 674% % 675% % 676%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 677% 678% IsCoderTreeInstantiated() determines if the coder tree is instantiated. If 679% not, it instantiates the tree and returns it. 680% 681% The format of the IsCoderInstantiated method is: 682% 683% MagickBooleanType IsCoderTreeInstantiated(ExceptionInfo *exception) 684% 685% A description of each parameter follows. 686% 687% o exception: return any errors or warnings in this structure. 688% 689*/ 690static MagickBooleanType IsCoderTreeInstantiated(ExceptionInfo *exception) 691{ 692 if (coder_cache == (SplayTreeInfo *) NULL) 693 { 694 if (coder_semaphore == (SemaphoreInfo *) NULL) 695 ActivateSemaphoreInfo(&coder_semaphore); 696 LockSemaphoreInfo(coder_semaphore); 697 if (coder_cache == (SplayTreeInfo *) NULL) 698 coder_cache=AcquireCoderCache(MagickCoderFilename,exception); 699 UnlockSemaphoreInfo(coder_semaphore); 700 } 701 return(coder_cache != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse); 702} 703 704/* 705%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 706% % 707% % 708% % 709% L i s t C o d e r I n f o % 710% % 711% % 712% % 713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 714% 715% ListCoderInfo() lists the coder info to a file. 716% 717% The format of the ListCoderInfo coder is: 718% 719% MagickBooleanType ListCoderInfo(FILE *file,ExceptionInfo *exception) 720% 721% A description of each parameter follows. 722% 723% o file: An pointer to a FILE. 724% 725% o exception: return any errors or warnings in this structure. 726% 727*/ 728MagickExport MagickBooleanType ListCoderInfo(FILE *file, 729 ExceptionInfo *exception) 730{ 731 const char 732 *path; 733 734 const CoderInfo 735 **coder_info; 736 737 register ssize_t 738 i; 739 740 size_t 741 number_coders; 742 743 ssize_t 744 j; 745 746 if (file == (const FILE *) NULL) 747 file=stdout; 748 coder_info=GetCoderInfoList("*",&number_coders,exception); 749 if (coder_info == (const CoderInfo **) NULL) 750 return(MagickFalse); 751 path=(const char *) NULL; 752 for (i=0; i < (ssize_t) number_coders; i++) 753 { 754 if (coder_info[i]->stealth != MagickFalse) 755 continue; 756 if ((path == (const char *) NULL) || 757 (LocaleCompare(path,coder_info[i]->path) != 0)) 758 { 759 if (coder_info[i]->path != (char *) NULL) 760 (void) FormatLocaleFile(file,"\nPath: %s\n\n",coder_info[i]->path); 761 (void) FormatLocaleFile(file,"Magick Coder\n"); 762 (void) FormatLocaleFile(file, 763 "-------------------------------------------------" 764 "------------------------------\n"); 765 } 766 path=coder_info[i]->path; 767 (void) FormatLocaleFile(file,"%s",coder_info[i]->magick); 768 for (j=(ssize_t) strlen(coder_info[i]->magick); j <= 11; j++) 769 (void) FormatLocaleFile(file," "); 770 if (coder_info[i]->name != (char *) NULL) 771 (void) FormatLocaleFile(file,"%s",coder_info[i]->name); 772 (void) FormatLocaleFile(file,"\n"); 773 } 774 coder_info=(const CoderInfo **) RelinquishMagickMemory((void *) coder_info); 775 (void) fflush(file); 776 return(MagickTrue); 777} 778 779/* 780%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 781% % 782% % 783% % 784+ L o a d C o d e r C a c h e % 785% % 786% % 787% % 788%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 789% 790% LoadCoderCache() loads the coder configurations which provides a 791% mapping between coder attributes and a coder name. 792% 793% The format of the LoadCoderCache coder is: 794% 795% MagickBooleanType LoadCoderCache(SplayTreeInfo *cache,const char *xml, 796% const char *filename,const size_t depth,ExceptionInfo *exception) 797% 798% A description of each parameter follows: 799% 800% o xml: The coder list in XML format. 801% 802% o filename: The coder list filename. 803% 804% o depth: depth of <include /> statements. 805% 806% o exception: return any errors or warnings in this structure. 807% 808*/ 809static MagickBooleanType LoadCoderCache(SplayTreeInfo *cache,const char *xml, 810 const char *filename,const size_t depth,ExceptionInfo *exception) 811{ 812 char 813 keyword[MagickPathExtent], 814 *token; 815 816 const char 817 *q; 818 819 CoderInfo 820 *coder_info; 821 822 MagickStatusType 823 status; 824 825 size_t 826 extent; 827 828 /* 829 Load the coder map file. 830 */ 831 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(), 832 "Loading coder configuration file \"%s\" ...",filename); 833 if (xml == (const char *) NULL) 834 return(MagickFalse); 835 status=MagickTrue; 836 coder_info=(CoderInfo *) NULL; 837 token=AcquireString(xml); 838 extent=strlen(token)+MagickPathExtent; 839 for (q=(char *) xml; *q != '\0'; ) 840 { 841 /* 842 Interpret XML. 843 */ 844 GetNextToken(q,&q,extent,token); 845 if (*token == '\0') 846 break; 847 (void) CopyMagickString(keyword,token,MagickPathExtent); 848 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0) 849 { 850 /* 851 Doctype element. 852 */ 853 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0')) 854 GetNextToken(q,&q,extent,token); 855 continue; 856 } 857 if (LocaleNCompare(keyword,"<!--",4) == 0) 858 { 859 /* 860 Comment element. 861 */ 862 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0')) 863 GetNextToken(q,&q,extent,token); 864 continue; 865 } 866 if (LocaleCompare(keyword,"<include") == 0) 867 { 868 /* 869 Include element. 870 */ 871 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0')) 872 { 873 (void) CopyMagickString(keyword,token,MagickPathExtent); 874 GetNextToken(q,&q,extent,token); 875 if (*token != '=') 876 continue; 877 GetNextToken(q,&q,extent,token); 878 if (LocaleCompare(keyword,"file") == 0) 879 { 880 if (depth > 200) 881 (void) ThrowMagickException(exception,GetMagickModule(), 882 ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token); 883 else 884 { 885 char 886 path[MagickPathExtent], 887 *file_xml; 888 889 GetPathComponent(filename,HeadPath,path); 890 if (*path != '\0') 891 (void) ConcatenateMagickString(path,DirectorySeparator, 892 MagickPathExtent); 893 if (*token == *DirectorySeparator) 894 (void) CopyMagickString(path,token,MagickPathExtent); 895 else 896 (void) ConcatenateMagickString(path,token,MagickPathExtent); 897 file_xml=FileToXML(path,~0UL); 898 if (file_xml != (char *) NULL) 899 { 900 status&=LoadCoderCache(cache,file_xml,path,depth+1, 901 exception); 902 file_xml=DestroyString(file_xml); 903 } 904 } 905 } 906 } 907 continue; 908 } 909 if (LocaleCompare(keyword,"<coder") == 0) 910 { 911 /* 912 Coder element. 913 */ 914 coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info)); 915 if (coder_info == (CoderInfo *) NULL) 916 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 917 (void) ResetMagickMemory(coder_info,0,sizeof(*coder_info)); 918 coder_info->path=ConstantString(filename); 919 coder_info->exempt=MagickFalse; 920 coder_info->signature=MagickCoreSignature; 921 continue; 922 } 923 if (coder_info == (CoderInfo *) NULL) 924 continue; 925 if (LocaleCompare(keyword,"/>") == 0) 926 { 927 status=AddValueToSplayTree(cache,ConstantString(coder_info->magick), 928 coder_info); 929 if (status == MagickFalse) 930 (void) ThrowMagickException(exception,GetMagickModule(), 931 ResourceLimitError,"MemoryAllocationFailed","`%s'", 932 coder_info->magick); 933 coder_info=(CoderInfo *) NULL; 934 continue; 935 } 936 GetNextToken(q,(const char **) NULL,extent,token); 937 if (*token != '=') 938 continue; 939 GetNextToken(q,&q,extent,token); 940 GetNextToken(q,&q,extent,token); 941 switch (*keyword) 942 { 943 case 'M': 944 case 'm': 945 { 946 if (LocaleCompare((char *) keyword,"magick") == 0) 947 { 948 coder_info->magick=ConstantString(token); 949 break; 950 } 951 break; 952 } 953 case 'N': 954 case 'n': 955 { 956 if (LocaleCompare((char *) keyword,"name") == 0) 957 { 958 coder_info->name=ConstantString(token); 959 break; 960 } 961 break; 962 } 963 case 'S': 964 case 's': 965 { 966 if (LocaleCompare((char *) keyword,"stealth") == 0) 967 { 968 coder_info->stealth=IsStringTrue(token); 969 break; 970 } 971 break; 972 } 973 default: 974 break; 975 } 976 } 977 token=(char *) RelinquishMagickMemory(token); 978 return(status != 0 ? MagickTrue : MagickFalse); 979} 980