blob: 0b6772b60ecb4918fd8a08aac4e24ce198fe9b76 [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% %
cristy1454be72011-12-19 01:52:48 +000021% Copyright 1999-2012 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"
cristy2c5fc272012-02-22 01:27:46 +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{
cristy7ce14bc2010-01-17 00:01:01 +0000668 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristybf2766a2010-01-17 03:33:23 +0000669 return(SetMagickPrecision(0));
cristy7ce14bc2010-01-17 00:01:01 +0000670}
671
672/*
673%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
674% %
675% %
676% %
677+ 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 +0000678% %
679% %
680% %
681%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
682%
683% GetMagickRawSupport() returns the MagickTrue if the coder is a raw format.
684%
685% The format of the GetMagickRawSupport method is:
686%
687% MagickBooleanType GetMagickRawSupport(const MagickInfo *magick_info)
688%
689% A description of each parameter follows:
690%
691% o magick_info: The magick info.
692%
693*/
694MagickExport MagickBooleanType GetMagickRawSupport(
695 const MagickInfo *magick_info)
696{
697 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
698 assert(magick_info != (MagickInfo *) NULL);
699 assert(magick_info->signature == MagickSignature);
700 return(magick_info->raw);
701}
702
703/*
704%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
705% %
706% %
707% %
708+ G e t M a g i c k S e e k a b l e S t r e a m %
709% %
710% %
711% %
712%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
713%
714% GetMagickSeekableStream() returns MagickTrue if the magick supports a
715% seekable stream.
716%
717% The format of the GetMagickSeekableStream method is:
718%
719% MagickBooleanType GetMagickSeekableStream(const MagickInfo *magick_info)
720%
721% A description of each parameter follows:
722%
723% o magick_info: The magick info.
724%
725*/
726MagickExport MagickBooleanType GetMagickSeekableStream(
727 const MagickInfo *magick_info)
728{
729 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
730 assert(magick_info != (MagickInfo *) NULL);
731 assert(magick_info->signature == MagickSignature);
732 return(magick_info->seekable_stream);
733}
734
735/*
736%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
737% %
738% %
739% %
740+ G e t M a g i c k T h r e a d S u p p o r t %
741% %
742% %
743% %
744%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
745%
746% GetMagickThreadSupport() returns MagickTrue if the magick supports threads.
747%
748% The format of the GetMagickThreadSupport method is:
749%
750% MagickStatusType GetMagickThreadSupport(const MagickInfo *magick_info)
751%
752% A description of each parameter follows:
753%
754% o magick_info: The magick info.
755%
756*/
757MagickExport MagickStatusType GetMagickThreadSupport(
758 const MagickInfo *magick_info)
759{
760 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
761 assert(magick_info != (MagickInfo *) NULL);
762 assert(magick_info->signature == MagickSignature);
763 return(magick_info->thread_support);
764}
765
766/*
767%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
768% %
769% %
770% %
771+ I n i t i a l i z e M a g i c k L i s t %
772% %
773% %
774% %
775%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
776%
777% InitializeMagickList() initializes the magick list.
778%
779% The format of the InitializeMagickList() method is:
780%
781% InitializeMagickList(Exceptioninfo *exception)
782%
783% A description of each parameter follows.
784%
785% o exception: return any errors or warnings in this structure.
786%
787*/
788
789static void *DestroyMagickNode(void *magick_info)
790{
791 register MagickInfo
792 *p;
793
794 p=(MagickInfo *) magick_info;
795 if (p->name != (char *) NULL)
796 p->name=DestroyString(p->name);
797 if (p->description != (char *) NULL)
798 p->description=DestroyString(p->description);
799 if (p->version != (char *) NULL)
800 p->version=DestroyString(p->version);
801 if (p->note != (char *) NULL)
802 p->note=DestroyString(p->note);
803 if (p->module != (char *) NULL)
804 p->module=DestroyString(p->module);
805 return(RelinquishMagickMemory(p));
806}
807
808static MagickBooleanType InitializeMagickList(ExceptionInfo *exception)
809{
cristyf2e11662009-10-14 01:24:43 +0000810 (void) exception;
cristy3ed852e2009-09-05 21:47:34 +0000811 if ((magick_list == (SplayTreeInfo *) NULL) &&
812 (instantiate_magick == MagickFalse))
813 {
cristy4e1dff62009-10-25 20:36:03 +0000814 if (magick_semaphore == (SemaphoreInfo *) NULL)
815 AcquireSemaphoreInfo(&magick_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000816 LockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000817 if ((magick_list == (SplayTreeInfo *) NULL) &&
818 (instantiate_magick == MagickFalse))
819 {
820 MagickBooleanType
821 status;
822
823 MagickInfo
824 *magick_info;
825
826 magick_list=NewSplayTree(CompareSplayTreeString,
827 (void *(*)(void *)) NULL,DestroyMagickNode);
828 if (magick_list == (SplayTreeInfo *) NULL)
829 ThrowFatalException(ResourceLimitFatalError,
830 "MemoryAllocationFailed");
831 magick_info=SetMagickInfo("ephemeral");
832 magick_info->stealth=MagickTrue;
833 status=AddValueToSplayTree(magick_list,magick_info->name,magick_info);
834 if (status == MagickFalse)
835 ThrowFatalException(ResourceLimitFatalError,
836 "MemoryAllocationFailed");
837 magick_info=SetMagickInfo("clipmask");
838 magick_info->stealth=MagickTrue;
839 status=AddValueToSplayTree(magick_list,magick_info->name,magick_info);
840 if (status == MagickFalse)
841 {
842 char
843 *message;
844
845 message=GetExceptionMessage(errno);
846 ThrowFatalException(ResourceLimitFatalError,
847 "MemoryAllocationFailed");
848 message=DestroyString(message);
849 }
850#if defined(MAGICKCORE_MODULES_SUPPORT)
851 (void) GetModuleInfo((char *) NULL,exception);
852#endif
853#if !defined(MAGICKCORE_BUILD_MODULES)
854 RegisterStaticModules();
855#endif
856 instantiate_magick=MagickTrue;
857 }
cristyf84a1932010-01-03 18:00:18 +0000858 UnlockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000859 }
860 return(magick_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
861}
862
863/*
864%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
865% %
866% %
867% %
868+ I s M a g i c k C o n f l i c t %
869% %
870% %
871% %
872%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
873%
cristy05a9a622010-03-15 17:26:04 +0000874% IsMagickConflict() returns MagickTrue if the image format conflicts with a
875% logical drive (.e.g. X:).
cristy3ed852e2009-09-05 21:47:34 +0000876%
877% The format of the IsMagickConflict method is:
878%
879% MagickBooleanType IsMagickConflict(const char *magick)
880%
881% A description of each parameter follows:
882%
883% o magick: Specifies the image format.
884%
885*/
cristy7832dc22011-09-05 01:21:53 +0000886MagickPrivate MagickBooleanType IsMagickConflict(const char *magick)
cristy3ed852e2009-09-05 21:47:34 +0000887{
cristy3ed852e2009-09-05 21:47:34 +0000888 assert(magick != (char *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000889#if defined(macintosh)
890 return(MACIsMagickConflict(magick));
891#elif defined(vms)
892 return(VMSIsMagickConflict(magick));
cristy0157aea2010-04-24 21:12:18 +0000893#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000894 return(NTIsMagickConflict(magick));
895#else
896 return(MagickFalse);
897#endif
898}
899
900/*
901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902% %
903% %
904% %
905+ L i s t M a g i c k I n f o %
906% %
907% %
908% %
909%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
910%
911% ListMagickInfo() lists the image formats to a file.
912%
913% The format of the ListMagickInfo method is:
914%
915% MagickBooleanType ListMagickInfo(FILE *file,ExceptionInfo *exception)
916%
917% A description of each parameter follows.
918%
919% o file: A file handle.
920%
921% o exception: return any errors or warnings in this structure.
922%
923*/
924MagickExport MagickBooleanType ListMagickInfo(FILE *file,
925 ExceptionInfo *exception)
926{
927 const MagickInfo
928 **magick_info;
929
cristybb503372010-05-27 20:51:26 +0000930 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000931 i;
932
cristybb503372010-05-27 20:51:26 +0000933 size_t
cristy3ed852e2009-09-05 21:47:34 +0000934 number_formats;
935
cristy9d314ff2011-03-09 01:30:28 +0000936 ssize_t
937 j;
938
cristy3ed852e2009-09-05 21:47:34 +0000939 if (file == (FILE *) NULL)
940 file=stdout;
941 magick_info=GetMagickInfoList("*",&number_formats,exception);
942 if (magick_info == (const MagickInfo **) NULL)
943 return(MagickFalse);
944 ClearMagickException(exception);
945#if !defined(MAGICKCORE_MODULES_SUPPORT)
cristyb51dff52011-05-19 16:55:47 +0000946 (void) FormatLocaleFile(file," Format Mode Description\n");
cristy3ed852e2009-09-05 21:47:34 +0000947#else
cristyb51dff52011-05-19 16:55:47 +0000948 (void) FormatLocaleFile(file," Format Module Mode Description\n");
cristy3ed852e2009-09-05 21:47:34 +0000949#endif
cristy1e604812011-05-19 18:07:50 +0000950 (void) FormatLocaleFile(file,
951 "--------------------------------------------------------"
cristy3ed852e2009-09-05 21:47:34 +0000952 "-----------------------\n");
cristybb503372010-05-27 20:51:26 +0000953 for (i=0; i < (ssize_t) number_formats; i++)
cristy3ed852e2009-09-05 21:47:34 +0000954 {
955 if (magick_info[i]->stealth != MagickFalse)
956 continue;
cristy1e604812011-05-19 18:07:50 +0000957 (void) FormatLocaleFile(file,"%9s%c ",
958 magick_info[i]->name != (char *) NULL ? magick_info[i]->name : "",
cristy3ed852e2009-09-05 21:47:34 +0000959 magick_info[i]->blob_support != MagickFalse ? '*' : ' ');
960#if defined(MAGICKCORE_MODULES_SUPPORT)
961 {
962 char
963 module[MaxTextExtent];
964
965 *module='\0';
966 if (magick_info[i]->module != (char *) NULL)
967 (void) CopyMagickString(module,magick_info[i]->module,MaxTextExtent);
968 (void) ConcatenateMagickString(module," ",MaxTextExtent);
969 module[9]='\0';
cristyb51dff52011-05-19 16:55:47 +0000970 (void) FormatLocaleFile(file,"%9s ",module);
cristy3ed852e2009-09-05 21:47:34 +0000971 }
972#endif
cristyb51dff52011-05-19 16:55:47 +0000973 (void) FormatLocaleFile(file,"%c%c%c ",magick_info[i]->decoder ? 'r' : '-',
cristy3ed852e2009-09-05 21:47:34 +0000974 magick_info[i]->encoder ? 'w' : '-',magick_info[i]->encoder != NULL &&
975 magick_info[i]->adjoin != MagickFalse ? '+' : '-');
976 if (magick_info[i]->description != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000977 (void) FormatLocaleFile(file," %s",magick_info[i]->description);
cristy3ed852e2009-09-05 21:47:34 +0000978 if (magick_info[i]->version != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +0000979 (void) FormatLocaleFile(file," (%s)",magick_info[i]->version);
980 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +0000981 if (magick_info[i]->note != (char *) NULL)
982 {
983 char
984 **text;
985
986 text=StringToList(magick_info[i]->note);
987 if (text != (char **) NULL)
988 {
989 for (j=0; text[j] != (char *) NULL; j++)
990 {
cristyb51dff52011-05-19 16:55:47 +0000991 (void) FormatLocaleFile(file," %s\n",text[j]);
cristy3ed852e2009-09-05 21:47:34 +0000992 text[j]=DestroyString(text[j]);
993 }
994 text=(char **) RelinquishMagickMemory(text);
995 }
996 }
997 }
cristyb51dff52011-05-19 16:55:47 +0000998 (void) FormatLocaleFile(file,"\n* native blob support\n");
999 (void) FormatLocaleFile(file,"r read support\n");
1000 (void) FormatLocaleFile(file,"w write support\n");
1001 (void) FormatLocaleFile(file,"+ support for multiple images\n");
cristy3ed852e2009-09-05 21:47:34 +00001002 (void) fflush(file);
1003 magick_info=(const MagickInfo **) RelinquishMagickMemory((void *)
1004 magick_info);
1005 return(MagickTrue);
1006}
1007
1008/*
1009%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1010% %
1011% %
1012% %
1013% I s M a g i c k I n s t a n t i a t e d %
1014% %
1015% %
1016% %
1017%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1018%
1019% IsMagickInstantiated() returns MagickTrue if the ImageMagick environment
1020% is currently instantiated: MagickCoreGenesis() has been called but
1021% MagickDestroy() has not.
1022%
1023% The format of the IsMagickInstantiated method is:
1024%
1025% MagickBooleanType IsMagickInstantiated(void)
1026%
1027*/
1028MagickExport MagickBooleanType IsMagickInstantiated(void)
1029{
1030 return(instantiate_magick);
1031}
1032
1033/*
1034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1035% %
1036% %
1037% %
cristyf34a1452009-10-24 22:29:27 +00001038+ M a g i c k C o m p o n e n t G e n e s i s %
1039% %
1040% %
1041% %
1042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1043%
1044% MagickComponentGenesis() instantiates the magick component.
1045%
1046% The format of the MagickComponentGenesis method is:
1047%
1048% MagickBooleanType MagickComponentGenesis(void)
1049%
1050*/
cristy5ff4eaf2011-09-03 01:38:02 +00001051MagickPrivate MagickBooleanType MagickComponentGenesis(void)
cristyf34a1452009-10-24 22:29:27 +00001052{
cristy165b6092009-10-26 13:52:10 +00001053 AcquireSemaphoreInfo(&magick_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001054 return(MagickTrue);
1055}
1056
1057/*
1058%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1059% %
1060% %
1061% %
1062+ M a g i c k C o m p o n e n t T e r m i n u s %
1063% %
1064% %
1065% %
1066%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1067%
1068% MagickComponentTerminus() destroys the magick component.
1069%
1070% The format of the MagickComponentTerminus method is:
1071%
1072% void MagickComponentTerminus(void)
1073%
1074*/
cristy5ff4eaf2011-09-03 01:38:02 +00001075MagickPrivate void MagickComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001076{
cristy18b17442009-10-25 18:36:48 +00001077 if (magick_semaphore == (SemaphoreInfo *) NULL)
1078 AcquireSemaphoreInfo(&magick_semaphore);
cristyf84a1932010-01-03 18:00:18 +00001079 LockSemaphoreInfo(magick_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001080 if (magick_list != (SplayTreeInfo *) NULL)
1081 magick_list=DestroySplayTree(magick_list);
1082 instantiate_magick=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +00001083 UnlockSemaphoreInfo(magick_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001084 DestroySemaphoreInfo(&magick_semaphore);
1085}
1086
1087/*
1088%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1089% %
1090% %
1091% %
cristy3ed852e2009-09-05 21:47:34 +00001092% M a g i c k C o r e G e n e s i s %
1093% %
1094% %
1095% %
1096%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1097%
1098% MagickCoreGenesis() initializes the MagickCore environment.
1099%
1100% The format of the MagickCoreGenesis function is:
1101%
1102% MagickCoreGenesis(const char *path,
1103% const MagickBooleanType establish_signal_handlers)
1104%
1105% A description of each parameter follows:
1106%
1107% o path: the execution path of the current ImageMagick client.
1108%
1109% o establish_signal_handlers: set to MagickTrue to use MagickCore's own
1110% signal handlers for common signals.
1111%
1112*/
1113
1114static SignalHandler *SetMagickSignalHandler(int signal_number,
1115 SignalHandler *handler)
1116{
1117#if defined(MAGICKCORE_HAVE_SIGACTION) && defined(MAGICKCORE_HAVE_SIGEMPTYSET)
1118 int
1119 status;
1120
1121 sigset_t
1122 mask;
1123
1124 struct sigaction
1125 action,
1126 previous_action;
1127
1128 sigemptyset(&mask);
1129 sigaddset(&mask,signal_number);
1130 sigprocmask(SIG_BLOCK,&mask,NULL);
1131 action.sa_mask=mask;
1132 action.sa_handler=handler;
1133 action.sa_flags=0;
1134#if defined(SA_INTERRUPT)
1135 action.sa_flags|=SA_INTERRUPT;
1136#endif
1137 status=sigaction(signal_number,&action,&previous_action);
1138 if (status < 0)
1139 return(SIG_ERR);
1140 sigprocmask(SIG_UNBLOCK,&mask,NULL);
1141 return(previous_action.sa_handler);
1142#else
1143 return(signal(signal_number,handler));
1144#endif
1145}
1146
1147static void MagickSignalHandler(int signal_number)
1148{
1149#if !defined(MAGICKCORE_HAVE_SIGACTION)
1150 (void) signal(signal_number,SIG_IGN);
1151#endif
cristyf34a1452009-10-24 22:29:27 +00001152 AsynchronousResourceComponentTerminus();
cristy3ed852e2009-09-05 21:47:34 +00001153 instantiate_magick=MagickFalse;
1154 (void) SetMagickSignalHandler(signal_number,signal_handlers[signal_number]);
1155#if defined(MAGICKCORE_HAVE_RAISE)
1156 if (signal_handlers[signal_number] != MagickSignalHandler)
1157 raise(signal_number);
1158#endif
cristy5f03dab2011-02-20 21:55:17 +00001159#if defined(SIGQUIT)
1160 if (signal_number == SIGQUIT)
1161 abort();
1162#endif
1163#if defined(SIGABRT)
1164 if (signal_number == SIGABRT)
1165 abort();
1166#endif
1167#if defined(SIGFPE)
1168 if (signal_number == SIGFPE)
1169 abort();
1170#endif
1171#if defined(SIGXCPU)
1172 if (signal_number == SIGXCPU)
1173 abort();
1174#endif
1175#if defined(SIGXFSZ)
1176 if (signal_number == SIGXFSZ)
1177 abort();
1178#endif
cristy32a348b2011-04-22 16:03:42 +00001179#if defined(SIGSEGV)
1180 if (signal_number == SIGSEGV)
cristy7ae29582011-04-21 16:10:06 +00001181 abort();
1182#endif
cristy3ed852e2009-09-05 21:47:34 +00001183#if !defined(MAGICKCORE_HAVE__EXIT)
1184 exit(signal_number);
1185#else
1186#if defined(SIGHUP)
1187 if (signal_number == SIGHUP)
1188 exit(signal_number);
1189#endif
cristy0157aea2010-04-24 21:12:18 +00001190#if defined(SIGINT) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001191 if (signal_number == SIGINT)
1192 exit(signal_number);
1193#endif
1194#if defined(SIGTERM)
1195 if (signal_number == SIGTERM)
1196 exit(signal_number);
1197#endif
cristy70bda3d2011-02-20 21:58:06 +00001198 _exit(signal_number); /* do not invoke registered atexit() methods */
cristy3ed852e2009-09-05 21:47:34 +00001199#endif
1200}
1201
1202static SignalHandler *RegisterMagickSignalHandler(int signal_number)
1203{
1204 SignalHandler
1205 *handler;
1206
1207 handler=SetMagickSignalHandler(signal_number,MagickSignalHandler);
1208 if (handler == SIG_ERR)
1209 return(handler);
1210 if (handler != SIG_DFL)
1211 handler=SetMagickSignalHandler(signal_number,handler);
1212 else
1213 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1214 "Register handler for signal: %d",signal_number);
1215 return(handler);
1216}
1217
1218MagickExport void MagickCoreGenesis(const char *path,
1219 const MagickBooleanType establish_signal_handlers)
1220{
1221 char
1222 *events,
1223 execution_path[MaxTextExtent],
1224 filename[MaxTextExtent];
1225
cristy3ed852e2009-09-05 21:47:34 +00001226 /*
1227 Initialize the Magick environment.
1228 */
cristyd1ebf4a2010-05-13 01:54:31 +00001229 LockMagickMutex();
1230 if (instantiate_magickcore != MagickFalse)
1231 {
1232 UnlockMagickMutex();
1233 return;
1234 }
cristyf34a1452009-10-24 22:29:27 +00001235 (void) SemaphoreComponentGenesis();
1236 (void) LogComponentGenesis();
1237 (void) LocaleComponentGenesis();
1238 (void) RandomComponentGenesis();
cristy3ed852e2009-09-05 21:47:34 +00001239 events=GetEnvironmentValue("MAGICK_DEBUG");
1240 if (events != (char *) NULL)
1241 {
1242 (void) SetLogEventMask(events);
1243 events=DestroyString(events);
1244 }
cristy0157aea2010-04-24 21:12:18 +00001245#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001246#if defined(_DEBUG) && !defined(__BORLANDC__) && !defined(__MINGW32__)
1247 if (IsEventLogging() != MagickFalse)
1248 {
1249 int
1250 debug;
1251
1252 debug=_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
1253 debug|=_CRTDBG_CHECK_ALWAYS_DF |_CRTDBG_DELAY_FREE_MEM_DF |
1254 _CRTDBG_LEAK_CHECK_DF;
1255 if (0)
1256 {
1257 debug=_CrtSetDbgFlag(debug);
1258 _ASSERTE(_CrtCheckMemory());
1259 }
1260 }
1261#endif
1262#endif
1263 /*
1264 Set client name and execution path.
1265 */
1266 (void) GetExecutionPath(execution_path,MaxTextExtent);
cristy695e8c32011-11-09 18:27:04 +00001267 if ((path != (const char *) NULL) && (*path == *DirectorySeparator) &&
cristy905e5302011-11-09 18:08:43 +00001268 (IsPathAccessible(path) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001269 (void) CopyMagickString(execution_path,path,MaxTextExtent);
1270 GetPathComponent(execution_path,TailPath,filename);
1271 (void) SetClientName(filename);
1272 GetPathComponent(execution_path,HeadPath,execution_path);
1273 (void) SetClientPath(execution_path);
1274 if (establish_signal_handlers != MagickFalse)
1275 {
1276 /*
1277 Set signal handlers.
1278 */
1279#if defined(SIGABRT)
1280 if (signal_handlers[SIGABRT] == (SignalHandler *) NULL)
1281 signal_handlers[SIGABRT]=RegisterMagickSignalHandler(SIGABRT);
1282#endif
cristy32a348b2011-04-22 16:03:42 +00001283#if defined(SIGSEGV)
1284 if (signal_handlers[SIGSEGV] == (SignalHandler *) NULL)
1285 signal_handlers[SIGSEGV]=RegisterMagickSignalHandler(SIGSEGV);
cristy7ae29582011-04-21 16:10:06 +00001286#endif
cristy3ed852e2009-09-05 21:47:34 +00001287#if defined(SIGFPE)
1288 if (signal_handlers[SIGFPE] == (SignalHandler *) NULL)
1289 signal_handlers[SIGFPE]=RegisterMagickSignalHandler(SIGFPE);
1290#endif
1291#if defined(SIGHUP)
1292 if (signal_handlers[SIGHUP] == (SignalHandler *) NULL)
1293 signal_handlers[SIGHUP]=RegisterMagickSignalHandler(SIGHUP);
1294#endif
cristy0157aea2010-04-24 21:12:18 +00001295#if defined(SIGINT) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001296 if (signal_handlers[SIGINT] == (SignalHandler *) NULL)
1297 signal_handlers[SIGINT]=RegisterMagickSignalHandler(SIGINT);
1298#endif
1299#if defined(SIGQUIT)
1300 if (signal_handlers[SIGQUIT] == (SignalHandler *) NULL)
1301 signal_handlers[SIGQUIT]=RegisterMagickSignalHandler(SIGQUIT);
1302#endif
1303#if defined(SIGTERM)
1304 if (signal_handlers[SIGTERM] == (SignalHandler *) NULL)
1305 signal_handlers[SIGTERM]=RegisterMagickSignalHandler(SIGTERM);
1306#endif
1307#if defined(SIGXCPU)
1308 if (signal_handlers[SIGXCPU] == (SignalHandler *) NULL)
1309 signal_handlers[SIGXCPU]=RegisterMagickSignalHandler(SIGXCPU);
1310#endif
1311#if defined(SIGXFSZ)
1312 if (signal_handlers[SIGXFSZ] == (SignalHandler *) NULL)
1313 signal_handlers[SIGXFSZ]=RegisterMagickSignalHandler(SIGXFSZ);
1314#endif
1315 }
1316 /*
cristyaf8b5cd2009-10-24 00:29:23 +00001317 Instantiate magick resources.
cristy3ed852e2009-09-05 21:47:34 +00001318 */
cristy18b17442009-10-25 18:36:48 +00001319 (void) ConfigureComponentGenesis();
cristyf34a1452009-10-24 22:29:27 +00001320 (void) PolicyComponentGenesis();
1321 (void) CacheComponentGenesis();
1322 (void) RegistryComponentGenesis();
1323 (void) ResourceComponentGenesis();
1324 (void) CoderComponentGenesis();
1325 (void) MagickComponentGenesis();
cristyaf8b5cd2009-10-24 00:29:23 +00001326#if defined(MAGICKCORE_MODULES_SUPPORT)
cristyf34a1452009-10-24 22:29:27 +00001327 (void) ModuleComponentGenesis();
cristyaf8b5cd2009-10-24 00:29:23 +00001328#endif
cristyf34a1452009-10-24 22:29:27 +00001329 (void) DelegateComponentGenesis();
1330 (void) MagicComponentGenesis();
1331 (void) ColorComponentGenesis();
1332 (void) TypeComponentGenesis();
cristyf34a1452009-10-24 22:29:27 +00001333 (void) MimeComponentGenesis();
1334 (void) ConstituteComponentGenesis();
cristyd7ecaca2011-01-24 14:14:53 +00001335 (void) AnnotateComponentGenesis();
cristy0157aea2010-04-24 21:12:18 +00001336#if defined(MAGICKCORE_X11_DELEGATE)
cristyf34a1452009-10-24 22:29:27 +00001337 (void) XComponentGenesis();
cristy0157aea2010-04-24 21:12:18 +00001338#endif
cristyd1ebf4a2010-05-13 01:54:31 +00001339 instantiate_magickcore=MagickTrue;
1340 UnlockMagickMutex();
cristy3ed852e2009-09-05 21:47:34 +00001341}
1342
1343/*
1344%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1345% %
1346% %
1347% %
1348% M a g i c k C o r e T e r m i n u s %
1349% %
1350% %
1351% %
1352%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1353%
1354% MagickCoreTerminus() destroys the MagickCore environment.
1355%
cristyf34a1452009-10-24 22:29:27 +00001356% The format of the MagickCoreTerminus function is:
cristy3ed852e2009-09-05 21:47:34 +00001357%
1358% MagickCoreTerminus(void)
1359%
1360*/
1361MagickExport void MagickCoreTerminus(void)
1362{
cristyd1ebf4a2010-05-13 01:54:31 +00001363 LockMagickMutex();
1364 if (instantiate_magickcore == MagickFalse)
1365 {
1366 UnlockMagickMutex();
1367 return;
1368 }
cristy3ed852e2009-09-05 21:47:34 +00001369#if defined(MAGICKCORE_X11_DELEGATE)
cristyf34a1452009-10-24 22:29:27 +00001370 XComponentTerminus();
cristy3ed852e2009-09-05 21:47:34 +00001371#endif
cristyd7ecaca2011-01-24 14:14:53 +00001372 AnnotateComponentTerminus();
cristyf34a1452009-10-24 22:29:27 +00001373 ConstituteComponentTerminus();
1374 MimeComponentTerminus();
cristyf34a1452009-10-24 22:29:27 +00001375 TypeComponentTerminus();
1376 ColorComponentTerminus();
cristy0157aea2010-04-24 21:12:18 +00001377#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001378 NTGhostscriptUnLoadDLL();
1379#endif
cristyf34a1452009-10-24 22:29:27 +00001380 MagicComponentTerminus();
1381 DelegateComponentTerminus();
1382 MagickComponentTerminus();
cristyaf8b5cd2009-10-24 00:29:23 +00001383#if !defined(MAGICKCORE_BUILD_MODULES)
1384 UnregisterStaticModules();
1385#endif
1386#if defined(MAGICKCORE_MODULES_SUPPORT)
cristyf34a1452009-10-24 22:29:27 +00001387 ModuleComponentTerminus();
cristyaf8b5cd2009-10-24 00:29:23 +00001388#endif
cristyf34a1452009-10-24 22:29:27 +00001389 CoderComponentTerminus();
1390 ResourceComponentTerminus();
1391 RegistryComponentTerminus();
1392 CacheComponentTerminus();
1393 PolicyComponentTerminus();
cristy18b17442009-10-25 18:36:48 +00001394 ConfigureComponentTerminus();
cristyf34a1452009-10-24 22:29:27 +00001395 RandomComponentTerminus();
1396 LocaleComponentTerminus();
1397 LogComponentTerminus();
1398 SemaphoreComponentTerminus();
cristyd1ebf4a2010-05-13 01:54:31 +00001399 instantiate_magickcore=MagickFalse;
1400 UnlockMagickMutex();
cristy3ed852e2009-09-05 21:47:34 +00001401}
1402
1403/*
1404%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1405% %
1406% %
1407% %
1408+ R e g i s t e r M a g i c k I n f o %
1409% %
1410% %
1411% %
1412%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1413%
1414% RegisterMagickInfo() adds attributes for a particular image format to the
1415% list of supported formats. The attributes include the image format name,
1416% a method to read and/or write the format, whether the format supports the
1417% saving of more than one frame to the same file or blob, whether the format
1418% supports native in-memory I/O, and a brief description of the format.
1419%
1420% The format of the RegisterMagickInfo method is:
1421%
1422% MagickInfo *RegisterMagickInfo(MagickInfo *magick_info)
1423%
1424% A description of each parameter follows:
1425%
1426% o magick_info: the magick info.
1427%
1428*/
1429MagickExport MagickInfo *RegisterMagickInfo(MagickInfo *magick_info)
1430{
1431 MagickBooleanType
1432 status;
1433
1434 /*
1435 Delete any existing name.
1436 */
1437 assert(magick_info != (MagickInfo *) NULL);
1438 assert(magick_info->signature == MagickSignature);
1439 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",magick_info->name);
1440 if (magick_list == (SplayTreeInfo *) NULL)
1441 return((MagickInfo *) NULL);
1442 status=AddValueToSplayTree(magick_list,magick_info->name,magick_info);
1443 if (status == MagickFalse)
1444 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1445 return(magick_info);
1446}
1447
1448/*
1449%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1450% %
1451% %
1452% %
1453+ S e t M a g i c k I n f o %
1454% %
1455% %
1456% %
1457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1458%
1459% SetMagickInfo() allocates a MagickInfo structure and initializes the members
1460% to default values.
1461%
1462% The format of the SetMagickInfo method is:
1463%
1464% MagickInfo *SetMagickInfo(const char *name)
1465%
1466% A description of each parameter follows:
1467%
1468% o magick_info: Method SetMagickInfo returns the allocated and initialized
1469% MagickInfo structure.
1470%
1471% o name: a character string that represents the image format associated
1472% with the MagickInfo structure.
1473%
1474*/
1475MagickExport MagickInfo *SetMagickInfo(const char *name)
1476{
1477 MagickInfo
1478 *magick_info;
1479
1480 assert(name != (const char *) NULL);
1481 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
cristy73bd4a52010-10-05 11:24:23 +00001482 magick_info=(MagickInfo *) AcquireMagickMemory(sizeof(*magick_info));
cristy3ed852e2009-09-05 21:47:34 +00001483 if (magick_info == (MagickInfo *) NULL)
1484 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1485 (void) ResetMagickMemory(magick_info,0,sizeof(*magick_info));
1486 magick_info->name=ConstantString(name);
1487 magick_info->adjoin=MagickTrue;
1488 magick_info->blob_support=MagickTrue;
1489 magick_info->thread_support=(MagickStatusType) (DecoderThreadSupport |
1490 EncoderThreadSupport);
1491 magick_info->signature=MagickSignature;
1492 return(magick_info);
1493}
1494
1495/*
1496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1497% %
1498% %
1499% %
cristye7f51092010-01-17 00:39:37 +00001500% S e t M a g i c k P r e c i s i o n %
1501% %
1502% %
1503% %
1504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1505%
1506% SetMagickPrecision() sets the maximum number of significant digits to be
anthonybc6fc132012-01-16 07:02:46 +00001507% printed.
1508%
1509% An input argument of 0 returns the current precision setting.
1510%
cristyabdd5b72012-01-18 03:02:15 +00001511% A negative value forces the precision to reset to a default value according
1512% to the environment variable "MAGICK_PRECISION", the current 'policy'
1513% configuration setting, or the default value of '6', in that order.
cristye7f51092010-01-17 00:39:37 +00001514%
1515% The format of the SetMagickPrecision method is:
1516%
cristybf2766a2010-01-17 03:33:23 +00001517% int SetMagickPrecision(const int precision)
cristye7f51092010-01-17 00:39:37 +00001518%
1519% A description of each parameter follows:
1520%
1521% o precision: set the maximum number of significant digits to be printed.
1522%
1523*/
cristybf2766a2010-01-17 03:33:23 +00001524MagickExport int SetMagickPrecision(const int precision)
cristye7f51092010-01-17 00:39:37 +00001525{
anthonybc6fc132012-01-16 07:02:46 +00001526#define MagickPrecision 6
1527
cristybf2766a2010-01-17 03:33:23 +00001528 static int
1529 magick_precision = 0;
1530
cristye7f51092010-01-17 00:39:37 +00001531 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
anthony82c09922012-01-16 06:38:16 +00001532 if (precision > 0)
cristyabdd5b72012-01-18 03:02:15 +00001533 magick_precision=precision;
1534 if ((precision < 0) || (magick_precision == 0))
anthonybc6fc132012-01-16 07:02:46 +00001535 {
1536 char
1537 *limit;
1538
1539 /*
cristyabdd5b72012-01-18 03:02:15 +00001540 Precision reset, or it has not been set yet
anthonybc6fc132012-01-16 07:02:46 +00001541 */
1542 magick_precision = MagickPrecision;
1543 limit=GetEnvironmentValue("MAGICK_PRECISION");
1544 if (limit == (char *) NULL)
1545 limit=GetPolicyValue("precision");
1546 if (limit != (char *) NULL)
1547 {
cristyabdd5b72012-01-18 03:02:15 +00001548 magick_precision=StringToInteger(limit);
anthonybc6fc132012-01-16 07:02:46 +00001549 limit=DestroyString(limit);
1550 }
1551 }
cristybf2766a2010-01-17 03:33:23 +00001552 return(magick_precision);
cristye7f51092010-01-17 00:39:37 +00001553}
1554
1555/*
1556%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1557% %
1558% %
1559% %
cristy3ed852e2009-09-05 21:47:34 +00001560+ U n r e g i s t e r M a g i c k I n f o %
1561% %
1562% %
1563% %
1564%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1565%
1566% UnregisterMagickInfo() removes a name from the magick info list. It returns
1567% MagickFalse if the name does not exist in the list otherwise MagickTrue.
1568%
1569% The format of the UnregisterMagickInfo method is:
1570%
1571% MagickBooleanType UnregisterMagickInfo(const char *name)
1572%
1573% A description of each parameter follows:
1574%
1575% o name: a character string that represents the image format we are
1576% looking for.
1577%
1578*/
1579MagickExport MagickBooleanType UnregisterMagickInfo(const char *name)
1580{
1581 register const MagickInfo
1582 *p;
1583
1584 MagickBooleanType
1585 status;
1586
1587 assert(name != (const char *) NULL);
1588 if (magick_list == (SplayTreeInfo *) NULL)
1589 return(MagickFalse);
1590 if (GetNumberOfNodesInSplayTree(magick_list) == 0)
1591 return(MagickFalse);
cristyf84a1932010-01-03 18:00:18 +00001592 LockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001593 ResetSplayTreeIterator(magick_list);
1594 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
1595 while (p != (const MagickInfo *) NULL)
1596 {
1597 if (LocaleCompare(p->name,name) == 0)
1598 break;
1599 p=(const MagickInfo *) GetNextValueInSplayTree(magick_list);
1600 }
1601 status=DeleteNodeByValueFromSplayTree(magick_list,p);
cristyf84a1932010-01-03 18:00:18 +00001602 UnlockSemaphoreInfo(magick_semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001603 return(status);
1604}