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