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