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