blob: 94db46e62d352a105bfbe30f3722389b6b3a1e71 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
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% John Cristy %
18% November 1998 %
19% %
20% %
cristy7e41fe82010-12-04 23:12:08 +000021% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000022% 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% http://www.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*/
cristy4c08aed2011-07-01 19:47:50 +000043#include "MagickCore/studio.h"
cristy5ff4eaf2011-09-03 01:38:02 +000044#include "MagickCore/annotate-private.h"
cristy4c08aed2011-07-01 19:47:50 +000045#include "MagickCore/blob.h"
46#include "MagickCore/blob-private.h"
47#include "MagickCore/cache.h"
cristy5ff4eaf2011-09-03 01:38:02 +000048#include "MagickCore/cache-private.h"
49#include "MagickCore/coder-private.h"
cristy4c08aed2011-07-01 19:47:50 +000050#include "MagickCore/client.h"
cristy5ff4eaf2011-09-03 01:38:02 +000051#include "MagickCore/color-private.h"
52#include "MagickCore/configure-private.h"
53#include "MagickCore/constitute-private.h"
54#include "MagickCore/delegate-private.h"
cristy4c08aed2011-07-01 19:47:50 +000055#include "MagickCore/draw.h"
56#include "MagickCore/exception.h"
57#include "MagickCore/exception-private.h"
cristy5ff4eaf2011-09-03 01:38:02 +000058#include "MagickCore/locale-private.h"
59#include "MagickCore/log-private.h"
60#include "MagickCore/magic-private.h"
cristy4c08aed2011-07-01 19:47:50 +000061#include "MagickCore/magick.h"
cristy5ff4eaf2011-09-03 01:38:02 +000062#include "MagickCore/magick-private.h"
cristy4c08aed2011-07-01 19:47:50 +000063#include "MagickCore/memory_.h"
cristy5ff4eaf2011-09-03 01:38:02 +000064#include "MagickCore/mime-private.h"
cristy4c08aed2011-07-01 19:47:50 +000065#include "MagickCore/module.h"
cristy5ff4eaf2011-09-03 01:38:02 +000066#include "MagickCore/module-private.h"
cristy0740a982011-10-13 15:01:01 +000067#include "MagickCore/nt-base-private.h"
cristy5ff4eaf2011-09-03 01:38:02 +000068#include "MagickCore/random-private.h"
cristy4c08aed2011-07-01 19:47:50 +000069#include "MagickCore/registry.h"
cristy5ff4eaf2011-09-03 01:38:02 +000070#include "MagickCore/registry-private.h"
cristy4c08aed2011-07-01 19:47:50 +000071#include "MagickCore/resource_.h"
cristy0a4d92f2011-08-31 19:25:00 +000072#include "MagickCore/resource-private.h"
cristy4c08aed2011-07-01 19:47:50 +000073#include "MagickCore/policy.h"
cristy5ff4eaf2011-09-03 01:38:02 +000074#include "MagickCore/policy-private.h"
cristy4c08aed2011-07-01 19:47:50 +000075#include "MagickCore/semaphore.h"
76#include "MagickCore/semaphore-private.h"
77#include "MagickCore/signature-private.h"
78#include "MagickCore/splay-tree.h"
79#include "MagickCore/string_.h"
80#include "MagickCore/string-private.h"
81#include "MagickCore/thread_.h"
82#include "MagickCore/thread-private.h"
cristy5ff4eaf2011-09-03 01:38:02 +000083#include "MagickCore/type-private.h"
cristy4c08aed2011-07-01 19:47:50 +000084#include "MagickCore/token.h"
85#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000086#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000087#include "MagickCore/xwindow-private.h"
cristy3ed852e2009-09-05 21:47:34 +000088
89/*
90 Define declarations.
91*/
92#if !defined(MAGICKCORE_RETSIGTYPE)
93# define MAGICKCORE_RETSIGTYPE void
94#endif
95#if !defined(SIG_DFL)
96# define SIG_DFL ((SignalHandler *) 0)
97#endif
98#if !defined(SIG_ERR)
99# define SIG_ERR ((SignalHandler *) -1)
100#endif
101#if !defined(SIGMAX)
102#define SIGMAX 64
103#endif
104
105/*
106 Typedef declarations.
107*/
108typedef MAGICKCORE_RETSIGTYPE
109 SignalHandler(int);
110
111/*
112 Global declarations.
113*/
114static SemaphoreInfo
115 *magick_semaphore = (SemaphoreInfo *) NULL;
116
117static SignalHandler
118 *signal_handlers[SIGMAX] = { (SignalHandler *) NULL };
119
120static SplayTreeInfo
121 *magick_list = (SplayTreeInfo *) NULL;
122
123static volatile MagickBooleanType
cristyd1ebf4a2010-05-13 01:54:31 +0000124 instantiate_magick = MagickFalse,
125 instantiate_magickcore = MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000126
127/*
128 Forward declarations.
129*/
130static MagickBooleanType
131 InitializeMagickList(ExceptionInfo *);
132
133/*
134%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135% %
136% %
137% %
cristy3ed852e2009-09-05 21:47:34 +0000138+ G e t I m a g e D e c o d e r %
139% %
140% %
141% %
142%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143%
144% GetImageDecoder() returns the image decoder.
145%
146% The format of the GetImageDecoder method is:
147%
148% DecodeImageHandler *GetImageDecoder(const MagickInfo *magick_info)
149%
150% A description of each parameter follows:
151%
152% o magick_info: The magick info.
153%
154*/
155MagickExport DecodeImageHandler *GetImageDecoder(const MagickInfo *magick_info)
156{
157 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
158 assert(magick_info != (MagickInfo *) NULL);
159 assert(magick_info->signature == MagickSignature);
160 return(magick_info->decoder);
161}
162
163/*
164%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
165% %
166% %
167% %
168+ G e t I m a g e E n c o d e r %
169% %
170% %
171% %
172%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173%
174% GetImageEncoder() returns the image encoder.
175%
176% The format of the GetImageEncoder method is:
177%
178% EncodeImageHandler *GetImageEncoder(const MagickInfo *magick_info)
179%
180% A description of each parameter follows:
181%
182% o magick_info: The magick info.
183%
184*/
185MagickExport EncodeImageHandler *GetImageEncoder(const MagickInfo *magick_info)
186{
187 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
188 assert(magick_info != (MagickInfo *) NULL);
189 assert(magick_info->signature == MagickSignature);
190 return(magick_info->encoder);
191}
192
193/*
194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
195% %
196% %
197% %
198+ G e t I m a g e M a g i c k %
199% %
200% %
201% %
202%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
203%
204% GetImageMagick() searches for an image format that matches the specified
205% magick string. If one is found, MagickTrue is returned otherwise
206% MagickFalse.
207%
208% The format of the GetImageMagick method is:
209%
210% MagickBooleanType GetImageMagick(const unsigned char *magick,
211% const size_t length,char *format)
212%
213% A description of each parameter follows:
214%
215% o magick: the image format we are searching for.
216%
217% o length: the length of the binary string.
218%
219% o format: the image format as determined by the magick bytes.
220%
221*/
222MagickExport MagickBooleanType GetImageMagick(const unsigned char *magick,
223 const size_t length,char *format)
224{
225 ExceptionInfo
226 *exception;
227
228 MagickBooleanType
229 status;
230
231 register const MagickInfo
232 *p;
233
234 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
235 assert(magick != (const unsigned char *) NULL);
236 exception=AcquireExceptionInfo();
237 p=GetMagickInfo("*",exception);
238 exception=DestroyExceptionInfo(exception);
239 if (p == (const MagickInfo *) NULL)
240 return(MagickFalse);
241 status=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +0000242 LockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000243 ResetSplayTreeIterator(magick_list);
244 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
245 while (p != (const MagickInfo *) NULL)
246 {
247 if ((p->magick != (IsImageFormatHandler *) NULL) &&
248 (p->magick(magick,length) != 0))
249 {
250 status=MagickTrue;
251 (void) CopyMagickString(format,p->name,MaxTextExtent);
252 break;
253 }
254 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
255 }
cristyf84a1932010-01-03 18:00:18 +0000256 UnlockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000257 return(status);
258}
259
260/*
261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262% %
263% %
264% %
265+ G e t M a g i c k A d j o i n %
266% %
267% %
268% %
269%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270%
271% GetMagickAdjoin() returns MagickTrue if the magick adjoin is MagickTrue.
272%
273% The format of the GetMagickAdjoin method is:
274%
275% MagickBooleanType GetMagickAdjoin(const MagickInfo *magick_info)
276%
277% A description of each parameter follows:
278%
279% o magick_info: The magick info.
280%
281*/
282MagickExport MagickBooleanType GetMagickAdjoin(const MagickInfo *magick_info)
283{
284 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
285 assert(magick_info != (MagickInfo *) NULL);
286 assert(magick_info->signature == MagickSignature);
287 return(magick_info->adjoin);
288}
289
290/*
291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
292% %
293% %
294% %
295+ G e t M a g i c k B l o b S u p p o r t %
296% %
297% %
298% %
299%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
300%
301% GetMagickBlobSupport() returns MagickTrue if the magick supports blobs.
302%
303% The format of the GetMagickBlobSupport method is:
304%
305% MagickBooleanType GetMagickBlobSupport(const MagickInfo *magick_info)
306%
307% A description of each parameter follows:
308%
309% o magick_info: The magick info.
310%
311*/
312MagickExport MagickBooleanType GetMagickBlobSupport(
313 const MagickInfo *magick_info)
314{
315 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
316 assert(magick_info != (MagickInfo *) NULL);
317 assert(magick_info->signature == MagickSignature);
318 return(magick_info->blob_support);
319}
320
321/*
322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
323% %
324% %
325% %
326+ G e t M a g i c k D e s c r i p t i o n %
327% %
328% %
329% %
330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
331%
332% GetMagickDescription() returns the magick description.
333%
334% The format of the GetMagickDescription method is:
335%
336% const char *GetMagickDescription(const MagickInfo *magick_info)
337%
338% A description of each parameter follows:
339%
340% o magick_info: The magick info.
341%
342*/
343MagickExport const char *GetMagickDescription(const MagickInfo *magick_info)
344{
345 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
346 assert(magick_info != (MagickInfo *) NULL);
347 assert(magick_info->signature == MagickSignature);
348 return(magick_info->description);
349}
350
351/*
352%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353% %
354% %
355% %
356+ G e t M a g i c k E n d i a n S u p p o r t %
357% %
358% %
359% %
360%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361%
362% GetMagickEndianSupport() returns the MagickTrue if the coder respects
363% endianness other than MSBEndian.
364%
365% The format of the GetMagickEndianSupport method is:
366%
367% MagickBooleanType GetMagickEndianSupport(const MagickInfo *magick_info)
368%
369% A description of each parameter follows:
370%
371% o magick_info: The magick info.
372%
373*/
374MagickExport MagickBooleanType GetMagickEndianSupport(
375 const MagickInfo *magick_info)
376{
377 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
378 assert(magick_info != (MagickInfo *) NULL);
379 assert(magick_info->signature == MagickSignature);
380 return(magick_info->endian_support);
381}
382
383/*
384%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
385% %
386% %
387% %
388+ G e t M a g i c k I n f o %
389% %
390% %
391% %
392%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
393%
394% GetMagickInfo() returns a pointer MagickInfo structure that matches
395% the specified name. If name is NULL, the head of the image format list
396% is returned.
397%
398% The format of the GetMagickInfo method is:
399%
400% const MagickInfo *GetMagickInfo(const char *name,Exception *exception)
401%
402% A description of each parameter follows:
403%
404% o name: the image format we are looking for.
405%
406% o exception: return any errors or warnings in this structure.
407%
408*/
409MagickExport const MagickInfo *GetMagickInfo(const char *name,
410 ExceptionInfo *exception)
411{
412 register const MagickInfo
413 *p;
414
415 assert(exception != (ExceptionInfo *) NULL);
416 if ((magick_list == (SplayTreeInfo *) NULL) ||
417 (instantiate_magick == MagickFalse))
418 if (InitializeMagickList(exception) == MagickFalse)
419 return((const MagickInfo *) NULL);
420 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
421 {
422#if defined(MAGICKCORE_MODULES_SUPPORT)
423 if (LocaleCompare(name,"*") == 0)
424 (void) OpenModules(exception);
425#endif
cristyf84a1932010-01-03 18:00:18 +0000426 LockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000427 ResetSplayTreeIterator(magick_list);
428 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
cristyf84a1932010-01-03 18:00:18 +0000429 UnlockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000430 return(p);
431 }
432 /*
433 Find name in list.
434 */
cristyf84a1932010-01-03 18:00:18 +0000435 LockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000436 ResetSplayTreeIterator(magick_list);
437 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
438 while (p != (const MagickInfo *) NULL)
439 {
440 if (LocaleCompare(p->name,name) == 0)
441 break;
442 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
443 }
444#if defined(MAGICKCORE_MODULES_SUPPORT)
445 if (p == (const MagickInfo *) NULL)
446 {
447 if (*name != '\0')
448 (void) OpenModule(name,exception);
449 ResetSplayTreeIterator(magick_list);
450 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
451 while (p != (const MagickInfo *) NULL)
452 {
453 if (LocaleCompare(p->name,name) == 0)
454 break;
455 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
456 }
457 }
458#endif
cristyf84a1932010-01-03 18:00:18 +0000459 UnlockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000460 return(p);
461}
462
463/*
464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
465% %
466% %
467% %
468+ G e t M a g i c k I n f o L i s t %
469% %
470% %
471% %
472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
473%
474% GetMagickInfoList() returns any image formats that match the specified
475% pattern.
476%
477% The format of the GetMagickInfoList function is:
478%
479% const MagickInfo **GetMagickInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000480% size_t *number_formats,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000481%
482% A description of each parameter follows:
483%
484% o pattern: Specifies a pointer to a text string containing a pattern.
485%
486% o number_formats: This integer returns the number of formats in the list.
487%
488% o exception: return any errors or warnings in this structure.
489%
490*/
491
492#if defined(__cplusplus) || defined(c_plusplus)
493extern "C" {
494#endif
495
496static int MagickInfoCompare(const void *x,const void *y)
497{
498 const MagickInfo
499 **p,
500 **q;
501
502 p=(const MagickInfo **) x,
503 q=(const MagickInfo **) y;
504 return(LocaleCompare((*p)->name,(*q)->name));
505}
506
507#if defined(__cplusplus) || defined(c_plusplus)
508}
509#endif
510
511MagickExport const MagickInfo **GetMagickInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000512 size_t *number_formats,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000513{
514 const MagickInfo
515 **formats;
516
517 register const MagickInfo
518 *p;
519
cristybb503372010-05-27 20:51:26 +0000520 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000521 i;
522
523 /*
524 Allocate magick list.
525 */
526 assert(pattern != (char *) NULL);
527 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000528 assert(number_formats != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000529 *number_formats=0;
530 p=GetMagickInfo("*",exception);
531 if (p == (const MagickInfo *) NULL)
532 return((const MagickInfo **) NULL);
533 formats=(const MagickInfo **) AcquireQuantumMemory((size_t)
534 GetNumberOfNodesInSplayTree(magick_list)+1UL,sizeof(*formats));
535 if (formats == (const MagickInfo **) NULL)
536 return((const MagickInfo **) NULL);
537 /*
538 Generate magick list.
539 */
cristyf84a1932010-01-03 18:00:18 +0000540 LockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000541 ResetSplayTreeIterator(magick_list);
542 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
543 for (i=0; p != (const MagickInfo *) NULL; )
544 {
545 if ((p->stealth == MagickFalse) &&
546 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
547 formats[i++]=p;
548 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
549 }
cristyf84a1932010-01-03 18:00:18 +0000550 UnlockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000551 qsort((void *) formats,(size_t) i,sizeof(*formats),MagickInfoCompare);
552 formats[i]=(MagickInfo *) NULL;
cristybb503372010-05-27 20:51:26 +0000553 *number_formats=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000554 return(formats);
555}
556
557/*
558%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
559% %
560% %
561% %
562+ G e t M a g i c k L i s t %
563% %
564% %
565% %
566%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567%
568% GetMagickList() returns any image formats that match the specified pattern.
569%
570% The format of the GetMagickList function is:
571%
cristybb503372010-05-27 20:51:26 +0000572% char **GetMagickList(const char *pattern,size_t *number_formats,
cristy3ed852e2009-09-05 21:47:34 +0000573% ExceptionInfo *exception)
574%
575% A description of each parameter follows:
576%
577% o pattern: Specifies a pointer to a text string containing a pattern.
578%
579% o number_formats: This integer returns the number of formats in the list.
580%
581% o exception: return any errors or warnings in this structure.
582%
583*/
584
585#if defined(__cplusplus) || defined(c_plusplus)
586extern "C" {
587#endif
588
589static int MagickCompare(const void *x,const void *y)
590{
591 register const char
592 **p,
593 **q;
594
595 p=(const char **) x;
596 q=(const char **) y;
597 return(LocaleCompare(*p,*q));
598}
599
600#if defined(__cplusplus) || defined(c_plusplus)
601}
602#endif
603
604MagickExport char **GetMagickList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000605 size_t *number_formats,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000606{
607 char
608 **formats;
609
610 register const MagickInfo
611 *p;
612
cristybb503372010-05-27 20:51:26 +0000613 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000614 i;
615
616 /*
617 Allocate magick list.
618 */
619 assert(pattern != (char *) NULL);
620 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000621 assert(number_formats != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000622 *number_formats=0;
623 p=GetMagickInfo("*",exception);
624 if (p == (const MagickInfo *) NULL)
625 return((char **) NULL);
626 formats=(char **) AcquireQuantumMemory((size_t)
627 GetNumberOfNodesInSplayTree(magick_list)+1UL,sizeof(*formats));
628 if (formats == (char **) NULL)
629 return((char **) NULL);
cristyf84a1932010-01-03 18:00:18 +0000630 LockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000631 ResetSplayTreeIterator(magick_list);
632 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
633 for (i=0; p != (const MagickInfo *) NULL; )
634 {
635 if ((p->stealth == MagickFalse) &&
636 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
637 formats[i++]=ConstantString(p->name);
638 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
639 }
cristyf84a1932010-01-03 18:00:18 +0000640 UnlockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000641 qsort((void *) formats,(size_t) i,sizeof(*formats),MagickCompare);
642 formats[i]=(char *) NULL;
cristybb503372010-05-27 20:51:26 +0000643 *number_formats=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000644 return(formats);
645}
646
647/*
648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
649% %
650% %
651% %
cristye7f51092010-01-17 00:39:37 +0000652% G e t M a g i c k P r e c i s i o n %
cristy7ce14bc2010-01-17 00:01:01 +0000653% %
654% %
655% %
656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
657%
658% GetMagickPrecision() returns the maximum number of significant digits to be
659% printed.
660%
661% The format of the GetMagickPrecision method is:
662%
cristye7f51092010-01-17 00:39:37 +0000663% int GetMagickPrecision(void)
cristy7ce14bc2010-01-17 00:01:01 +0000664%
665*/
cristye7f51092010-01-17 00:39:37 +0000666MagickExport int GetMagickPrecision(void)
cristy7ce14bc2010-01-17 00:01:01 +0000667{
cristye7f51092010-01-17 00:39:37 +0000668#define MagickPrecision 6
cristy7ce14bc2010-01-17 00:01:01 +0000669
670 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristybf2766a2010-01-17 03:33:23 +0000671 if (SetMagickPrecision(0) == 0)
cristy7ce14bc2010-01-17 00:01:01 +0000672 {
673 char
674 *limit;
675
cristybf2766a2010-01-17 03:33:23 +0000676 (void) SetMagickPrecision(MagickPrecision);
cristye7f51092010-01-17 00:39:37 +0000677 limit=GetEnvironmentValue("MAGICK_PRECISION");
678 if (limit == (char *) NULL)
679 limit=GetPolicyValue("precision");
680 if (limit != (char *) NULL)
681 {
cristybf2766a2010-01-17 03:33:23 +0000682 (void) SetMagickPrecision(StringToInteger(limit));
cristye7f51092010-01-17 00:39:37 +0000683 limit=DestroyString(limit);
684 }
cristy7ce14bc2010-01-17 00:01:01 +0000685 }
cristybf2766a2010-01-17 03:33:23 +0000686 return(SetMagickPrecision(0));
cristy7ce14bc2010-01-17 00:01:01 +0000687}
688
689/*
690%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
691% %
692% %
693% %
694+ G e t M a g i c k R a w S u p p o r t %
cristy3ed852e2009-09-05 21:47:34 +0000695% %
696% %
697% %
698%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
699%
700% GetMagickRawSupport() returns the MagickTrue if the coder is a raw format.
701%
702% The format of the GetMagickRawSupport method is:
703%
704% MagickBooleanType GetMagickRawSupport(const MagickInfo *magick_info)
705%
706% A description of each parameter follows:
707%
708% o magick_info: The magick info.
709%
710*/
711MagickExport MagickBooleanType GetMagickRawSupport(
712 const MagickInfo *magick_info)
713{
714 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
715 assert(magick_info != (MagickInfo *) NULL);
716 assert(magick_info->signature == MagickSignature);
717 return(magick_info->raw);
718}
719
720/*
721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722% %
723% %
724% %
725+ G e t M a g i c k S e e k a b l e S t r e a m %
726% %
727% %
728% %
729%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
730%
731% GetMagickSeekableStream() returns MagickTrue if the magick supports a
732% seekable stream.
733%
734% The format of the GetMagickSeekableStream method is:
735%
736% MagickBooleanType GetMagickSeekableStream(const MagickInfo *magick_info)
737%
738% A description of each parameter follows:
739%
740% o magick_info: The magick info.
741%
742*/
743MagickExport MagickBooleanType GetMagickSeekableStream(
744 const MagickInfo *magick_info)
745{
746 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
747 assert(magick_info != (MagickInfo *) NULL);
748 assert(magick_info->signature == MagickSignature);
749 return(magick_info->seekable_stream);
750}
751
752/*
753%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
754% %
755% %
756% %
757+ G e t M a g i c k T h r e a d S u p p o r t %
758% %
759% %
760% %
761%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
762%
763% GetMagickThreadSupport() returns MagickTrue if the magick supports threads.
764%
765% The format of the GetMagickThreadSupport method is:
766%
767% MagickStatusType GetMagickThreadSupport(const MagickInfo *magick_info)
768%
769% A description of each parameter follows:
770%
771% o magick_info: The magick info.
772%
773*/
774MagickExport MagickStatusType GetMagickThreadSupport(
775 const MagickInfo *magick_info)
776{
777 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
778 assert(magick_info != (MagickInfo *) NULL);
779 assert(magick_info->signature == MagickSignature);
780 return(magick_info->thread_support);
781}
782
783/*
784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
785% %
786% %
787% %
788+ I n i t i a l i z e M a g i c k L i s t %
789% %
790% %
791% %
792%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
793%
794% InitializeMagickList() initializes the magick list.
795%
796% The format of the InitializeMagickList() method is:
797%
798% InitializeMagickList(Exceptioninfo *exception)
799%
800% A description of each parameter follows.
801%
802% o exception: return any errors or warnings in this structure.
803%
804*/
805
806static void *DestroyMagickNode(void *magick_info)
807{
808 register MagickInfo
809 *p;
810
811 p=(MagickInfo *) magick_info;
812 if (p->name != (char *) NULL)
813 p->name=DestroyString(p->name);
814 if (p->description != (char *) NULL)
815 p->description=DestroyString(p->description);
816 if (p->version != (char *) NULL)
817 p->version=DestroyString(p->version);
818 if (p->note != (char *) NULL)
819 p->note=DestroyString(p->note);
820 if (p->module != (char *) NULL)
821 p->module=DestroyString(p->module);
822 return(RelinquishMagickMemory(p));
823}
824
825static MagickBooleanType InitializeMagickList(ExceptionInfo *exception)
826{
cristyf2e11662009-10-14 01:24:43 +0000827 (void) exception;
cristy3ed852e2009-09-05 21:47:34 +0000828 if ((magick_list == (SplayTreeInfo *) NULL) &&
829 (instantiate_magick == MagickFalse))
830 {
cristy4e1dff62009-10-25 20:36:03 +0000831 if (magick_semaphore == (SemaphoreInfo *) NULL)
832 AcquireSemaphoreInfo(&magick_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000833 LockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000834 if ((magick_list == (SplayTreeInfo *) NULL) &&
835 (instantiate_magick == MagickFalse))
836 {
837 MagickBooleanType
838 status;
839
840 MagickInfo
841 *magick_info;
842
843 magick_list=NewSplayTree(CompareSplayTreeString,
844 (void *(*)(void *)) NULL,DestroyMagickNode);
845 if (magick_list == (SplayTreeInfo *) NULL)
846 ThrowFatalException(ResourceLimitFatalError,
847 "MemoryAllocationFailed");
848 magick_info=SetMagickInfo("ephemeral");
849 magick_info->stealth=MagickTrue;
850 status=AddValueToSplayTree(magick_list,magick_info->name,magick_info);
851 if (status == MagickFalse)
852 ThrowFatalException(ResourceLimitFatalError,
853 "MemoryAllocationFailed");
854 magick_info=SetMagickInfo("clipmask");
855 magick_info->stealth=MagickTrue;
856 status=AddValueToSplayTree(magick_list,magick_info->name,magick_info);
857 if (status == MagickFalse)
858 {
859 char
860 *message;
861
862 message=GetExceptionMessage(errno);
863 ThrowFatalException(ResourceLimitFatalError,
864 "MemoryAllocationFailed");
865 message=DestroyString(message);
866 }
867#if defined(MAGICKCORE_MODULES_SUPPORT)
868 (void) GetModuleInfo((char *) NULL,exception);
869#endif
870#if !defined(MAGICKCORE_BUILD_MODULES)
871 RegisterStaticModules();
872#endif
873 instantiate_magick=MagickTrue;
874 }
cristyf84a1932010-01-03 18:00:18 +0000875 UnlockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000876 }
877 return(magick_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
878}
879
880/*
881%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
882% %
883% %
884% %
885+ I s M a g i c k C o n f l i c t %
886% %
887% %
888% %
889%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
890%
cristy05a9a622010-03-15 17:26:04 +0000891% IsMagickConflict() returns MagickTrue if the image format conflicts with a
892% logical drive (.e.g. X:).
cristy3ed852e2009-09-05 21:47:34 +0000893%
894% The format of the IsMagickConflict method is:
895%
896% MagickBooleanType IsMagickConflict(const char *magick)
897%
898% A description of each parameter follows:
899%
900% o magick: Specifies the image format.
901%
902*/
cristy7832dc22011-09-05 01:21:53 +0000903MagickPrivate MagickBooleanType IsMagickConflict(const char *magick)
cristy3ed852e2009-09-05 21:47:34 +0000904{
cristy3ed852e2009-09-05 21:47:34 +0000905 assert(magick != (char *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000906#if defined(macintosh)
907 return(MACIsMagickConflict(magick));
908#elif defined(vms)
909 return(VMSIsMagickConflict(magick));
cristy0157aea2010-04-24 21:12:18 +0000910#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000911 return(NTIsMagickConflict(magick));
912#else
913 return(MagickFalse);
914#endif
915}
916
917/*
918%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
919% %
920% %
921% %
922+ L i s t M a g i c k I n f o %
923% %
924% %
925% %
926%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
927%
928% ListMagickInfo() lists the image formats to a file.
929%
930% The format of the ListMagickInfo method is:
931%
932% MagickBooleanType ListMagickInfo(FILE *file,ExceptionInfo *exception)
933%
934% A description of each parameter follows.
935%
936% o file: A file handle.
937%
938% o exception: return any errors or warnings in this structure.
939%
940*/
941MagickExport MagickBooleanType ListMagickInfo(FILE *file,
942 ExceptionInfo *exception)
943{
944 const MagickInfo
945 **magick_info;
946
cristybb503372010-05-27 20:51:26 +0000947 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000948 i;
949
cristybb503372010-05-27 20:51:26 +0000950 size_t
cristy3ed852e2009-09-05 21:47:34 +0000951 number_formats;
952
cristy9d314ff2011-03-09 01:30:28 +0000953 ssize_t
954 j;
955
cristy3ed852e2009-09-05 21:47:34 +0000956 if (file == (FILE *) NULL)
957 file=stdout;
958 magick_info=GetMagickInfoList("*",&number_formats,exception);
959 if (magick_info == (const MagickInfo **) NULL)
960 return(MagickFalse);
961 ClearMagickException(exception);
962#if !defined(MAGICKCORE_MODULES_SUPPORT)
cristyb51dff52011-05-19 16:55:47 +0000963 (void) FormatLocaleFile(file," Format Mode Description\n");
cristy3ed852e2009-09-05 21:47:34 +0000964#else
cristyb51dff52011-05-19 16:55:47 +0000965 (void) FormatLocaleFile(file," Format Module Mode Description\n");
cristy3ed852e2009-09-05 21:47:34 +0000966#endif
cristy1e604812011-05-19 18:07:50 +0000967 (void) FormatLocaleFile(file,
968 "--------------------------------------------------------"
cristy3ed852e2009-09-05 21:47:34 +0000969 "-----------------------\n");
cristybb503372010-05-27 20:51:26 +0000970 for (i=0; i < (ssize_t) number_formats; i++)
cristy3ed852e2009-09-05 21:47:34 +0000971 {
972 if (magick_info[i]->stealth != MagickFalse)
973 continue;
cristy1e604812011-05-19 18:07:50 +0000974 (void) FormatLocaleFile(file,"%9s%c ",
975 magick_info[i]->name != (char *) NULL ? magick_info[i]->name : "",
cristy3ed852e2009-09-05 21:47:34 +0000976 magick_info[i]->blob_support != MagickFalse ? '*' : ' ');
977#if defined(MAGICKCORE_MODULES_SUPPORT)
978 {
979 char
980 module[MaxTextExtent];
981
982 *module='\0';
983 if (magick_info[i]->module != (char *) NULL)
984 (void) CopyMagickString(module,magick_info[i]->module,MaxTextExtent);
985 (void) ConcatenateMagickString(module," ",MaxTextExtent);
986 module[9]='\0';
cristyb51dff52011-05-19 16:55:47 +0000987 (void) FormatLocaleFile(file,"%9s ",module);
cristy3ed852e2009-09-05 21:47:34 +0000988 }
989#endif
cristyb51dff52011-05-19 16:55:47 +0000990 (void) FormatLocaleFile(file,"%c%c%c ",magick_info[i]->decoder ? 'r' : '-',
cristy3ed852e2009-09-05 21:47:34 +0000991 magick_info[i]->encoder ? 'w' : '-',magick_info[i]->encoder != NULL &&
992 magick_info[i]->adjoin != MagickFalse ? '+' : '-');
993 if (magick_info[i]->description != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000994 (void) FormatLocaleFile(file," %s",magick_info[i]->description);
cristy3ed852e2009-09-05 21:47:34 +0000995 if (magick_info[i]->version != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000996 (void) FormatLocaleFile(file," (%s)",magick_info[i]->version);
997 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +0000998 if (magick_info[i]->note != (char *) NULL)
999 {
1000 char
1001 **text;
1002
1003 text=StringToList(magick_info[i]->note);
1004 if (text != (char **) NULL)
1005 {
1006 for (j=0; text[j] != (char *) NULL; j++)
1007 {
cristyb51dff52011-05-19 16:55:47 +00001008 (void) FormatLocaleFile(file," %s\n",text[j]);
cristy3ed852e2009-09-05 21:47:34 +00001009 text[j]=DestroyString(text[j]);
1010 }
1011 text=(char **) RelinquishMagickMemory(text);
1012 }
1013 }
1014 }
cristyb51dff52011-05-19 16:55:47 +00001015 (void) FormatLocaleFile(file,"\n* native blob support\n");
1016 (void) FormatLocaleFile(file,"r read support\n");
1017 (void) FormatLocaleFile(file,"w write support\n");
1018 (void) FormatLocaleFile(file,"+ support for multiple images\n");
cristy3ed852e2009-09-05 21:47:34 +00001019 (void) fflush(file);
1020 magick_info=(const MagickInfo **) RelinquishMagickMemory((void *)
1021 magick_info);
1022 return(MagickTrue);
1023}
1024
1025/*
1026%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1027% %
1028% %
1029% %
1030% I s M a g i c k I n s t a n t i a t e d %
1031% %
1032% %
1033% %
1034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1035%
1036% IsMagickInstantiated() returns MagickTrue if the ImageMagick environment
1037% is currently instantiated: MagickCoreGenesis() has been called but
1038% MagickDestroy() has not.
1039%
1040% The format of the IsMagickInstantiated method is:
1041%
1042% MagickBooleanType IsMagickInstantiated(void)
1043%
1044*/
1045MagickExport MagickBooleanType IsMagickInstantiated(void)
1046{
1047 return(instantiate_magick);
1048}
1049
1050/*
1051%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1052% %
1053% %
1054% %
cristyf34a1452009-10-24 22:29:27 +00001055+ M a g i c k C o m p o n e n t G e n e s i s %
1056% %
1057% %
1058% %
1059%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1060%
1061% MagickComponentGenesis() instantiates the magick component.
1062%
1063% The format of the MagickComponentGenesis method is:
1064%
1065% MagickBooleanType MagickComponentGenesis(void)
1066%
1067*/
cristy5ff4eaf2011-09-03 01:38:02 +00001068MagickPrivate MagickBooleanType MagickComponentGenesis(void)
cristyf34a1452009-10-24 22:29:27 +00001069{
cristy165b6092009-10-26 13:52:10 +00001070 AcquireSemaphoreInfo(&magick_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001071 return(MagickTrue);
1072}
1073
1074/*
1075%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1076% %
1077% %
1078% %
1079+ M a g i c k C o m p o n e n t T e r m i n u s %
1080% %
1081% %
1082% %
1083%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1084%
1085% MagickComponentTerminus() destroys the magick component.
1086%
1087% The format of the MagickComponentTerminus method is:
1088%
1089% void MagickComponentTerminus(void)
1090%
1091*/
cristy5ff4eaf2011-09-03 01:38:02 +00001092MagickPrivate void MagickComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001093{
cristy18b17442009-10-25 18:36:48 +00001094 if (magick_semaphore == (SemaphoreInfo *) NULL)
1095 AcquireSemaphoreInfo(&magick_semaphore);
cristyf84a1932010-01-03 18:00:18 +00001096 LockSemaphoreInfo(magick_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001097 if (magick_list != (SplayTreeInfo *) NULL)
1098 magick_list=DestroySplayTree(magick_list);
1099 instantiate_magick=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +00001100 UnlockSemaphoreInfo(magick_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001101 DestroySemaphoreInfo(&magick_semaphore);
1102}
1103
1104/*
1105%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1106% %
1107% %
1108% %
cristy3ed852e2009-09-05 21:47:34 +00001109% M a g i c k C o r e G e n e s i s %
1110% %
1111% %
1112% %
1113%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1114%
1115% MagickCoreGenesis() initializes the MagickCore environment.
1116%
1117% The format of the MagickCoreGenesis function is:
1118%
1119% MagickCoreGenesis(const char *path,
1120% const MagickBooleanType establish_signal_handlers)
1121%
1122% A description of each parameter follows:
1123%
1124% o path: the execution path of the current ImageMagick client.
1125%
1126% o establish_signal_handlers: set to MagickTrue to use MagickCore's own
1127% signal handlers for common signals.
1128%
1129*/
1130
1131static SignalHandler *SetMagickSignalHandler(int signal_number,
1132 SignalHandler *handler)
1133{
1134#if defined(MAGICKCORE_HAVE_SIGACTION) && defined(MAGICKCORE_HAVE_SIGEMPTYSET)
1135 int
1136 status;
1137
1138 sigset_t
1139 mask;
1140
1141 struct sigaction
1142 action,
1143 previous_action;
1144
1145 sigemptyset(&mask);
1146 sigaddset(&mask,signal_number);
1147 sigprocmask(SIG_BLOCK,&mask,NULL);
1148 action.sa_mask=mask;
1149 action.sa_handler=handler;
1150 action.sa_flags=0;
1151#if defined(SA_INTERRUPT)
1152 action.sa_flags|=SA_INTERRUPT;
1153#endif
1154 status=sigaction(signal_number,&action,&previous_action);
1155 if (status < 0)
1156 return(SIG_ERR);
1157 sigprocmask(SIG_UNBLOCK,&mask,NULL);
1158 return(previous_action.sa_handler);
1159#else
1160 return(signal(signal_number,handler));
1161#endif
1162}
1163
1164static void MagickSignalHandler(int signal_number)
1165{
1166#if !defined(MAGICKCORE_HAVE_SIGACTION)
1167 (void) signal(signal_number,SIG_IGN);
1168#endif
cristyf34a1452009-10-24 22:29:27 +00001169 AsynchronousResourceComponentTerminus();
cristy3ed852e2009-09-05 21:47:34 +00001170 instantiate_magick=MagickFalse;
1171 (void) SetMagickSignalHandler(signal_number,signal_handlers[signal_number]);
1172#if defined(MAGICKCORE_HAVE_RAISE)
1173 if (signal_handlers[signal_number] != MagickSignalHandler)
1174 raise(signal_number);
1175#endif
cristy5f03dab2011-02-20 21:55:17 +00001176#if defined(SIGQUIT)
1177 if (signal_number == SIGQUIT)
1178 abort();
1179#endif
1180#if defined(SIGABRT)
1181 if (signal_number == SIGABRT)
1182 abort();
1183#endif
1184#if defined(SIGFPE)
1185 if (signal_number == SIGFPE)
1186 abort();
1187#endif
1188#if defined(SIGXCPU)
1189 if (signal_number == SIGXCPU)
1190 abort();
1191#endif
1192#if defined(SIGXFSZ)
1193 if (signal_number == SIGXFSZ)
1194 abort();
1195#endif
cristy32a348b2011-04-22 16:03:42 +00001196#if defined(SIGSEGV)
1197 if (signal_number == SIGSEGV)
cristy7ae29582011-04-21 16:10:06 +00001198 abort();
1199#endif
cristy3ed852e2009-09-05 21:47:34 +00001200#if !defined(MAGICKCORE_HAVE__EXIT)
1201 exit(signal_number);
1202#else
1203#if defined(SIGHUP)
1204 if (signal_number == SIGHUP)
1205 exit(signal_number);
1206#endif
cristy0157aea2010-04-24 21:12:18 +00001207#if defined(SIGINT) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001208 if (signal_number == SIGINT)
1209 exit(signal_number);
1210#endif
1211#if defined(SIGTERM)
1212 if (signal_number == SIGTERM)
1213 exit(signal_number);
1214#endif
cristy70bda3d2011-02-20 21:58:06 +00001215 _exit(signal_number); /* do not invoke registered atexit() methods */
cristy3ed852e2009-09-05 21:47:34 +00001216#endif
1217}
1218
1219static SignalHandler *RegisterMagickSignalHandler(int signal_number)
1220{
1221 SignalHandler
1222 *handler;
1223
1224 handler=SetMagickSignalHandler(signal_number,MagickSignalHandler);
1225 if (handler == SIG_ERR)
1226 return(handler);
1227 if (handler != SIG_DFL)
1228 handler=SetMagickSignalHandler(signal_number,handler);
1229 else
1230 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1231 "Register handler for signal: %d",signal_number);
1232 return(handler);
1233}
1234
1235MagickExport void MagickCoreGenesis(const char *path,
1236 const MagickBooleanType establish_signal_handlers)
1237{
1238 char
1239 *events,
1240 execution_path[MaxTextExtent],
1241 filename[MaxTextExtent];
1242
cristy3ed852e2009-09-05 21:47:34 +00001243 /*
1244 Initialize the Magick environment.
1245 */
cristyd1ebf4a2010-05-13 01:54:31 +00001246 LockMagickMutex();
1247 if (instantiate_magickcore != MagickFalse)
1248 {
1249 UnlockMagickMutex();
1250 return;
1251 }
cristyf34a1452009-10-24 22:29:27 +00001252 (void) SemaphoreComponentGenesis();
1253 (void) LogComponentGenesis();
1254 (void) LocaleComponentGenesis();
1255 (void) RandomComponentGenesis();
cristy3ed852e2009-09-05 21:47:34 +00001256 events=GetEnvironmentValue("MAGICK_DEBUG");
1257 if (events != (char *) NULL)
1258 {
1259 (void) SetLogEventMask(events);
1260 events=DestroyString(events);
1261 }
cristy0157aea2010-04-24 21:12:18 +00001262#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001263#if defined(_DEBUG) && !defined(__BORLANDC__) && !defined(__MINGW32__)
1264 if (IsEventLogging() != MagickFalse)
1265 {
1266 int
1267 debug;
1268
1269 debug=_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
1270 debug|=_CRTDBG_CHECK_ALWAYS_DF |_CRTDBG_DELAY_FREE_MEM_DF |
1271 _CRTDBG_LEAK_CHECK_DF;
1272 if (0)
1273 {
1274 debug=_CrtSetDbgFlag(debug);
1275 _ASSERTE(_CrtCheckMemory());
1276 }
1277 }
1278#endif
1279#endif
1280 /*
1281 Set client name and execution path.
1282 */
1283 (void) GetExecutionPath(execution_path,MaxTextExtent);
cristy905e5302011-11-09 18:08:43 +00001284 if ((path != (const char *) NULL) && (*path != '\0') &&
1285 (IsPathAccessible(path) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001286 (void) CopyMagickString(execution_path,path,MaxTextExtent);
1287 GetPathComponent(execution_path,TailPath,filename);
1288 (void) SetClientName(filename);
1289 GetPathComponent(execution_path,HeadPath,execution_path);
1290 (void) SetClientPath(execution_path);
1291 if (establish_signal_handlers != MagickFalse)
1292 {
1293 /*
1294 Set signal handlers.
1295 */
1296#if defined(SIGABRT)
1297 if (signal_handlers[SIGABRT] == (SignalHandler *) NULL)
1298 signal_handlers[SIGABRT]=RegisterMagickSignalHandler(SIGABRT);
1299#endif
cristy32a348b2011-04-22 16:03:42 +00001300#if defined(SIGSEGV)
1301 if (signal_handlers[SIGSEGV] == (SignalHandler *) NULL)
1302 signal_handlers[SIGSEGV]=RegisterMagickSignalHandler(SIGSEGV);
cristy7ae29582011-04-21 16:10:06 +00001303#endif
cristy3ed852e2009-09-05 21:47:34 +00001304#if defined(SIGFPE)
1305 if (signal_handlers[SIGFPE] == (SignalHandler *) NULL)
1306 signal_handlers[SIGFPE]=RegisterMagickSignalHandler(SIGFPE);
1307#endif
1308#if defined(SIGHUP)
1309 if (signal_handlers[SIGHUP] == (SignalHandler *) NULL)
1310 signal_handlers[SIGHUP]=RegisterMagickSignalHandler(SIGHUP);
1311#endif
cristy0157aea2010-04-24 21:12:18 +00001312#if defined(SIGINT) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001313 if (signal_handlers[SIGINT] == (SignalHandler *) NULL)
1314 signal_handlers[SIGINT]=RegisterMagickSignalHandler(SIGINT);
1315#endif
1316#if defined(SIGQUIT)
1317 if (signal_handlers[SIGQUIT] == (SignalHandler *) NULL)
1318 signal_handlers[SIGQUIT]=RegisterMagickSignalHandler(SIGQUIT);
1319#endif
1320#if defined(SIGTERM)
1321 if (signal_handlers[SIGTERM] == (SignalHandler *) NULL)
1322 signal_handlers[SIGTERM]=RegisterMagickSignalHandler(SIGTERM);
1323#endif
1324#if defined(SIGXCPU)
1325 if (signal_handlers[SIGXCPU] == (SignalHandler *) NULL)
1326 signal_handlers[SIGXCPU]=RegisterMagickSignalHandler(SIGXCPU);
1327#endif
1328#if defined(SIGXFSZ)
1329 if (signal_handlers[SIGXFSZ] == (SignalHandler *) NULL)
1330 signal_handlers[SIGXFSZ]=RegisterMagickSignalHandler(SIGXFSZ);
1331#endif
1332 }
1333 /*
cristyaf8b5cd2009-10-24 00:29:23 +00001334 Instantiate magick resources.
cristy3ed852e2009-09-05 21:47:34 +00001335 */
cristy18b17442009-10-25 18:36:48 +00001336 (void) ConfigureComponentGenesis();
cristyf34a1452009-10-24 22:29:27 +00001337 (void) PolicyComponentGenesis();
1338 (void) CacheComponentGenesis();
1339 (void) RegistryComponentGenesis();
1340 (void) ResourceComponentGenesis();
1341 (void) CoderComponentGenesis();
1342 (void) MagickComponentGenesis();
cristyaf8b5cd2009-10-24 00:29:23 +00001343#if defined(MAGICKCORE_MODULES_SUPPORT)
cristyf34a1452009-10-24 22:29:27 +00001344 (void) ModuleComponentGenesis();
cristyaf8b5cd2009-10-24 00:29:23 +00001345#endif
cristyf34a1452009-10-24 22:29:27 +00001346 (void) DelegateComponentGenesis();
1347 (void) MagicComponentGenesis();
1348 (void) ColorComponentGenesis();
1349 (void) TypeComponentGenesis();
cristyf34a1452009-10-24 22:29:27 +00001350 (void) MimeComponentGenesis();
1351 (void) ConstituteComponentGenesis();
cristyd7ecaca2011-01-24 14:14:53 +00001352 (void) AnnotateComponentGenesis();
cristy0157aea2010-04-24 21:12:18 +00001353#if defined(MAGICKCORE_X11_DELEGATE)
cristyf34a1452009-10-24 22:29:27 +00001354 (void) XComponentGenesis();
cristy0157aea2010-04-24 21:12:18 +00001355#endif
cristyd1ebf4a2010-05-13 01:54:31 +00001356 instantiate_magickcore=MagickTrue;
1357 UnlockMagickMutex();
cristy3ed852e2009-09-05 21:47:34 +00001358}
1359
1360/*
1361%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1362% %
1363% %
1364% %
1365% M a g i c k C o r e T e r m i n u s %
1366% %
1367% %
1368% %
1369%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1370%
1371% MagickCoreTerminus() destroys the MagickCore environment.
1372%
cristyf34a1452009-10-24 22:29:27 +00001373% The format of the MagickCoreTerminus function is:
cristy3ed852e2009-09-05 21:47:34 +00001374%
1375% MagickCoreTerminus(void)
1376%
1377*/
1378MagickExport void MagickCoreTerminus(void)
1379{
cristyd1ebf4a2010-05-13 01:54:31 +00001380 LockMagickMutex();
1381 if (instantiate_magickcore == MagickFalse)
1382 {
1383 UnlockMagickMutex();
1384 return;
1385 }
cristy3ed852e2009-09-05 21:47:34 +00001386#if defined(MAGICKCORE_X11_DELEGATE)
cristyf34a1452009-10-24 22:29:27 +00001387 XComponentTerminus();
cristy3ed852e2009-09-05 21:47:34 +00001388#endif
cristyd7ecaca2011-01-24 14:14:53 +00001389 AnnotateComponentTerminus();
cristyf34a1452009-10-24 22:29:27 +00001390 ConstituteComponentTerminus();
1391 MimeComponentTerminus();
cristyf34a1452009-10-24 22:29:27 +00001392 TypeComponentTerminus();
1393 ColorComponentTerminus();
cristy0157aea2010-04-24 21:12:18 +00001394#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001395 NTGhostscriptUnLoadDLL();
1396#endif
cristyf34a1452009-10-24 22:29:27 +00001397 MagicComponentTerminus();
1398 DelegateComponentTerminus();
1399 MagickComponentTerminus();
cristyaf8b5cd2009-10-24 00:29:23 +00001400#if !defined(MAGICKCORE_BUILD_MODULES)
1401 UnregisterStaticModules();
1402#endif
1403#if defined(MAGICKCORE_MODULES_SUPPORT)
cristyf34a1452009-10-24 22:29:27 +00001404 ModuleComponentTerminus();
cristyaf8b5cd2009-10-24 00:29:23 +00001405#endif
cristyf34a1452009-10-24 22:29:27 +00001406 CoderComponentTerminus();
1407 ResourceComponentTerminus();
1408 RegistryComponentTerminus();
1409 CacheComponentTerminus();
1410 PolicyComponentTerminus();
cristy18b17442009-10-25 18:36:48 +00001411 ConfigureComponentTerminus();
cristyf34a1452009-10-24 22:29:27 +00001412 RandomComponentTerminus();
1413 LocaleComponentTerminus();
1414 LogComponentTerminus();
1415 SemaphoreComponentTerminus();
cristyd1ebf4a2010-05-13 01:54:31 +00001416 instantiate_magickcore=MagickFalse;
1417 UnlockMagickMutex();
cristy3ed852e2009-09-05 21:47:34 +00001418}
1419
1420/*
1421%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1422% %
1423% %
1424% %
1425+ R e g i s t e r M a g i c k I n f o %
1426% %
1427% %
1428% %
1429%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1430%
1431% RegisterMagickInfo() adds attributes for a particular image format to the
1432% list of supported formats. The attributes include the image format name,
1433% a method to read and/or write the format, whether the format supports the
1434% saving of more than one frame to the same file or blob, whether the format
1435% supports native in-memory I/O, and a brief description of the format.
1436%
1437% The format of the RegisterMagickInfo method is:
1438%
1439% MagickInfo *RegisterMagickInfo(MagickInfo *magick_info)
1440%
1441% A description of each parameter follows:
1442%
1443% o magick_info: the magick info.
1444%
1445*/
1446MagickExport MagickInfo *RegisterMagickInfo(MagickInfo *magick_info)
1447{
1448 MagickBooleanType
1449 status;
1450
1451 /*
1452 Delete any existing name.
1453 */
1454 assert(magick_info != (MagickInfo *) NULL);
1455 assert(magick_info->signature == MagickSignature);
1456 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",magick_info->name);
1457 if (magick_list == (SplayTreeInfo *) NULL)
1458 return((MagickInfo *) NULL);
1459 status=AddValueToSplayTree(magick_list,magick_info->name,magick_info);
1460 if (status == MagickFalse)
1461 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1462 return(magick_info);
1463}
1464
1465/*
1466%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1467% %
1468% %
1469% %
1470+ S e t M a g i c k I n f o %
1471% %
1472% %
1473% %
1474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1475%
1476% SetMagickInfo() allocates a MagickInfo structure and initializes the members
1477% to default values.
1478%
1479% The format of the SetMagickInfo method is:
1480%
1481% MagickInfo *SetMagickInfo(const char *name)
1482%
1483% A description of each parameter follows:
1484%
1485% o magick_info: Method SetMagickInfo returns the allocated and initialized
1486% MagickInfo structure.
1487%
1488% o name: a character string that represents the image format associated
1489% with the MagickInfo structure.
1490%
1491*/
1492MagickExport MagickInfo *SetMagickInfo(const char *name)
1493{
1494 MagickInfo
1495 *magick_info;
1496
1497 assert(name != (const char *) NULL);
1498 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
cristy73bd4a52010-10-05 11:24:23 +00001499 magick_info=(MagickInfo *) AcquireMagickMemory(sizeof(*magick_info));
cristy3ed852e2009-09-05 21:47:34 +00001500 if (magick_info == (MagickInfo *) NULL)
1501 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1502 (void) ResetMagickMemory(magick_info,0,sizeof(*magick_info));
1503 magick_info->name=ConstantString(name);
1504 magick_info->adjoin=MagickTrue;
1505 magick_info->blob_support=MagickTrue;
1506 magick_info->thread_support=(MagickStatusType) (DecoderThreadSupport |
1507 EncoderThreadSupport);
1508 magick_info->signature=MagickSignature;
1509 return(magick_info);
1510}
1511
1512/*
1513%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1514% %
1515% %
1516% %
cristye7f51092010-01-17 00:39:37 +00001517% S e t M a g i c k P r e c i s i o n %
1518% %
1519% %
1520% %
1521%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1522%
1523% SetMagickPrecision() sets the maximum number of significant digits to be
cristybf2766a2010-01-17 03:33:23 +00001524% printed and returns it.
cristye7f51092010-01-17 00:39:37 +00001525%
1526% The format of the SetMagickPrecision method is:
1527%
cristybf2766a2010-01-17 03:33:23 +00001528% int SetMagickPrecision(const int precision)
cristye7f51092010-01-17 00:39:37 +00001529%
1530% A description of each parameter follows:
1531%
1532% o precision: set the maximum number of significant digits to be printed.
1533%
1534*/
cristybf2766a2010-01-17 03:33:23 +00001535MagickExport int SetMagickPrecision(const int precision)
cristye7f51092010-01-17 00:39:37 +00001536{
cristybf2766a2010-01-17 03:33:23 +00001537 static int
1538 magick_precision = 0;
1539
cristye7f51092010-01-17 00:39:37 +00001540 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristybf2766a2010-01-17 03:33:23 +00001541 if (precision != 0)
1542 magick_precision=precision;
1543 return(magick_precision);
cristye7f51092010-01-17 00:39:37 +00001544}
1545
1546/*
1547%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1548% %
1549% %
1550% %
cristy3ed852e2009-09-05 21:47:34 +00001551+ U n r e g i s t e r M a g i c k I n f o %
1552% %
1553% %
1554% %
1555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1556%
1557% UnregisterMagickInfo() removes a name from the magick info list. It returns
1558% MagickFalse if the name does not exist in the list otherwise MagickTrue.
1559%
1560% The format of the UnregisterMagickInfo method is:
1561%
1562% MagickBooleanType UnregisterMagickInfo(const char *name)
1563%
1564% A description of each parameter follows:
1565%
1566% o name: a character string that represents the image format we are
1567% looking for.
1568%
1569*/
1570MagickExport MagickBooleanType UnregisterMagickInfo(const char *name)
1571{
1572 register const MagickInfo
1573 *p;
1574
1575 MagickBooleanType
1576 status;
1577
1578 assert(name != (const char *) NULL);
1579 if (magick_list == (SplayTreeInfo *) NULL)
1580 return(MagickFalse);
1581 if (GetNumberOfNodesInSplayTree(magick_list) == 0)
1582 return(MagickFalse);
cristyf84a1932010-01-03 18:00:18 +00001583 LockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001584 ResetSplayTreeIterator(magick_list);
1585 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
1586 while (p != (const MagickInfo *) NULL)
1587 {
1588 if (LocaleCompare(p->name,name) == 0)
1589 break;
1590 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
1591 }
1592 status=DeleteNodeByValueFromSplayTree(magick_list,p);
cristyf84a1932010-01-03 18:00:18 +00001593 UnlockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001594 return(status);
1595}