Home | History | Annotate | Download | only in MagickCore
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
      7 %                  MM MM  A   A  G        I    C      K  K                    %
      8 %                  M M M  AAAAA  G GGG    I    C      KKK                     %
      9 %                  M   M  A   A  G   G    I    C      K  K                    %
     10 %                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
     11 %                                                                             %
     12 %                                                                             %
     13 %               Methods to Read or List ImageMagick Image formats             %
     14 %                                                                             %
     15 %                            Software Design                                  %
     16 %                            Bob Friesenhahn                                  %
     17 %                                 Cristy                                      %
     18 %                             November 1998                                   %
     19 %                                                                             %
     20 %                                                                             %
     21 %  Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization      %
     22 %  dedicated to making software imaging solutions freely available.           %
     23 %                                                                             %
     24 %  You may not use this file except in compliance with the License.  You may  %
     25 %  obtain a copy of the License at                                            %
     26 %                                                                             %
     27 %    https://imagemagick.org/script/license.php                               %
     28 %                                                                             %
     29 %  Unless required by applicable law or agreed to in writing, software        %
     30 %  distributed under the License is distributed on an "AS IS" BASIS,          %
     31 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
     32 %  See the License for the specific language governing permissions and        %
     33 %  limitations under the License.                                             %
     34 %                                                                             %
     35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     36 %
     37 %
     38 */
     39 
     40 /*
     42   Include declarations.
     43 */
     44 #include "MagickCore/studio.h"
     45 #include "MagickCore/annotate-private.h"
     46 #include "MagickCore/blob.h"
     47 #include "MagickCore/blob-private.h"
     48 #include "MagickCore/cache.h"
     49 #include "MagickCore/cache-private.h"
     50 #include "MagickCore/coder-private.h"
     51 #include "MagickCore/client.h"
     52 #include "MagickCore/color-private.h"
     53 #include "MagickCore/configure-private.h"
     54 #include "MagickCore/constitute-private.h"
     55 #include "MagickCore/delegate-private.h"
     56 #include "MagickCore/draw.h"
     57 #include "MagickCore/exception.h"
     58 #include "MagickCore/exception-private.h"
     59 #include "MagickCore/locale-private.h"
     60 #include "MagickCore/log-private.h"
     61 #include "MagickCore/magic-private.h"
     62 #include "MagickCore/magick.h"
     63 #include "MagickCore/magick-private.h"
     64 #include "MagickCore/memory_.h"
     65 #include "MagickCore/memory-private.h"
     66 #include "MagickCore/mime-private.h"
     67 #include "MagickCore/monitor-private.h"
     68 #include "MagickCore/module.h"
     69 #include "MagickCore/module-private.h"
     70 #include "MagickCore/nt-base-private.h"
     71 #include "MagickCore/nt-feature.h"
     72 #include "MagickCore/opencl-private.h"
     73 #include "MagickCore/option-private.h"
     74 #include "MagickCore/random-private.h"
     75 #include "MagickCore/registry.h"
     76 #include "MagickCore/registry-private.h"
     77 #include "MagickCore/resource_.h"
     78 #include "MagickCore/resource-private.h"
     79 #include "MagickCore/policy.h"
     80 #include "MagickCore/policy-private.h"
     81 #include "MagickCore/semaphore.h"
     82 #include "MagickCore/semaphore-private.h"
     83 #include "MagickCore/signature-private.h"
     84 #include "MagickCore/splay-tree.h"
     85 #include "MagickCore/static.h"
     86 #include "MagickCore/string_.h"
     87 #include "MagickCore/string-private.h"
     88 #include "MagickCore/thread_.h"
     89 #include "MagickCore/thread-private.h"
     90 #include "MagickCore/type-private.h"
     91 #include "MagickCore/token.h"
     92 #include "MagickCore/utility.h"
     93 #include "MagickCore/utility-private.h"
     94 #include "MagickCore/xwindow-private.h"
     95 #if defined(MAGICKCORE_XML_DELEGATE)
     96 #  if defined(MAGICKCORE_WINDOWS_SUPPORT)
     97 #    if !defined(__MINGW32__)
     98 #      include <win32config.h>
     99 #    endif
    100 #  endif
    101 #  include <libxml/parser.h>
    102 #endif
    103 
    104 /*
    106   Define declarations.
    107 */
    108 #if !defined(MAGICKCORE_RETSIGTYPE)
    109 # define MAGICKCORE_RETSIGTYPE  void
    110 #endif
    111 #if !defined(SIG_DFL)
    112 # define SIG_DFL  ((SignalHandler *) 0)
    113 #endif
    114 #if !defined(SIG_ERR)
    115 # define SIG_ERR  ((SignalHandler *) -1)
    116 #endif
    117 #if !defined(SIGMAX)
    118 #define SIGMAX  64
    119 #endif
    120 
    121 /*
    123   Typedef declarations.
    124 */
    125 typedef MAGICKCORE_RETSIGTYPE
    126   SignalHandler(int);
    127 
    128 /*
    130   Global declarations.
    131 */
    132 static SemaphoreInfo
    133   *magick_semaphore = (SemaphoreInfo *) NULL;
    134 
    135 static SignalHandler
    136   *signal_handlers[SIGMAX] = { (SignalHandler *) NULL };
    137 
    138 static SplayTreeInfo
    139   *magick_list = (SplayTreeInfo *) NULL;
    140 
    141 static volatile MagickBooleanType
    142   instantiate_magickcore = MagickFalse,
    143   magickcore_signal_in_progress = MagickFalse,
    144   magick_list_initialized = MagickFalse;
    145 
    146 static int
    147   magick_precision = 0;
    148 
    149 /*
    151   Forward declarations.
    152 */
    153 static MagickBooleanType
    154   IsMagickTreeInstantiated(ExceptionInfo *);
    155 
    156 /*
    158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    159 %                                                                             %
    160 %                                                                             %
    161 %                                                                             %
    162 %    A c q u i r e M a g i c k I n f o                                        %
    163 %                                                                             %
    164 %                                                                             %
    165 %                                                                             %
    166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    167 %
    168 %  AcquireMagickInfo() allocates a MagickInfo structure and initializes the
    169 %  members to default values.
    170 %
    171 %  The format of the AcquireMagickInfo method is:
    172 %
    173 %      MagickInfo *AcquireMagickInfo(const char *module, const char *name,)
    174 %
    175 %  A description of each parameter follows:
    176 %
    177 %    o module: a character string that represents the module associated
    178 %      with the MagickInfo structure.
    179 %
    180 %    o name: a character string that represents the image format associated
    181 %      with the MagickInfo structure.
    182 %
    183 %    o description: a character string that represents the image format
    184 %      associated with the MagickInfo structure.
    185 %
    186 */
    187 MagickExport MagickInfo *AcquireMagickInfo(const char *module,const char *name,
    188   const char *description)
    189 {
    190   MagickInfo
    191     *magick_info;
    192 
    193   assert(module != (const char *) NULL);
    194   assert(name != (const char *) NULL);
    195   assert(description != (const char *) NULL);
    196   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
    197   magick_info=(MagickInfo *) AcquireCriticalMemory(sizeof(*magick_info));
    198   (void) memset(magick_info,0,sizeof(*magick_info));
    199   magick_info->module=ConstantString(module);
    200   magick_info->name=ConstantString(name);
    201   magick_info->description=ConstantString(description);
    202   magick_info->flags=CoderAdjoinFlag | CoderBlobSupportFlag |
    203     CoderDecoderThreadSupportFlag | CoderEncoderThreadSupportFlag |
    204     CoderUseExtensionFlag;
    205   magick_info->signature=MagickCoreSignature;
    206   return(magick_info);
    207 }
    208 
    209 /*
    211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    212 %                                                                             %
    213 %                                                                             %
    214 %                                                                             %
    215 +   G e t I m a g e D e c o d e r                                             %
    216 %                                                                             %
    217 %                                                                             %
    218 %                                                                             %
    219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    220 %
    221 %  GetImageDecoder() returns the image decoder.
    222 %
    223 %  The format of the GetImageDecoder method is:
    224 %
    225 %      DecodeImageHandler *GetImageDecoder(const MagickInfo *magick_info)
    226 %
    227 %  A description of each parameter follows:
    228 %
    229 %    o magick_info:  The magick info.
    230 %
    231 */
    232 MagickExport DecodeImageHandler *GetImageDecoder(const MagickInfo *magick_info)
    233 {
    234   if (magick_info == (MagickInfo *) NULL)
    235     return((DecodeImageHandler *) NULL);
    236   assert(magick_info->signature == MagickCoreSignature);
    237   return(magick_info->decoder);
    238 }
    239 
    240 /*
    242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    243 %                                                                             %
    244 %                                                                             %
    245 %                                                                             %
    246 +   G e t I m a g e E n c o d e r                                             %
    247 %                                                                             %
    248 %                                                                             %
    249 %                                                                             %
    250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    251 %
    252 %  GetImageEncoder() returns the image encoder.
    253 %
    254 %  The format of the GetImageEncoder method is:
    255 %
    256 %      EncodeImageHandler *GetImageEncoder(const MagickInfo *magick_info)
    257 %
    258 %  A description of each parameter follows:
    259 %
    260 %    o magick_info:  The magick info.
    261 %
    262 */
    263 MagickExport EncodeImageHandler *GetImageEncoder(const MagickInfo *magick_info)
    264 {
    265   if (magick_info == (MagickInfo *) NULL)
    266     return((EncodeImageHandler *) NULL);
    267   assert(magick_info->signature == MagickCoreSignature);
    268   return(magick_info->encoder);
    269 }
    270 
    271 /*
    273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    274 %                                                                             %
    275 %                                                                             %
    276 %                                                                             %
    277 +   G e t I m a g e M a g i c k                                               %
    278 %                                                                             %
    279 %                                                                             %
    280 %                                                                             %
    281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    282 %
    283 %  GetImageMagick() searches for an image format that matches the specified
    284 %  magick string.  If one is found, MagickTrue is returned otherwise
    285 %  MagickFalse.
    286 %
    287 %  The format of the GetImageMagick method is:
    288 %
    289 %      MagickBooleanType GetImageMagick(const unsigned char *magick,
    290 %        const size_t length,char *format)
    291 %
    292 %  A description of each parameter follows:
    293 %
    294 %    o magick: the image format we are searching for.
    295 %
    296 %    o length: the length of the binary string.
    297 %
    298 %    o format: the image format as determined by the magick bytes.
    299 %
    300 */
    301 MagickExport MagickBooleanType GetImageMagick(const unsigned char *magick,
    302   const size_t length,char *format)
    303 {
    304   ExceptionInfo
    305     *exception;
    306 
    307   MagickBooleanType
    308     status;
    309 
    310   register const MagickInfo
    311     *p;
    312 
    313   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
    314   assert(magick != (const unsigned char *) NULL);
    315   exception=AcquireExceptionInfo();
    316   p=GetMagickInfo("*",exception);
    317   exception=DestroyExceptionInfo(exception);
    318   if (p == (const MagickInfo *) NULL)
    319     return(MagickFalse);
    320   status=MagickFalse;
    321   LockSemaphoreInfo(magick_semaphore);
    322   ResetSplayTreeIterator(magick_list);
    323   p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
    324   while (p != (const MagickInfo *) NULL)
    325   {
    326     if ((p->magick != (IsImageFormatHandler *) NULL) &&
    327         (p->magick(magick,length) != 0))
    328       {
    329         status=MagickTrue;
    330         (void) CopyMagickString(format,p->name,MagickPathExtent);
    331         break;
    332       }
    333     p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
    334   }
    335   UnlockSemaphoreInfo(magick_semaphore);
    336   return(status);
    337 }
    338 
    339 /*
    341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    342 %                                                                             %
    343 %                                                                             %
    344 %                                                                             %
    345 +   G e t M a g i c k A d j o i n                                             %
    346 %                                                                             %
    347 %                                                                             %
    348 %                                                                             %
    349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    350 %
    351 %  GetMagickAdjoin() returns MagickTrue if the magick adjoin is MagickTrue.
    352 %
    353 %  The format of the GetMagickAdjoin method is:
    354 %
    355 %      MagickBooleanType GetMagickAdjoin(const MagickInfo *magick_info)
    356 %
    357 %  A description of each parameter follows:
    358 %
    359 %    o magick_info:  The magick info.
    360 %
    361 */
    362 MagickExport MagickBooleanType GetMagickAdjoin(const MagickInfo *magick_info)
    363 {
    364   assert(magick_info != (MagickInfo *) NULL);
    365   assert(magick_info->signature == MagickCoreSignature);
    366   return(((magick_info->flags & CoderAdjoinFlag) == 0) ? MagickFalse :
    367     MagickTrue);
    368 }
    369 
    370 /*
    372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    373 %                                                                             %
    374 %                                                                             %
    375 %                                                                             %
    376 +   G e t M a g i c k B l o b S u p p o r t                                   %
    377 %                                                                             %
    378 %                                                                             %
    379 %                                                                             %
    380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    381 %
    382 %  GetMagickBlobSupport() returns MagickTrue if the magick supports blobs.
    383 %
    384 %  The format of the GetMagickBlobSupport method is:
    385 %
    386 %      MagickBooleanType GetMagickBlobSupport(const MagickInfo *magick_info)
    387 %
    388 %  A description of each parameter follows:
    389 %
    390 %    o magick_info:  The magick info.
    391 %
    392 */
    393 MagickExport MagickBooleanType GetMagickBlobSupport(
    394   const MagickInfo *magick_info)
    395 {
    396   assert(magick_info != (MagickInfo *) NULL);
    397   assert(magick_info->signature == MagickCoreSignature);
    398   return(((magick_info->flags & CoderBlobSupportFlag) == 0) ? MagickFalse :
    399     MagickTrue);
    400 }
    401 
    402 /*
    404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    405 %                                                                             %
    406 %                                                                             %
    407 %                                                                             %
    408 +   G e t M a g i c k D e c o d e r S e e k a b l e S t r e a m               %
    409 %                                                                             %
    410 %                                                                             %
    411 %                                                                             %
    412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    413 %
    414 %  GetMagickDecoderSeekableStream() returns MagickTrue if the magick supports a
    415 %  seekable stream in the decoder.
    416 %
    417 %  The format of the GetMagickDecoderSeekableStream method is:
    418 %
    419 %      MagickBooleanType GetMagickDecoderSeekableStream(
    420 %        const MagickInfo *magick_info)
    421 %
    422 %  A description of each parameter follows:
    423 %
    424 %    o magick_info:  The magick info.
    425 %
    426 */
    427 MagickExport MagickBooleanType GetMagickDecoderSeekableStream(
    428   const MagickInfo *magick_info)
    429 {
    430   assert(magick_info != (MagickInfo *) NULL);
    431   assert(magick_info->signature == MagickCoreSignature);
    432   if ((magick_info->flags & CoderDecoderSeekableStreamFlag) == 0)
    433     return(MagickFalse);
    434   return(MagickTrue);
    435 }
    436 
    437 /*
    439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    440 %                                                                             %
    441 %                                                                             %
    442 %                                                                             %
    443 +   G e t M a g i c k D e c o d e r T h r e a d S u p p o r t                 %
    444 %                                                                             %
    445 %                                                                             %
    446 %                                                                             %
    447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    448 %
    449 %  GetMagickDecoderThreadSupport() returns MagickTrue if the decoder supports
    450 %  threads.
    451 %
    452 %  The format of the GetMagickDecoderThreadSupport method is:
    453 %
    454 %      MagickStatusType GetMagickDecoderThreadSupport(
    455 %        const MagickInfo *magick_info)
    456 %
    457 %  A description of each parameter follows:
    458 %
    459 %    o magick_info:  The magick info.
    460 %
    461 */
    462 MagickExport MagickBooleanType GetMagickDecoderThreadSupport(
    463   const MagickInfo *magick_info)
    464 {
    465   assert(magick_info != (MagickInfo *) NULL);
    466   assert(magick_info->signature == MagickCoreSignature);
    467   return(((magick_info->flags & CoderDecoderThreadSupportFlag) == 0) ?
    468     MagickFalse : MagickTrue);
    469 }
    470 
    471 /*
    473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    474 %                                                                             %
    475 %                                                                             %
    476 %                                                                             %
    477 +   G e t M a g i c k D e s c r i p t i o n                                   %
    478 %                                                                             %
    479 %                                                                             %
    480 %                                                                             %
    481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    482 %
    483 %  GetMagickDescription() returns the magick description.
    484 %
    485 %  The format of the GetMagickDescription method is:
    486 %
    487 %      const char *GetMagickDescription(const MagickInfo *magick_info)
    488 %
    489 %  A description of each parameter follows:
    490 %
    491 %    o magick_info:  The magick info.
    492 %
    493 */
    494 MagickExport const char *GetMagickDescription(const MagickInfo *magick_info)
    495 {
    496   assert(magick_info != (MagickInfo *) NULL);
    497   assert(magick_info->signature == MagickCoreSignature);
    498   return(magick_info->description);
    499 }
    500 
    501 /*
    503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    504 %                                                                             %
    505 %                                                                             %
    506 %                                                                             %
    507 +   G e t M a g i c k E n c o d e r S e e k a b l e S t r e a m               %
    508 %                                                                             %
    509 %                                                                             %
    510 %                                                                             %
    511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    512 %
    513 %  GetMagickEncoderSeekableStream() returns MagickTrue if the magick supports a
    514 %  seekable stream in the encoder.
    515 %
    516 %  The format of the GetMagickEncoderSeekableStream method is:
    517 %
    518 %      MagickBooleanType GetMagickEncoderSeekableStream(
    519 %        const MagickInfo *magick_info)
    520 %
    521 %  A description of each parameter follows:
    522 %
    523 %    o magick_info:  The magick info.
    524 %
    525 */
    526 MagickExport MagickBooleanType GetMagickEncoderSeekableStream(
    527   const MagickInfo *magick_info)
    528 {
    529   assert(magick_info != (MagickInfo *) NULL);
    530   assert(magick_info->signature == MagickCoreSignature);
    531   if ((magick_info->flags & CoderEncoderSeekableStreamFlag) == 0)
    532     return(MagickFalse);
    533   return(MagickTrue);
    534 }
    535 
    536 /*
    538 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    539 %                                                                             %
    540 %                                                                             %
    541 %                                                                             %
    542 +   G e t M a g i c k E n c o d e r T h r e a d S u p p o r t                 %
    543 %                                                                             %
    544 %                                                                             %
    545 %                                                                             %
    546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    547 %
    548 %  GetMagickEncoderThreadSupport() returns MagickTrue if the encoder supports
    549 %  threads.
    550 %
    551 %  The format of the GetMagickEncoderThreadSupport method is:
    552 %
    553 %      MagickStatusType GetMagickEncoderThreadSupport(
    554 %        const MagickInfo *magick_info)
    555 %
    556 %  A description of each parameter follows:
    557 %
    558 %    o magick_info:  The magick info.
    559 %
    560 */
    561 MagickExport MagickBooleanType GetMagickEncoderThreadSupport(
    562   const MagickInfo *magick_info)
    563 {
    564   assert(magick_info != (MagickInfo *) NULL);
    565   assert(magick_info->signature == MagickCoreSignature);
    566   return(((magick_info->flags & CoderDecoderThreadSupportFlag) == 0) ?
    567     MagickFalse : MagickTrue);
    568 }
    569 
    570 /*
    572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    573 %                                                                             %
    574 %                                                                             %
    575 %                                                                             %
    576 +   G e t M a g i c k E n d i a n S u p p o r t                               %
    577 %                                                                             %
    578 %                                                                             %
    579 %                                                                             %
    580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    581 %
    582 %  GetMagickEndianSupport() returns the MagickTrue if the coder respects
    583 %  endianness other than MSBEndian.
    584 %
    585 %  The format of the GetMagickEndianSupport method is:
    586 %
    587 %      MagickBooleanType GetMagickEndianSupport(const MagickInfo *magick_info)
    588 %
    589 %  A description of each parameter follows:
    590 %
    591 %    o magick_info:  The magick info.
    592 %
    593 */
    594 MagickExport MagickBooleanType GetMagickEndianSupport(
    595   const MagickInfo *magick_info)
    596 {
    597   assert(magick_info != (MagickInfo *) NULL);
    598   assert(magick_info->signature == MagickCoreSignature);
    599   return(((magick_info->flags & CoderEndianSupportFlag) == 0) ? MagickFalse :
    600     MagickTrue);
    601 }
    602 
    603 /*
    605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    606 %                                                                             %
    607 %                                                                             %
    608 %                                                                             %
    609 +   G e t M a g i c k I n f o                                                 %
    610 %                                                                             %
    611 %                                                                             %
    612 %                                                                             %
    613 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    614 %
    615 %  GetMagickInfo() returns a pointer MagickInfo structure that matches
    616 %  the specified name.  If name is NULL, the head of the image format list
    617 %  is returned.
    618 %
    619 %  The format of the GetMagickInfo method is:
    620 %
    621 %      const MagickInfo *GetMagickInfo(const char *name,Exception *exception)
    622 %
    623 %  A description of each parameter follows:
    624 %
    625 %    o name: the image format we are looking for.
    626 %
    627 %    o exception: return any errors or warnings in this structure.
    628 %
    629 */
    630 MagickExport const MagickInfo *GetMagickInfo(const char *name,
    631   ExceptionInfo *exception)
    632 {
    633   register const MagickInfo
    634     *magick_info;
    635 
    636   /*
    637     Find named module attributes.
    638   */
    639   assert(exception != (ExceptionInfo *) NULL);
    640   if (IsMagickTreeInstantiated(exception) == MagickFalse)
    641     return((const MagickInfo *) NULL);
    642   magick_info=(const MagickInfo *) NULL;
    643   if ((name != (const char *) NULL) && (*name != '\0'))
    644     {
    645       LockSemaphoreInfo(magick_semaphore);
    646       if (LocaleCompare(name,"*") == 0)
    647 #if defined(MAGICKCORE_BUILD_MODULES)
    648         (void) OpenModules(exception);
    649 #else
    650         RegisterStaticModules();
    651 #endif
    652       else
    653         {
    654           magick_info=(const MagickInfo *) GetValueFromSplayTree(magick_list,
    655             name);
    656           if (magick_info == (const MagickInfo *) NULL)
    657 #if defined(MAGICKCORE_BUILD_MODULES)
    658             (void) OpenModule(name,exception);
    659 #else
    660             (void) RegisterStaticModule(name,exception);
    661 #endif
    662         }
    663       UnlockSemaphoreInfo(magick_semaphore);
    664     }
    665   if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
    666     return((const MagickInfo *) GetRootValueFromSplayTree(magick_list));
    667   if (magick_info == (const MagickInfo *) NULL)
    668     magick_info=(const MagickInfo *) GetValueFromSplayTree(magick_list,name);
    669   return(magick_info);
    670 }
    671 
    672 /*
    674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    675 %                                                                             %
    676 %                                                                             %
    677 %                                                                             %
    678 +   G e t M a g i c k I n f o L i s t                                         %
    679 %                                                                             %
    680 %                                                                             %
    681 %                                                                             %
    682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    683 %
    684 %  GetMagickInfoList() returns any image formats that match the specified
    685 %  pattern.
    686 %
    687 %  The format of the GetMagickInfoList function is:
    688 %
    689 %      const MagickInfo **GetMagickInfoList(const char *pattern,
    690 %        size_t *number_formats,ExceptionInfo *exception)
    691 %
    692 %  A description of each parameter follows:
    693 %
    694 %    o pattern: Specifies a pointer to a text string containing a pattern.
    695 %
    696 %    o number_formats:  This integer returns the number of formats in the list.
    697 %
    698 %    o exception: return any errors or warnings in this structure.
    699 %
    700 */
    701 
    702 #if defined(__cplusplus) || defined(c_plusplus)
    703 extern "C" {
    704 #endif
    705 
    706 static int MagickInfoCompare(const void *x,const void *y)
    707 {
    708   const MagickInfo
    709     **p,
    710     **q;
    711 
    712   p=(const MagickInfo **) x,
    713   q=(const MagickInfo **) y;
    714   return(LocaleCompare((*p)->name,(*q)->name));
    715 }
    716 
    717 #if defined(__cplusplus) || defined(c_plusplus)
    718 }
    719 #endif
    720 
    721 MagickExport const MagickInfo **GetMagickInfoList(const char *pattern,
    722   size_t *number_formats,ExceptionInfo *exception)
    723 {
    724   const MagickInfo
    725     **formats;
    726 
    727   register const MagickInfo
    728     *p;
    729 
    730   register ssize_t
    731     i;
    732 
    733   /*
    734     Allocate magick list.
    735   */
    736   assert(pattern != (char *) NULL);
    737   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
    738   assert(number_formats != (size_t *) NULL);
    739   *number_formats=0;
    740   p=GetMagickInfo("*",exception);
    741   if (p == (const MagickInfo *) NULL)
    742     return((const MagickInfo **) NULL);
    743   formats=(const MagickInfo **) AcquireQuantumMemory((size_t)
    744     GetNumberOfNodesInSplayTree(magick_list)+1UL,sizeof(*formats));
    745   if (formats == (const MagickInfo **) NULL)
    746     return((const MagickInfo **) NULL);
    747   /*
    748     Generate magick list.
    749   */
    750   LockSemaphoreInfo(magick_semaphore);
    751   ResetSplayTreeIterator(magick_list);
    752   p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
    753   for (i=0; p != (const MagickInfo *) NULL; )
    754   {
    755     if ((GetMagickStealth(p) == MagickFalse) &&
    756         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
    757       formats[i++]=p;
    758     p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
    759   }
    760   UnlockSemaphoreInfo(magick_semaphore);
    761   qsort((void *) formats,(size_t) i,sizeof(*formats),MagickInfoCompare);
    762   formats[i]=(MagickInfo *) NULL;
    763   *number_formats=(size_t) i;
    764   return(formats);
    765 }
    766 
    767 /*
    769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    770 %                                                                             %
    771 %                                                                             %
    772 %                                                                             %
    773 +   G e t M a g i c k L i s t                                                 %
    774 %                                                                             %
    775 %                                                                             %
    776 %                                                                             %
    777 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    778 %
    779 %  GetMagickList() returns any image formats that match the specified pattern.
    780 %
    781 %  The format of the GetMagickList function is:
    782 %
    783 %      char **GetMagickList(const char *pattern,size_t *number_formats,
    784 %        ExceptionInfo *exception)
    785 %
    786 %  A description of each parameter follows:
    787 %
    788 %    o pattern: Specifies a pointer to a text string containing a pattern.
    789 %
    790 %    o number_formats:  This integer returns the number of formats in the list.
    791 %
    792 %    o exception: return any errors or warnings in this structure.
    793 %
    794 */
    795 
    796 #if defined(__cplusplus) || defined(c_plusplus)
    797 extern "C" {
    798 #endif
    799 
    800 static int MagickCompare(const void *x,const void *y)
    801 {
    802   register const char
    803     **p,
    804     **q;
    805 
    806   p=(const char **) x;
    807   q=(const char **) y;
    808   return(LocaleCompare(*p,*q));
    809 }
    810 
    811 #if defined(__cplusplus) || defined(c_plusplus)
    812 }
    813 #endif
    814 
    815 MagickExport char **GetMagickList(const char *pattern,
    816   size_t *number_formats,ExceptionInfo *exception)
    817 {
    818   char
    819     **formats;
    820 
    821   register const MagickInfo
    822     *p;
    823 
    824   register ssize_t
    825     i;
    826 
    827   /*
    828     Allocate magick list.
    829   */
    830   assert(pattern != (char *) NULL);
    831   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
    832   assert(number_formats != (size_t *) NULL);
    833   *number_formats=0;
    834   p=GetMagickInfo("*",exception);
    835   if (p == (const MagickInfo *) NULL)
    836     return((char **) NULL);
    837   formats=(char **) AcquireQuantumMemory((size_t)
    838     GetNumberOfNodesInSplayTree(magick_list)+1UL,sizeof(*formats));
    839   if (formats == (char **) NULL)
    840     return((char **) NULL);
    841   LockSemaphoreInfo(magick_semaphore);
    842   ResetSplayTreeIterator(magick_list);
    843   p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
    844   for (i=0; p != (const MagickInfo *) NULL; )
    845   {
    846     if ((GetMagickStealth(p) == MagickFalse) &&
    847         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
    848       formats[i++]=ConstantString(p->name);
    849     p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
    850   }
    851   UnlockSemaphoreInfo(magick_semaphore);
    852   qsort((void *) formats,(size_t) i,sizeof(*formats),MagickCompare);
    853   formats[i]=(char *) NULL;
    854   *number_formats=(size_t) i;
    855   return(formats);
    856 }
    857 
    858 /*
    860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    861 %                                                                             %
    862 %                                                                             %
    863 %                                                                             %
    864 +   G e t M a g i c k M i m e T y p e                                         %
    865 %                                                                             %
    866 %                                                                             %
    867 %                                                                             %
    868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    869 %
    870 %  GetMagickMimeType() returns the magick mime type.
    871 %
    872 %  The format of the GetMagickMimeType method is:
    873 %
    874 %      const char *GetMagickMimeType(const MagickInfo *magick_info)
    875 %
    876 %  A description of each parameter follows:
    877 %
    878 %    o magick_info:  The magick info.
    879 %
    880 */
    881 MagickExport const char *GetMagickMimeType(const MagickInfo *magick_info)
    882 {
    883   assert(magick_info != (MagickInfo *) NULL);
    884   assert(magick_info->signature == MagickCoreSignature);
    885   return(magick_info->mime_type);
    886 }
    887 
    888 /*
    890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    891 %                                                                             %
    892 %                                                                             %
    893 %                                                                             %
    894 %   G e t M a g i c k P r e c i s i o n                                       %
    895 %                                                                             %
    896 %                                                                             %
    897 %                                                                             %
    898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    899 %
    900 %  GetMagickPrecision() returns the maximum number of significant digits to be
    901 %  printed.
    902 %
    903 %  The format of the GetMagickPrecision method is:
    904 %
    905 %      int GetMagickPrecision(void)
    906 %
    907 */
    908 MagickExport int GetMagickPrecision(void)
    909 {
    910   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
    911   return(SetMagickPrecision(0));
    912 }
    913 
    914 /*
    916 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    917 %                                                                             %
    918 %                                                                             %
    919 %                                                                             %
    920 +   G e t M a g i c k R a w S u p p o r t                                     %
    921 %                                                                             %
    922 %                                                                             %
    923 %                                                                             %
    924 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    925 %
    926 %  GetMagickRawSupport() returns the MagickTrue if the coder is a raw format.
    927 %
    928 %  The format of the GetMagickRawSupport method is:
    929 %
    930 %      MagickBooleanType GetMagickRawSupport(const MagickInfo *magick_info)
    931 %
    932 %  A description of each parameter follows:
    933 %
    934 %    o magick_info:  The magick info.
    935 %
    936 */
    937 MagickExport MagickBooleanType GetMagickRawSupport(
    938   const MagickInfo *magick_info)
    939 {
    940   assert(magick_info != (MagickInfo *) NULL);
    941   assert(magick_info->signature == MagickCoreSignature);
    942   return(((magick_info->flags & CoderRawSupportFlag) == 0) ? MagickFalse :
    943     MagickTrue);
    944 }
    945 
    946 
    947 /*
    948 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    949 %                                                                             %
    950 %                                                                             %
    951 %                                                                             %
    952 +   G e t M a g i c k S t e a l t h                                           %
    953 %                                                                             %
    954 %                                                                             %
    955 %                                                                             %
    956 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    957 %
    958 %  GetMagickStealth() returns MagickTrue if the magick is a stealth coder.
    959 %
    960 %  The format of the GetMagickStealth method is:
    961 %
    962 %      MagickBooleanType GetMagickStealth(const MagickInfo *magick_info)
    963 %
    964 %  A description of each parameter follows:
    965 %
    966 %    o magick_info:  The magick info.
    967 %
    968 */
    969 MagickExport MagickBooleanType GetMagickStealth(const MagickInfo *magick_info)
    970 {
    971   assert(magick_info != (MagickInfo *) NULL);
    972   assert(magick_info->signature == MagickCoreSignature);
    973   return(((magick_info->flags & CoderStealthFlag) == 0) ? MagickFalse :
    974     MagickTrue);
    975 }
    976 
    977 
    978 /*
    979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    980 %                                                                             %
    981 %                                                                             %
    982 %                                                                             %
    983 +   G e t M a g i c k U s e E x t e n s i o n                                 %
    984 %                                                                             %
    985 %                                                                             %
    986 %                                                                             %
    987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    988 %
    989 %  GetMagickUseExtension() returns MagickTrue if the magick can use the
    990 %  extension of the format if the format return by IsImageFormatHandler uses
    991 %  the same coder.
    992 %
    993 %  The format of the GetMagickUseExtension method is:
    994 %
    995 %      MagickBooleanType GetMagickUseExtension(const MagickInfo *magick_info)
    996 %
    997 %  A description of each parameter follows:
    998 %
    999 %    o magick_info:  The magick info.
   1000 %
   1001 */
   1002 MagickExport MagickBooleanType GetMagickUseExtension(
   1003   const MagickInfo *magick_info)
   1004 {
   1005   assert(magick_info != (MagickInfo *) NULL);
   1006   assert(magick_info->signature == MagickCoreSignature);
   1007   return(((magick_info->flags & CoderUseExtensionFlag) == 0) ? MagickFalse :
   1008     MagickTrue);
   1009 }
   1010 
   1011 /*
   1013 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1014 %                                                                             %
   1015 %                                                                             %
   1016 %                                                                             %
   1017 +   I s M a g i c k T r e e I n s t a n t i a t e d                           %
   1018 %                                                                             %
   1019 %                                                                             %
   1020 %                                                                             %
   1021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1022 %
   1023 %  IsMagickTreeInstantiated() determines if the magick tree is instantiated.
   1024 %  If not, it instantiates the tree and returns it.
   1025 %
   1026 %  The format of the IsMagickTreeInstantiated() method is:
   1027 %
   1028 %      IsMagickTreeInstantiated(Exceptioninfo *exception)
   1029 %
   1030 %  A description of each parameter follows.
   1031 %
   1032 %    o exception: return any errors or warnings in this structure.
   1033 %
   1034 */
   1035 
   1036 static void *DestroyMagickNode(void *magick_info)
   1037 {
   1038   register MagickInfo
   1039     *p;
   1040 
   1041   p=(MagickInfo *) magick_info;
   1042   if (p->module != (char *) NULL)
   1043     p->module=DestroyString(p->module);
   1044   if (p->note != (char *) NULL)
   1045     p->note=DestroyString(p->note);
   1046   if (p->mime_type != (char *) NULL)
   1047     p->mime_type=DestroyString(p->mime_type);
   1048   if (p->version != (char *) NULL)
   1049     p->version=DestroyString(p->version);
   1050   if (p->description != (char *) NULL)
   1051     p->description=DestroyString(p->description);
   1052   if (p->name != (char *) NULL)
   1053     p->name=DestroyString(p->name);
   1054   if (p->semaphore != (SemaphoreInfo *) NULL)
   1055     RelinquishSemaphoreInfo(&p->semaphore);
   1056   return(RelinquishMagickMemory(p));
   1057 }
   1058 
   1059 static MagickBooleanType IsMagickTreeInstantiated(ExceptionInfo *exception)
   1060 {
   1061   if (magick_list_initialized == MagickFalse)
   1062     {
   1063       if (magick_semaphore == (SemaphoreInfo *) NULL)
   1064         ActivateSemaphoreInfo(&magick_semaphore);
   1065       LockSemaphoreInfo(magick_semaphore);
   1066       if (magick_list_initialized == MagickFalse)
   1067         {
   1068           magick_list=NewSplayTree(CompareSplayTreeString,(void *(*)(void *))
   1069             NULL,DestroyMagickNode);
   1070 #if defined(MAGICKCORE_MODULES_SUPPORT)
   1071           (void) GetModuleInfo((char *) NULL,exception);
   1072 #endif
   1073           magick_list_initialized=MagickTrue;
   1074         }
   1075       UnlockSemaphoreInfo(magick_semaphore);
   1076     }
   1077   return(magick_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
   1078 }
   1079 
   1080 /*
   1082 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1083 %                                                                             %
   1084 %                                                                             %
   1085 %                                                                             %
   1086 +   I s M a g i c k C o n f l i c t                                           %
   1087 %                                                                             %
   1088 %                                                                             %
   1089 %                                                                             %
   1090 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1091 %
   1092 %  IsMagickConflict() returns MagickTrue if the image format conflicts with a
   1093 %  logical drive (.e.g. X:).
   1094 %
   1095 %  The format of the IsMagickConflict method is:
   1096 %
   1097 %      MagickBooleanType IsMagickConflict(const char *magick)
   1098 %
   1099 %  A description of each parameter follows:
   1100 %
   1101 %    o magick: Specifies the image format.
   1102 %
   1103 */
   1104 MagickPrivate MagickBooleanType IsMagickConflict(const char *magick)
   1105 {
   1106   assert(magick != (char *) NULL);
   1107 #if defined(macintosh)
   1108   return(MACIsMagickConflict(magick));
   1109 #elif defined(vms)
   1110   return(VMSIsMagickConflict(magick));
   1111 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
   1112   return(NTIsMagickConflict(magick));
   1113 #else
   1114   return(MagickFalse);
   1115 #endif
   1116 }
   1117 
   1118 /*
   1120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1121 %                                                                             %
   1122 %                                                                             %
   1123 %                                                                             %
   1124 +  L i s t M a g i c k I n f o                                                %
   1125 %                                                                             %
   1126 %                                                                             %
   1127 %                                                                             %
   1128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1129 %
   1130 %  ListMagickInfo() lists the image formats to a file.
   1131 %
   1132 %  The format of the ListMagickInfo method is:
   1133 %
   1134 %      MagickBooleanType ListMagickInfo(FILE *file,ExceptionInfo *exception)
   1135 %
   1136 %  A description of each parameter follows.
   1137 %
   1138 %    o file: A file handle.
   1139 %
   1140 %    o exception: return any errors or warnings in this structure.
   1141 %
   1142 */
   1143 MagickExport MagickBooleanType ListMagickInfo(FILE *file,
   1144   ExceptionInfo *exception)
   1145 {
   1146   const MagickInfo
   1147     **magick_info;
   1148 
   1149   register ssize_t
   1150     i;
   1151 
   1152   size_t
   1153     number_formats;
   1154 
   1155   ssize_t
   1156     j;
   1157 
   1158   if (file == (FILE *) NULL)
   1159     file=stdout;
   1160   magick_info=GetMagickInfoList("*",&number_formats,exception);
   1161   if (magick_info == (const MagickInfo **) NULL)
   1162     return(MagickFalse);
   1163   ClearMagickException(exception);
   1164 #if !defined(MAGICKCORE_MODULES_SUPPORT)
   1165   (void) FormatLocaleFile(file,"   Format  Mode  Description\n");
   1166 #else
   1167   (void) FormatLocaleFile(file,"   Format  Module    Mode  Description\n");
   1168 #endif
   1169   (void) FormatLocaleFile(file,
   1170     "--------------------------------------------------------"
   1171     "-----------------------\n");
   1172   for (i=0; i < (ssize_t) number_formats; i++)
   1173   {
   1174     if (GetMagickStealth(magick_info[i]) != MagickFalse)
   1175       continue;
   1176     (void) FormatLocaleFile(file,"%9s%c ",
   1177       magick_info[i]->name != (char *) NULL ? magick_info[i]->name : "",
   1178       GetMagickBlobSupport(magick_info[i]) != MagickFalse ? '*' : ' ');
   1179 #if defined(MAGICKCORE_MODULES_SUPPORT)
   1180     {
   1181       char
   1182         module[MagickPathExtent];
   1183 
   1184       *module='\0';
   1185       if (magick_info[i]->module != (char *) NULL)
   1186         (void) CopyMagickString(module,magick_info[i]->module,MagickPathExtent);
   1187       (void) ConcatenateMagickString(module,"          ",MagickPathExtent);
   1188       module[9]='\0';
   1189       (void) FormatLocaleFile(file,"%9s ",module);
   1190     }
   1191 #endif
   1192     (void) FormatLocaleFile(file,"%c%c%c ",magick_info[i]->decoder ? 'r' : '-',
   1193       magick_info[i]->encoder ? 'w' : '-',magick_info[i]->encoder != NULL &&
   1194       GetMagickAdjoin(magick_info[i]) != MagickFalse ? '+' : '-');
   1195     if (magick_info[i]->description != (char *) NULL)
   1196       (void) FormatLocaleFile(file,"  %s",magick_info[i]->description);
   1197     if (magick_info[i]->version != (char *) NULL)
   1198       (void) FormatLocaleFile(file," (%s)",magick_info[i]->version);
   1199     (void) FormatLocaleFile(file,"\n");
   1200     if (magick_info[i]->note != (char *) NULL)
   1201       {
   1202         char
   1203           **text;
   1204 
   1205         text=StringToList(magick_info[i]->note);
   1206         if (text != (char **) NULL)
   1207           {
   1208             for (j=0; text[j] != (char *) NULL; j++)
   1209             {
   1210               (void) FormatLocaleFile(file,"           %s\n",text[j]);
   1211               text[j]=DestroyString(text[j]);
   1212             }
   1213             text=(char **) RelinquishMagickMemory(text);
   1214           }
   1215       }
   1216   }
   1217   (void) FormatLocaleFile(file,"\n* native blob support\n");
   1218   (void) FormatLocaleFile(file,"r read support\n");
   1219   (void) FormatLocaleFile(file,"w write support\n");
   1220   (void) FormatLocaleFile(file,"+ support for multiple images\n");
   1221   (void) fflush(file);
   1222   magick_info=(const MagickInfo **) RelinquishMagickMemory((void *)
   1223     magick_info);
   1224   return(MagickTrue);
   1225 }
   1226 
   1227 /*
   1229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1230 %                                                                             %
   1231 %                                                                             %
   1232 %                                                                             %
   1233 %  I s M a g i c k C o r e I n s t a n t i a t e d                            %
   1234 %                                                                             %
   1235 %                                                                             %
   1236 %                                                                             %
   1237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1238 %
   1239 %  IsMagickCoreInstantiated() returns MagickTrue if the ImageMagick environment
   1240 %  is currently instantiated:  MagickCoreGenesis() has been called but
   1241 %  MagickDestroy() has not.
   1242 %
   1243 %  The format of the IsMagickCoreInstantiated method is:
   1244 %
   1245 %      MagickBooleanType IsMagickCoreInstantiated(void)
   1246 %
   1247 */
   1248 MagickExport MagickBooleanType IsMagickCoreInstantiated(void)
   1249 {
   1250   return(instantiate_magickcore);
   1251 }
   1252 
   1253 /*
   1255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1256 %                                                                             %
   1257 %                                                                             %
   1258 %                                                                             %
   1259 +   M a g i c k C o m p o n e n t G e n e s i s                               %
   1260 %                                                                             %
   1261 %                                                                             %
   1262 %                                                                             %
   1263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1264 %
   1265 %  MagickComponentGenesis() instantiates the magick component.
   1266 %
   1267 %  The format of the MagickComponentGenesis method is:
   1268 %
   1269 %      MagickBooleanType MagickComponentGenesis(void)
   1270 %
   1271 */
   1272 MagickPrivate MagickBooleanType MagickComponentGenesis(void)
   1273 {
   1274   if (magick_semaphore == (SemaphoreInfo *) NULL)
   1275     magick_semaphore=AcquireSemaphoreInfo();
   1276   return(MagickTrue);
   1277 }
   1278 
   1279 /*
   1281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1282 %                                                                             %
   1283 %                                                                             %
   1284 %                                                                             %
   1285 +   M a g i c k C o m p o n e n t T e r m i n u s                             %
   1286 %                                                                             %
   1287 %                                                                             %
   1288 %                                                                             %
   1289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1290 %
   1291 %  MagickComponentTerminus() destroys the magick component.
   1292 %
   1293 %  The format of the MagickComponentTerminus method is:
   1294 %
   1295 %      void MagickComponentTerminus(void)
   1296 %
   1297 */
   1298 MagickPrivate void MagickComponentTerminus(void)
   1299 {
   1300   if (magick_semaphore == (SemaphoreInfo *) NULL)
   1301     ActivateSemaphoreInfo(&magick_semaphore);
   1302   LockSemaphoreInfo(magick_semaphore);
   1303   if (magick_list != (SplayTreeInfo *) NULL)
   1304     {
   1305       magick_list=DestroySplayTree(magick_list);
   1306       magick_list_initialized=MagickFalse;
   1307     }
   1308   UnlockSemaphoreInfo(magick_semaphore);
   1309   RelinquishSemaphoreInfo(&magick_semaphore);
   1310 }
   1311 
   1312 /*
   1314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1315 %                                                                             %
   1316 %                                                                             %
   1317 %                                                                             %
   1318 %   M a g i c k C o r e G e n e s i s                                         %
   1319 %                                                                             %
   1320 %                                                                             %
   1321 %                                                                             %
   1322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1323 %
   1324 %  MagickCoreGenesis() initializes the MagickCore environment.
   1325 %
   1326 %  The format of the MagickCoreGenesis function is:
   1327 %
   1328 %      MagickCoreGenesis(const char *path,
   1329 %        const MagickBooleanType establish_signal_handlers)
   1330 %
   1331 %  A description of each parameter follows:
   1332 %
   1333 %    o path: the execution path of the current ImageMagick client.
   1334 %
   1335 %    o establish_signal_handlers: set to MagickTrue to use MagickCore's own
   1336 %      signal handlers for common signals.
   1337 %
   1338 */
   1339 
   1340 static SignalHandler *SetMagickSignalHandler(int signal_number,
   1341   SignalHandler *handler)
   1342 {
   1343 #if defined(MAGICKCORE_HAVE_SIGACTION) && defined(MAGICKCORE_HAVE_SIGEMPTYSET)
   1344   int
   1345     status;
   1346 
   1347   sigset_t
   1348     mask;
   1349 
   1350   struct sigaction
   1351     action,
   1352     previous_action;
   1353 
   1354   sigemptyset(&mask);
   1355   sigaddset(&mask,signal_number);
   1356   sigprocmask(SIG_BLOCK,&mask,NULL);
   1357   action.sa_mask=mask;
   1358   action.sa_handler=handler;
   1359   action.sa_flags=0;
   1360 #if defined(SA_INTERRUPT)
   1361   action.sa_flags|=SA_INTERRUPT;
   1362 #endif
   1363 #if defined(SA_ONSTACK)
   1364   action.sa_flags|=SA_ONSTACK;
   1365 #endif
   1366   status=sigaction(signal_number,&action,&previous_action);
   1367   if (status < 0)
   1368     return(SIG_ERR);
   1369   sigprocmask(SIG_UNBLOCK,&mask,NULL);
   1370   return(previous_action.sa_handler);
   1371 #else
   1372   return(signal(signal_number,handler));
   1373 #endif
   1374 }
   1375 
   1376 static void MagickSignalHandler(int signal_number)
   1377 {
   1378   if (magickcore_signal_in_progress != MagickFalse)
   1379     (void) SetMagickSignalHandler(signal_number,signal_handlers[signal_number]);
   1380   magickcore_signal_in_progress=MagickTrue;
   1381   AsynchronousResourceComponentTerminus();
   1382 #if defined(SIGQUIT)
   1383   if (signal_number == SIGQUIT)
   1384     abort();
   1385 #endif
   1386 #if defined(SIGABRT)
   1387   if (signal_number == SIGABRT)
   1388     abort();
   1389 #endif
   1390 #if defined(SIGBUS)
   1391   if (signal_number == SIGBUS)
   1392     abort();
   1393 #endif
   1394 #if defined(SIGFPE)
   1395   if (signal_number == SIGFPE)
   1396     abort();
   1397 #endif
   1398 #if defined(SIGXCPU)
   1399   if (signal_number == SIGXCPU)
   1400     abort();
   1401 #endif
   1402 #if defined(SIGXFSZ)
   1403   if (signal_number == SIGXFSZ)
   1404     abort();
   1405 #endif
   1406 #if defined(SIGSEGV)
   1407   if (signal_number == SIGSEGV)
   1408     abort();
   1409 #endif
   1410 #if !defined(MAGICKCORE_HAVE__EXIT)
   1411   exit(signal_number);
   1412 #else
   1413 #if defined(SIGHUP)
   1414   if (signal_number == SIGHUP)
   1415     _exit(signal_number);
   1416 #endif
   1417 #if defined(SIGINT)
   1418   if (signal_number == SIGINT)
   1419     _exit(signal_number);
   1420 #endif
   1421 #if defined(SIGBUS)
   1422   if (signal_number == SIGBUS)
   1423     _exit(signal_number);
   1424 #endif
   1425 #if defined(MAGICKCORE_HAVE_RAISE)
   1426   if (signal_handlers[signal_number] != MagickSignalHandler)
   1427     raise(signal_number);
   1428 #endif
   1429   _exit(signal_number);  /* do not invoke registered atexit() methods */
   1430 #endif
   1431 }
   1432 
   1433 static SignalHandler *RegisterMagickSignalHandler(int signal_number)
   1434 {
   1435   SignalHandler
   1436     *handler;
   1437 
   1438   handler=SetMagickSignalHandler(signal_number,MagickSignalHandler);
   1439   if (handler == SIG_ERR)
   1440     return(handler);
   1441   if (handler != SIG_DFL)
   1442     handler=SetMagickSignalHandler(signal_number,handler);
   1443   else
   1444     (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
   1445       "Register handler for signal: %d",signal_number);
   1446   return(handler);
   1447 }
   1448 
   1449 MagickExport void MagickCoreGenesis(const char *path,
   1450   const MagickBooleanType establish_signal_handlers)
   1451 {
   1452   char
   1453     *events,
   1454     execution_path[MagickPathExtent],
   1455     filename[MagickPathExtent];
   1456 
   1457   /*
   1458     Initialize the Magick environment.
   1459   */
   1460   InitializeMagickMutex();
   1461   LockMagickMutex();
   1462   if (instantiate_magickcore != MagickFalse)
   1463     {
   1464       UnlockMagickMutex();
   1465       return;
   1466     }
   1467   (void) SemaphoreComponentGenesis();
   1468   (void) LogComponentGenesis();
   1469   (void) LocaleComponentGenesis();
   1470   (void) RandomComponentGenesis();
   1471   events=GetEnvironmentValue("MAGICK_DEBUG");
   1472   if (events != (char *) NULL)
   1473     {
   1474       (void) SetLogEventMask(events);
   1475       events=DestroyString(events);
   1476     }
   1477 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
   1478   NTWindowsGenesis();
   1479 #endif
   1480   /*
   1481     Set client name and execution path.
   1482   */
   1483 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
   1484   if ((path != (const char *) NULL) && (IsPathAccessible(path) != MagickFalse))
   1485 #else
   1486   if ((path != (const char *) NULL) && (*path == *DirectorySeparator) &&
   1487       (IsPathAccessible(path) != MagickFalse))
   1488 #endif
   1489     (void) CopyMagickString(execution_path,path,MagickPathExtent);
   1490   else
   1491     (void) GetExecutionPath(execution_path,MagickPathExtent);
   1492   GetPathComponent(execution_path,TailPath,filename);
   1493   (void) SetClientName(filename);
   1494   GetPathComponent(execution_path,HeadPath,execution_path);
   1495   (void) SetClientPath(execution_path);
   1496   if (establish_signal_handlers != MagickFalse)
   1497     {
   1498       /*
   1499         Set signal handlers.
   1500       */
   1501 #if defined(SIGABRT)
   1502       if (signal_handlers[SIGABRT] == (SignalHandler *) NULL)
   1503         signal_handlers[SIGABRT]=RegisterMagickSignalHandler(SIGABRT);
   1504 #endif
   1505 #if defined(SIGBUS)
   1506       if (signal_handlers[SIGBUS] == (SignalHandler *) NULL)
   1507         signal_handlers[SIGBUS]=RegisterMagickSignalHandler(SIGBUS);
   1508 #endif
   1509 #if defined(SIGSEGV)
   1510       if (signal_handlers[SIGSEGV] == (SignalHandler *) NULL)
   1511         signal_handlers[SIGSEGV]=RegisterMagickSignalHandler(SIGSEGV);
   1512 #endif
   1513 #if defined(SIGFPE)
   1514       if (signal_handlers[SIGFPE] == (SignalHandler *) NULL)
   1515         signal_handlers[SIGFPE]=RegisterMagickSignalHandler(SIGFPE);
   1516 #endif
   1517 #if defined(SIGHUP)
   1518       if (signal_handlers[SIGHUP] == (SignalHandler *) NULL)
   1519         signal_handlers[SIGHUP]=RegisterMagickSignalHandler(SIGHUP);
   1520 #endif
   1521 #if defined(SIGINT)
   1522       if (signal_handlers[SIGINT] == (SignalHandler *) NULL)
   1523         signal_handlers[SIGINT]=RegisterMagickSignalHandler(SIGINT);
   1524 #endif
   1525 #if defined(SIGQUIT)
   1526       if (signal_handlers[SIGQUIT] == (SignalHandler *) NULL)
   1527         signal_handlers[SIGQUIT]=RegisterMagickSignalHandler(SIGQUIT);
   1528 #endif
   1529 #if defined(SIGTERM)
   1530       if (signal_handlers[SIGTERM] == (SignalHandler *) NULL)
   1531         signal_handlers[SIGTERM]=RegisterMagickSignalHandler(SIGTERM);
   1532 #endif
   1533 #if defined(SIGXCPU)
   1534       if (signal_handlers[SIGXCPU] == (SignalHandler *) NULL)
   1535         signal_handlers[SIGXCPU]=RegisterMagickSignalHandler(SIGXCPU);
   1536 #endif
   1537 #if defined(SIGXFSZ)
   1538       if (signal_handlers[SIGXFSZ] == (SignalHandler *) NULL)
   1539         signal_handlers[SIGXFSZ]=RegisterMagickSignalHandler(SIGXFSZ);
   1540 #endif
   1541     }
   1542   /*
   1543     Instantiate magick resources.
   1544   */
   1545   (void) ConfigureComponentGenesis();
   1546   (void) PolicyComponentGenesis();
   1547 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
   1548   (void) ZeroConfigurationPolicy;
   1549 #endif
   1550   (void) CacheComponentGenesis();
   1551   (void) ResourceComponentGenesis();
   1552   (void) CoderComponentGenesis();
   1553   (void) MagickComponentGenesis();
   1554 #if defined(MAGICKCORE_MODULES_SUPPORT)
   1555   (void) ModuleComponentGenesis();
   1556 #endif
   1557   (void) DelegateComponentGenesis();
   1558   (void) MagicComponentGenesis();
   1559   (void) ColorComponentGenesis();
   1560   (void) TypeComponentGenesis();
   1561   (void) MimeComponentGenesis();
   1562   (void) AnnotateComponentGenesis();
   1563 #if defined(MAGICKCORE_X11_DELEGATE)
   1564   (void) XComponentGenesis();
   1565 #endif
   1566   (void) RegistryComponentGenesis();
   1567   (void) MonitorComponentGenesis();
   1568   instantiate_magickcore=MagickTrue;
   1569   UnlockMagickMutex();
   1570 }
   1571 
   1572 /*
   1574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1575 %                                                                             %
   1576 %                                                                             %
   1577 %                                                                             %
   1578 %   M a g i c k C o r e T e r m i n u s                                       %
   1579 %                                                                             %
   1580 %                                                                             %
   1581 %                                                                             %
   1582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1583 %
   1584 %  MagickCoreTerminus() destroys the MagickCore environment.
   1585 %
   1586 %  The format of the MagickCoreTerminus function is:
   1587 %
   1588 %      MagickCoreTerminus(void)
   1589 %
   1590 */
   1591 MagickExport void MagickCoreTerminus(void)
   1592 {
   1593   InitializeMagickMutex();
   1594   LockMagickMutex();
   1595   if (instantiate_magickcore == MagickFalse)
   1596     {
   1597       UnlockMagickMutex();
   1598       return;
   1599     }
   1600   MonitorComponentTerminus();
   1601   RegistryComponentTerminus();
   1602 #if defined(MAGICKCORE_X11_DELEGATE)
   1603   XComponentTerminus();
   1604 #endif
   1605 #if defined(MAGICKCORE_XML_DELEGATE)
   1606   xmlCleanupParser();
   1607 #endif
   1608   AnnotateComponentTerminus();
   1609   MimeComponentTerminus();
   1610   TypeComponentTerminus();
   1611 #if defined(MAGICKCORE_OPENCL_SUPPORT)
   1612   OpenCLTerminus();
   1613 #endif
   1614   ColorComponentTerminus();
   1615 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
   1616   NTWindowsTerminus();
   1617 #endif
   1618   MagicComponentTerminus();
   1619   DelegateComponentTerminus();
   1620   MagickComponentTerminus();
   1621 #if !defined(MAGICKCORE_BUILD_MODULES)
   1622   UnregisterStaticModules();
   1623 #endif
   1624 #if defined(MAGICKCORE_MODULES_SUPPORT)
   1625   ModuleComponentTerminus();
   1626 #endif
   1627   CoderComponentTerminus();
   1628   ResourceComponentTerminus();
   1629   CacheComponentTerminus();
   1630   PolicyComponentTerminus();
   1631   ConfigureComponentTerminus();
   1632   RandomComponentTerminus();
   1633   LocaleComponentTerminus();
   1634   LogComponentTerminus();
   1635   instantiate_magickcore=MagickFalse;
   1636   UnlockMagickMutex();
   1637   SemaphoreComponentTerminus();
   1638 }
   1639 
   1640 /*
   1642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1643 %                                                                             %
   1644 %                                                                             %
   1645 %                                                                             %
   1646 +   R e g i s t e r M a g i c k I n f o                                       %
   1647 %                                                                             %
   1648 %                                                                             %
   1649 %                                                                             %
   1650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1651 %
   1652 %  RegisterMagickInfo() adds attributes for a particular image format to the
   1653 %  list of supported formats.  The attributes include the image format name,
   1654 %  a method to read and/or write the format, whether the format supports the
   1655 %  saving of more than one frame to the same file or blob, whether the format
   1656 %  supports native in-memory I/O, and a brief description of the format.
   1657 %
   1658 %  The format of the RegisterMagickInfo method is:
   1659 %
   1660 %      MagickInfo *RegisterMagickInfo(MagickInfo *magick_info)
   1661 %
   1662 %  A description of each parameter follows:
   1663 %
   1664 %    o magick_info: the magick info.
   1665 %
   1666 */
   1667 MagickExport MagickBooleanType RegisterMagickInfo(MagickInfo *magick_info)
   1668 {
   1669   MagickBooleanType
   1670     status;
   1671 
   1672   /*
   1673     Register a new image format.
   1674   */
   1675   assert(magick_info != (MagickInfo *) NULL);
   1676   assert(magick_info->signature == MagickCoreSignature);
   1677   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",magick_info->name);
   1678   if (magick_list == (SplayTreeInfo *) NULL)
   1679     return(MagickFalse);
   1680   if ((GetMagickDecoderThreadSupport(magick_info) == MagickFalse) ||
   1681       (GetMagickEncoderThreadSupport(magick_info) == MagickFalse))
   1682     magick_info->semaphore=AcquireSemaphoreInfo();
   1683   status=AddValueToSplayTree(magick_list,magick_info->name,magick_info);
   1684   return(status);
   1685 }
   1686 
   1687 /*
   1689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1690 %                                                                             %
   1691 %                                                                             %
   1692 %                                                                             %
   1693 +   R e s e t M a g i c k P r e c i s i o n                                   %
   1694 %                                                                             %
   1695 %                                                                             %
   1696 %                                                                             %
   1697 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1698 %
   1699 %  ResetMagickPrecision() resets the magick_precision value.
   1700 %
   1701 %  The format of the ResetMagickPrecision method is:
   1702 %
   1703 %      void ResetMagickPrecision(void)
   1704 %
   1705 */
   1706 MagickPrivate void ResetMagickPrecision(void)
   1707 {
   1708   magick_precision=0;
   1709 }
   1710 
   1711 /*
   1713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1714 %                                                                             %
   1715 %                                                                             %
   1716 %                                                                             %
   1717 %   S e t M a g i c k P r e c i s i o n                                       %
   1718 %                                                                             %
   1719 %                                                                             %
   1720 %                                                                             %
   1721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1722 %
   1723 %  SetMagickPrecision() sets the maximum number of significant digits to be
   1724 %  printed.
   1725 %
   1726 %  An input argument of 0 returns the current precision setting.
   1727 %
   1728 %  A negative value forces the precision to reset to a default value according
   1729 %  to the environment variable "MAGICK_PRECISION", the current 'policy'
   1730 %  configuration setting, or the default value of '6', in that order.
   1731 %
   1732 %  The format of the SetMagickPrecision method is:
   1733 %
   1734 %      int SetMagickPrecision(const int precision)
   1735 %
   1736 %  A description of each parameter follows:
   1737 %
   1738 %    o precision: set the maximum number of significant digits to be printed.
   1739 %
   1740 */
   1741 MagickExport int SetMagickPrecision(const int precision)
   1742 {
   1743 #define MagickPrecision  6
   1744 
   1745   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   1746   if (precision > 0)
   1747     magick_precision=precision;
   1748   if ((precision < 0) || (magick_precision == 0))
   1749     {
   1750       char
   1751         *limit;
   1752 
   1753       /*
   1754         Precision reset, or it has not been set yet
   1755       */
   1756       magick_precision=MagickPrecision;
   1757       limit=GetEnvironmentValue("MAGICK_PRECISION");
   1758       if (limit == (char *) NULL)
   1759         limit=GetPolicyValue("system:precision");
   1760       if (limit != (char *) NULL)
   1761         {
   1762           magick_precision=StringToInteger(limit);
   1763           limit=DestroyString(limit);
   1764         }
   1765     }
   1766   return(magick_precision);
   1767 }
   1768 
   1769 /*
   1771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1772 %                                                                             %
   1773 %                                                                             %
   1774 %                                                                             %
   1775 +   U n r e g i s t e r M a g i c k I n f o                                   %
   1776 %                                                                             %
   1777 %                                                                             %
   1778 %                                                                             %
   1779 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1780 %
   1781 %  UnregisterMagickInfo() removes a name from the magick info list.  It returns
   1782 %  MagickFalse if the name does not exist in the list otherwise MagickTrue.
   1783 %
   1784 %  The format of the UnregisterMagickInfo method is:
   1785 %
   1786 %      MagickBooleanType UnregisterMagickInfo(const char *name)
   1787 %
   1788 %  A description of each parameter follows:
   1789 %
   1790 %    o name: a character string that represents the image format we are
   1791 %      looking for.
   1792 %
   1793 */
   1794 MagickExport MagickBooleanType UnregisterMagickInfo(const char *name)
   1795 {
   1796   register const MagickInfo
   1797     *p;
   1798 
   1799   MagickBooleanType
   1800     status;
   1801 
   1802   assert(name != (const char *) NULL);
   1803   if (magick_list == (SplayTreeInfo *) NULL)
   1804     return(MagickFalse);
   1805   if (GetNumberOfNodesInSplayTree(magick_list) == 0)
   1806     return(MagickFalse);
   1807   LockSemaphoreInfo(magick_semaphore);
   1808   ResetSplayTreeIterator(magick_list);
   1809   p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
   1810   while (p != (const MagickInfo *) NULL)
   1811   {
   1812     if (LocaleCompare(p->name,name) == 0)
   1813       break;
   1814     p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
   1815   }
   1816   status=DeleteNodeByValueFromSplayTree(magick_list,p);
   1817   UnlockSemaphoreInfo(magick_semaphore);
   1818   return(status);
   1819 }
   1820