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