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