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