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