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