blob: 38a8b10538e43d2f22ba30800c49a2d7b9b7ca56 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% M M IIIII FFFFF FFFFF %
7% MM MM I F F %
8% M M M I FFF FFF %
9% M M I F F %
10% M M IIIII F F %
11% %
12% %
13% Read/Write MIFF Image Format %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy45ef08f2012-12-07 13:13:34 +000020% Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% 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% http://www.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*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/attribute.h"
44#include "MagickCore/blob.h"
45#include "MagickCore/blob-private.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/color.h"
48#include "MagickCore/color-private.h"
49#include "MagickCore/colormap.h"
50#include "MagickCore/colormap-private.h"
51#include "MagickCore/colorspace.h"
cristy325cfdc2012-04-28 01:00:09 +000052#include "MagickCore/colorspace-private.h"
cristy4c08aed2011-07-01 19:47:50 +000053#include "MagickCore/constitute.h"
54#include "MagickCore/exception.h"
55#include "MagickCore/exception-private.h"
56#include "MagickCore/hashmap.h"
57#include "MagickCore/geometry.h"
58#include "MagickCore/image.h"
59#include "MagickCore/image-private.h"
60#include "MagickCore/list.h"
61#include "MagickCore/magick.h"
62#include "MagickCore/memory_.h"
63#include "MagickCore/module.h"
64#include "MagickCore/monitor.h"
65#include "MagickCore/monitor-private.h"
66#include "MagickCore/option.h"
67#include "MagickCore/pixel.h"
68#include "MagickCore/pixel-accessor.h"
69#include "MagickCore/profile.h"
70#include "MagickCore/property.h"
71#include "MagickCore/quantum-private.h"
72#include "MagickCore/static.h"
73#include "MagickCore/statistic.h"
74#include "MagickCore/string_.h"
75#include "MagickCore/string-private.h"
cristy3ed852e2009-09-05 21:47:34 +000076#if defined(MAGICKCORE_BZLIB_DELEGATE)
77#include "bzlib.h"
78#endif
cristy26377172010-12-20 19:01:58 +000079#if defined(MAGICKCORE_LZMA_DELEGATE)
80#include "lzma.h"
81#endif
82#if defined(MAGICKCORE_ZLIB_DELEGATE)
83#include "zlib.h"
84#endif
cristy3ed852e2009-09-05 21:47:34 +000085
86/*
cristya7a341e2010-12-22 20:28:51 +000087 Define declarations.
88*/
89#if !defined(LZMA_OK)
90#define LZMA_OK 0
91#endif
92
93/*
cristy3ed852e2009-09-05 21:47:34 +000094 Forward declarations.
95*/
96static MagickBooleanType
cristy1e178e72011-08-28 19:44:34 +000097 WriteMIFFImage(const ImageInfo *,Image *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +000098
99/*
100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
101% %
102% %
103% %
104% I s M I F F %
105% %
106% %
107% %
108%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109%
110% IsMIFF() returns MagickTrue if the image format type, identified by the
111% magick string, is MIFF.
112%
113% The format of the IsMIFF method is:
114%
115% MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
116%
117% A description of each parameter follows:
118%
119% o magick: compare image format pattern against these bytes.
120%
121% o length: Specifies the length of the magick string.
122%
123*/
124static MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
125{
126 if (length < 14)
127 return(MagickFalse);
128 if (LocaleNCompare((const char *) magick,"id=ImageMagick",14) == 0)
129 return(MagickTrue);
130 return(MagickFalse);
131}
132
133/*
134%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135% %
136% %
137% %
138% R e a d M I F F I m a g e %
139% %
140% %
141% %
142%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143%
144% ReadMIFFImage() reads a MIFF image file and returns it. It allocates the
145% memory necessary for the new Image structure and returns a pointer to the
146% new image.
147%
148% The format of the ReadMIFFImage method is:
149%
150% Image *ReadMIFFImage(const ImageInfo *image_info,
151% ExceptionInfo *exception)
152%
153% Decompression code contributed by Kyle Shorter.
154%
155% A description of each parameter follows:
156%
157% o image_info: the image info.
158%
159% o exception: return any errors or warnings in this structure.
160%
161*/
162
163#if defined(MAGICKCORE_BZLIB_DELEGATE)
164static void *AcquireBZIPMemory(void *context,int items,int size)
165{
166 (void) context;
167 return((void *) AcquireQuantumMemory((size_t) items,(size_t) size));
168}
169#endif
170
cristy4b46dba2010-12-20 19:18:20 +0000171#if defined(MAGICKCORE_LZMA_DELEGATE)
172static void *AcquireLZMAMemory(void *context,size_t items,size_t size)
173{
174 (void) context;
175 return((void *) AcquireQuantumMemory((size_t) items,(size_t) size));
176}
177#endif
178
cristy3ed852e2009-09-05 21:47:34 +0000179#if defined(MAGICKCORE_ZLIB_DELEGATE)
180static voidpf AcquireZIPMemory(voidpf context,unsigned int items,
181 unsigned int size)
182{
183 (void) context;
184 return((voidpf) AcquireQuantumMemory(items,size));
185}
186#endif
187
188static inline size_t MagickMax(const size_t x,const size_t y)
189{
190 if (x > y)
191 return(x);
192 return(y);
193}
194
195static inline size_t MagickMin(const size_t x,const size_t y)
196{
197 if (x < y)
198 return(x);
199 return(y);
200}
201
202static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
cristyc82a27b2011-10-21 01:07:16 +0000203 size_t *length,PixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000204{
205 const unsigned char
206 *p;
207
208 p=pixels;
209 if (image->storage_class == PseudoClass)
210 {
cristy4c08aed2011-07-01 19:47:50 +0000211 pixel->index=0;
cristy3ed852e2009-09-05 21:47:34 +0000212 switch (image->depth)
213 {
214 case 32:
215 {
cristy4c08aed2011-07-01 19:47:50 +0000216 pixel->index=ConstrainColormapIndex(image,
cristyc82a27b2011-10-21 01:07:16 +0000217 (*p << 24) | (*(p+1) << 16) | (*(p+2) << 8) | *(p+3),exception);
cristy3ed852e2009-09-05 21:47:34 +0000218 p+=4;
219 break;
220 }
221 case 16:
222 {
cristyc82a27b2011-10-21 01:07:16 +0000223 pixel->index=ConstrainColormapIndex(image,(*p << 8) | *(p+1),
224 exception);
cristy3ed852e2009-09-05 21:47:34 +0000225 p+=2;
226 break;
227 }
228 case 8:
229 {
cristyc82a27b2011-10-21 01:07:16 +0000230 pixel->index=ConstrainColormapIndex(image,*p,exception);
cristy3ed852e2009-09-05 21:47:34 +0000231 p++;
232 break;
233 }
234 default:
cristyc82a27b2011-10-21 01:07:16 +0000235 (void) ThrowMagickException(exception,GetMagickModule(),
cristy3ed852e2009-09-05 21:47:34 +0000236 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
237 }
cristy3ed852e2009-09-05 21:47:34 +0000238 switch (image->depth)
239 {
240 case 8:
241 {
242 unsigned char
243 quantum;
244
cristy8a46d822012-08-28 23:32:39 +0000245 if (image->alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +0000246 {
247 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000248 pixel->alpha=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000249 }
250 break;
251 }
252 case 16:
253 {
254 unsigned short
255 quantum;
256
cristy8a46d822012-08-28 23:32:39 +0000257 if (image->alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +0000258 {
259 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000260 pixel->alpha=(Quantum) (quantum >> (image->depth-
cristy3ed852e2009-09-05 21:47:34 +0000261 MAGICKCORE_QUANTUM_DEPTH));
262 }
263 break;
264 }
265 case 32:
266 {
cristy4cb162a2010-05-30 03:04:47 +0000267 unsigned int
cristy3ed852e2009-09-05 21:47:34 +0000268 quantum;
269
cristy8a46d822012-08-28 23:32:39 +0000270 if (image->alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +0000271 {
272 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000273 pixel->alpha=(Quantum) (quantum >> (image->depth-
cristy3ed852e2009-09-05 21:47:34 +0000274 MAGICKCORE_QUANTUM_DEPTH));
275 }
276 break;
277 }
278 default:
cristyc82a27b2011-10-21 01:07:16 +0000279 (void) ThrowMagickException(exception,GetMagickModule(),
cristy3ed852e2009-09-05 21:47:34 +0000280 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
281 }
282 *length=(size_t) (*p++)+1;
283 return;
284 }
285 switch (image->depth)
286 {
287 case 8:
288 {
289 unsigned char
290 quantum;
291
292 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000293 pixel->red=ScaleCharToQuantum(quantum);
cristy325cfdc2012-04-28 01:00:09 +0000294 pixel->green=pixel->red;
295 pixel->blue=pixel->red;
296 if (IsGrayColorspace(image->colorspace) == MagickFalse)
297 {
298 p=PushCharPixel(p,&quantum);
299 pixel->green=ScaleCharToQuantum(quantum);
300 p=PushCharPixel(p,&quantum);
301 pixel->blue=ScaleCharToQuantum(quantum);
302 }
cristy3ed852e2009-09-05 21:47:34 +0000303 if (image->colorspace == CMYKColorspace)
304 {
305 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000306 pixel->black=ScaleCharToQuantum(quantum);
307 }
cristy8a46d822012-08-28 23:32:39 +0000308 if (image->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +0000309 {
310 p=PushCharPixel(p,&quantum);
311 pixel->alpha=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000312 }
313 break;
314 }
315 case 16:
316 {
317 unsigned short
318 quantum;
319
320 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000321 pixel->red=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy325cfdc2012-04-28 01:00:09 +0000322 pixel->green=pixel->red;
323 pixel->blue=pixel->red;
324 if (IsGrayColorspace(image->colorspace) == MagickFalse)
325 {
326 p=PushShortPixel(MSBEndian,p,&quantum);
327 pixel->green=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
328 p=PushShortPixel(MSBEndian,p,&quantum);
329 pixel->blue=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
330 }
cristy3ed852e2009-09-05 21:47:34 +0000331 if (image->colorspace == CMYKColorspace)
332 {
333 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000334 pixel->black=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
335 }
cristy8a46d822012-08-28 23:32:39 +0000336 if (image->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +0000337 {
338 p=PushShortPixel(MSBEndian,p,&quantum);
339 pixel->alpha=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000340 }
341 break;
342 }
343 case 32:
344 {
cristy4cb162a2010-05-30 03:04:47 +0000345 unsigned int
cristy3ed852e2009-09-05 21:47:34 +0000346 quantum;
347
348 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000349 pixel->red=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy325cfdc2012-04-28 01:00:09 +0000350 pixel->green=pixel->red;
351 pixel->blue=pixel->red;
352 if (IsGrayColorspace(image->colorspace) == MagickFalse)
353 {
354 p=PushLongPixel(MSBEndian,p,&quantum);
355 pixel->green=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
356 p=PushLongPixel(MSBEndian,p,&quantum);
357 pixel->blue=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
358 }
cristy3ed852e2009-09-05 21:47:34 +0000359 if (image->colorspace == CMYKColorspace)
360 {
361 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000362 pixel->black=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
363 }
cristy8a46d822012-08-28 23:32:39 +0000364 if (image->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +0000365 {
366 p=PushLongPixel(MSBEndian,p,&quantum);
367 pixel->alpha=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000368 }
369 break;
370 }
371 default:
cristyc82a27b2011-10-21 01:07:16 +0000372 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
373 "ImageDepthNotSupported","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +0000374 }
375 *length=(size_t) (*p++)+1;
376}
377
cristy4b46dba2010-12-20 19:18:20 +0000378#if defined(MAGICKCORE_BZLIB_DELEGATE)
379static void RelinquishBZIPMemory(void *context,void *memory)
cristy3ed852e2009-09-05 21:47:34 +0000380{
381 (void) context;
382 memory=RelinquishMagickMemory(memory);
383}
384#endif
385
cristy4b46dba2010-12-20 19:18:20 +0000386#if defined(MAGICKCORE_LZMA_DELEGATE)
387static void RelinquishLZMAMemory(void *context,void *memory)
388{
389 (void) context;
390 memory=RelinquishMagickMemory(memory);
391}
392#endif
393
394#if defined(MAGICKCORE_ZLIB_DELEGATE)
395static void RelinquishZIPMemory(voidpf context,voidpf memory)
cristy3ed852e2009-09-05 21:47:34 +0000396{
397 (void) context;
398 memory=RelinquishMagickMemory(memory);
399}
400#endif
401
402static Image *ReadMIFFImage(const ImageInfo *image_info,
403 ExceptionInfo *exception)
404{
405#define BZipMaxExtent(x) ((x)+((x)/100)+600)
cristy26377172010-12-20 19:01:58 +0000406#define LZMAMaxExtent(x) ((x)+((x)/3)+128)
cristy3ed852e2009-09-05 21:47:34 +0000407#define ZipMaxExtent(x) ((x)+(((x)+7) >> 3)+(((x)+63) >> 6)+11)
408
409#if defined(MAGICKCORE_BZLIB_DELEGATE)
410 bz_stream
411 bzip_info;
412#endif
413
414 char
415 id[MaxTextExtent],
416 keyword[MaxTextExtent],
417 *options;
418
419 const unsigned char
420 *p;
421
422 double
423 version;
424
425 GeometryInfo
426 geometry_info;
427
428 Image
429 *image;
430
cristy3ed852e2009-09-05 21:47:34 +0000431 int
cristy3a99dcf2011-12-17 01:29:40 +0000432 c;
cristy3ed852e2009-09-05 21:47:34 +0000433
cristyde626a22012-05-13 00:39:00 +0000434 LinkedListInfo
435 *profiles;
436
cristy26377172010-12-20 19:01:58 +0000437#if defined(MAGICKCORE_LZMA_DELEGATE)
438 lzma_stream
cristy330af6c2010-12-21 14:36:06 +0000439 initialize_lzma = LZMA_STREAM_INIT,
440 lzma_info;
cristy4b46dba2010-12-20 19:18:20 +0000441
442 lzma_allocator
443 allocator;
cristy26377172010-12-20 19:01:58 +0000444#endif
445
cristy3ed852e2009-09-05 21:47:34 +0000446 MagickBooleanType
447 status;
448
cristy4c08aed2011-07-01 19:47:50 +0000449 PixelInfo
450 pixel;
451
cristy3ed852e2009-09-05 21:47:34 +0000452 MagickStatusType
453 flags;
454
cristy3ed852e2009-09-05 21:47:34 +0000455 QuantumFormatType
456 quantum_format;
457
458 QuantumInfo
459 *quantum_info;
460
461 QuantumType
462 quantum_type;
463
cristybb503372010-05-27 20:51:26 +0000464 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000465 i;
466
467 size_t
468 length,
469 packet_size;
470
471 ssize_t
472 count;
473
474 unsigned char
475 *compress_pixels,
476 *pixels;
477
cristybb503372010-05-27 20:51:26 +0000478 size_t
cristy3ed852e2009-09-05 21:47:34 +0000479 colors;
480
cristy26377172010-12-20 19:01:58 +0000481 ssize_t
482 y;
483
cristy3ed852e2009-09-05 21:47:34 +0000484#if defined(MAGICKCORE_ZLIB_DELEGATE)
485 z_stream
486 zip_info;
487#endif
488
489 /*
490 Open image file.
491 */
492 assert(image_info != (const ImageInfo *) NULL);
493 assert(image_info->signature == MagickSignature);
494 if (image_info->debug != MagickFalse)
495 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
496 image_info->filename);
497 assert(exception != (ExceptionInfo *) NULL);
498 assert(exception->signature == MagickSignature);
cristy9950d572011-10-01 18:22:35 +0000499 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000500 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
501 if (status == MagickFalse)
502 {
503 image=DestroyImageList(image);
504 return((Image *) NULL);
505 }
506 /*
507 Decode image header; header terminates one character beyond a ':'.
508 */
509 c=ReadBlobByte(image);
510 if (c == EOF)
511 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
cristy3ed852e2009-09-05 21:47:34 +0000512 *id='\0';
513 (void) ResetMagickMemory(keyword,0,sizeof(keyword));
514 version=0.0;
cristy51f4b1b2012-02-21 13:56:07 +0000515 (void) version;
cristy3ed852e2009-09-05 21:47:34 +0000516 do
517 {
518 /*
519 Decode image header; header terminates one character beyond a ':'.
520 */
521 length=MaxTextExtent;
522 options=AcquireString((char *) NULL);
523 quantum_format=UndefinedQuantumFormat;
524 profiles=(LinkedListInfo *) NULL;
525 colors=0;
526 image->depth=8UL;
527 image->compression=NoCompression;
528 while ((isgraph(c) != MagickFalse) && (c != (int) ':'))
529 {
530 register char
531 *p;
532
533 if (c == (int) '{')
534 {
535 char
536 *comment;
537
538 /*
539 Read comment-- any text between { }.
540 */
541 length=MaxTextExtent;
542 comment=AcquireString((char *) NULL);
543 for (p=comment; comment != (char *) NULL; p++)
544 {
545 c=ReadBlobByte(image);
cristyb880ee82012-04-07 15:08:14 +0000546 if (c == (int) '\\')
547 c=ReadBlobByte(image);
548 else
549 if ((c == EOF) || (c == (int) '}'))
550 break;
cristy3ed852e2009-09-05 21:47:34 +0000551 if ((size_t) (p-comment+1) >= length)
552 {
553 *p='\0';
554 length<<=1;
555 comment=(char *) ResizeQuantumMemory(comment,length+
556 MaxTextExtent,sizeof(*comment));
557 if (comment == (char *) NULL)
558 break;
559 p=comment+strlen(comment);
560 }
561 *p=(char) c;
562 }
563 if (comment == (char *) NULL)
564 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
565 *p='\0';
cristyd15e6592011-10-15 00:13:06 +0000566 (void) SetImageProperty(image,"comment",comment,exception);
cristy3ed852e2009-09-05 21:47:34 +0000567 comment=DestroyString(comment);
568 c=ReadBlobByte(image);
569 }
570 else
571 if (isalnum(c) != MagickFalse)
572 {
573 /*
574 Get the keyword.
575 */
576 p=keyword;
577 do
578 {
cristy3ed852e2009-09-05 21:47:34 +0000579 if (c == (int) '=')
580 break;
581 if ((size_t) (p-keyword) < (MaxTextExtent-1))
582 *p++=(char) c;
583 c=ReadBlobByte(image);
584 } while (c != EOF);
585 *p='\0';
586 p=options;
cristy93505cf2010-08-10 21:37:49 +0000587 while ((isspace((int) ((unsigned char) c)) != 0) && (c != EOF))
cristy3ed852e2009-09-05 21:47:34 +0000588 c=ReadBlobByte(image);
589 if (c == (int) '=')
590 {
591 /*
592 Get the keyword value.
593 */
594 c=ReadBlobByte(image);
595 while ((c != (int) '}') && (c != EOF))
596 {
597 if ((size_t) (p-options+1) >= length)
598 {
599 *p='\0';
600 length<<=1;
601 options=(char *) ResizeQuantumMemory(options,length+
602 MaxTextExtent,sizeof(*options));
603 if (options == (char *) NULL)
604 break;
605 p=options+strlen(options);
606 }
607 if (options == (char *) NULL)
608 ThrowReaderException(ResourceLimitError,
609 "MemoryAllocationFailed");
610 *p++=(char) c;
611 c=ReadBlobByte(image);
cristyb880ee82012-04-07 15:08:14 +0000612 if (c == '\\')
613 {
614 c=ReadBlobByte(image);
615 if (c == (int) '}')
616 {
617 *p++=(char) c;
618 c=ReadBlobByte(image);
619 }
620 }
cristy3ed852e2009-09-05 21:47:34 +0000621 if (*options != '{')
622 if (isspace((int) ((unsigned char) c)) != 0)
623 break;
cristy8a46d822012-08-28 23:32:39 +0000624 } }
cristy3ed852e2009-09-05 21:47:34 +0000625 *p='\0';
626 if (*options == '{')
cristybfae51d2012-10-05 15:40:35 +0000627 (void) CopyMagickString(options,options+1,strlen(options));
cristy3ed852e2009-09-05 21:47:34 +0000628 /*
629 Assign a value to the specified keyword.
630 */
631 switch (*keyword)
632 {
cristy8a46d822012-08-28 23:32:39 +0000633 case 'a':
634 case 'A':
635 {
636 if (LocaleCompare(keyword,"alpha-trait") == 0)
637 {
638 ssize_t
639 alpha_trait;
640
641 alpha_trait=ParseCommandOption(MagickPixelTraitOptions,
642 MagickFalse,options);
643 if (alpha_trait < 0)
644 break;
645 image->alpha_trait=(PixelTrait) alpha_trait;
646 break;
647 }
648 (void) SetImageProperty(image,keyword,options,exception);
649 break;
650 }
cristy3ed852e2009-09-05 21:47:34 +0000651 case 'b':
652 case 'B':
653 {
654 if (LocaleCompare(keyword,"background-color") == 0)
655 {
cristy9950d572011-10-01 18:22:35 +0000656 (void) QueryColorCompliance(options,AllCompliance,
657 &image->background_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000658 break;
659 }
660 if (LocaleCompare(keyword,"blue-primary") == 0)
661 {
662 flags=ParseGeometry(options,&geometry_info);
663 image->chromaticity.blue_primary.x=geometry_info.rho;
664 image->chromaticity.blue_primary.y=geometry_info.sigma;
665 if ((flags & SigmaValue) == 0)
666 image->chromaticity.blue_primary.y=
667 image->chromaticity.blue_primary.x;
668 break;
669 }
670 if (LocaleCompare(keyword,"border-color") == 0)
671 {
cristy9950d572011-10-01 18:22:35 +0000672 (void) QueryColorCompliance(options,AllCompliance,
673 &image->border_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000674 break;
675 }
cristyd15e6592011-10-15 00:13:06 +0000676 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000677 break;
678 }
679 case 'c':
680 case 'C':
681 {
682 if (LocaleCompare(keyword,"class") == 0)
683 {
cristybb503372010-05-27 20:51:26 +0000684 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000685 storage_class;
686
cristy042ee782011-04-22 18:48:30 +0000687 storage_class=ParseCommandOption(MagickClassOptions,
cristy3ed852e2009-09-05 21:47:34 +0000688 MagickFalse,options);
689 if (storage_class < 0)
690 break;
691 image->storage_class=(ClassType) storage_class;
692 break;
693 }
694 if (LocaleCompare(keyword,"colors") == 0)
695 {
cristye27293e2009-12-18 02:53:20 +0000696 colors=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000697 break;
698 }
699 if (LocaleCompare(keyword,"colorspace") == 0)
700 {
cristybb503372010-05-27 20:51:26 +0000701 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000702 colorspace;
703
cristy042ee782011-04-22 18:48:30 +0000704 colorspace=ParseCommandOption(MagickColorspaceOptions,
cristy3ed852e2009-09-05 21:47:34 +0000705 MagickFalse,options);
706 if (colorspace < 0)
707 break;
cristy02a27d52013-03-05 01:06:21 +0000708 image->colorspace=(ColorspaceType) colorspace;
cristy3ed852e2009-09-05 21:47:34 +0000709 break;
710 }
711 if (LocaleCompare(keyword,"compression") == 0)
712 {
cristybb503372010-05-27 20:51:26 +0000713 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000714 compression;
715
cristy042ee782011-04-22 18:48:30 +0000716 compression=ParseCommandOption(MagickCompressOptions,
cristy3ed852e2009-09-05 21:47:34 +0000717 MagickFalse,options);
718 if (compression < 0)
719 break;
720 image->compression=(CompressionType) compression;
721 break;
722 }
723 if (LocaleCompare(keyword,"columns") == 0)
724 {
cristye27293e2009-12-18 02:53:20 +0000725 image->columns=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000726 break;
727 }
cristyd15e6592011-10-15 00:13:06 +0000728 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000729 break;
730 }
731 case 'd':
732 case 'D':
733 {
734 if (LocaleCompare(keyword,"delay") == 0)
735 {
cristye27293e2009-12-18 02:53:20 +0000736 image->delay=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000737 break;
738 }
739 if (LocaleCompare(keyword,"depth") == 0)
740 {
cristye27293e2009-12-18 02:53:20 +0000741 image->depth=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000742 break;
743 }
744 if (LocaleCompare(keyword,"dispose") == 0)
745 {
cristybb503372010-05-27 20:51:26 +0000746 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000747 dispose;
748
cristy042ee782011-04-22 18:48:30 +0000749 dispose=ParseCommandOption(MagickDisposeOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000750 options);
751 if (dispose < 0)
752 break;
753 image->dispose=(DisposeType) dispose;
754 break;
755 }
cristyd15e6592011-10-15 00:13:06 +0000756 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000757 break;
758 }
759 case 'e':
760 case 'E':
761 {
762 if (LocaleCompare(keyword,"endian") == 0)
763 {
cristybb503372010-05-27 20:51:26 +0000764 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000765 endian;
766
cristy042ee782011-04-22 18:48:30 +0000767 endian=ParseCommandOption(MagickEndianOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000768 options);
769 if (endian < 0)
770 break;
771 image->endian=(EndianType) endian;
772 break;
773 }
cristyd15e6592011-10-15 00:13:06 +0000774 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000775 break;
776 }
777 case 'g':
778 case 'G':
779 {
780 if (LocaleCompare(keyword,"gamma") == 0)
781 {
cristydbdd0e32011-11-04 23:29:40 +0000782 image->gamma=StringToDouble(options,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000783 break;
784 }
785 if (LocaleCompare(keyword,"gravity") == 0)
786 {
cristybb503372010-05-27 20:51:26 +0000787 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000788 gravity;
789
cristy042ee782011-04-22 18:48:30 +0000790 gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000791 options);
792 if (gravity < 0)
793 break;
794 image->gravity=(GravityType) gravity;
795 break;
796 }
797 if (LocaleCompare(keyword,"green-primary") == 0)
798 {
799 flags=ParseGeometry(options,&geometry_info);
800 image->chromaticity.green_primary.x=geometry_info.rho;
801 image->chromaticity.green_primary.y=geometry_info.sigma;
802 if ((flags & SigmaValue) == 0)
803 image->chromaticity.green_primary.y=
804 image->chromaticity.green_primary.x;
805 break;
806 }
cristyd15e6592011-10-15 00:13:06 +0000807 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000808 break;
809 }
810 case 'i':
811 case 'I':
812 {
813 if (LocaleCompare(keyword,"id") == 0)
814 {
815 (void) CopyMagickString(id,options,MaxTextExtent);
816 break;
817 }
818 if (LocaleCompare(keyword,"iterations") == 0)
819 {
cristye27293e2009-12-18 02:53:20 +0000820 image->iterations=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000821 break;
822 }
cristyd15e6592011-10-15 00:13:06 +0000823 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000824 break;
825 }
826 case 'm':
827 case 'M':
828 {
829 if (LocaleCompare(keyword,"matte") == 0)
830 {
cristybb503372010-05-27 20:51:26 +0000831 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000832 matte;
833
cristy042ee782011-04-22 18:48:30 +0000834 matte=ParseCommandOption(MagickBooleanOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000835 options);
836 if (matte < 0)
837 break;
cristy8a46d822012-08-28 23:32:39 +0000838 image->alpha_trait=matte == 0 ? UndefinedPixelTrait :
839 BlendPixelTrait;
cristy3ed852e2009-09-05 21:47:34 +0000840 break;
841 }
842 if (LocaleCompare(keyword,"matte-color") == 0)
843 {
cristy9950d572011-10-01 18:22:35 +0000844 (void) QueryColorCompliance(options,AllCompliance,
845 &image->matte_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000846 break;
847 }
848 if (LocaleCompare(keyword,"montage") == 0)
849 {
850 (void) CloneString(&image->montage,options);
851 break;
852 }
cristyd15e6592011-10-15 00:13:06 +0000853 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000854 break;
855 }
856 case 'o':
857 case 'O':
858 {
cristy3ed852e2009-09-05 21:47:34 +0000859 if (LocaleCompare(keyword,"orientation") == 0)
860 {
cristybb503372010-05-27 20:51:26 +0000861 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000862 orientation;
863
cristy042ee782011-04-22 18:48:30 +0000864 orientation=ParseCommandOption(MagickOrientationOptions,
cristy3ed852e2009-09-05 21:47:34 +0000865 MagickFalse,options);
866 if (orientation < 0)
867 break;
868 image->orientation=(OrientationType) orientation;
869 break;
870 }
cristyd15e6592011-10-15 00:13:06 +0000871 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000872 break;
873 }
874 case 'p':
875 case 'P':
876 {
877 if (LocaleCompare(keyword,"page") == 0)
878 {
879 char
880 *geometry;
881
882 geometry=GetPageGeometry(options);
883 (void) ParseAbsoluteGeometry(geometry,&image->page);
884 geometry=DestroyString(geometry);
885 break;
886 }
cristy3e4e9f42013-04-06 22:29:40 +0000887 if (LocaleCompare(keyword,"pixel-intensity") == 0)
888 {
889 ssize_t
890 intensity;
891
892 intensity=ParseCommandOption(MagickPixelIntensityOptions,
893 MagickFalse,options);
894 if (intensity < 0)
895 break;
896 image->intensity=(PixelIntensityMethod) intensity;
897 break;
898 }
cristy3ed852e2009-09-05 21:47:34 +0000899 if ((LocaleNCompare(keyword,"profile:",8) == 0) ||
900 (LocaleNCompare(keyword,"profile-",8) == 0))
901 {
902 StringInfo
903 *profile;
904
905 if (profiles == (LinkedListInfo *) NULL)
906 profiles=NewLinkedList(0);
907 (void) AppendValueToLinkedList(profiles,
908 AcquireString(keyword+8));
cristy63f9b8e2011-09-01 13:40:50 +0000909 profile=BlobToStringInfo((const void *) NULL,(size_t)
910 StringToLong(options));
cristy49f5e9f2011-09-01 13:44:57 +0000911 if (profile == (StringInfo *) NULL)
cristy63f9b8e2011-09-01 13:40:50 +0000912 ThrowReaderException(ResourceLimitError,
913 "MemoryAllocationFailed");
cristyd15e6592011-10-15 00:13:06 +0000914 (void) SetImageProfile(image,keyword+8,profile,exception);
cristy3ed852e2009-09-05 21:47:34 +0000915 profile=DestroyStringInfo(profile);
916 break;
917 }
cristyd15e6592011-10-15 00:13:06 +0000918 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000919 break;
920 }
921 case 'q':
922 case 'Q':
923 {
924 if (LocaleCompare(keyword,"quality") == 0)
925 {
cristye27293e2009-12-18 02:53:20 +0000926 image->quality=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000927 break;
928 }
929 if ((LocaleCompare(keyword,"quantum-format") == 0) ||
930 (LocaleCompare(keyword,"quantum:format") == 0))
931 {
cristybb503372010-05-27 20:51:26 +0000932 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000933 format;
934
cristy042ee782011-04-22 18:48:30 +0000935 format=ParseCommandOption(MagickQuantumFormatOptions,
cristy3ed852e2009-09-05 21:47:34 +0000936 MagickFalse,options);
937 if (format < 0)
938 break;
939 quantum_format=(QuantumFormatType) format;
940 break;
941 }
cristyd15e6592011-10-15 00:13:06 +0000942 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000943 break;
944 }
945 case 'r':
946 case 'R':
947 {
948 if (LocaleCompare(keyword,"red-primary") == 0)
949 {
950 flags=ParseGeometry(options,&geometry_info);
951 image->chromaticity.red_primary.x=geometry_info.rho;
952 image->chromaticity.red_primary.y=geometry_info.sigma;
953 if ((flags & SigmaValue) == 0)
954 image->chromaticity.red_primary.y=
955 image->chromaticity.red_primary.x;
956 break;
957 }
958 if (LocaleCompare(keyword,"rendering-intent") == 0)
959 {
cristybb503372010-05-27 20:51:26 +0000960 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000961 rendering_intent;
962
cristy042ee782011-04-22 18:48:30 +0000963 rendering_intent=ParseCommandOption(MagickIntentOptions,
cristy3ed852e2009-09-05 21:47:34 +0000964 MagickFalse,options);
965 if (rendering_intent < 0)
966 break;
967 image->rendering_intent=(RenderingIntent) rendering_intent;
968 break;
969 }
970 if (LocaleCompare(keyword,"resolution") == 0)
971 {
972 flags=ParseGeometry(options,&geometry_info);
cristy2a11bef2011-10-28 18:33:11 +0000973 image->resolution.x=geometry_info.rho;
974 image->resolution.y=geometry_info.sigma;
cristy3ed852e2009-09-05 21:47:34 +0000975 if ((flags & SigmaValue) == 0)
cristy2a11bef2011-10-28 18:33:11 +0000976 image->resolution.y=image->resolution.x;
cristy3ed852e2009-09-05 21:47:34 +0000977 break;
978 }
979 if (LocaleCompare(keyword,"rows") == 0)
980 {
cristye27293e2009-12-18 02:53:20 +0000981 image->rows=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000982 break;
983 }
cristyd15e6592011-10-15 00:13:06 +0000984 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000985 break;
986 }
987 case 's':
988 case 'S':
989 {
990 if (LocaleCompare(keyword,"scene") == 0)
991 {
cristye27293e2009-12-18 02:53:20 +0000992 image->scene=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000993 break;
994 }
cristyd15e6592011-10-15 00:13:06 +0000995 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000996 break;
997 }
998 case 't':
999 case 'T':
1000 {
1001 if (LocaleCompare(keyword,"ticks-per-second") == 0)
1002 {
cristy15893a42010-11-20 18:57:15 +00001003 image->ticks_per_second=(ssize_t) StringToLong(options);
cristy3ed852e2009-09-05 21:47:34 +00001004 break;
1005 }
1006 if (LocaleCompare(keyword,"tile-offset") == 0)
1007 {
1008 char
1009 *geometry;
1010
1011 geometry=GetPageGeometry(options);
1012 (void) ParseAbsoluteGeometry(geometry,&image->tile_offset);
1013 geometry=DestroyString(geometry);
1014 break;
1015 }
1016 if (LocaleCompare(keyword,"type") == 0)
1017 {
cristybb503372010-05-27 20:51:26 +00001018 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001019 type;
1020
cristy042ee782011-04-22 18:48:30 +00001021 type=ParseCommandOption(MagickTypeOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +00001022 options);
1023 if (type < 0)
1024 break;
1025 image->type=(ImageType) type;
1026 break;
1027 }
cristyd15e6592011-10-15 00:13:06 +00001028 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +00001029 break;
1030 }
1031 case 'u':
1032 case 'U':
1033 {
1034 if (LocaleCompare(keyword,"units") == 0)
1035 {
cristybb503372010-05-27 20:51:26 +00001036 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001037 units;
1038
cristyfbbafc92011-05-05 01:22:11 +00001039 units=ParseCommandOption(MagickResolutionOptions,
1040 MagickFalse,options);
cristy3ed852e2009-09-05 21:47:34 +00001041 if (units < 0)
1042 break;
1043 image->units=(ResolutionType) units;
1044 break;
1045 }
cristyd15e6592011-10-15 00:13:06 +00001046 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +00001047 break;
1048 }
1049 case 'v':
1050 case 'V':
1051 {
1052 if (LocaleCompare(keyword,"version") == 0)
1053 {
cristydbdd0e32011-11-04 23:29:40 +00001054 version=StringToDouble(options,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +00001055 break;
1056 }
cristyd15e6592011-10-15 00:13:06 +00001057 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +00001058 break;
1059 }
1060 case 'w':
1061 case 'W':
1062 {
1063 if (LocaleCompare(keyword,"white-point") == 0)
1064 {
1065 flags=ParseGeometry(options,&geometry_info);
1066 image->chromaticity.white_point.x=geometry_info.rho;
cristy37f88d92012-05-04 11:14:52 +00001067 image->chromaticity.white_point.y=geometry_info.sigma;
cristy74ca1502012-06-21 13:10:47 +00001068 if ((flags & SigmaValue) == 0)
cristy3ed852e2009-09-05 21:47:34 +00001069 image->chromaticity.white_point.y=
1070 image->chromaticity.white_point.x;
1071 break;
1072 }
cristyd15e6592011-10-15 00:13:06 +00001073 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +00001074 break;
1075 }
1076 default:
1077 {
cristyd15e6592011-10-15 00:13:06 +00001078 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +00001079 break;
1080 }
1081 }
1082 }
1083 else
1084 c=ReadBlobByte(image);
1085 while (isspace((int) ((unsigned char) c)) != 0)
1086 c=ReadBlobByte(image);
1087 }
1088 options=DestroyString(options);
1089 (void) ReadBlobByte(image);
1090 /*
1091 Verify that required image information is defined.
1092 */
1093 if ((LocaleCompare(id,"ImageMagick") != 0) ||
1094 (image->storage_class == UndefinedClass) ||
1095 (image->columns == 0) || (image->rows == 0))
1096 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1097 if (image->montage != (char *) NULL)
1098 {
1099 register char
1100 *p;
1101
1102 /*
1103 Image directory.
1104 */
1105 length=MaxTextExtent;
1106 image->directory=AcquireString((char *) NULL);
1107 p=image->directory;
1108 do
1109 {
1110 *p='\0';
1111 if ((strlen(image->directory)+MaxTextExtent) >= length)
1112 {
1113 /*
1114 Allocate more memory for the image directory.
1115 */
1116 length<<=1;
1117 image->directory=(char *) ResizeQuantumMemory(image->directory,
1118 length+MaxTextExtent,sizeof(*image->directory));
1119 if (image->directory == (char *) NULL)
1120 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1121 p=image->directory+strlen(image->directory);
1122 }
1123 c=ReadBlobByte(image);
1124 *p++=(char) c;
1125 } while (c != (int) '\0');
1126 }
1127 if (profiles != (LinkedListInfo *) NULL)
1128 {
1129 const char
1130 *name;
1131
1132 const StringInfo
1133 *profile;
1134
1135 /*
1136 Read image profiles.
1137 */
1138 ResetLinkedListIterator(profiles);
1139 name=(const char *) GetNextValueInLinkedList(profiles);
1140 while (name != (const char *) NULL)
1141 {
1142 profile=GetImageProfile(image,name);
1143 if (profile != (StringInfo *) NULL)
1144 {
1145 register unsigned char
1146 *p;
1147
1148 p=GetStringInfoDatum(profile);
1149 count=ReadBlob(image,GetStringInfoLength(profile),p);
cristyda16f162011-02-19 23:52:17 +00001150 (void) count;
cristy3ed852e2009-09-05 21:47:34 +00001151 }
1152 name=(const char *) GetNextValueInLinkedList(profiles);
1153 }
1154 profiles=DestroyLinkedList(profiles,RelinquishMagickMemory);
1155 }
1156 image->depth=GetImageQuantumDepth(image,MagickFalse);
1157 if (image->storage_class == PseudoClass)
1158 {
1159 /*
1160 Create image colormap.
1161 */
cristy018f07f2011-09-04 21:15:19 +00001162 status=AcquireImageColormap(image,colors != 0 ? colors : 256,exception);
cristy3ed852e2009-09-05 21:47:34 +00001163 if (status == MagickFalse)
1164 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1165 if (colors != 0)
1166 {
1167 size_t
1168 packet_size;
1169
1170 unsigned char
1171 *colormap;
1172
1173 /*
1174 Read image colormap from file.
1175 */
1176 packet_size=(size_t) (3UL*image->depth/8UL);
1177 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
1178 packet_size*sizeof(*colormap));
1179 if (colormap == (unsigned char *) NULL)
1180 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1181 count=ReadBlob(image,packet_size*image->colors,colormap);
1182 p=colormap;
1183 switch (image->depth)
1184 {
1185 default:
1186 ThrowReaderException(CorruptImageError,
1187 "ImageDepthNotSupported");
1188 case 8:
1189 {
1190 unsigned char
1191 pixel;
1192
cristybb503372010-05-27 20:51:26 +00001193 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001194 {
1195 p=PushCharPixel(p,&pixel);
1196 image->colormap[i].red=ScaleCharToQuantum(pixel);
1197 p=PushCharPixel(p,&pixel);
1198 image->colormap[i].green=ScaleCharToQuantum(pixel);
1199 p=PushCharPixel(p,&pixel);
1200 image->colormap[i].blue=ScaleCharToQuantum(pixel);
1201 }
1202 break;
1203 }
1204 case 16:
1205 {
1206 unsigned short
1207 pixel;
1208
cristybb503372010-05-27 20:51:26 +00001209 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001210 {
1211 p=PushShortPixel(MSBEndian,p,&pixel);
1212 image->colormap[i].red=ScaleShortToQuantum(pixel);
1213 p=PushShortPixel(MSBEndian,p,&pixel);
1214 image->colormap[i].green=ScaleShortToQuantum(pixel);
1215 p=PushShortPixel(MSBEndian,p,&pixel);
1216 image->colormap[i].blue=ScaleShortToQuantum(pixel);
1217 }
1218 break;
1219 }
1220 case 32:
1221 {
cristy4cb162a2010-05-30 03:04:47 +00001222 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001223 pixel;
1224
cristybb503372010-05-27 20:51:26 +00001225 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001226 {
1227 p=PushLongPixel(MSBEndian,p,&pixel);
1228 image->colormap[i].red=ScaleLongToQuantum(pixel);
1229 p=PushLongPixel(MSBEndian,p,&pixel);
1230 image->colormap[i].green=ScaleLongToQuantum(pixel);
1231 p=PushLongPixel(MSBEndian,p,&pixel);
1232 image->colormap[i].blue=ScaleLongToQuantum(pixel);
1233 }
1234 break;
1235 }
1236 }
1237 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
1238 }
1239 }
1240 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1241 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1242 break;
1243 /*
1244 Allocate image pixels.
1245 */
1246 quantum_info=AcquireQuantumInfo(image_info,image);
1247 if (quantum_info == (QuantumInfo *) NULL)
1248 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1249 if (quantum_format != UndefinedQuantumFormat)
1250 {
1251 status=SetQuantumFormat(image,quantum_info,quantum_format);
1252 if (status == MagickFalse)
1253 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1254 }
1255 packet_size=(size_t) (quantum_info->depth/8);
1256 if (image->storage_class == DirectClass)
1257 packet_size=(size_t) (3*quantum_info->depth/8);
cristy325cfdc2012-04-28 01:00:09 +00001258 if (IsGrayColorspace(image->colorspace) != MagickFalse)
cristy0a30e182011-09-01 01:43:15 +00001259 packet_size=quantum_info->depth/8;
cristy8a46d822012-08-28 23:32:39 +00001260 if (image->alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00001261 packet_size+=quantum_info->depth/8;
1262 if (image->colorspace == CMYKColorspace)
1263 packet_size+=quantum_info->depth/8;
1264 if (image->compression == RLECompression)
1265 packet_size++;
1266 length=image->columns;
cristy26377172010-12-20 19:01:58 +00001267 length=MagickMax(MagickMax(BZipMaxExtent(packet_size*image->columns),
1268 LZMAMaxExtent(packet_size*image->columns)),ZipMaxExtent(packet_size*
1269 image->columns));
cristy3ed852e2009-09-05 21:47:34 +00001270 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
1271 sizeof(*compress_pixels));
1272 if (compress_pixels == (unsigned char *) NULL)
1273 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1274 /*
1275 Read image pixels.
1276 */
1277 quantum_type=RGBQuantum;
cristy8a46d822012-08-28 23:32:39 +00001278 if (image->alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00001279 quantum_type=RGBAQuantum;
1280 if (image->colorspace == CMYKColorspace)
1281 {
1282 quantum_type=CMYKQuantum;
cristy8a46d822012-08-28 23:32:39 +00001283 if (image->alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00001284 quantum_type=CMYKAQuantum;
1285 }
cristy325cfdc2012-04-28 01:00:09 +00001286 if (IsGrayColorspace(image->colorspace) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001287 {
1288 quantum_type=GrayQuantum;
cristy8a46d822012-08-28 23:32:39 +00001289 if (image->alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00001290 quantum_type=GrayAlphaQuantum;
1291 }
cristybdbf4b62012-05-13 22:22:59 +00001292 if (image->storage_class == PseudoClass)
1293 {
1294 quantum_type=IndexQuantum;
cristy8a46d822012-08-28 23:32:39 +00001295 if (image->alpha_trait == BlendPixelTrait)
cristybdbf4b62012-05-13 22:22:59 +00001296 quantum_type=IndexAlphaQuantum;
1297 }
cristy330af6c2010-12-21 14:36:06 +00001298 status=MagickTrue;
1299 switch (image->compression)
1300 {
1301#if defined(MAGICKCORE_BZLIB_DELEGATE)
1302 case BZipCompression:
1303 {
cristy3a99dcf2011-12-17 01:29:40 +00001304 int
1305 code;
1306
cristy330af6c2010-12-21 14:36:06 +00001307 (void) ResetMagickMemory(&bzip_info,0,sizeof(bzip_info));
1308 bzip_info.bzalloc=AcquireBZIPMemory;
1309 bzip_info.bzfree=RelinquishBZIPMemory;
1310 bzip_info.opaque=(void *) NULL;
1311 code=BZ2_bzDecompressInit(&bzip_info,(int) image_info->verbose,
1312 MagickFalse);
1313 if (code != BZ_OK)
1314 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001315 break;
1316 }
1317#endif
1318#if defined(MAGICKCORE_LZMA_DELEGATE)
1319 case LZMACompression:
1320 {
cristy3a99dcf2011-12-17 01:29:40 +00001321 int
1322 code;
1323
cristy9d72f1a2010-12-21 20:46:59 +00001324 (void) ResetMagickMemory(&allocator,0,sizeof(allocator));
1325 allocator.alloc=AcquireLZMAMemory;
1326 allocator.free=RelinquishLZMAMemory;
cristy330af6c2010-12-21 14:36:06 +00001327 lzma_info=initialize_lzma;
cristy9d72f1a2010-12-21 20:46:59 +00001328 lzma_info.allocator=(&allocator);
cristy330af6c2010-12-21 14:36:06 +00001329 code=lzma_auto_decoder(&lzma_info,-1,0);
1330 if (code != LZMA_OK)
1331 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001332 break;
1333 }
1334#endif
1335#if defined(MAGICKCORE_ZLIB_DELEGATE)
1336 case LZWCompression:
1337 case ZipCompression:
1338 {
cristy3a99dcf2011-12-17 01:29:40 +00001339 int
1340 code;
1341
cristy330af6c2010-12-21 14:36:06 +00001342 (void) ResetMagickMemory(&zip_info,0,sizeof(zip_info));
1343 zip_info.zalloc=AcquireZIPMemory;
1344 zip_info.zfree=RelinquishZIPMemory;
1345 zip_info.opaque=(voidpf) NULL;
1346 code=inflateInit(&zip_info);
1347 if (code != Z_OK)
1348 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001349 break;
1350 }
1351#endif
1352 case RLECompression:
1353 {
cristy4c08aed2011-07-01 19:47:50 +00001354 GetPixelInfo(image,&pixel);
cristy330af6c2010-12-21 14:36:06 +00001355 break;
1356 }
1357 default:
1358 break;
1359 }
cristy3ed852e2009-09-05 21:47:34 +00001360 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001361 length=0;
cristybb503372010-05-27 20:51:26 +00001362 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001363 {
cristybb503372010-05-27 20:51:26 +00001364 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001365 x;
1366
cristy4c08aed2011-07-01 19:47:50 +00001367 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00001368 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001369
cristy330af6c2010-12-21 14:36:06 +00001370 if (status == MagickFalse)
1371 break;
cristy3ed852e2009-09-05 21:47:34 +00001372 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00001373 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001374 break;
cristy3ed852e2009-09-05 21:47:34 +00001375 switch (image->compression)
1376 {
cristy3ed852e2009-09-05 21:47:34 +00001377#if defined(MAGICKCORE_BZLIB_DELEGATE)
1378 case BZipCompression:
1379 {
cristy3ed852e2009-09-05 21:47:34 +00001380 bzip_info.next_out=(char *) pixels;
1381 bzip_info.avail_out=(unsigned int) (packet_size*image->columns);
1382 do
1383 {
1384 if (bzip_info.avail_in == 0)
1385 {
1386 bzip_info.next_in=(char *) compress_pixels;
1387 length=(size_t) BZipMaxExtent(packet_size*image->columns);
cristy261ce822012-02-19 22:08:28 +00001388 if (version != 0.0)
cristy3ed852e2009-09-05 21:47:34 +00001389 length=(size_t) ReadBlobMSBLong(image);
1390 bzip_info.avail_in=(unsigned int) ReadBlob(image,length,
1391 (unsigned char *) bzip_info.next_in);
1392 }
1393 if (BZ2_bzDecompress(&bzip_info) == BZ_STREAM_END)
1394 break;
1395 } while (bzip_info.avail_out != 0);
cristy26377172010-12-20 19:01:58 +00001396 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1397 quantum_type,pixels,exception);
1398 break;
1399 }
1400#endif
1401#if defined(MAGICKCORE_LZMA_DELEGATE)
1402 case LZMACompression:
1403 {
cristy26377172010-12-20 19:01:58 +00001404 lzma_info.next_out=pixels;
cristy330af6c2010-12-21 14:36:06 +00001405 lzma_info.avail_out=packet_size*image->columns;
cristy26377172010-12-20 19:01:58 +00001406 do
1407 {
cristy3a99dcf2011-12-17 01:29:40 +00001408 int
1409 code;
1410
cristy26377172010-12-20 19:01:58 +00001411 if (lzma_info.avail_in == 0)
1412 {
1413 lzma_info.next_in=compress_pixels;
1414 length=(size_t) ReadBlobMSBLong(image);
1415 lzma_info.avail_in=(unsigned int) ReadBlob(image,length,
1416 (unsigned char *) lzma_info.next_in);
1417 }
1418 code=lzma_code(&lzma_info,LZMA_RUN);
cristy330af6c2010-12-21 14:36:06 +00001419 if (code < 0)
1420 {
1421 status=MagickFalse;
1422 break;
1423 }
1424 if (code == LZMA_STREAM_END)
cristy26377172010-12-20 19:01:58 +00001425 break;
1426 } while (lzma_info.avail_out != 0);
cristy26377172010-12-20 19:01:58 +00001427 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1428 quantum_type,pixels,exception);
1429 break;
1430 }
1431#endif
1432#if defined(MAGICKCORE_ZLIB_DELEGATE)
1433 case LZWCompression:
1434 case ZipCompression:
1435 {
cristy26377172010-12-20 19:01:58 +00001436 zip_info.next_out=pixels;
1437 zip_info.avail_out=(uInt) (packet_size*image->columns);
1438 do
1439 {
1440 if (zip_info.avail_in == 0)
1441 {
1442 zip_info.next_in=compress_pixels;
1443 length=(size_t) ZipMaxExtent(packet_size*image->columns);
cristy261ce822012-02-19 22:08:28 +00001444 if (version != 0.0)
cristy26377172010-12-20 19:01:58 +00001445 length=(size_t) ReadBlobMSBLong(image);
1446 zip_info.avail_in=(unsigned int) ReadBlob(image,length,
1447 zip_info.next_in);
1448 }
1449 if (inflate(&zip_info,Z_SYNC_FLUSH) == Z_STREAM_END)
1450 break;
1451 } while (zip_info.avail_out != 0);
cristy3ed852e2009-09-05 21:47:34 +00001452 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1453 quantum_type,pixels,exception);
1454 break;
1455 }
1456#endif
1457 case RLECompression:
1458 {
cristybb503372010-05-27 20:51:26 +00001459 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001460 {
1461 if (length == 0)
1462 {
1463 count=ReadBlob(image,packet_size,pixels);
cristyc82a27b2011-10-21 01:07:16 +00001464 PushRunlengthPacket(image,pixels,&length,&pixel,exception);
cristy3ed852e2009-09-05 21:47:34 +00001465 }
1466 length--;
cristy4c08aed2011-07-01 19:47:50 +00001467 if (image->storage_class == PseudoClass)
cristy94b11832011-09-08 19:46:03 +00001468 SetPixelIndex(image,ClampToQuantum(pixel.index),q);
cristy4c08aed2011-07-01 19:47:50 +00001469 else
1470 {
cristy94b11832011-09-08 19:46:03 +00001471 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1472 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1473 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
cristy4c08aed2011-07-01 19:47:50 +00001474 if (image->colorspace == CMYKColorspace)
cristy94b11832011-09-08 19:46:03 +00001475 SetPixelBlack(image,ClampToQuantum(pixel.black),q);
cristy4c08aed2011-07-01 19:47:50 +00001476 }
cristy8a46d822012-08-28 23:32:39 +00001477 if (image->alpha_trait == BlendPixelTrait)
cristy94b11832011-09-08 19:46:03 +00001478 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
cristyed231572011-07-14 02:18:59 +00001479 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001480 }
1481 break;
1482 }
1483 default:
1484 {
1485 count=ReadBlob(image,packet_size*image->columns,pixels);
1486 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1487 quantum_type,pixels,exception);
1488 break;
1489 }
1490 }
1491 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1492 break;
1493 }
1494 SetQuantumImageType(image,quantum_type);
cristy330af6c2010-12-21 14:36:06 +00001495 switch (image->compression)
1496 {
1497#if defined(MAGICKCORE_BZLIB_DELEGATE)
1498 case BZipCompression:
1499 {
cristy3a99dcf2011-12-17 01:29:40 +00001500 int
1501 code;
1502
cristy261ce822012-02-19 22:08:28 +00001503 if (version == 0.0)
cristy330af6c2010-12-21 14:36:06 +00001504 {
1505 MagickOffsetType
1506 offset;
1507
1508 offset=SeekBlob(image,-((MagickOffsetType)
1509 bzip_info.avail_in),SEEK_CUR);
1510 if (offset < 0)
cristy3e4e9f42013-04-06 22:29:40 +00001511 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
cristy330af6c2010-12-21 14:36:06 +00001512 }
1513 code=BZ2_bzDecompressEnd(&bzip_info);
1514 if (code != BZ_OK)
1515 status=MagickFalse;
1516 break;
1517 }
1518#endif
1519#if defined(MAGICKCORE_LZMA_DELEGATE)
1520 case LZMACompression:
1521 {
cristy3a99dcf2011-12-17 01:29:40 +00001522 int
1523 code;
1524
cristy3b788a02010-12-27 15:59:54 +00001525 code=lzma_code(&lzma_info,LZMA_FINISH);
1526 if ((code != LZMA_STREAM_END) && (code != LZMA_OK))
cristyb977da52010-12-22 15:55:53 +00001527 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001528 lzma_end(&lzma_info);
1529 break;
1530 }
1531#endif
1532#if defined(MAGICKCORE_ZLIB_DELEGATE)
1533 case LZWCompression:
1534 case ZipCompression:
1535 {
cristy3a99dcf2011-12-17 01:29:40 +00001536 int
1537 code;
1538
cristy261ce822012-02-19 22:08:28 +00001539 if (version == 0.0)
cristy330af6c2010-12-21 14:36:06 +00001540 {
1541 MagickOffsetType
1542 offset;
1543
1544 offset=SeekBlob(image,-((MagickOffsetType) zip_info.avail_in),
1545 SEEK_CUR);
1546 if (offset < 0)
cristy3e4e9f42013-04-06 22:29:40 +00001547 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
cristy330af6c2010-12-21 14:36:06 +00001548 }
1549 code=inflateEnd(&zip_info);
1550 if (code != LZMA_OK)
1551 status=MagickFalse;
1552 break;
1553 }
1554#endif
1555 default:
1556 break;
1557 }
cristy3ed852e2009-09-05 21:47:34 +00001558 quantum_info=DestroyQuantumInfo(quantum_info);
1559 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
cristybb503372010-05-27 20:51:26 +00001560 if (((y != (ssize_t) image->rows)) || (status == MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001561 {
1562 image=DestroyImageList(image);
1563 return((Image *) NULL);
1564 }
1565 if (EOFBlob(image) != MagickFalse)
1566 {
1567 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1568 image->filename);
1569 break;
1570 }
1571 /*
1572 Proceed to next image.
1573 */
1574 if (image_info->number_scenes != 0)
1575 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1576 break;
1577 do
1578 {
1579 c=ReadBlobByte(image);
1580 } while ((isgraph(c) == MagickFalse) && (c != EOF));
1581 if (c != EOF)
1582 {
1583 /*
1584 Allocate next image structure.
1585 */
cristy9950d572011-10-01 18:22:35 +00001586 AcquireNextImage(image_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001587 if (GetNextImageInList(image) == (Image *) NULL)
1588 {
1589 image=DestroyImageList(image);
1590 return((Image *) NULL);
1591 }
1592 image=SyncNextImageInList(image);
1593 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1594 GetBlobSize(image));
1595 if (status == MagickFalse)
1596 break;
1597 }
1598 } while (c != EOF);
1599 (void) CloseBlob(image);
1600 return(GetFirstImageInList(image));
1601}
1602
1603/*
1604%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1605% %
1606% %
1607% %
1608% R e g i s t e r M I F F I m a g e %
1609% %
1610% %
1611% %
1612%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1613%
1614% RegisterMIFFImage() adds properties for the MIFF image format to the list of
1615% supported formats. The properties include the image format tag, a method to
1616% read and/or write the format, whether the format supports the saving of more
1617% than one frame to the same file or blob, whether the format supports native
1618% in-memory I/O, and a brief description of the format.
1619%
1620% The format of the RegisterMIFFImage method is:
1621%
cristybb503372010-05-27 20:51:26 +00001622% size_t RegisterMIFFImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001623%
1624*/
cristybb503372010-05-27 20:51:26 +00001625ModuleExport size_t RegisterMIFFImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001626{
1627 char
1628 version[MaxTextExtent];
1629
1630 MagickInfo
1631 *entry;
1632
1633 *version='\0';
1634#if defined(MagickImageCoderSignatureText)
1635 (void) CopyMagickString(version,MagickLibVersionText,MaxTextExtent);
1636#if defined(ZLIB_VERSION)
1637 (void) ConcatenateMagickString(version," with Zlib ",MaxTextExtent);
1638 (void) ConcatenateMagickString(version,ZLIB_VERSION,MaxTextExtent);
1639#endif
1640#if defined(MAGICKCORE_BZLIB_DELEGATE)
1641 (void) ConcatenateMagickString(version," and BZlib",MaxTextExtent);
1642#endif
1643#endif
1644 entry=SetMagickInfo("MIFF");
1645 entry->decoder=(DecodeImageHandler *) ReadMIFFImage;
1646 entry->encoder=(EncodeImageHandler *) WriteMIFFImage;
1647 entry->magick=(IsImageFormatHandler *) IsMIFF;
cristyffaf9782011-04-13 19:50:51 +00001648 entry->seekable_stream=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00001649 entry->description=ConstantString("Magick Image File Format");
1650 if (*version != '\0')
1651 entry->version=ConstantString(version);
1652 entry->module=ConstantString("MIFF");
1653 (void) RegisterMagickInfo(entry);
1654 return(MagickImageCoderSignature);
1655}
1656
1657/*
1658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1659% %
1660% %
1661% %
1662% U n r e g i s t e r M I F F I m a g e %
1663% %
1664% %
1665% %
1666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1667%
1668% UnregisterMIFFImage() removes format registrations made by the MIFF module
1669% from the list of supported formats.
1670%
1671% The format of the UnregisterMIFFImage method is:
1672%
1673% UnregisterMIFFImage(void)
1674%
1675*/
1676ModuleExport void UnregisterMIFFImage(void)
1677{
1678 (void) UnregisterMagickInfo("MIFF");
1679}
1680
1681/*
1682%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1683% %
1684% %
1685% %
1686% W r i t e M I F F I m a g e %
1687% %
1688% %
1689% %
1690%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1691%
1692% WriteMIFFImage() writes a MIFF image to a file.
1693%
1694% The format of the WriteMIFFImage method is:
1695%
1696% MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
cristy1e178e72011-08-28 19:44:34 +00001697% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001698%
1699% Compression code contributed by Kyle Shorter.
1700%
1701% A description of each parameter follows:
1702%
1703% o image_info: the image info.
1704%
1705% o image: the image.
1706%
cristy1e178e72011-08-28 19:44:34 +00001707% o exception: return any errors or warnings in this structure.
1708%
cristy3ed852e2009-09-05 21:47:34 +00001709*/
1710
1711static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
cristyc82a27b2011-10-21 01:07:16 +00001712 size_t length,PixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001713{
1714 if (image->storage_class != DirectClass)
1715 {
1716 switch (image->depth)
1717 {
1718 case 32:
1719 {
cristy4c08aed2011-07-01 19:47:50 +00001720 *pixels++=(unsigned char) ((size_t) pixel->index >> 24);
1721 *pixels++=(unsigned char) ((size_t) pixel->index >> 16);
cristy3ed852e2009-09-05 21:47:34 +00001722 }
1723 case 16:
cristy4c08aed2011-07-01 19:47:50 +00001724 *pixels++=(unsigned char) ((size_t) pixel->index >> 8);
cristy3ed852e2009-09-05 21:47:34 +00001725 case 8:
1726 {
cristy4c08aed2011-07-01 19:47:50 +00001727 *pixels++=(unsigned char) pixel->index;
cristy3ed852e2009-09-05 21:47:34 +00001728 break;
1729 }
1730 default:
cristyc82a27b2011-10-21 01:07:16 +00001731 (void) ThrowMagickException(exception,GetMagickModule(),
cristy3ed852e2009-09-05 21:47:34 +00001732 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1733 }
1734 switch (image->depth)
1735 {
1736 case 32:
1737 {
cristy4cb162a2010-05-30 03:04:47 +00001738 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001739 value;
1740
cristy8a46d822012-08-28 23:32:39 +00001741 if (image->alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00001742 {
cristy94b11832011-09-08 19:46:03 +00001743 value=ScaleQuantumToLong(ClampToQuantum(pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001744 pixels=PopLongPixel(MSBEndian,value,pixels);
1745 }
1746 break;
1747 }
1748 case 16:
1749 {
1750 unsigned short
1751 value;
1752
cristy8a46d822012-08-28 23:32:39 +00001753 if (image->alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00001754 {
cristy94b11832011-09-08 19:46:03 +00001755 value=ScaleQuantumToShort(ClampToQuantum(pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001756 pixels=PopShortPixel(MSBEndian,value,pixels);
1757 }
1758 break;
1759 }
1760 case 8:
1761 {
1762 unsigned char
1763 value;
1764
cristy8a46d822012-08-28 23:32:39 +00001765 if (image->alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00001766 {
cristy94b11832011-09-08 19:46:03 +00001767 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1768 pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001769 pixels=PopCharPixel(value,pixels);
1770 }
1771 break;
1772 }
1773 default:
cristyc82a27b2011-10-21 01:07:16 +00001774 (void) ThrowMagickException(exception,GetMagickModule(),
cristy3ed852e2009-09-05 21:47:34 +00001775 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1776 }
1777 *pixels++=(unsigned char) length;
1778 return(pixels);
1779 }
1780 switch (image->depth)
1781 {
1782 case 32:
1783 {
cristy4cb162a2010-05-30 03:04:47 +00001784 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001785 value;
1786
cristy94b11832011-09-08 19:46:03 +00001787 value=ScaleQuantumToLong(ClampToQuantum(pixel->red));
cristy3ed852e2009-09-05 21:47:34 +00001788 pixels=PopLongPixel(MSBEndian,value,pixels);
cristy325cfdc2012-04-28 01:00:09 +00001789 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1790 {
1791 value=ScaleQuantumToLong(ClampToQuantum(pixel->green));
1792 pixels=PopLongPixel(MSBEndian,value,pixels);
1793 value=ScaleQuantumToLong(ClampToQuantum(pixel->blue));
1794 pixels=PopLongPixel(MSBEndian,value,pixels);
1795 }
cristy3ed852e2009-09-05 21:47:34 +00001796 if (image->colorspace == CMYKColorspace)
1797 {
cristy94b11832011-09-08 19:46:03 +00001798 value=ScaleQuantumToLong(ClampToQuantum(pixel->black));
cristy4c08aed2011-07-01 19:47:50 +00001799 pixels=PopLongPixel(MSBEndian,value,pixels);
1800 }
cristy8a46d822012-08-28 23:32:39 +00001801 if (image->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00001802 {
cristy94b11832011-09-08 19:46:03 +00001803 value=ScaleQuantumToLong(ClampToQuantum(pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001804 pixels=PopLongPixel(MSBEndian,value,pixels);
1805 }
1806 break;
1807 }
1808 case 16:
1809 {
1810 unsigned short
1811 value;
1812
cristy94b11832011-09-08 19:46:03 +00001813 value=ScaleQuantumToShort(ClampToQuantum(pixel->red));
cristy3ed852e2009-09-05 21:47:34 +00001814 pixels=PopShortPixel(MSBEndian,value,pixels);
cristy325cfdc2012-04-28 01:00:09 +00001815 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1816 {
1817 value=ScaleQuantumToShort(ClampToQuantum(pixel->green));
1818 pixels=PopShortPixel(MSBEndian,value,pixels);
1819 value=ScaleQuantumToShort(ClampToQuantum(pixel->blue));
1820 pixels=PopShortPixel(MSBEndian,value,pixels);
1821 }
cristy3ed852e2009-09-05 21:47:34 +00001822 if (image->colorspace == CMYKColorspace)
1823 {
cristy94b11832011-09-08 19:46:03 +00001824 value=ScaleQuantumToShort(ClampToQuantum(pixel->black));
cristy4c08aed2011-07-01 19:47:50 +00001825 pixels=PopShortPixel(MSBEndian,value,pixels);
1826 }
cristy8a46d822012-08-28 23:32:39 +00001827 if (image->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00001828 {
cristy94b11832011-09-08 19:46:03 +00001829 value=ScaleQuantumToShort(ClampToQuantum(pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001830 pixels=PopShortPixel(MSBEndian,value,pixels);
1831 }
1832 break;
1833 }
1834 case 8:
1835 {
1836 unsigned char
1837 value;
1838
cristy94b11832011-09-08 19:46:03 +00001839 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->red));
cristy3ed852e2009-09-05 21:47:34 +00001840 pixels=PopCharPixel(value,pixels);
cristy325cfdc2012-04-28 01:00:09 +00001841 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1842 {
1843 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1844 pixel->green));
1845 pixels=PopCharPixel(value,pixels);
1846 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->blue));
1847 pixels=PopCharPixel(value,pixels);
1848 }
cristy3ed852e2009-09-05 21:47:34 +00001849 if (image->colorspace == CMYKColorspace)
1850 {
cristy94b11832011-09-08 19:46:03 +00001851 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1852 pixel->black));
cristy4c08aed2011-07-01 19:47:50 +00001853 pixels=PopCharPixel(value,pixels);
1854 }
cristy8a46d822012-08-28 23:32:39 +00001855 if (image->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +00001856 {
cristy94b11832011-09-08 19:46:03 +00001857 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1858 pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001859 pixels=PopCharPixel(value,pixels);
1860 }
1861 break;
1862 }
1863 default:
cristyc82a27b2011-10-21 01:07:16 +00001864 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
1865 "ImageDepthNotSupported","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +00001866 }
1867 *pixels++=(unsigned char) length;
1868 return(pixels);
1869}
1870
1871static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
cristy1e178e72011-08-28 19:44:34 +00001872 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001873{
1874#if defined(MAGICKCORE_BZLIB_DELEGATE)
1875 bz_stream
1876 bzip_info;
1877#endif
1878
1879 char
1880 buffer[MaxTextExtent];
1881
1882 CompressionType
1883 compression;
1884
1885 const char
1886 *property,
1887 *value;
1888
cristy26377172010-12-20 19:01:58 +00001889#if defined(MAGICKCORE_LZMA_DELEGATE)
cristy4b46dba2010-12-20 19:18:20 +00001890 lzma_allocator
1891 allocator;
1892
cristy26377172010-12-20 19:01:58 +00001893 lzma_stream
cristy330af6c2010-12-21 14:36:06 +00001894 initialize_lzma = LZMA_STREAM_INIT,
1895 lzma_info;
cristy26377172010-12-20 19:01:58 +00001896#endif
cristy3ed852e2009-09-05 21:47:34 +00001897
1898 MagickBooleanType
1899 status;
1900
1901 MagickOffsetType
1902 scene;
1903
cristy4c08aed2011-07-01 19:47:50 +00001904 PixelInfo
1905 pixel,
1906 target;
cristy3ed852e2009-09-05 21:47:34 +00001907
1908 QuantumInfo
1909 *quantum_info;
1910
1911 QuantumType
1912 quantum_type;
1913
cristybb503372010-05-27 20:51:26 +00001914 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001915 i;
1916
1917 size_t
1918 length,
1919 packet_size;
1920
cristy26377172010-12-20 19:01:58 +00001921 ssize_t
1922 y;
1923
cristy3ed852e2009-09-05 21:47:34 +00001924 unsigned char
1925 *compress_pixels,
1926 *pixels,
1927 *q;
1928
1929#if defined(MAGICKCORE_ZLIB_DELEGATE)
1930 z_stream
1931 zip_info;
1932#endif
1933
1934 /*
1935 Open output image file.
1936 */
1937 assert(image_info != (const ImageInfo *) NULL);
1938 assert(image_info->signature == MagickSignature);
1939 assert(image != (Image *) NULL);
1940 assert(image->signature == MagickSignature);
1941 if (image->debug != MagickFalse)
1942 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy3a37efd2011-08-28 20:31:03 +00001943 assert(exception != (ExceptionInfo *) NULL);
1944 assert(exception->signature == MagickSignature);
cristy1e178e72011-08-28 19:44:34 +00001945 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy3ed852e2009-09-05 21:47:34 +00001946 if (status == MagickFalse)
1947 return(status);
cristy3ed852e2009-09-05 21:47:34 +00001948 scene=0;
1949 do
1950 {
1951 /*
1952 Allocate image pixels.
1953 */
cristyd7f03932013-04-07 01:19:28 +00001954 if ((image->storage_class == PseudoClass) &&
1955 (image->colors > (size_t) (GetQuantumRange(image->depth)+1)))
1956 (void) SetImageStorageClass(image,DirectClass,exception);
1957 if (IsImageGray(image,exception) != MagickFalse)
1958 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristyca5fbf32013-03-30 00:04:11 +00001959 image->depth=image->depth <= 8 ? 8UL : image->depth <= 16 ? 16UL :
1960 image->depth <= 32 ? 32UL : 64UL;
cristy3ed852e2009-09-05 21:47:34 +00001961 quantum_info=AcquireQuantumInfo(image_info,image);
1962 if (quantum_info == (QuantumInfo *) NULL)
1963 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1964 if ((image->storage_class != PseudoClass) && (image->depth >= 32) &&
1965 (quantum_info->format == UndefinedQuantumFormat) &&
cristy1e178e72011-08-28 19:44:34 +00001966 (IsHighDynamicRangeImage(image,exception) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001967 {
1968 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1969 if (status == MagickFalse)
1970 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1971 }
cristy3ed852e2009-09-05 21:47:34 +00001972 compression=image->compression;
1973 if (image_info->compression != UndefinedCompression)
1974 compression=image_info->compression;
1975 switch (compression)
1976 {
1977#if !defined(MAGICKCORE_ZLIB_DELEGATE)
cristy26377172010-12-20 19:01:58 +00001978 case LZMACompression: compression=NoCompression; break;
1979#endif
1980#if !defined(MAGICKCORE_ZLIB_DELEGATE)
cristy3ed852e2009-09-05 21:47:34 +00001981 case LZWCompression:
1982 case ZipCompression: compression=NoCompression; break;
1983#endif
1984#if !defined(MAGICKCORE_BZLIB_DELEGATE)
1985 case BZipCompression: compression=NoCompression; break;
1986#endif
1987 case RLECompression:
1988 {
1989 if (quantum_info->format == FloatingPointQuantumFormat)
1990 compression=NoCompression;
cristy4c08aed2011-07-01 19:47:50 +00001991 GetPixelInfo(image,&target);
cristy3ed852e2009-09-05 21:47:34 +00001992 break;
1993 }
1994 default:
1995 break;
1996 }
1997 packet_size=(size_t) (quantum_info->depth/8);
1998 if (image->storage_class == DirectClass)
1999 packet_size=(size_t) (3*quantum_info->depth/8);
cristy325cfdc2012-04-28 01:00:09 +00002000 if (IsGrayColorspace(image->colorspace) != MagickFalse)
cristy0a30e182011-09-01 01:43:15 +00002001 packet_size=(size_t) (quantum_info->depth/8);
cristy8a46d822012-08-28 23:32:39 +00002002 if (image->alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00002003 packet_size+=quantum_info->depth/8;
2004 if (image->colorspace == CMYKColorspace)
2005 packet_size+=quantum_info->depth/8;
2006 if (compression == RLECompression)
2007 packet_size++;
2008 length=image->columns;
2009 length=MagickMax(BZipMaxExtent(packet_size*image->columns),ZipMaxExtent(
2010 packet_size*image->columns));
2011 if ((compression == BZipCompression) || (compression == ZipCompression))
2012 if (length != (size_t) ((unsigned int) length))
2013 compression=NoCompression;
2014 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
2015 sizeof(*compress_pixels));
2016 if (compress_pixels == (unsigned char *) NULL)
2017 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2018 /*
2019 Write MIFF header.
2020 */
2021 (void) WriteBlobString(image,"id=ImageMagick version=1.0\n");
cristyb51dff52011-05-19 16:55:47 +00002022 (void) FormatLocaleString(buffer,MaxTextExtent,
cristy8a46d822012-08-28 23:32:39 +00002023 "class=%s colors=%.20g alpha-trait=%s\n",CommandOptionToMnemonic(
cristye8c25f92010-06-03 00:53:06 +00002024 MagickClassOptions,image->storage_class),(double) image->colors,
cristy8a46d822012-08-28 23:32:39 +00002025 CommandOptionToMnemonic(MagickPixelTraitOptions,(ssize_t)
2026 image->alpha_trait));
cristy3ed852e2009-09-05 21:47:34 +00002027 (void) WriteBlobString(image,buffer);
cristyb51dff52011-05-19 16:55:47 +00002028 (void) FormatLocaleString(buffer,MaxTextExtent,"columns=%.20g rows=%.20g "
cristye8c25f92010-06-03 00:53:06 +00002029 "depth=%.20g\n",(double) image->columns,(double) image->rows,(double)
2030 image->depth);
cristy3ed852e2009-09-05 21:47:34 +00002031 (void) WriteBlobString(image,buffer);
cristy5f1c1ff2010-12-23 21:38:06 +00002032 if (image->type != UndefinedType)
cristy3ed852e2009-09-05 21:47:34 +00002033 {
cristyb51dff52011-05-19 16:55:47 +00002034 (void) FormatLocaleString(buffer,MaxTextExtent,"type=%s\n",
cristy042ee782011-04-22 18:48:30 +00002035 CommandOptionToMnemonic(MagickTypeOptions,image->type));
cristy3ed852e2009-09-05 21:47:34 +00002036 (void) WriteBlobString(image,buffer);
2037 }
2038 if (image->colorspace != UndefinedColorspace)
2039 {
cristyb51dff52011-05-19 16:55:47 +00002040 (void) FormatLocaleString(buffer,MaxTextExtent,"colorspace=%s\n",
cristy042ee782011-04-22 18:48:30 +00002041 CommandOptionToMnemonic(MagickColorspaceOptions,image->colorspace));
cristy3ed852e2009-09-05 21:47:34 +00002042 (void) WriteBlobString(image,buffer);
2043 }
cristy3e4e9f42013-04-06 22:29:40 +00002044 if (image->intensity != UndefinedPixelIntensityMethod)
2045 {
2046 (void) FormatLocaleString(buffer,MaxTextExtent,"pixel-intensity=%s\n",
2047 CommandOptionToMnemonic(MagickPixelIntensityOptions,
2048 image->intensity));
2049 (void) WriteBlobString(image,buffer);
2050 }
2051 if (image->endian != UndefinedEndian)
2052 {
2053 (void) FormatLocaleString(buffer,MaxTextExtent,"endian=%s\n",
2054 CommandOptionToMnemonic(MagickEndianOptions,image->endian));
2055 (void) WriteBlobString(image,buffer);
2056 }
cristy3ed852e2009-09-05 21:47:34 +00002057 if (compression != UndefinedCompression)
2058 {
cristyb51dff52011-05-19 16:55:47 +00002059 (void) FormatLocaleString(buffer,MaxTextExtent,"compression=%s "
cristy042ee782011-04-22 18:48:30 +00002060 "quality=%.20g\n",CommandOptionToMnemonic(MagickCompressOptions,
cristye8c25f92010-06-03 00:53:06 +00002061 compression),(double) image->quality);
cristy3ed852e2009-09-05 21:47:34 +00002062 (void) WriteBlobString(image,buffer);
2063 }
2064 if (image->units != UndefinedResolution)
2065 {
cristyb51dff52011-05-19 16:55:47 +00002066 (void) FormatLocaleString(buffer,MaxTextExtent,"units=%s\n",
cristy042ee782011-04-22 18:48:30 +00002067 CommandOptionToMnemonic(MagickResolutionOptions,image->units));
cristy3ed852e2009-09-05 21:47:34 +00002068 (void) WriteBlobString(image,buffer);
2069 }
cristy2a11bef2011-10-28 18:33:11 +00002070 if ((image->resolution.x != 0) || (image->resolution.y != 0))
cristy3ed852e2009-09-05 21:47:34 +00002071 {
cristyb51dff52011-05-19 16:55:47 +00002072 (void) FormatLocaleString(buffer,MaxTextExtent,
cristy2a11bef2011-10-28 18:33:11 +00002073 "resolution=%gx%g\n",image->resolution.x,image->resolution.y);
cristy3ed852e2009-09-05 21:47:34 +00002074 (void) WriteBlobString(image,buffer);
2075 }
2076 if ((image->page.width != 0) || (image->page.height != 0))
2077 {
cristyb51dff52011-05-19 16:55:47 +00002078 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00002079 "page=%.20gx%.20g%+.20g%+.20g\n",(double) image->page.width,(double)
2080 image->page.height,(double) image->page.x,(double) image->page.y);
cristy3ed852e2009-09-05 21:47:34 +00002081 (void) WriteBlobString(image,buffer);
2082 }
2083 else
2084 if ((image->page.x != 0) || (image->page.y != 0))
2085 {
cristyb51dff52011-05-19 16:55:47 +00002086 (void) FormatLocaleString(buffer,MaxTextExtent,"page=%+ld%+ld\n",
cristyf2faecf2010-05-28 19:19:36 +00002087 (long) image->page.x,(long) image->page.y);
cristy3ed852e2009-09-05 21:47:34 +00002088 (void) WriteBlobString(image,buffer);
2089 }
2090 if ((image->tile_offset.x != 0) || (image->tile_offset.y != 0))
2091 {
cristyb51dff52011-05-19 16:55:47 +00002092 (void) FormatLocaleString(buffer,MaxTextExtent,"tile-offset=%+ld%+ld\n",
cristyf2faecf2010-05-28 19:19:36 +00002093 (long) image->tile_offset.x,(long) image->tile_offset.y);
cristy3ed852e2009-09-05 21:47:34 +00002094 (void) WriteBlobString(image,buffer);
2095 }
2096 if ((GetNextImageInList(image) != (Image *) NULL) ||
2097 (GetPreviousImageInList(image) != (Image *) NULL))
2098 {
2099 if (image->scene == 0)
cristyb51dff52011-05-19 16:55:47 +00002100 (void) FormatLocaleString(buffer,MaxTextExtent,"iterations=%.20g "
cristye8c25f92010-06-03 00:53:06 +00002101 "delay=%.20g ticks-per-second=%.20g\n",(double) image->iterations,
2102 (double) image->delay,(double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002103 else
cristyb51dff52011-05-19 16:55:47 +00002104 (void) FormatLocaleString(buffer,MaxTextExtent,"scene=%.20g "
cristye8c25f92010-06-03 00:53:06 +00002105 "iterations=%.20g delay=%.20g ticks-per-second=%.20g\n",(double)
2106 image->scene,(double) image->iterations,(double) image->delay,
2107 (double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002108 (void) WriteBlobString(image,buffer);
2109 }
2110 else
2111 {
2112 if (image->scene != 0)
2113 {
cristyb51dff52011-05-19 16:55:47 +00002114 (void) FormatLocaleString(buffer,MaxTextExtent,"scene=%.20g\n",
cristye8c25f92010-06-03 00:53:06 +00002115 (double) image->scene);
cristy3ed852e2009-09-05 21:47:34 +00002116 (void) WriteBlobString(image,buffer);
2117 }
2118 if (image->iterations != 0)
2119 {
cristyb51dff52011-05-19 16:55:47 +00002120 (void) FormatLocaleString(buffer,MaxTextExtent,"iterations=%.20g\n",
cristye8c25f92010-06-03 00:53:06 +00002121 (double) image->iterations);
cristy3ed852e2009-09-05 21:47:34 +00002122 (void) WriteBlobString(image,buffer);
2123 }
2124 if (image->delay != 0)
2125 {
cristyb51dff52011-05-19 16:55:47 +00002126 (void) FormatLocaleString(buffer,MaxTextExtent,"delay=%.20g\n",
cristye8c25f92010-06-03 00:53:06 +00002127 (double) image->delay);
cristy3ed852e2009-09-05 21:47:34 +00002128 (void) WriteBlobString(image,buffer);
2129 }
2130 if (image->ticks_per_second != UndefinedTicksPerSecond)
2131 {
cristyb51dff52011-05-19 16:55:47 +00002132 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00002133 "ticks-per-second=%.20g\n",(double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002134 (void) WriteBlobString(image,buffer);
2135 }
2136 }
2137 if (image->gravity != UndefinedGravity)
2138 {
cristyb51dff52011-05-19 16:55:47 +00002139 (void) FormatLocaleString(buffer,MaxTextExtent,"gravity=%s\n",
cristy042ee782011-04-22 18:48:30 +00002140 CommandOptionToMnemonic(MagickGravityOptions,image->gravity));
cristy3ed852e2009-09-05 21:47:34 +00002141 (void) WriteBlobString(image,buffer);
2142 }
2143 if (image->dispose != UndefinedDispose)
2144 {
cristyb51dff52011-05-19 16:55:47 +00002145 (void) FormatLocaleString(buffer,MaxTextExtent,"dispose=%s\n",
cristy042ee782011-04-22 18:48:30 +00002146 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
cristy3ed852e2009-09-05 21:47:34 +00002147 (void) WriteBlobString(image,buffer);
2148 }
2149 if (image->rendering_intent != UndefinedIntent)
2150 {
cristy0a30e182011-09-01 01:43:15 +00002151 (void) FormatLocaleString(buffer,MaxTextExtent,"rendering-intent=%s\n",
2152 CommandOptionToMnemonic(MagickIntentOptions,image->rendering_intent));
cristy3ed852e2009-09-05 21:47:34 +00002153 (void) WriteBlobString(image,buffer);
2154 }
2155 if (image->gamma != 0.0)
2156 {
cristyb51dff52011-05-19 16:55:47 +00002157 (void) FormatLocaleString(buffer,MaxTextExtent,"gamma=%g\n",
cristy3ed852e2009-09-05 21:47:34 +00002158 image->gamma);
2159 (void) WriteBlobString(image,buffer);
2160 }
2161 if (image->chromaticity.white_point.x != 0.0)
2162 {
2163 /*
2164 Note chomaticity points.
2165 */
cristyb51dff52011-05-19 16:55:47 +00002166 (void) FormatLocaleString(buffer,MaxTextExtent,"red-primary=%g,"
cristye7f51092010-01-17 00:39:37 +00002167 "%g green-primary=%g,%g blue-primary=%g,%g\n",
cristy3ed852e2009-09-05 21:47:34 +00002168 image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
2169 image->chromaticity.green_primary.x,
2170 image->chromaticity.green_primary.y,
2171 image->chromaticity.blue_primary.x,
2172 image->chromaticity.blue_primary.y);
2173 (void) WriteBlobString(image,buffer);
cristyb51dff52011-05-19 16:55:47 +00002174 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye7f51092010-01-17 00:39:37 +00002175 "white-point=%g,%g\n",image->chromaticity.white_point.x,
cristy8cd5b312010-01-07 01:10:24 +00002176 image->chromaticity.white_point.y);
cristy3ed852e2009-09-05 21:47:34 +00002177 (void) WriteBlobString(image,buffer);
2178 }
2179 if (image->orientation != UndefinedOrientation)
2180 {
cristyb51dff52011-05-19 16:55:47 +00002181 (void) FormatLocaleString(buffer,MaxTextExtent,"orientation=%s\n",
cristy042ee782011-04-22 18:48:30 +00002182 CommandOptionToMnemonic(MagickOrientationOptions,image->orientation));
cristy3ed852e2009-09-05 21:47:34 +00002183 (void) WriteBlobString(image,buffer);
2184 }
2185 if (image->profiles != (void *) NULL)
2186 {
2187 const char
2188 *name;
2189
2190 const StringInfo
2191 *profile;
2192
2193 /*
2194 Write image profiles.
2195 */
2196 ResetImageProfileIterator(image);
2197 name=GetNextImageProfile(image);
2198 while (name != (const char *) NULL)
2199 {
2200 profile=GetImageProfile(image,name);
2201 if (profile != (StringInfo *) NULL)
2202 {
cristyb51dff52011-05-19 16:55:47 +00002203 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00002204 "profile:%s=%.20g\n",name,(double)
2205 GetStringInfoLength(profile));
cristy3ed852e2009-09-05 21:47:34 +00002206 (void) WriteBlobString(image,buffer);
2207 }
2208 name=GetNextImageProfile(image);
2209 }
2210 }
2211 if (image->montage != (char *) NULL)
2212 {
cristyb51dff52011-05-19 16:55:47 +00002213 (void) FormatLocaleString(buffer,MaxTextExtent,"montage=%s\n",
cristy3ed852e2009-09-05 21:47:34 +00002214 image->montage);
2215 (void) WriteBlobString(image,buffer);
2216 }
2217 if (quantum_info->format == FloatingPointQuantumFormat)
cristyd15e6592011-10-15 00:13:06 +00002218 (void) SetImageProperty(image,"quantum:format","floating-point",
2219 exception);
cristy3ed852e2009-09-05 21:47:34 +00002220 ResetImagePropertyIterator(image);
2221 property=GetNextImageProperty(image);
2222 while (property != (const char *) NULL)
2223 {
cristyb51dff52011-05-19 16:55:47 +00002224 (void) FormatLocaleString(buffer,MaxTextExtent,"%s=",property);
cristy3ed852e2009-09-05 21:47:34 +00002225 (void) WriteBlobString(image,buffer);
cristyd15e6592011-10-15 00:13:06 +00002226 value=GetImageProperty(image,property,exception);
cristy3ed852e2009-09-05 21:47:34 +00002227 if (value != (const char *) NULL)
2228 {
cristyd76ed5d2012-05-20 16:15:57 +00002229 size_t
2230 length;
2231
cristy0e75d752012-05-20 16:10:32 +00002232 length=strlen(value);
2233 for (i=0; i < (ssize_t) length; i++)
cristy3ed852e2009-09-05 21:47:34 +00002234 if (isspace((int) ((unsigned char) value[i])) != 0)
2235 break;
cristy0e75d752012-05-20 16:10:32 +00002236 if (i == (ssize_t) length)
2237 (void) WriteBlob(image,length,(const unsigned char *) value);
cristyb880ee82012-04-07 15:08:14 +00002238 else
2239 {
2240 (void) WriteBlobByte(image,'{');
cristy3d136bd2012-05-04 12:16:20 +00002241 if (strchr(value,'}') == (char *) NULL)
cristy0e75d752012-05-20 16:10:32 +00002242 (void) WriteBlob(image,length,(const unsigned char *) value);
cristy3d136bd2012-05-04 12:16:20 +00002243 else
cristy0e75d752012-05-20 16:10:32 +00002244 for (i=0; i < (ssize_t) length; i++)
cristy3d136bd2012-05-04 12:16:20 +00002245 {
2246 if (value[i] == (int) '}')
2247 (void) WriteBlobByte(image,'\\');
2248 (void) WriteBlobByte(image,value[i]);
2249 }
cristyb880ee82012-04-07 15:08:14 +00002250 (void) WriteBlobByte(image,'}');
2251 }
cristy3ed852e2009-09-05 21:47:34 +00002252 }
2253 (void) WriteBlobByte(image,'\n');
2254 property=GetNextImageProperty(image);
2255 }
2256 (void) WriteBlobString(image,"\f\n:\032");
2257 if (image->montage != (char *) NULL)
2258 {
2259 /*
2260 Write montage tile directory.
2261 */
2262 if (image->directory != (char *) NULL)
2263 (void) WriteBlob(image,strlen(image->directory),(unsigned char *)
2264 image->directory);
2265 (void) WriteBlobByte(image,'\0');
2266 }
2267 if (image->profiles != (void *) NULL)
2268 {
2269 const char
2270 *name;
2271
2272 const StringInfo
2273 *profile;
2274
2275 /*
2276 Generic profile.
2277 */
2278 ResetImageProfileIterator(image);
2279 name=GetNextImageProfile(image);
2280 while (name != (const char *) NULL)
2281 {
2282 profile=GetImageProfile(image,name);
2283 (void) WriteBlob(image,GetStringInfoLength(profile),
2284 GetStringInfoDatum(profile));
2285 name=GetNextImageProfile(image);
2286 }
2287 }
2288 if (image->storage_class == PseudoClass)
2289 {
2290 size_t
2291 packet_size;
2292
2293 unsigned char
2294 *colormap,
2295 *q;
2296
2297 /*
2298 Allocate colormap.
2299 */
2300 packet_size=(size_t) (3*quantum_info->depth/8);
2301 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
2302 packet_size*sizeof(*colormap));
2303 if (colormap == (unsigned char *) NULL)
2304 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2305 /*
2306 Write colormap to file.
2307 */
2308 q=colormap;
cristybb503372010-05-27 20:51:26 +00002309 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00002310 {
2311 switch (quantum_info->depth)
2312 {
2313 default:
2314 ThrowWriterException(CorruptImageError,"ImageDepthNotSupported");
2315 case 32:
2316 {
cristy4cb162a2010-05-30 03:04:47 +00002317 register unsigned int
cristy3ed852e2009-09-05 21:47:34 +00002318 pixel;
2319
2320 pixel=ScaleQuantumToLong(image->colormap[i].red);
2321 q=PopLongPixel(MSBEndian,pixel,q);
2322 pixel=ScaleQuantumToLong(image->colormap[i].green);
2323 q=PopLongPixel(MSBEndian,pixel,q);
2324 pixel=ScaleQuantumToLong(image->colormap[i].blue);
2325 q=PopLongPixel(MSBEndian,pixel,q);
2326 break;
2327 }
2328 case 16:
2329 {
2330 register unsigned short
2331 pixel;
2332
2333 pixel=ScaleQuantumToShort(image->colormap[i].red);
2334 q=PopShortPixel(MSBEndian,pixel,q);
2335 pixel=ScaleQuantumToShort(image->colormap[i].green);
2336 q=PopShortPixel(MSBEndian,pixel,q);
2337 pixel=ScaleQuantumToShort(image->colormap[i].blue);
2338 q=PopShortPixel(MSBEndian,pixel,q);
2339 break;
2340 }
2341 case 8:
2342 {
2343 register unsigned char
2344 pixel;
2345
2346 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].red);
2347 q=PopCharPixel(pixel,q);
2348 pixel=(unsigned char) ScaleQuantumToChar(
2349 image->colormap[i].green);
2350 q=PopCharPixel(pixel,q);
2351 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].blue);
2352 q=PopCharPixel(pixel,q);
2353 break;
2354 }
2355 }
2356 }
2357 (void) WriteBlob(image,packet_size*image->colors,colormap);
2358 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
2359 }
2360 /*
2361 Write image pixels to file.
2362 */
cristy330af6c2010-12-21 14:36:06 +00002363 status=MagickTrue;
2364 switch (compression)
2365 {
2366#if defined(MAGICKCORE_BZLIB_DELEGATE)
2367 case BZipCompression:
2368 {
cristy3a99dcf2011-12-17 01:29:40 +00002369 int
2370 code;
2371
cristy330af6c2010-12-21 14:36:06 +00002372 (void) ResetMagickMemory(&bzip_info,0,sizeof(bzip_info));
2373 bzip_info.bzalloc=AcquireBZIPMemory;
2374 bzip_info.bzfree=RelinquishBZIPMemory;
2375 code=BZ2_bzCompressInit(&bzip_info,(int) (image->quality ==
2376 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,
2377 9)),(int) image_info->verbose,0);
2378 if (code != BZ_OK)
2379 status=MagickFalse;
2380 break;
2381 }
2382#endif
2383#if defined(MAGICKCORE_LZMA_DELEGATE)
2384 case LZMACompression:
2385 {
cristy3a99dcf2011-12-17 01:29:40 +00002386 int
2387 code;
2388
cristy330af6c2010-12-21 14:36:06 +00002389 (void) ResetMagickMemory(&allocator,0,sizeof(allocator));
2390 allocator.alloc=AcquireLZMAMemory;
2391 allocator.free=RelinquishLZMAMemory;
cristy9d72f1a2010-12-21 20:46:59 +00002392 lzma_info=initialize_lzma;
cristy330af6c2010-12-21 14:36:06 +00002393 lzma_info.allocator=&allocator;
cristy9d72f1a2010-12-21 20:46:59 +00002394 code=lzma_easy_encoder(&lzma_info,image->quality/10,LZMA_CHECK_SHA256);
2395 if (code != LZMA_OK)
2396 status=MagickTrue;
cristy330af6c2010-12-21 14:36:06 +00002397 break;
2398 }
2399#endif
2400#if defined(MAGICKCORE_ZLIB_DELEGATE)
2401 case LZWCompression:
2402 case ZipCompression:
2403 {
cristy3a99dcf2011-12-17 01:29:40 +00002404 int
2405 code;
2406
cristy330af6c2010-12-21 14:36:06 +00002407 (void) ResetMagickMemory(&zip_info,0,sizeof(zip_info));
2408 zip_info.zalloc=AcquireZIPMemory;
2409 zip_info.zfree=RelinquishZIPMemory;
2410 code=deflateInit(&zip_info,(int) (image->quality ==
2411 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9)));
2412 if (code != Z_OK)
2413 status=MagickFalse;
2414 break;
2415 }
2416#endif
2417 default:
2418 break;
2419 }
cristy1e178e72011-08-28 19:44:34 +00002420 quantum_type=GetQuantumType(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002421 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002422 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002423 {
cristy4c08aed2011-07-01 19:47:50 +00002424 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00002425 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002426
cristybb503372010-05-27 20:51:26 +00002427 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002428 x;
2429
cristy330af6c2010-12-21 14:36:06 +00002430 if (status == MagickFalse)
2431 break;
cristy1e178e72011-08-28 19:44:34 +00002432 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002433 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002434 break;
cristy3ed852e2009-09-05 21:47:34 +00002435 q=pixels;
2436 switch (compression)
2437 {
cristy3ed852e2009-09-05 21:47:34 +00002438#if defined(MAGICKCORE_BZLIB_DELEGATE)
2439 case BZipCompression:
2440 {
cristy3ed852e2009-09-05 21:47:34 +00002441 bzip_info.next_in=(char *) pixels;
2442 bzip_info.avail_in=(unsigned int) (packet_size*image->columns);
cristydeec0c22013-04-18 14:46:41 +00002443 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2444 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002445 do
2446 {
cristy3a99dcf2011-12-17 01:29:40 +00002447 int
2448 code;
2449
cristy3ed852e2009-09-05 21:47:34 +00002450 bzip_info.next_out=(char *) compress_pixels;
2451 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2452 image->columns);
2453 code=BZ2_bzCompress(&bzip_info,BZ_FLUSH);
cristy26377172010-12-20 19:01:58 +00002454 if (code != BZ_OK)
2455 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00002456 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2457 if (length != 0)
2458 {
2459 (void) WriteBlobMSBLong(image,(unsigned int) length);
2460 (void) WriteBlob(image,length,compress_pixels);
2461 }
2462 } while (bzip_info.avail_in != 0);
cristy26377172010-12-20 19:01:58 +00002463 break;
2464 }
2465#endif
2466#if defined(MAGICKCORE_LZMA_DELEGATE)
2467 case LZMACompression:
2468 {
cristy26377172010-12-20 19:01:58 +00002469 lzma_info.next_in=pixels;
cristy330af6c2010-12-21 14:36:06 +00002470 lzma_info.avail_in=packet_size*image->columns;
cristydeec0c22013-04-18 14:46:41 +00002471 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2472 quantum_type,pixels,exception);
cristy26377172010-12-20 19:01:58 +00002473 do
2474 {
cristy3a99dcf2011-12-17 01:29:40 +00002475 int
2476 code;
2477
cristy26377172010-12-20 19:01:58 +00002478 lzma_info.next_out=compress_pixels;
2479 lzma_info.avail_out=packet_size*image->columns;
2480 code=lzma_code(&lzma_info,LZMA_RUN);
2481 if (code != LZMA_OK)
2482 status=MagickFalse;
2483 length=(size_t) (lzma_info.next_out-compress_pixels);
2484 if (length != 0)
2485 {
2486 (void) WriteBlobMSBLong(image,(unsigned int) length);
2487 (void) WriteBlob(image,length,compress_pixels);
2488 }
2489 } while (lzma_info.avail_in != 0);
cristy26377172010-12-20 19:01:58 +00002490 break;
2491 }
2492#endif
2493#if defined(MAGICKCORE_ZLIB_DELEGATE)
2494 case LZWCompression:
2495 case ZipCompression:
2496 {
cristy26377172010-12-20 19:01:58 +00002497 zip_info.next_in=pixels;
2498 zip_info.avail_in=(uInt) (packet_size*image->columns);
cristydeec0c22013-04-18 14:46:41 +00002499 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2500 quantum_type,pixels,exception);
cristy26377172010-12-20 19:01:58 +00002501 do
2502 {
cristy3a99dcf2011-12-17 01:29:40 +00002503 int
2504 code;
2505
cristy26377172010-12-20 19:01:58 +00002506 zip_info.next_out=compress_pixels;
2507 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns);
2508 code=deflate(&zip_info,Z_SYNC_FLUSH);
2509 if (code != Z_OK)
2510 status=MagickFalse;
2511 length=(size_t) (zip_info.next_out-compress_pixels);
2512 if (length != 0)
2513 {
2514 (void) WriteBlobMSBLong(image,(unsigned int) length);
2515 (void) WriteBlob(image,length,compress_pixels);
2516 }
2517 } while (zip_info.avail_in != 0);
cristy3ed852e2009-09-05 21:47:34 +00002518 break;
2519 }
2520#endif
2521 case RLECompression:
2522 {
cristy4c08aed2011-07-01 19:47:50 +00002523 length=0;
cristy803640d2011-11-17 02:11:32 +00002524 GetPixelInfoPixel(image,p,&pixel);
cristyed231572011-07-14 02:18:59 +00002525 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00002526 for (x=1; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002527 {
cristy803640d2011-11-17 02:11:32 +00002528 GetPixelInfoPixel(image,p,&target);
cristy4c08aed2011-07-01 19:47:50 +00002529 if ((length < 255) &&
2530 (IsPixelInfoEquivalent(&pixel,&target) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00002531 length++;
2532 else
2533 {
cristyc82a27b2011-10-21 01:07:16 +00002534 q=PopRunlengthPacket(image,q,length,&pixel,exception);
cristy3ed852e2009-09-05 21:47:34 +00002535 length=0;
2536 }
cristy803640d2011-11-17 02:11:32 +00002537 GetPixelInfoPixel(image,p,&pixel);
cristyed231572011-07-14 02:18:59 +00002538 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002539 }
cristyc82a27b2011-10-21 01:07:16 +00002540 q=PopRunlengthPacket(image,q,length,&pixel,exception);
cristy3ed852e2009-09-05 21:47:34 +00002541 (void) WriteBlob(image,(size_t) (q-pixels),pixels);
2542 break;
2543 }
2544 default:
2545 {
cristydeec0c22013-04-18 14:46:41 +00002546 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2547 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002548 (void) WriteBlob(image,packet_size*image->columns,pixels);
2549 break;
2550 }
2551 }
cristycee97112010-05-28 00:44:52 +00002552 if (image->previous == (Image *) NULL)
2553 {
2554 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2555 image->rows);
2556 if (status == MagickFalse)
2557 break;
2558 }
cristy3ed852e2009-09-05 21:47:34 +00002559 }
cristy330af6c2010-12-21 14:36:06 +00002560 switch (compression)
2561 {
2562#if defined(MAGICKCORE_BZLIB_DELEGATE)
2563 case BZipCompression:
2564 {
cristy3a99dcf2011-12-17 01:29:40 +00002565 int
2566 code;
2567
cristy330af6c2010-12-21 14:36:06 +00002568 for ( ; ; )
2569 {
2570 if (status == MagickFalse)
2571 break;
2572 bzip_info.next_out=(char *) compress_pixels;
2573 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2574 image->columns);
2575 code=BZ2_bzCompress(&bzip_info,BZ_FINISH);
cristy330af6c2010-12-21 14:36:06 +00002576 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2577 if (length != 0)
2578 {
2579 (void) WriteBlobMSBLong(image,(unsigned int) length);
2580 (void) WriteBlob(image,length,compress_pixels);
2581 }
2582 if (code == BZ_STREAM_END)
2583 break;
2584 }
2585 code=BZ2_bzCompressEnd(&bzip_info);
2586 if (code != BZ_OK)
2587 status=MagickFalse;
2588 break;
2589 }
2590#endif
2591#if defined(MAGICKCORE_LZMA_DELEGATE)
2592 case LZMACompression:
2593 {
cristy3a99dcf2011-12-17 01:29:40 +00002594 int
2595 code;
2596
cristy330af6c2010-12-21 14:36:06 +00002597 for ( ; ; )
2598 {
2599 if (status == MagickFalse)
2600 break;
2601 lzma_info.next_out=compress_pixels;
2602 lzma_info.avail_out=packet_size*image->columns;
2603 code=lzma_code(&lzma_info,LZMA_FINISH);
cristy330af6c2010-12-21 14:36:06 +00002604 length=(size_t) (lzma_info.next_out-compress_pixels);
2605 if (length > 6)
2606 {
2607 (void) WriteBlobMSBLong(image,(unsigned int) length);
2608 (void) WriteBlob(image,length,compress_pixels);
2609 }
2610 if (code == LZMA_STREAM_END)
2611 break;
2612 }
2613 lzma_end(&lzma_info);
2614 break;
2615 }
2616#endif
2617#if defined(MAGICKCORE_ZLIB_DELEGATE)
2618 case LZWCompression:
2619 case ZipCompression:
2620 {
cristy3a99dcf2011-12-17 01:29:40 +00002621 int
2622 code;
2623
cristy330af6c2010-12-21 14:36:06 +00002624 for ( ; ; )
2625 {
2626 if (status == MagickFalse)
2627 break;
2628 zip_info.next_out=compress_pixels;
cristyc3ca81b2011-10-17 18:05:54 +00002629 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns);
cristy330af6c2010-12-21 14:36:06 +00002630 code=deflate(&zip_info,Z_FINISH);
cristy330af6c2010-12-21 14:36:06 +00002631 length=(size_t) (zip_info.next_out-compress_pixels);
2632 if (length > 6)
2633 {
2634 (void) WriteBlobMSBLong(image,(unsigned int) length);
2635 (void) WriteBlob(image,length,compress_pixels);
2636 }
2637 if (code == Z_STREAM_END)
2638 break;
2639 }
2640 code=deflateEnd(&zip_info);
2641 if (code != Z_OK)
2642 status=MagickFalse;
2643 break;
2644 }
2645#endif
2646 default:
2647 break;
2648 }
cristy3ed852e2009-09-05 21:47:34 +00002649 quantum_info=DestroyQuantumInfo(quantum_info);
2650 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
2651 if (GetNextImageInList(image) == (Image *) NULL)
2652 break;
2653 image=SyncNextImageInList(image);
2654 status=SetImageProgress(image,SaveImagesTag,scene++,
2655 GetImageListLength(image));
2656 if (status == MagickFalse)
2657 break;
2658 } while (image_info->adjoin != MagickFalse);
2659 (void) CloseBlob(image);
2660 return(status);
2661}