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