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