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