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