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