MagickCore 7.1.0
Convert, Edit, Or Compose Bitmap Images
Loading...
Searching...
No Matches
coder.c
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% CCCC OOO DDDD EEEEE RRRR %
7% C O O D D E R R %
8% C O O D D EEE RRRR %
9% C O O D D E R R %
10% CCCC OOO DDDD EEEEE R R %
11% %
12% %
13% MagickCore Image Coder Methods %
14% %
15% Software Design %
16% Cristy %
17% May 2001 %
18% %
19% %
20% Copyright @ 2001 ImageMagick Studio LLC, a non-profit organization %
21% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% https://imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
42#include "MagickCore/studio.h"
43#include "MagickCore/blob.h"
44#include "MagickCore/client.h"
45#include "MagickCore/coder.h"
46#include "MagickCore/coder-private.h"
47#include "MagickCore/configure.h"
48#include "MagickCore/draw.h"
49#include "MagickCore/exception.h"
50#include "MagickCore/exception-private.h"
51#include "MagickCore/log.h"
52#include "MagickCore/memory_.h"
53#include "MagickCore/memory-private.h"
54#include "MagickCore/option.h"
55#include "MagickCore/semaphore.h"
56#include "MagickCore/string_.h"
57#include "MagickCore/splay-tree.h"
58#include "MagickCore/token.h"
59#include "MagickCore/utility.h"
60#include "MagickCore/utility-private.h"
61#include "coders/coders.h"
62
63/*
64 Define declarations.
65*/
66#define AddMagickCoder(coder) Magick ## coder ## Aliases
67
68/*
69 Typedef declarations.
70*/
71typedef struct _CoderMapInfo
72{
73 const char
74 *magick,
75 *name;
77
78/*
79 Static declarations.
80*/
81static const CoderMapInfo
82 CoderMap[] =
83 {
84 #include "coders/coders-list.h"
85 };
86
87static SemaphoreInfo
88 *coder_semaphore = (SemaphoreInfo *) NULL;
89
90static SplayTreeInfo
91 *coder_cache = (SplayTreeInfo *) NULL;
92
93/*
94 Forward declarations.
95*/
96static MagickBooleanType
97 IsCoderTreeInstantiated(ExceptionInfo *);
98
99/*
100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
101% %
102% %
103% %
104+ A c q u i r e C o d e r C a c h e %
105% %
106% %
107% %
108%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109%
110% AcquireCoderCache() caches one or more coder configurations which provides a
111% mapping between coder attributes and a coder name.
112%
113% The format of the AcquireCoderCache coder is:
114%
115% SplayTreeInfo *AcquireCoderCache(ExceptionInfo *exception)
116%
117% A description of each parameter follows:
118%
119% o exception: return any errors or warnings in this structure.
120%
121*/
122
123static void *DestroyCoderNode(void *coder_info)
124{
126 *p;
127
128 p=(CoderInfo *) coder_info;
129 if (p->exempt == MagickFalse)
130 {
131 if (p->path != (char *) NULL)
132 p->path=DestroyString(p->path);
133 if (p->name != (char *) NULL)
134 p->name=DestroyString(p->name);
135 if (p->magick != (char *) NULL)
136 p->magick=DestroyString(p->magick);
137 }
138 return(RelinquishMagickMemory(p));
139}
140
141static SplayTreeInfo *AcquireCoderCache(ExceptionInfo *exception)
142{
143 MagickStatusType
144 status;
145
146 ssize_t
147 i;
148
150 *cache;
151
152 /*
153 Load built-in coder map.
154 */
155 cache=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
156 DestroyCoderNode);
157 status=MagickTrue;
158 for (i=0; i < (ssize_t) (sizeof(CoderMap)/sizeof(*CoderMap)); i++)
159 {
161 *coder_info;
162
163 const CoderMapInfo
164 *p;
165
166 p=CoderMap+i;
167 coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info));
168 if (coder_info == (CoderInfo *) NULL)
169 {
170 (void) ThrowMagickException(exception,GetMagickModule(),
171 ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
172 continue;
173 }
174 (void) memset(coder_info,0,sizeof(*coder_info));
175 coder_info->path=(char *) "[built-in]";
176 coder_info->magick=(char *) p->magick;
177 coder_info->name=(char *) p->name;
178 coder_info->exempt=MagickTrue;
179 coder_info->signature=MagickCoreSignature;
180 status&=AddValueToSplayTree(cache,ConstantString(coder_info->magick),
181 coder_info);
182 if (status == MagickFalse)
183 (void) ThrowMagickException(exception,GetMagickModule(),
184 ResourceLimitError,"MemoryAllocationFailed","`%s'",coder_info->name);
185 }
186 return(cache);
187}
188
189/*
190%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191% %
192% %
193% %
194+ C o d e r C o m p o n e n t G e n e s i s %
195% %
196% %
197% %
198%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199%
200% CoderComponentGenesis() instantiates the coder component.
201%
202% The format of the CoderComponentGenesis method is:
203%
204% MagickBooleanType CoderComponentGenesis(void)
205%
206*/
207MagickPrivate MagickBooleanType CoderComponentGenesis(void)
208{
209 if (coder_semaphore == (SemaphoreInfo *) NULL)
210 coder_semaphore=AcquireSemaphoreInfo();
211 return(MagickTrue);
212}
213
214/*
215%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216% %
217% %
218% %
219+ C o d e r C o m p o n e n t T e r m i n u s %
220% %
221% %
222% %
223%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224%
225% CoderComponentTerminus() destroys the coder component.
226%
227% The format of the CoderComponentTerminus method is:
228%
229% CoderComponentTerminus(void)
230%
231*/
232MagickPrivate void CoderComponentTerminus(void)
233{
234 if (coder_semaphore == (SemaphoreInfo *) NULL)
235 ActivateSemaphoreInfo(&coder_semaphore);
236 LockSemaphoreInfo(coder_semaphore);
237 if (coder_cache != (SplayTreeInfo *) NULL)
238 coder_cache=DestroySplayTree(coder_cache);
239 UnlockSemaphoreInfo(coder_semaphore);
240 RelinquishSemaphoreInfo(&coder_semaphore);
241}
242
243/*
244%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
245% %
246% %
247% %
248+ G e t C o d e r I n f o %
249% %
250% %
251% %
252%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253%
254% GetCoderInfo searches the coder list for the specified name and if found
255% returns attributes for that coder.
256%
257% The format of the GetCoderInfo method is:
258%
259% const CoderInfo *GetCoderInfo(const char *name,ExceptionInfo *exception)
260%
261% A description of each parameter follows:
262%
263% o name: the coder name.
264%
265% o exception: return any errors or warnings in this structure.
266%
267*/
268MagickExport const CoderInfo *GetCoderInfo(const char *name,
269 ExceptionInfo *exception)
270{
271 assert(exception != (ExceptionInfo *) NULL);
272 if (IsCoderTreeInstantiated(exception) == MagickFalse)
273 return((const CoderInfo *) NULL);
274 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
275 return((const CoderInfo *) GetRootValueFromSplayTree(coder_cache));
276 return((const CoderInfo *) GetValueFromSplayTree(coder_cache,name));
277}
278
279/*
280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
281% %
282% %
283% %
284% G e t C o d e r I n f o L i s t %
285% %
286% %
287% %
288%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289%
290% GetCoderInfoList() returns any coder_map that match the specified pattern.
291% The format of the GetCoderInfoList function is:
292%
293% const CoderInfo **GetCoderInfoList(const char *pattern,
294% size_t *number_coders,ExceptionInfo *exception)
295%
296% A description of each parameter follows:
297%
298% o pattern: Specifies a pointer to a text string containing a pattern.
299%
300% o number_coders: This integer returns the number of coders in the list.
301%
302% o exception: return any errors or warnings in this structure.
303%
304*/
305
306static int CoderInfoCompare(const void *x,const void *y)
307{
308 const CoderInfo
309 **p,
310 **q;
311
312 p=(const CoderInfo **) x,
313 q=(const CoderInfo **) y;
314 if (LocaleCompare((*p)->path,(*q)->path) == 0)
315 return(LocaleCompare((*p)->name,(*q)->name));
316 return(LocaleCompare((*p)->path,(*q)->path));
317}
318
319MagickExport const CoderInfo **GetCoderInfoList(const char *pattern,
320 size_t *number_coders,ExceptionInfo *exception)
321{
322 const CoderInfo
323 **coder_map;
324
325 const CoderInfo
326 *p;
327
328 ssize_t
329 i;
330
331 /*
332 Allocate coder list.
333 */
334 assert(pattern != (char *) NULL);
335 assert(number_coders != (size_t *) NULL);
336 if (IsEventLogging() != MagickFalse)
337 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
338 *number_coders=0;
339 p=GetCoderInfo("*",exception);
340 if (p == (const CoderInfo *) NULL)
341 return((const CoderInfo **) NULL);
342 coder_map=(const CoderInfo **) AcquireQuantumMemory((size_t)
343 GetNumberOfNodesInSplayTree(coder_cache)+1UL,sizeof(*coder_map));
344 if (coder_map == (const CoderInfo **) NULL)
345 return((const CoderInfo **) NULL);
346 /*
347 Generate coder list.
348 */
349 LockSemaphoreInfo(coder_semaphore);
350 ResetSplayTreeIterator(coder_cache);
351 p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache);
352 for (i=0; p != (const CoderInfo *) NULL; )
353 {
354 if ((p->stealth == MagickFalse) &&
355 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
356 coder_map[i++]=p;
357 p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache);
358 }
359 UnlockSemaphoreInfo(coder_semaphore);
360 qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderInfoCompare);
361 coder_map[i]=(CoderInfo *) NULL;
362 *number_coders=(size_t) i;
363 return(coder_map);
364}
365
366/*
367%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
368% %
369% %
370% %
371% G e t C o d e r L i s t %
372% %
373% %
374% %
375%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376%
377% GetCoderList() returns any coder_map that match the specified pattern.
378%
379% The format of the GetCoderList function is:
380%
381% char **GetCoderList(const char *pattern,size_t *number_coders,
382% ExceptionInfo *exception)
383%
384% A description of each parameter follows:
385%
386% o pattern: Specifies a pointer to a text string containing a pattern.
387%
388% o number_coders: This integer returns the number of coders in the list.
389%
390% o exception: return any errors or warnings in this structure.
391%
392*/
393
394static int CoderCompare(const void *x,const void *y)
395{
396 const char
397 **p,
398 **q;
399
400 p=(const char **) x;
401 q=(const char **) y;
402 return(LocaleCompare(*p,*q));
403}
404
405MagickExport char **GetCoderList(const char *pattern,
406 size_t *number_coders,ExceptionInfo *exception)
407{
408 char
409 **coder_map;
410
411 const CoderInfo
412 *p;
413
414 ssize_t
415 i;
416
417 /*
418 Allocate coder list.
419 */
420 assert(pattern != (char *) NULL);
421 assert(number_coders != (size_t *) NULL);
422 if (IsEventLogging() != MagickFalse)
423 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
424 *number_coders=0;
425 p=GetCoderInfo("*",exception);
426 if (p == (const CoderInfo *) NULL)
427 return((char **) NULL);
428 coder_map=(char **) AcquireQuantumMemory((size_t)
429 GetNumberOfNodesInSplayTree(coder_cache)+1UL,sizeof(*coder_map));
430 if (coder_map == (char **) NULL)
431 return((char **) NULL);
432 /*
433 Generate coder list.
434 */
435 LockSemaphoreInfo(coder_semaphore);
436 ResetSplayTreeIterator(coder_cache);
437 p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache);
438 for (i=0; p != (const CoderInfo *) NULL; )
439 {
440 if ((p->stealth == MagickFalse) &&
441 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
442 coder_map[i++]=ConstantString(p->name);
443 p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache);
444 }
445 UnlockSemaphoreInfo(coder_semaphore);
446 qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderCompare);
447 coder_map[i]=(char *) NULL;
448 *number_coders=(size_t) i;
449 return(coder_map);
450}
451
452/*
453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
454% %
455% %
456% %
457+ I s C o d e r T r e e I n s t a n t i a t e d %
458% %
459% %
460% %
461%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462%
463% IsCoderTreeInstantiated() determines if the coder tree is instantiated. If
464% not, it instantiates the tree and returns it.
465%
466% The format of the IsCoderInstantiated method is:
467%
468% MagickBooleanType IsCoderTreeInstantiated(ExceptionInfo *exception)
469%
470% A description of each parameter follows.
471%
472% o exception: return any errors or warnings in this structure.
473%
474*/
475static MagickBooleanType IsCoderTreeInstantiated(ExceptionInfo *exception)
476{
477 if (coder_cache == (SplayTreeInfo *) NULL)
478 {
479 if (coder_semaphore == (SemaphoreInfo *) NULL)
480 ActivateSemaphoreInfo(&coder_semaphore);
481 LockSemaphoreInfo(coder_semaphore);
482 if (coder_cache == (SplayTreeInfo *) NULL)
483 coder_cache=AcquireCoderCache(exception);
484 UnlockSemaphoreInfo(coder_semaphore);
485 }
486 return(coder_cache != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
487}
488
489/*
490%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
491% %
492% %
493% %
494% L i s t C o d e r I n f o %
495% %
496% %
497% %
498%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
499%
500% ListCoderInfo() lists the coder info to a file.
501%
502% The format of the ListCoderInfo coder is:
503%
504% MagickBooleanType ListCoderInfo(FILE *file,ExceptionInfo *exception)
505%
506% A description of each parameter follows.
507%
508% o file: An pointer to a FILE.
509%
510% o exception: return any errors or warnings in this structure.
511%
512*/
513MagickExport MagickBooleanType ListCoderInfo(FILE *file,
514 ExceptionInfo *exception)
515{
516 const char
517 *path;
518
519 const CoderInfo
520 **coder_info;
521
522 ssize_t
523 i;
524
525 size_t
526 number_coders;
527
528 ssize_t
529 j;
530
531 if (file == (const FILE *) NULL)
532 file=stdout;
533 coder_info=GetCoderInfoList("*",&number_coders,exception);
534 if (coder_info == (const CoderInfo **) NULL)
535 return(MagickFalse);
536 path=(const char *) NULL;
537 for (i=0; i < (ssize_t) number_coders; i++)
538 {
539 if (coder_info[i]->stealth != MagickFalse)
540 continue;
541 if ((path == (const char *) NULL) ||
542 (LocaleCompare(path,coder_info[i]->path) != 0))
543 {
544 if (coder_info[i]->path != (char *) NULL)
545 (void) FormatLocaleFile(file,"\nPath: %s\n\n",coder_info[i]->path);
546 (void) FormatLocaleFile(file,"Magick Coder\n");
547 (void) FormatLocaleFile(file,
548 "-------------------------------------------------"
549 "------------------------------\n");
550 }
551 path=coder_info[i]->path;
552 (void) FormatLocaleFile(file,"%s",coder_info[i]->magick);
553 for (j=(ssize_t) strlen(coder_info[i]->magick); j <= 15; j++)
554 (void) FormatLocaleFile(file," ");
555 if (coder_info[i]->name != (char *) NULL)
556 (void) FormatLocaleFile(file,"%s",coder_info[i]->name);
557 (void) FormatLocaleFile(file,"\n");
558 }
559 coder_info=(const CoderInfo **) RelinquishMagickMemory((void *) coder_info);
560 (void) fflush(file);
561 return(MagickTrue);
562}