blob: be9335050baf22da89e6ba7b25f6b38c1405df6e [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% %
cristy7e41fe82010-12-04 23:12:08 +000020% Copyright 1999-2011 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"
52#include "MagickCore/constitute.h"
53#include "MagickCore/exception.h"
54#include "MagickCore/exception-private.h"
55#include "MagickCore/hashmap.h"
56#include "MagickCore/geometry.h"
57#include "MagickCore/image.h"
58#include "MagickCore/image-private.h"
59#include "MagickCore/list.h"
60#include "MagickCore/magick.h"
61#include "MagickCore/memory_.h"
62#include "MagickCore/module.h"
63#include "MagickCore/monitor.h"
64#include "MagickCore/monitor-private.h"
65#include "MagickCore/option.h"
66#include "MagickCore/pixel.h"
67#include "MagickCore/pixel-accessor.h"
68#include "MagickCore/profile.h"
69#include "MagickCore/property.h"
70#include "MagickCore/quantum-private.h"
71#include "MagickCore/static.h"
72#include "MagickCore/statistic.h"
73#include "MagickCore/string_.h"
74#include "MagickCore/string-private.h"
cristy3ed852e2009-09-05 21:47:34 +000075#if defined(MAGICKCORE_BZLIB_DELEGATE)
76#include "bzlib.h"
77#endif
cristy26377172010-12-20 19:01:58 +000078#if defined(MAGICKCORE_LZMA_DELEGATE)
79#include "lzma.h"
80#endif
81#if defined(MAGICKCORE_ZLIB_DELEGATE)
82#include "zlib.h"
83#endif
cristy3ed852e2009-09-05 21:47:34 +000084
85/*
cristya7a341e2010-12-22 20:28:51 +000086 Define declarations.
87*/
88#if !defined(LZMA_OK)
89#define LZMA_OK 0
90#endif
91
92/*
cristy3ed852e2009-09-05 21:47:34 +000093 Forward declarations.
94*/
95static MagickBooleanType
96 WriteMIFFImage(const ImageInfo *,Image *);
97
98/*
99%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
100% %
101% %
102% %
103% I s M I F F %
104% %
105% %
106% %
107%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108%
109% IsMIFF() returns MagickTrue if the image format type, identified by the
110% magick string, is MIFF.
111%
112% The format of the IsMIFF method is:
113%
114% MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
115%
116% A description of each parameter follows:
117%
118% o magick: compare image format pattern against these bytes.
119%
120% o length: Specifies the length of the magick string.
121%
122*/
123static MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
124{
125 if (length < 14)
126 return(MagickFalse);
127 if (LocaleNCompare((const char *) magick,"id=ImageMagick",14) == 0)
128 return(MagickTrue);
129 return(MagickFalse);
130}
131
132/*
133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
134% %
135% %
136% %
137% R e a d M I F F I m a g e %
138% %
139% %
140% %
141%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142%
143% ReadMIFFImage() reads a MIFF image file and returns it. It allocates the
144% memory necessary for the new Image structure and returns a pointer to the
145% new image.
146%
147% The format of the ReadMIFFImage method is:
148%
149% Image *ReadMIFFImage(const ImageInfo *image_info,
150% ExceptionInfo *exception)
151%
152% Decompression code contributed by Kyle Shorter.
153%
154% A description of each parameter follows:
155%
156% o image_info: the image info.
157%
158% o exception: return any errors or warnings in this structure.
159%
160*/
161
162#if defined(MAGICKCORE_BZLIB_DELEGATE)
163static void *AcquireBZIPMemory(void *context,int items,int size)
164{
165 (void) context;
166 return((void *) AcquireQuantumMemory((size_t) items,(size_t) size));
167}
168#endif
169
cristy4b46dba2010-12-20 19:18:20 +0000170#if defined(MAGICKCORE_LZMA_DELEGATE)
171static void *AcquireLZMAMemory(void *context,size_t items,size_t size)
172{
173 (void) context;
174 return((void *) AcquireQuantumMemory((size_t) items,(size_t) size));
175}
176#endif
177
cristy3ed852e2009-09-05 21:47:34 +0000178#if defined(MAGICKCORE_ZLIB_DELEGATE)
179static voidpf AcquireZIPMemory(voidpf context,unsigned int items,
180 unsigned int size)
181{
182 (void) context;
183 return((voidpf) AcquireQuantumMemory(items,size));
184}
185#endif
186
187static inline size_t MagickMax(const size_t x,const size_t y)
188{
189 if (x > y)
190 return(x);
191 return(y);
192}
193
194static inline size_t MagickMin(const size_t x,const size_t y)
195{
196 if (x < y)
197 return(x);
198 return(y);
199}
200
201static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
cristy4c08aed2011-07-01 19:47:50 +0000202 size_t *length,PixelInfo *pixel)
cristy3ed852e2009-09-05 21:47:34 +0000203{
204 const unsigned char
205 *p;
206
207 p=pixels;
208 if (image->storage_class == PseudoClass)
209 {
cristy4c08aed2011-07-01 19:47:50 +0000210 pixel->index=0;
cristy3ed852e2009-09-05 21:47:34 +0000211 switch (image->depth)
212 {
213 case 32:
214 {
cristy4c08aed2011-07-01 19:47:50 +0000215 pixel->index=ConstrainColormapIndex(image,
cristy3ed852e2009-09-05 21:47:34 +0000216 (*p << 24) | (*(p+1) << 16) | (*(p+2) << 8) | *(p+3));
217 p+=4;
218 break;
219 }
220 case 16:
221 {
cristy4c08aed2011-07-01 19:47:50 +0000222 pixel->index=ConstrainColormapIndex(image,(*p << 8) | *(p+1));
cristy3ed852e2009-09-05 21:47:34 +0000223 p+=2;
224 break;
225 }
226 case 8:
227 {
cristy4c08aed2011-07-01 19:47:50 +0000228 pixel->index=ConstrainColormapIndex(image,*p);
cristy3ed852e2009-09-05 21:47:34 +0000229 p++;
230 break;
231 }
232 default:
233 (void) ThrowMagickException(&image->exception,GetMagickModule(),
234 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
235 }
cristy3ed852e2009-09-05 21:47:34 +0000236 switch (image->depth)
237 {
238 case 8:
239 {
240 unsigned char
241 quantum;
242
243 if (image->matte != MagickFalse)
244 {
245 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000246 pixel->alpha=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000247 }
248 break;
249 }
250 case 16:
251 {
252 unsigned short
253 quantum;
254
255 if (image->matte != MagickFalse)
256 {
257 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000258 pixel->alpha=(Quantum) (quantum >> (image->depth-
cristy3ed852e2009-09-05 21:47:34 +0000259 MAGICKCORE_QUANTUM_DEPTH));
260 }
261 break;
262 }
263 case 32:
264 {
cristy4cb162a2010-05-30 03:04:47 +0000265 unsigned int
cristy3ed852e2009-09-05 21:47:34 +0000266 quantum;
267
268 if (image->matte != MagickFalse)
269 {
270 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000271 pixel->alpha=(Quantum) (quantum >> (image->depth-
cristy3ed852e2009-09-05 21:47:34 +0000272 MAGICKCORE_QUANTUM_DEPTH));
273 }
274 break;
275 }
276 default:
277 (void) ThrowMagickException(&image->exception,GetMagickModule(),
278 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
279 }
280 *length=(size_t) (*p++)+1;
281 return;
282 }
283 switch (image->depth)
284 {
285 case 8:
286 {
287 unsigned char
288 quantum;
289
290 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000291 pixel->red=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000292 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000293 pixel->green=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000294 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000295 pixel->blue=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000296 if (image->colorspace == CMYKColorspace)
297 {
298 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000299 pixel->black=ScaleCharToQuantum(quantum);
300 }
301 if (image->matte != MagickFalse)
302 {
303 p=PushCharPixel(p,&quantum);
304 pixel->alpha=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000305 }
306 break;
307 }
308 case 16:
309 {
310 unsigned short
311 quantum;
312
313 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000314 pixel->red=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000315 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000316 pixel->green=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristyfbbafc92011-05-05 01:22:11 +0000317 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000318 pixel->blue=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000319 if (image->colorspace == CMYKColorspace)
320 {
321 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000322 pixel->black=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
323 }
324 if (image->matte != MagickFalse)
325 {
326 p=PushShortPixel(MSBEndian,p,&quantum);
327 pixel->alpha=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000328 }
329 break;
330 }
331 case 32:
332 {
cristy4cb162a2010-05-30 03:04:47 +0000333 unsigned int
cristy3ed852e2009-09-05 21:47:34 +0000334 quantum;
335
336 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000337 pixel->red=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000338 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000339 pixel->green=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristyfbbafc92011-05-05 01:22:11 +0000340 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000341 pixel->blue=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000342 if (image->colorspace == CMYKColorspace)
343 {
344 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000345 pixel->black=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
346 }
347 if (image->matte != MagickFalse)
348 {
349 p=PushLongPixel(MSBEndian,p,&quantum);
350 pixel->alpha=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000351 }
352 break;
353 }
354 default:
355 (void) ThrowMagickException(&image->exception,GetMagickModule(),
356 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
357 }
358 *length=(size_t) (*p++)+1;
359}
360
cristy4b46dba2010-12-20 19:18:20 +0000361#if defined(MAGICKCORE_BZLIB_DELEGATE)
362static void RelinquishBZIPMemory(void *context,void *memory)
cristy3ed852e2009-09-05 21:47:34 +0000363{
364 (void) context;
365 memory=RelinquishMagickMemory(memory);
366}
367#endif
368
cristy4b46dba2010-12-20 19:18:20 +0000369#if defined(MAGICKCORE_LZMA_DELEGATE)
370static void RelinquishLZMAMemory(void *context,void *memory)
371{
372 (void) context;
373 memory=RelinquishMagickMemory(memory);
374}
375#endif
376
377#if defined(MAGICKCORE_ZLIB_DELEGATE)
378static void RelinquishZIPMemory(voidpf context,voidpf memory)
cristy3ed852e2009-09-05 21:47:34 +0000379{
380 (void) context;
381 memory=RelinquishMagickMemory(memory);
382}
383#endif
384
385static Image *ReadMIFFImage(const ImageInfo *image_info,
386 ExceptionInfo *exception)
387{
388#define BZipMaxExtent(x) ((x)+((x)/100)+600)
cristy26377172010-12-20 19:01:58 +0000389#define LZMAMaxExtent(x) ((x)+((x)/3)+128)
cristy3ed852e2009-09-05 21:47:34 +0000390#define ZipMaxExtent(x) ((x)+(((x)+7) >> 3)+(((x)+63) >> 6)+11)
391
392#if defined(MAGICKCORE_BZLIB_DELEGATE)
393 bz_stream
394 bzip_info;
395#endif
396
397 char
398 id[MaxTextExtent],
399 keyword[MaxTextExtent],
400 *options;
401
402 const unsigned char
403 *p;
404
405 double
406 version;
407
408 GeometryInfo
409 geometry_info;
410
411 Image
412 *image;
413
cristy3ed852e2009-09-05 21:47:34 +0000414 int
415 c,
416 code;
417
cristy26377172010-12-20 19:01:58 +0000418#if defined(MAGICKCORE_LZMA_DELEGATE)
419 lzma_stream
cristy330af6c2010-12-21 14:36:06 +0000420 initialize_lzma = LZMA_STREAM_INIT,
421 lzma_info;
cristy4b46dba2010-12-20 19:18:20 +0000422
423 lzma_allocator
424 allocator;
cristy26377172010-12-20 19:01:58 +0000425#endif
426
cristy3ed852e2009-09-05 21:47:34 +0000427 LinkedListInfo
428 *profiles;
429
cristy3ed852e2009-09-05 21:47:34 +0000430 MagickBooleanType
431 status;
432
cristy4c08aed2011-07-01 19:47:50 +0000433 PixelInfo
434 pixel;
435
cristy3ed852e2009-09-05 21:47:34 +0000436 MagickStatusType
437 flags;
438
cristy3ed852e2009-09-05 21:47:34 +0000439 QuantumFormatType
440 quantum_format;
441
442 QuantumInfo
443 *quantum_info;
444
445 QuantumType
446 quantum_type;
447
cristybb503372010-05-27 20:51:26 +0000448 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000449 i;
450
451 size_t
452 length,
453 packet_size;
454
455 ssize_t
456 count;
457
458 unsigned char
459 *compress_pixels,
460 *pixels;
461
cristybb503372010-05-27 20:51:26 +0000462 size_t
cristy3ed852e2009-09-05 21:47:34 +0000463 colors;
464
cristy26377172010-12-20 19:01:58 +0000465 ssize_t
466 y;
467
cristy3ed852e2009-09-05 21:47:34 +0000468#if defined(MAGICKCORE_ZLIB_DELEGATE)
469 z_stream
470 zip_info;
471#endif
472
473 /*
474 Open image file.
475 */
476 assert(image_info != (const ImageInfo *) NULL);
477 assert(image_info->signature == MagickSignature);
478 if (image_info->debug != MagickFalse)
479 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
480 image_info->filename);
481 assert(exception != (ExceptionInfo *) NULL);
482 assert(exception->signature == MagickSignature);
483 image=AcquireImage(image_info);
484 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
485 if (status == MagickFalse)
486 {
487 image=DestroyImageList(image);
488 return((Image *) NULL);
489 }
490 /*
491 Decode image header; header terminates one character beyond a ':'.
492 */
493 c=ReadBlobByte(image);
494 if (c == EOF)
495 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
496 code=0;
497 *id='\0';
498 (void) ResetMagickMemory(keyword,0,sizeof(keyword));
499 version=0.0;
500 do
501 {
502 /*
503 Decode image header; header terminates one character beyond a ':'.
504 */
505 length=MaxTextExtent;
506 options=AcquireString((char *) NULL);
507 quantum_format=UndefinedQuantumFormat;
508 profiles=(LinkedListInfo *) NULL;
509 colors=0;
510 image->depth=8UL;
511 image->compression=NoCompression;
512 while ((isgraph(c) != MagickFalse) && (c != (int) ':'))
513 {
514 register char
515 *p;
516
517 if (c == (int) '{')
518 {
519 char
520 *comment;
521
522 /*
523 Read comment-- any text between { }.
524 */
525 length=MaxTextExtent;
526 comment=AcquireString((char *) NULL);
527 for (p=comment; comment != (char *) NULL; p++)
528 {
529 c=ReadBlobByte(image);
530 if ((c == EOF) || (c == (int) '}'))
531 break;
532 if ((size_t) (p-comment+1) >= length)
533 {
534 *p='\0';
535 length<<=1;
536 comment=(char *) ResizeQuantumMemory(comment,length+
537 MaxTextExtent,sizeof(*comment));
538 if (comment == (char *) NULL)
539 break;
540 p=comment+strlen(comment);
541 }
542 *p=(char) c;
543 }
544 if (comment == (char *) NULL)
545 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
546 *p='\0';
547 (void) SetImageProperty(image,"comment",comment);
548 comment=DestroyString(comment);
549 c=ReadBlobByte(image);
550 }
551 else
552 if (isalnum(c) != MagickFalse)
553 {
554 /*
555 Get the keyword.
556 */
557 p=keyword;
558 do
559 {
cristy3ed852e2009-09-05 21:47:34 +0000560 if (c == (int) '=')
561 break;
562 if ((size_t) (p-keyword) < (MaxTextExtent-1))
563 *p++=(char) c;
564 c=ReadBlobByte(image);
565 } while (c != EOF);
566 *p='\0';
567 p=options;
cristy93505cf2010-08-10 21:37:49 +0000568 while ((isspace((int) ((unsigned char) c)) != 0) && (c != EOF))
cristy3ed852e2009-09-05 21:47:34 +0000569 c=ReadBlobByte(image);
570 if (c == (int) '=')
571 {
572 /*
573 Get the keyword value.
574 */
575 c=ReadBlobByte(image);
576 while ((c != (int) '}') && (c != EOF))
577 {
578 if ((size_t) (p-options+1) >= length)
579 {
580 *p='\0';
581 length<<=1;
582 options=(char *) ResizeQuantumMemory(options,length+
583 MaxTextExtent,sizeof(*options));
584 if (options == (char *) NULL)
585 break;
586 p=options+strlen(options);
587 }
588 if (options == (char *) NULL)
589 ThrowReaderException(ResourceLimitError,
590 "MemoryAllocationFailed");
591 *p++=(char) c;
592 c=ReadBlobByte(image);
593 if (*options != '{')
594 if (isspace((int) ((unsigned char) c)) != 0)
595 break;
596 }
597 }
598 *p='\0';
599 if (*options == '{')
600 (void) CopyMagickString(options,options+1,MaxTextExtent);
601 /*
602 Assign a value to the specified keyword.
603 */
604 switch (*keyword)
605 {
606 case 'b':
607 case 'B':
608 {
609 if (LocaleCompare(keyword,"background-color") == 0)
610 {
611 (void) QueryColorDatabase(options,&image->background_color,
612 exception);
613 break;
614 }
615 if (LocaleCompare(keyword,"blue-primary") == 0)
616 {
617 flags=ParseGeometry(options,&geometry_info);
618 image->chromaticity.blue_primary.x=geometry_info.rho;
619 image->chromaticity.blue_primary.y=geometry_info.sigma;
620 if ((flags & SigmaValue) == 0)
621 image->chromaticity.blue_primary.y=
622 image->chromaticity.blue_primary.x;
623 break;
624 }
625 if (LocaleCompare(keyword,"border-color") == 0)
626 {
627 (void) QueryColorDatabase(options,&image->border_color,
628 exception);
629 break;
630 }
631 (void) SetImageProperty(image,keyword,options);
632 break;
633 }
634 case 'c':
635 case 'C':
636 {
637 if (LocaleCompare(keyword,"class") == 0)
638 {
cristybb503372010-05-27 20:51:26 +0000639 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000640 storage_class;
641
cristy042ee782011-04-22 18:48:30 +0000642 storage_class=ParseCommandOption(MagickClassOptions,
cristy3ed852e2009-09-05 21:47:34 +0000643 MagickFalse,options);
644 if (storage_class < 0)
645 break;
646 image->storage_class=(ClassType) storage_class;
647 break;
648 }
649 if (LocaleCompare(keyword,"colors") == 0)
650 {
cristye27293e2009-12-18 02:53:20 +0000651 colors=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000652 break;
653 }
654 if (LocaleCompare(keyword,"colorspace") == 0)
655 {
cristybb503372010-05-27 20:51:26 +0000656 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000657 colorspace;
658
cristy042ee782011-04-22 18:48:30 +0000659 colorspace=ParseCommandOption(MagickColorspaceOptions,
cristy3ed852e2009-09-05 21:47:34 +0000660 MagickFalse,options);
661 if (colorspace < 0)
662 break;
663 image->colorspace=(ColorspaceType) colorspace;
664 break;
665 }
666 if (LocaleCompare(keyword,"compression") == 0)
667 {
cristybb503372010-05-27 20:51:26 +0000668 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000669 compression;
670
cristy042ee782011-04-22 18:48:30 +0000671 compression=ParseCommandOption(MagickCompressOptions,
cristy3ed852e2009-09-05 21:47:34 +0000672 MagickFalse,options);
673 if (compression < 0)
674 break;
675 image->compression=(CompressionType) compression;
676 break;
677 }
678 if (LocaleCompare(keyword,"columns") == 0)
679 {
cristye27293e2009-12-18 02:53:20 +0000680 image->columns=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000681 break;
682 }
683 (void) SetImageProperty(image,keyword,options);
684 break;
685 }
686 case 'd':
687 case 'D':
688 {
689 if (LocaleCompare(keyword,"delay") == 0)
690 {
cristye27293e2009-12-18 02:53:20 +0000691 image->delay=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000692 break;
693 }
694 if (LocaleCompare(keyword,"depth") == 0)
695 {
cristye27293e2009-12-18 02:53:20 +0000696 image->depth=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000697 break;
698 }
699 if (LocaleCompare(keyword,"dispose") == 0)
700 {
cristybb503372010-05-27 20:51:26 +0000701 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000702 dispose;
703
cristy042ee782011-04-22 18:48:30 +0000704 dispose=ParseCommandOption(MagickDisposeOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000705 options);
706 if (dispose < 0)
707 break;
708 image->dispose=(DisposeType) dispose;
709 break;
710 }
711 (void) SetImageProperty(image,keyword,options);
712 break;
713 }
714 case 'e':
715 case 'E':
716 {
717 if (LocaleCompare(keyword,"endian") == 0)
718 {
cristybb503372010-05-27 20:51:26 +0000719 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000720 endian;
721
cristy042ee782011-04-22 18:48:30 +0000722 endian=ParseCommandOption(MagickEndianOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000723 options);
724 if (endian < 0)
725 break;
726 image->endian=(EndianType) endian;
727 break;
728 }
729 (void) SetImageProperty(image,keyword,options);
730 break;
731 }
732 case 'g':
733 case 'G':
734 {
735 if (LocaleCompare(keyword,"gamma") == 0)
736 {
cristyc1acd842011-05-19 23:05:47 +0000737 image->gamma=InterpretLocaleValue(options,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000738 break;
739 }
740 if (LocaleCompare(keyword,"gravity") == 0)
741 {
cristybb503372010-05-27 20:51:26 +0000742 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000743 gravity;
744
cristy042ee782011-04-22 18:48:30 +0000745 gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000746 options);
747 if (gravity < 0)
748 break;
749 image->gravity=(GravityType) gravity;
750 break;
751 }
752 if (LocaleCompare(keyword,"green-primary") == 0)
753 {
754 flags=ParseGeometry(options,&geometry_info);
755 image->chromaticity.green_primary.x=geometry_info.rho;
756 image->chromaticity.green_primary.y=geometry_info.sigma;
757 if ((flags & SigmaValue) == 0)
758 image->chromaticity.green_primary.y=
759 image->chromaticity.green_primary.x;
760 break;
761 }
762 (void) SetImageProperty(image,keyword,options);
763 break;
764 }
765 case 'i':
766 case 'I':
767 {
768 if (LocaleCompare(keyword,"id") == 0)
769 {
770 (void) CopyMagickString(id,options,MaxTextExtent);
771 break;
772 }
773 if (LocaleCompare(keyword,"iterations") == 0)
774 {
cristye27293e2009-12-18 02:53:20 +0000775 image->iterations=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000776 break;
777 }
778 (void) SetImageProperty(image,keyword,options);
779 break;
780 }
781 case 'm':
782 case 'M':
783 {
784 if (LocaleCompare(keyword,"matte") == 0)
785 {
cristybb503372010-05-27 20:51:26 +0000786 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000787 matte;
788
cristy042ee782011-04-22 18:48:30 +0000789 matte=ParseCommandOption(MagickBooleanOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000790 options);
791 if (matte < 0)
792 break;
793 image->matte=(MagickBooleanType) matte;
794 break;
795 }
796 if (LocaleCompare(keyword,"matte-color") == 0)
797 {
798 (void) QueryColorDatabase(options,&image->matte_color,
799 exception);
800 break;
801 }
802 if (LocaleCompare(keyword,"montage") == 0)
803 {
804 (void) CloneString(&image->montage,options);
805 break;
806 }
807 (void) SetImageProperty(image,keyword,options);
808 break;
809 }
810 case 'o':
811 case 'O':
812 {
813 if (LocaleCompare(keyword,"opaque") == 0)
814 {
cristybb503372010-05-27 20:51:26 +0000815 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000816 matte;
817
cristy042ee782011-04-22 18:48:30 +0000818 matte=ParseCommandOption(MagickBooleanOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000819 options);
820 if (matte < 0)
821 break;
822 image->matte=(MagickBooleanType) matte;
823 break;
824 }
825 if (LocaleCompare(keyword,"orientation") == 0)
826 {
cristybb503372010-05-27 20:51:26 +0000827 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000828 orientation;
829
cristy042ee782011-04-22 18:48:30 +0000830 orientation=ParseCommandOption(MagickOrientationOptions,
cristy3ed852e2009-09-05 21:47:34 +0000831 MagickFalse,options);
832 if (orientation < 0)
833 break;
834 image->orientation=(OrientationType) orientation;
835 break;
836 }
837 (void) SetImageProperty(image,keyword,options);
838 break;
839 }
840 case 'p':
841 case 'P':
842 {
843 if (LocaleCompare(keyword,"page") == 0)
844 {
845 char
846 *geometry;
847
848 geometry=GetPageGeometry(options);
849 (void) ParseAbsoluteGeometry(geometry,&image->page);
850 geometry=DestroyString(geometry);
851 break;
852 }
853 if ((LocaleNCompare(keyword,"profile:",8) == 0) ||
854 (LocaleNCompare(keyword,"profile-",8) == 0))
855 {
856 StringInfo
857 *profile;
858
859 if (profiles == (LinkedListInfo *) NULL)
860 profiles=NewLinkedList(0);
861 (void) AppendValueToLinkedList(profiles,
862 AcquireString(keyword+8));
cristyf2f27272009-12-17 14:48:46 +0000863 profile=AcquireStringInfo((size_t) StringToLong(options));
cristy3ed852e2009-09-05 21:47:34 +0000864 (void) SetImageProfile(image,keyword+8,profile);
865 profile=DestroyStringInfo(profile);
866 break;
867 }
868 (void) SetImageProperty(image,keyword,options);
869 break;
870 }
871 case 'q':
872 case 'Q':
873 {
874 if (LocaleCompare(keyword,"quality") == 0)
875 {
cristye27293e2009-12-18 02:53:20 +0000876 image->quality=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000877 break;
878 }
879 if ((LocaleCompare(keyword,"quantum-format") == 0) ||
880 (LocaleCompare(keyword,"quantum:format") == 0))
881 {
cristybb503372010-05-27 20:51:26 +0000882 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000883 format;
884
cristy042ee782011-04-22 18:48:30 +0000885 format=ParseCommandOption(MagickQuantumFormatOptions,
cristy3ed852e2009-09-05 21:47:34 +0000886 MagickFalse,options);
887 if (format < 0)
888 break;
889 quantum_format=(QuantumFormatType) format;
890 break;
891 }
892 (void) SetImageProperty(image,keyword,options);
893 break;
894 }
895 case 'r':
896 case 'R':
897 {
898 if (LocaleCompare(keyword,"red-primary") == 0)
899 {
900 flags=ParseGeometry(options,&geometry_info);
901 image->chromaticity.red_primary.x=geometry_info.rho;
902 image->chromaticity.red_primary.y=geometry_info.sigma;
903 if ((flags & SigmaValue) == 0)
904 image->chromaticity.red_primary.y=
905 image->chromaticity.red_primary.x;
906 break;
907 }
908 if (LocaleCompare(keyword,"rendering-intent") == 0)
909 {
cristybb503372010-05-27 20:51:26 +0000910 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000911 rendering_intent;
912
cristy042ee782011-04-22 18:48:30 +0000913 rendering_intent=ParseCommandOption(MagickIntentOptions,
cristy3ed852e2009-09-05 21:47:34 +0000914 MagickFalse,options);
915 if (rendering_intent < 0)
916 break;
917 image->rendering_intent=(RenderingIntent) rendering_intent;
918 break;
919 }
920 if (LocaleCompare(keyword,"resolution") == 0)
921 {
922 flags=ParseGeometry(options,&geometry_info);
923 image->x_resolution=geometry_info.rho;
924 image->y_resolution=geometry_info.sigma;
925 if ((flags & SigmaValue) == 0)
926 image->y_resolution=image->x_resolution;
927 break;
928 }
929 if (LocaleCompare(keyword,"rows") == 0)
930 {
cristye27293e2009-12-18 02:53:20 +0000931 image->rows=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000932 break;
933 }
934 (void) SetImageProperty(image,keyword,options);
935 break;
936 }
937 case 's':
938 case 'S':
939 {
940 if (LocaleCompare(keyword,"scene") == 0)
941 {
cristye27293e2009-12-18 02:53:20 +0000942 image->scene=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000943 break;
944 }
945 (void) SetImageProperty(image,keyword,options);
946 break;
947 }
948 case 't':
949 case 'T':
950 {
951 if (LocaleCompare(keyword,"ticks-per-second") == 0)
952 {
cristy15893a42010-11-20 18:57:15 +0000953 image->ticks_per_second=(ssize_t) StringToLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000954 break;
955 }
956 if (LocaleCompare(keyword,"tile-offset") == 0)
957 {
958 char
959 *geometry;
960
961 geometry=GetPageGeometry(options);
962 (void) ParseAbsoluteGeometry(geometry,&image->tile_offset);
963 geometry=DestroyString(geometry);
964 break;
965 }
966 if (LocaleCompare(keyword,"type") == 0)
967 {
cristybb503372010-05-27 20:51:26 +0000968 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000969 type;
970
cristy042ee782011-04-22 18:48:30 +0000971 type=ParseCommandOption(MagickTypeOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000972 options);
973 if (type < 0)
974 break;
975 image->type=(ImageType) type;
976 break;
977 }
978 (void) SetImageProperty(image,keyword,options);
979 break;
980 }
981 case 'u':
982 case 'U':
983 {
984 if (LocaleCompare(keyword,"units") == 0)
985 {
cristybb503372010-05-27 20:51:26 +0000986 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000987 units;
988
cristyfbbafc92011-05-05 01:22:11 +0000989 units=ParseCommandOption(MagickResolutionOptions,
990 MagickFalse,options);
cristy3ed852e2009-09-05 21:47:34 +0000991 if (units < 0)
992 break;
993 image->units=(ResolutionType) units;
994 break;
995 }
996 (void) SetImageProperty(image,keyword,options);
997 break;
998 }
999 case 'v':
1000 case 'V':
1001 {
1002 if (LocaleCompare(keyword,"version") == 0)
1003 {
cristyc1acd842011-05-19 23:05:47 +00001004 version=InterpretLocaleValue(options,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +00001005 break;
1006 }
1007 (void) SetImageProperty(image,keyword,options);
1008 break;
1009 }
1010 case 'w':
1011 case 'W':
1012 {
1013 if (LocaleCompare(keyword,"white-point") == 0)
1014 {
1015 flags=ParseGeometry(options,&geometry_info);
1016 image->chromaticity.white_point.x=geometry_info.rho;
1017 image->chromaticity.white_point.y=geometry_info.rho;
1018 if ((flags & SigmaValue) != 0)
1019 image->chromaticity.white_point.y=
1020 image->chromaticity.white_point.x;
1021 break;
1022 }
1023 (void) SetImageProperty(image,keyword,options);
1024 break;
1025 }
1026 default:
1027 {
1028 (void) SetImageProperty(image,keyword,options);
1029 break;
1030 }
1031 }
1032 }
1033 else
1034 c=ReadBlobByte(image);
1035 while (isspace((int) ((unsigned char) c)) != 0)
1036 c=ReadBlobByte(image);
1037 }
1038 options=DestroyString(options);
1039 (void) ReadBlobByte(image);
1040 /*
1041 Verify that required image information is defined.
1042 */
1043 if ((LocaleCompare(id,"ImageMagick") != 0) ||
1044 (image->storage_class == UndefinedClass) ||
1045 (image->columns == 0) || (image->rows == 0))
1046 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1047 if (image->montage != (char *) NULL)
1048 {
1049 register char
1050 *p;
1051
1052 /*
1053 Image directory.
1054 */
1055 length=MaxTextExtent;
1056 image->directory=AcquireString((char *) NULL);
1057 p=image->directory;
1058 do
1059 {
1060 *p='\0';
1061 if ((strlen(image->directory)+MaxTextExtent) >= length)
1062 {
1063 /*
1064 Allocate more memory for the image directory.
1065 */
1066 length<<=1;
1067 image->directory=(char *) ResizeQuantumMemory(image->directory,
1068 length+MaxTextExtent,sizeof(*image->directory));
1069 if (image->directory == (char *) NULL)
1070 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1071 p=image->directory+strlen(image->directory);
1072 }
1073 c=ReadBlobByte(image);
1074 *p++=(char) c;
1075 } while (c != (int) '\0');
1076 }
1077 if (profiles != (LinkedListInfo *) NULL)
1078 {
1079 const char
1080 *name;
1081
1082 const StringInfo
1083 *profile;
1084
1085 /*
1086 Read image profiles.
1087 */
1088 ResetLinkedListIterator(profiles);
1089 name=(const char *) GetNextValueInLinkedList(profiles);
1090 while (name != (const char *) NULL)
1091 {
1092 profile=GetImageProfile(image,name);
1093 if (profile != (StringInfo *) NULL)
1094 {
1095 register unsigned char
1096 *p;
1097
1098 p=GetStringInfoDatum(profile);
1099 count=ReadBlob(image,GetStringInfoLength(profile),p);
cristyda16f162011-02-19 23:52:17 +00001100 (void) count;
cristy3ed852e2009-09-05 21:47:34 +00001101 }
1102 name=(const char *) GetNextValueInLinkedList(profiles);
1103 }
1104 profiles=DestroyLinkedList(profiles,RelinquishMagickMemory);
1105 }
1106 image->depth=GetImageQuantumDepth(image,MagickFalse);
1107 if (image->storage_class == PseudoClass)
1108 {
1109 /*
1110 Create image colormap.
1111 */
1112 status=AcquireImageColormap(image,colors != 0 ? colors : 256);
1113 if (status == MagickFalse)
1114 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1115 if (colors != 0)
1116 {
1117 size_t
1118 packet_size;
1119
1120 unsigned char
1121 *colormap;
1122
1123 /*
1124 Read image colormap from file.
1125 */
1126 packet_size=(size_t) (3UL*image->depth/8UL);
1127 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
1128 packet_size*sizeof(*colormap));
1129 if (colormap == (unsigned char *) NULL)
1130 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1131 count=ReadBlob(image,packet_size*image->colors,colormap);
1132 p=colormap;
1133 switch (image->depth)
1134 {
1135 default:
1136 ThrowReaderException(CorruptImageError,
1137 "ImageDepthNotSupported");
1138 case 8:
1139 {
1140 unsigned char
1141 pixel;
1142
cristybb503372010-05-27 20:51:26 +00001143 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001144 {
1145 p=PushCharPixel(p,&pixel);
1146 image->colormap[i].red=ScaleCharToQuantum(pixel);
1147 p=PushCharPixel(p,&pixel);
1148 image->colormap[i].green=ScaleCharToQuantum(pixel);
1149 p=PushCharPixel(p,&pixel);
1150 image->colormap[i].blue=ScaleCharToQuantum(pixel);
1151 }
1152 break;
1153 }
1154 case 16:
1155 {
1156 unsigned short
1157 pixel;
1158
cristybb503372010-05-27 20:51:26 +00001159 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001160 {
1161 p=PushShortPixel(MSBEndian,p,&pixel);
1162 image->colormap[i].red=ScaleShortToQuantum(pixel);
1163 p=PushShortPixel(MSBEndian,p,&pixel);
1164 image->colormap[i].green=ScaleShortToQuantum(pixel);
1165 p=PushShortPixel(MSBEndian,p,&pixel);
1166 image->colormap[i].blue=ScaleShortToQuantum(pixel);
1167 }
1168 break;
1169 }
1170 case 32:
1171 {
cristy4cb162a2010-05-30 03:04:47 +00001172 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001173 pixel;
1174
cristybb503372010-05-27 20:51:26 +00001175 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001176 {
1177 p=PushLongPixel(MSBEndian,p,&pixel);
1178 image->colormap[i].red=ScaleLongToQuantum(pixel);
1179 p=PushLongPixel(MSBEndian,p,&pixel);
1180 image->colormap[i].green=ScaleLongToQuantum(pixel);
1181 p=PushLongPixel(MSBEndian,p,&pixel);
1182 image->colormap[i].blue=ScaleLongToQuantum(pixel);
1183 }
1184 break;
1185 }
1186 }
1187 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
1188 }
1189 }
1190 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1191 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1192 break;
1193 /*
1194 Allocate image pixels.
1195 */
1196 quantum_info=AcquireQuantumInfo(image_info,image);
1197 if (quantum_info == (QuantumInfo *) NULL)
1198 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1199 if (quantum_format != UndefinedQuantumFormat)
1200 {
1201 status=SetQuantumFormat(image,quantum_info,quantum_format);
1202 if (status == MagickFalse)
1203 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1204 }
1205 packet_size=(size_t) (quantum_info->depth/8);
1206 if (image->storage_class == DirectClass)
1207 packet_size=(size_t) (3*quantum_info->depth/8);
1208 if (image->matte != MagickFalse)
1209 packet_size+=quantum_info->depth/8;
1210 if (image->colorspace == CMYKColorspace)
1211 packet_size+=quantum_info->depth/8;
1212 if (image->compression == RLECompression)
1213 packet_size++;
1214 length=image->columns;
cristy26377172010-12-20 19:01:58 +00001215 length=MagickMax(MagickMax(BZipMaxExtent(packet_size*image->columns),
1216 LZMAMaxExtent(packet_size*image->columns)),ZipMaxExtent(packet_size*
1217 image->columns));
cristy3ed852e2009-09-05 21:47:34 +00001218 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
1219 sizeof(*compress_pixels));
1220 if (compress_pixels == (unsigned char *) NULL)
1221 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1222 /*
1223 Read image pixels.
1224 */
1225 quantum_type=RGBQuantum;
1226 if (image->matte != MagickFalse)
1227 quantum_type=RGBAQuantum;
1228 if (image->colorspace == CMYKColorspace)
1229 {
1230 quantum_type=CMYKQuantum;
1231 if (image->matte != MagickFalse)
1232 quantum_type=CMYKAQuantum;
1233 }
1234 if (image->storage_class == PseudoClass)
1235 {
1236 quantum_type=IndexQuantum;
1237 if (image->matte != MagickFalse)
1238 quantum_type=IndexAlphaQuantum;
1239 }
1240 if (image->colorspace == GRAYColorspace)
1241 {
1242 quantum_type=GrayQuantum;
1243 if (image->matte != MagickFalse)
1244 quantum_type=GrayAlphaQuantum;
1245 }
cristy330af6c2010-12-21 14:36:06 +00001246 status=MagickTrue;
1247 switch (image->compression)
1248 {
1249#if defined(MAGICKCORE_BZLIB_DELEGATE)
1250 case BZipCompression:
1251 {
1252 (void) ResetMagickMemory(&bzip_info,0,sizeof(bzip_info));
1253 bzip_info.bzalloc=AcquireBZIPMemory;
1254 bzip_info.bzfree=RelinquishBZIPMemory;
1255 bzip_info.opaque=(void *) NULL;
1256 code=BZ2_bzDecompressInit(&bzip_info,(int) image_info->verbose,
1257 MagickFalse);
1258 if (code != BZ_OK)
1259 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001260 break;
1261 }
1262#endif
1263#if defined(MAGICKCORE_LZMA_DELEGATE)
1264 case LZMACompression:
1265 {
cristy9d72f1a2010-12-21 20:46:59 +00001266 (void) ResetMagickMemory(&allocator,0,sizeof(allocator));
1267 allocator.alloc=AcquireLZMAMemory;
1268 allocator.free=RelinquishLZMAMemory;
cristy330af6c2010-12-21 14:36:06 +00001269 lzma_info=initialize_lzma;
cristy9d72f1a2010-12-21 20:46:59 +00001270 lzma_info.allocator=(&allocator);
cristy330af6c2010-12-21 14:36:06 +00001271 code=lzma_auto_decoder(&lzma_info,-1,0);
1272 if (code != LZMA_OK)
1273 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001274 break;
1275 }
1276#endif
1277#if defined(MAGICKCORE_ZLIB_DELEGATE)
1278 case LZWCompression:
1279 case ZipCompression:
1280 {
1281 (void) ResetMagickMemory(&zip_info,0,sizeof(zip_info));
1282 zip_info.zalloc=AcquireZIPMemory;
1283 zip_info.zfree=RelinquishZIPMemory;
1284 zip_info.opaque=(voidpf) NULL;
1285 code=inflateInit(&zip_info);
1286 if (code != Z_OK)
1287 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001288 break;
1289 }
1290#endif
1291 case RLECompression:
1292 {
cristy4c08aed2011-07-01 19:47:50 +00001293 GetPixelInfo(image,&pixel);
cristy330af6c2010-12-21 14:36:06 +00001294 break;
1295 }
1296 default:
1297 break;
1298 }
cristy3ed852e2009-09-05 21:47:34 +00001299 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001300 length=0;
cristybb503372010-05-27 20:51:26 +00001301 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001302 {
cristybb503372010-05-27 20:51:26 +00001303 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001304 x;
1305
cristy4c08aed2011-07-01 19:47:50 +00001306 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00001307 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001308
cristy330af6c2010-12-21 14:36:06 +00001309 if (status == MagickFalse)
1310 break;
cristy3ed852e2009-09-05 21:47:34 +00001311 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001312 if (q == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001313 break;
cristy3ed852e2009-09-05 21:47:34 +00001314 switch (image->compression)
1315 {
cristy3ed852e2009-09-05 21:47:34 +00001316#if defined(MAGICKCORE_BZLIB_DELEGATE)
1317 case BZipCompression:
1318 {
cristy3ed852e2009-09-05 21:47:34 +00001319 bzip_info.next_out=(char *) pixels;
1320 bzip_info.avail_out=(unsigned int) (packet_size*image->columns);
1321 do
1322 {
1323 if (bzip_info.avail_in == 0)
1324 {
1325 bzip_info.next_in=(char *) compress_pixels;
1326 length=(size_t) BZipMaxExtent(packet_size*image->columns);
1327 if (version != 0)
1328 length=(size_t) ReadBlobMSBLong(image);
1329 bzip_info.avail_in=(unsigned int) ReadBlob(image,length,
1330 (unsigned char *) bzip_info.next_in);
1331 }
1332 if (BZ2_bzDecompress(&bzip_info) == BZ_STREAM_END)
1333 break;
1334 } while (bzip_info.avail_out != 0);
cristy26377172010-12-20 19:01:58 +00001335 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1336 quantum_type,pixels,exception);
1337 break;
1338 }
1339#endif
1340#if defined(MAGICKCORE_LZMA_DELEGATE)
1341 case LZMACompression:
1342 {
cristy26377172010-12-20 19:01:58 +00001343 lzma_info.next_out=pixels;
cristy330af6c2010-12-21 14:36:06 +00001344 lzma_info.avail_out=packet_size*image->columns;
cristy26377172010-12-20 19:01:58 +00001345 do
1346 {
1347 if (lzma_info.avail_in == 0)
1348 {
1349 lzma_info.next_in=compress_pixels;
1350 length=(size_t) ReadBlobMSBLong(image);
1351 lzma_info.avail_in=(unsigned int) ReadBlob(image,length,
1352 (unsigned char *) lzma_info.next_in);
1353 }
1354 code=lzma_code(&lzma_info,LZMA_RUN);
cristy330af6c2010-12-21 14:36:06 +00001355 if (code < 0)
1356 {
1357 status=MagickFalse;
1358 break;
1359 }
1360 if (code == LZMA_STREAM_END)
cristy26377172010-12-20 19:01:58 +00001361 break;
1362 } while (lzma_info.avail_out != 0);
cristy26377172010-12-20 19:01:58 +00001363 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1364 quantum_type,pixels,exception);
1365 break;
1366 }
1367#endif
1368#if defined(MAGICKCORE_ZLIB_DELEGATE)
1369 case LZWCompression:
1370 case ZipCompression:
1371 {
cristy26377172010-12-20 19:01:58 +00001372 zip_info.next_out=pixels;
1373 zip_info.avail_out=(uInt) (packet_size*image->columns);
1374 do
1375 {
1376 if (zip_info.avail_in == 0)
1377 {
1378 zip_info.next_in=compress_pixels;
1379 length=(size_t) ZipMaxExtent(packet_size*image->columns);
1380 if (version != 0)
1381 length=(size_t) ReadBlobMSBLong(image);
1382 zip_info.avail_in=(unsigned int) ReadBlob(image,length,
1383 zip_info.next_in);
1384 }
1385 if (inflate(&zip_info,Z_SYNC_FLUSH) == Z_STREAM_END)
1386 break;
1387 } while (zip_info.avail_out != 0);
cristy3ed852e2009-09-05 21:47:34 +00001388 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1389 quantum_type,pixels,exception);
1390 break;
1391 }
1392#endif
1393 case RLECompression:
1394 {
cristybb503372010-05-27 20:51:26 +00001395 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001396 {
1397 if (length == 0)
1398 {
1399 count=ReadBlob(image,packet_size,pixels);
cristy4c08aed2011-07-01 19:47:50 +00001400 PushRunlengthPacket(image,pixels,&length,&pixel);
cristy3ed852e2009-09-05 21:47:34 +00001401 }
1402 length--;
cristy4c08aed2011-07-01 19:47:50 +00001403 if (image->storage_class == PseudoClass)
1404 SetPixelIndex(image,pixel.index,q);
1405 else
1406 {
1407 SetPixelRed(image,pixel.red,q);
1408 SetPixelGreen(image,pixel.green,q);
1409 SetPixelBlue(image,pixel.blue,q);
1410 if (image->colorspace == CMYKColorspace)
1411 SetPixelBlack(image,pixel.black,q);
1412 }
1413 if (image->matte != MagickFalse)
1414 SetPixelAlpha(image,pixel.alpha,q);
cristyed231572011-07-14 02:18:59 +00001415 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001416 }
1417 break;
1418 }
1419 default:
1420 {
1421 count=ReadBlob(image,packet_size*image->columns,pixels);
1422 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1423 quantum_type,pixels,exception);
1424 break;
1425 }
1426 }
1427 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1428 break;
1429 }
1430 SetQuantumImageType(image,quantum_type);
cristy330af6c2010-12-21 14:36:06 +00001431 switch (image->compression)
1432 {
1433#if defined(MAGICKCORE_BZLIB_DELEGATE)
1434 case BZipCompression:
1435 {
1436 if (version == 0)
1437 {
1438 MagickOffsetType
1439 offset;
1440
1441 offset=SeekBlob(image,-((MagickOffsetType)
1442 bzip_info.avail_in),SEEK_CUR);
1443 if (offset < 0)
1444 ThrowReaderException(CorruptImageError,
1445 "ImproperImageHeader");
1446 }
1447 code=BZ2_bzDecompressEnd(&bzip_info);
1448 if (code != BZ_OK)
1449 status=MagickFalse;
1450 break;
1451 }
1452#endif
1453#if defined(MAGICKCORE_LZMA_DELEGATE)
1454 case LZMACompression:
1455 {
cristy3b788a02010-12-27 15:59:54 +00001456 code=lzma_code(&lzma_info,LZMA_FINISH);
1457 if ((code != LZMA_STREAM_END) && (code != LZMA_OK))
cristyb977da52010-12-22 15:55:53 +00001458 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001459 lzma_end(&lzma_info);
1460 break;
1461 }
1462#endif
1463#if defined(MAGICKCORE_ZLIB_DELEGATE)
1464 case LZWCompression:
1465 case ZipCompression:
1466 {
1467 if (version == 0)
1468 {
1469 MagickOffsetType
1470 offset;
1471
1472 offset=SeekBlob(image,-((MagickOffsetType) zip_info.avail_in),
1473 SEEK_CUR);
1474 if (offset < 0)
1475 ThrowReaderException(CorruptImageError,
1476 "ImproperImageHeader");
1477 }
1478 code=inflateEnd(&zip_info);
1479 if (code != LZMA_OK)
1480 status=MagickFalse;
1481 break;
1482 }
1483#endif
1484 default:
1485 break;
1486 }
cristy3ed852e2009-09-05 21:47:34 +00001487 quantum_info=DestroyQuantumInfo(quantum_info);
1488 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
cristybb503372010-05-27 20:51:26 +00001489 if (((y != (ssize_t) image->rows)) || (status == MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001490 {
1491 image=DestroyImageList(image);
1492 return((Image *) NULL);
1493 }
1494 if (EOFBlob(image) != MagickFalse)
1495 {
1496 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1497 image->filename);
1498 break;
1499 }
1500 /*
1501 Proceed to next image.
1502 */
1503 if (image_info->number_scenes != 0)
1504 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1505 break;
1506 do
1507 {
1508 c=ReadBlobByte(image);
1509 } while ((isgraph(c) == MagickFalse) && (c != EOF));
1510 if (c != EOF)
1511 {
1512 /*
1513 Allocate next image structure.
1514 */
1515 AcquireNextImage(image_info,image);
1516 if (GetNextImageInList(image) == (Image *) NULL)
1517 {
1518 image=DestroyImageList(image);
1519 return((Image *) NULL);
1520 }
1521 image=SyncNextImageInList(image);
1522 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1523 GetBlobSize(image));
1524 if (status == MagickFalse)
1525 break;
1526 }
1527 } while (c != EOF);
1528 (void) CloseBlob(image);
1529 return(GetFirstImageInList(image));
1530}
1531
1532/*
1533%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1534% %
1535% %
1536% %
1537% R e g i s t e r M I F F I m a g e %
1538% %
1539% %
1540% %
1541%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1542%
1543% RegisterMIFFImage() adds properties for the MIFF image format to the list of
1544% supported formats. The properties include the image format tag, a method to
1545% read and/or write the format, whether the format supports the saving of more
1546% than one frame to the same file or blob, whether the format supports native
1547% in-memory I/O, and a brief description of the format.
1548%
1549% The format of the RegisterMIFFImage method is:
1550%
cristybb503372010-05-27 20:51:26 +00001551% size_t RegisterMIFFImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001552%
1553*/
cristybb503372010-05-27 20:51:26 +00001554ModuleExport size_t RegisterMIFFImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001555{
1556 char
1557 version[MaxTextExtent];
1558
1559 MagickInfo
1560 *entry;
1561
1562 *version='\0';
1563#if defined(MagickImageCoderSignatureText)
1564 (void) CopyMagickString(version,MagickLibVersionText,MaxTextExtent);
1565#if defined(ZLIB_VERSION)
1566 (void) ConcatenateMagickString(version," with Zlib ",MaxTextExtent);
1567 (void) ConcatenateMagickString(version,ZLIB_VERSION,MaxTextExtent);
1568#endif
1569#if defined(MAGICKCORE_BZLIB_DELEGATE)
1570 (void) ConcatenateMagickString(version," and BZlib",MaxTextExtent);
1571#endif
1572#endif
1573 entry=SetMagickInfo("MIFF");
1574 entry->decoder=(DecodeImageHandler *) ReadMIFFImage;
1575 entry->encoder=(EncodeImageHandler *) WriteMIFFImage;
1576 entry->magick=(IsImageFormatHandler *) IsMIFF;
cristyffaf9782011-04-13 19:50:51 +00001577 entry->seekable_stream=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00001578 entry->description=ConstantString("Magick Image File Format");
1579 if (*version != '\0')
1580 entry->version=ConstantString(version);
1581 entry->module=ConstantString("MIFF");
1582 (void) RegisterMagickInfo(entry);
1583 return(MagickImageCoderSignature);
1584}
1585
1586/*
1587%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1588% %
1589% %
1590% %
1591% U n r e g i s t e r M I F F I m a g e %
1592% %
1593% %
1594% %
1595%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1596%
1597% UnregisterMIFFImage() removes format registrations made by the MIFF module
1598% from the list of supported formats.
1599%
1600% The format of the UnregisterMIFFImage method is:
1601%
1602% UnregisterMIFFImage(void)
1603%
1604*/
1605ModuleExport void UnregisterMIFFImage(void)
1606{
1607 (void) UnregisterMagickInfo("MIFF");
1608}
1609
1610/*
1611%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1612% %
1613% %
1614% %
1615% W r i t e M I F F I m a g e %
1616% %
1617% %
1618% %
1619%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1620%
1621% WriteMIFFImage() writes a MIFF image to a file.
1622%
1623% The format of the WriteMIFFImage method is:
1624%
1625% MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
1626% Image *image)
1627%
1628% Compression code contributed by Kyle Shorter.
1629%
1630% A description of each parameter follows:
1631%
1632% o image_info: the image info.
1633%
1634% o image: the image.
1635%
1636*/
1637
1638static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
cristy4c08aed2011-07-01 19:47:50 +00001639 size_t length,PixelInfo *pixel)
cristy3ed852e2009-09-05 21:47:34 +00001640{
1641 if (image->storage_class != DirectClass)
1642 {
1643 switch (image->depth)
1644 {
1645 case 32:
1646 {
cristy4c08aed2011-07-01 19:47:50 +00001647 *pixels++=(unsigned char) ((size_t) pixel->index >> 24);
1648 *pixels++=(unsigned char) ((size_t) pixel->index >> 16);
cristy3ed852e2009-09-05 21:47:34 +00001649 }
1650 case 16:
cristy4c08aed2011-07-01 19:47:50 +00001651 *pixels++=(unsigned char) ((size_t) pixel->index >> 8);
cristy3ed852e2009-09-05 21:47:34 +00001652 case 8:
1653 {
cristy4c08aed2011-07-01 19:47:50 +00001654 *pixels++=(unsigned char) pixel->index;
cristy3ed852e2009-09-05 21:47:34 +00001655 break;
1656 }
1657 default:
1658 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1659 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1660 }
1661 switch (image->depth)
1662 {
1663 case 32:
1664 {
cristy4cb162a2010-05-30 03:04:47 +00001665 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001666 value;
1667
1668 if (image->matte != MagickFalse)
1669 {
cristy4c08aed2011-07-01 19:47:50 +00001670 value=ScaleQuantumToLong(pixel->alpha);
cristy3ed852e2009-09-05 21:47:34 +00001671 pixels=PopLongPixel(MSBEndian,value,pixels);
1672 }
1673 break;
1674 }
1675 case 16:
1676 {
1677 unsigned short
1678 value;
1679
1680 if (image->matte != MagickFalse)
1681 {
cristy4c08aed2011-07-01 19:47:50 +00001682 value=ScaleQuantumToShort(pixel->alpha);
cristy3ed852e2009-09-05 21:47:34 +00001683 pixels=PopShortPixel(MSBEndian,value,pixels);
1684 }
1685 break;
1686 }
1687 case 8:
1688 {
1689 unsigned char
1690 value;
1691
1692 if (image->matte != MagickFalse)
1693 {
cristy4c08aed2011-07-01 19:47:50 +00001694 value=(unsigned char) ScaleQuantumToChar(pixel->alpha);
cristy3ed852e2009-09-05 21:47:34 +00001695 pixels=PopCharPixel(value,pixels);
1696 }
1697 break;
1698 }
1699 default:
1700 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1701 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1702 }
1703 *pixels++=(unsigned char) length;
1704 return(pixels);
1705 }
1706 switch (image->depth)
1707 {
1708 case 32:
1709 {
cristy4cb162a2010-05-30 03:04:47 +00001710 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001711 value;
1712
cristy4c08aed2011-07-01 19:47:50 +00001713 value=ScaleQuantumToLong(pixel->red);
cristy3ed852e2009-09-05 21:47:34 +00001714 pixels=PopLongPixel(MSBEndian,value,pixels);
cristy4c08aed2011-07-01 19:47:50 +00001715 value=ScaleQuantumToLong(pixel->green);
cristy3ed852e2009-09-05 21:47:34 +00001716 pixels=PopLongPixel(MSBEndian,value,pixels);
cristy4c08aed2011-07-01 19:47:50 +00001717 value=ScaleQuantumToLong(pixel->blue);
cristy3ed852e2009-09-05 21:47:34 +00001718 pixels=PopLongPixel(MSBEndian,value,pixels);
cristy3ed852e2009-09-05 21:47:34 +00001719 if (image->colorspace == CMYKColorspace)
1720 {
cristy4c08aed2011-07-01 19:47:50 +00001721 value=ScaleQuantumToLong(pixel->black);
1722 pixels=PopLongPixel(MSBEndian,value,pixels);
1723 }
1724 if (image->matte != MagickFalse)
1725 {
1726 value=ScaleQuantumToLong(pixel->alpha);
cristy3ed852e2009-09-05 21:47:34 +00001727 pixels=PopLongPixel(MSBEndian,value,pixels);
1728 }
1729 break;
1730 }
1731 case 16:
1732 {
1733 unsigned short
1734 value;
1735
cristy4c08aed2011-07-01 19:47:50 +00001736 value=ScaleQuantumToShort(pixel->red);
cristy3ed852e2009-09-05 21:47:34 +00001737 pixels=PopShortPixel(MSBEndian,value,pixels);
cristy4c08aed2011-07-01 19:47:50 +00001738 value=ScaleQuantumToShort(pixel->green);
cristy3ed852e2009-09-05 21:47:34 +00001739 pixels=PopShortPixel(MSBEndian,value,pixels);
cristy4c08aed2011-07-01 19:47:50 +00001740 value=ScaleQuantumToShort(pixel->blue);
cristy3ed852e2009-09-05 21:47:34 +00001741 pixels=PopShortPixel(MSBEndian,value,pixels);
cristy3ed852e2009-09-05 21:47:34 +00001742 if (image->colorspace == CMYKColorspace)
1743 {
cristy4c08aed2011-07-01 19:47:50 +00001744 value=ScaleQuantumToShort(pixel->black);
1745 pixels=PopShortPixel(MSBEndian,value,pixels);
1746 }
1747 if (image->matte != MagickFalse)
1748 {
1749 value=ScaleQuantumToShort(pixel->alpha);
cristy3ed852e2009-09-05 21:47:34 +00001750 pixels=PopShortPixel(MSBEndian,value,pixels);
1751 }
1752 break;
1753 }
1754 case 8:
1755 {
1756 unsigned char
1757 value;
1758
cristy4c08aed2011-07-01 19:47:50 +00001759 value=(unsigned char) ScaleQuantumToChar(pixel->red);
cristy3ed852e2009-09-05 21:47:34 +00001760 pixels=PopCharPixel(value,pixels);
cristy4c08aed2011-07-01 19:47:50 +00001761 value=(unsigned char) ScaleQuantumToChar(pixel->green);
cristy3ed852e2009-09-05 21:47:34 +00001762 pixels=PopCharPixel(value,pixels);
cristy4c08aed2011-07-01 19:47:50 +00001763 value=(unsigned char) ScaleQuantumToChar(pixel->blue);
cristy3ed852e2009-09-05 21:47:34 +00001764 pixels=PopCharPixel(value,pixels);
cristy3ed852e2009-09-05 21:47:34 +00001765 if (image->colorspace == CMYKColorspace)
1766 {
cristy4c08aed2011-07-01 19:47:50 +00001767 value=(unsigned char) ScaleQuantumToChar(pixel->black);
1768 pixels=PopCharPixel(value,pixels);
1769 }
1770 if (image->matte != MagickFalse)
1771 {
1772 value=(unsigned char) ScaleQuantumToChar(pixel->alpha);
cristy3ed852e2009-09-05 21:47:34 +00001773 pixels=PopCharPixel(value,pixels);
1774 }
1775 break;
1776 }
1777 default:
1778 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1779 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1780 }
1781 *pixels++=(unsigned char) length;
1782 return(pixels);
1783}
1784
1785static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
1786 Image *image)
1787{
1788#if defined(MAGICKCORE_BZLIB_DELEGATE)
1789 bz_stream
1790 bzip_info;
1791#endif
1792
1793 char
1794 buffer[MaxTextExtent];
1795
1796 CompressionType
1797 compression;
1798
1799 const char
1800 *property,
1801 *value;
1802
cristy3ed852e2009-09-05 21:47:34 +00001803 int
1804 code;
1805
cristy26377172010-12-20 19:01:58 +00001806#if defined(MAGICKCORE_LZMA_DELEGATE)
cristy4b46dba2010-12-20 19:18:20 +00001807 lzma_allocator
1808 allocator;
1809
cristy26377172010-12-20 19:01:58 +00001810 lzma_stream
cristy330af6c2010-12-21 14:36:06 +00001811 initialize_lzma = LZMA_STREAM_INIT,
1812 lzma_info;
cristy26377172010-12-20 19:01:58 +00001813#endif
cristy3ed852e2009-09-05 21:47:34 +00001814
1815 MagickBooleanType
1816 status;
1817
1818 MagickOffsetType
1819 scene;
1820
cristy4c08aed2011-07-01 19:47:50 +00001821 PixelInfo
1822 pixel,
1823 target;
cristy3ed852e2009-09-05 21:47:34 +00001824
1825 QuantumInfo
1826 *quantum_info;
1827
1828 QuantumType
1829 quantum_type;
1830
cristybb503372010-05-27 20:51:26 +00001831 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001832 i;
1833
1834 size_t
1835 length,
1836 packet_size;
1837
cristy26377172010-12-20 19:01:58 +00001838 ssize_t
1839 y;
1840
cristy3ed852e2009-09-05 21:47:34 +00001841 unsigned char
1842 *compress_pixels,
1843 *pixels,
1844 *q;
1845
1846#if defined(MAGICKCORE_ZLIB_DELEGATE)
1847 z_stream
1848 zip_info;
1849#endif
1850
1851 /*
1852 Open output image file.
1853 */
1854 assert(image_info != (const ImageInfo *) NULL);
1855 assert(image_info->signature == MagickSignature);
1856 assert(image != (Image *) NULL);
1857 assert(image->signature == MagickSignature);
1858 if (image->debug != MagickFalse)
1859 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1860 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1861 if (status == MagickFalse)
1862 return(status);
1863 code=0;
1864 scene=0;
1865 do
1866 {
1867 /*
1868 Allocate image pixels.
1869 */
1870 image->depth=image->depth <= 8 ? 8UL : image->depth <= 16 ? 16UL :
1871 image->depth <= 32 ? 32UL : 64UL;
1872 quantum_info=AcquireQuantumInfo(image_info,image);
1873 if (quantum_info == (QuantumInfo *) NULL)
1874 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1875 if ((image->storage_class != PseudoClass) && (image->depth >= 32) &&
1876 (quantum_info->format == UndefinedQuantumFormat) &&
1877 (IsHighDynamicRangeImage(image,&image->exception) != MagickFalse))
1878 {
1879 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1880 if (status == MagickFalse)
1881 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1882 }
1883 if ((image->storage_class == PseudoClass) &&
cristybb503372010-05-27 20:51:26 +00001884 (image->colors > (size_t) (GetQuantumRange(image->depth)+1)))
cristy574cc262011-08-05 01:23:58 +00001885 (void) SetImageStorageClass(image,DirectClass,&image->exception);
cristy25775c32011-08-19 00:04:07 +00001886 if ((image->colorspace != sRGBColorspace) &&
1887 (IsImageGray(image,&image->exception) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001888 {
cristy63240882011-08-05 19:05:27 +00001889 (void) SetImageStorageClass(image,DirectClass,&image->exception);
1890 (void) SetImageColorspace(image,GRAYColorspace,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00001891 }
1892 compression=image->compression;
1893 if (image_info->compression != UndefinedCompression)
1894 compression=image_info->compression;
1895 switch (compression)
1896 {
1897#if !defined(MAGICKCORE_ZLIB_DELEGATE)
cristy26377172010-12-20 19:01:58 +00001898 case LZMACompression: compression=NoCompression; break;
1899#endif
1900#if !defined(MAGICKCORE_ZLIB_DELEGATE)
cristy3ed852e2009-09-05 21:47:34 +00001901 case LZWCompression:
1902 case ZipCompression: compression=NoCompression; break;
1903#endif
1904#if !defined(MAGICKCORE_BZLIB_DELEGATE)
1905 case BZipCompression: compression=NoCompression; break;
1906#endif
1907 case RLECompression:
1908 {
1909 if (quantum_info->format == FloatingPointQuantumFormat)
1910 compression=NoCompression;
cristy4c08aed2011-07-01 19:47:50 +00001911 GetPixelInfo(image,&target);
cristy3ed852e2009-09-05 21:47:34 +00001912 break;
1913 }
1914 default:
1915 break;
1916 }
1917 packet_size=(size_t) (quantum_info->depth/8);
1918 if (image->storage_class == DirectClass)
1919 packet_size=(size_t) (3*quantum_info->depth/8);
1920 if (image->matte != MagickFalse)
1921 packet_size+=quantum_info->depth/8;
1922 if (image->colorspace == CMYKColorspace)
1923 packet_size+=quantum_info->depth/8;
1924 if (compression == RLECompression)
1925 packet_size++;
1926 length=image->columns;
1927 length=MagickMax(BZipMaxExtent(packet_size*image->columns),ZipMaxExtent(
1928 packet_size*image->columns));
1929 if ((compression == BZipCompression) || (compression == ZipCompression))
1930 if (length != (size_t) ((unsigned int) length))
1931 compression=NoCompression;
1932 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
1933 sizeof(*compress_pixels));
1934 if (compress_pixels == (unsigned char *) NULL)
1935 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1936 /*
1937 Write MIFF header.
1938 */
1939 (void) WriteBlobString(image,"id=ImageMagick version=1.0\n");
cristyb51dff52011-05-19 16:55:47 +00001940 (void) FormatLocaleString(buffer,MaxTextExtent,
cristy042ee782011-04-22 18:48:30 +00001941 "class=%s colors=%.20g matte=%s\n",CommandOptionToMnemonic(
cristye8c25f92010-06-03 00:53:06 +00001942 MagickClassOptions,image->storage_class),(double) image->colors,
cristy042ee782011-04-22 18:48:30 +00001943 CommandOptionToMnemonic(MagickBooleanOptions,(ssize_t) image->matte));
cristy3ed852e2009-09-05 21:47:34 +00001944 (void) WriteBlobString(image,buffer);
cristyb51dff52011-05-19 16:55:47 +00001945 (void) FormatLocaleString(buffer,MaxTextExtent,"columns=%.20g rows=%.20g "
cristye8c25f92010-06-03 00:53:06 +00001946 "depth=%.20g\n",(double) image->columns,(double) image->rows,(double)
1947 image->depth);
cristy3ed852e2009-09-05 21:47:34 +00001948 (void) WriteBlobString(image,buffer);
cristy5f1c1ff2010-12-23 21:38:06 +00001949 if (image->type != UndefinedType)
cristy3ed852e2009-09-05 21:47:34 +00001950 {
cristyb51dff52011-05-19 16:55:47 +00001951 (void) FormatLocaleString(buffer,MaxTextExtent,"type=%s\n",
cristy042ee782011-04-22 18:48:30 +00001952 CommandOptionToMnemonic(MagickTypeOptions,image->type));
cristy3ed852e2009-09-05 21:47:34 +00001953 (void) WriteBlobString(image,buffer);
1954 }
1955 if (image->colorspace != UndefinedColorspace)
1956 {
cristyb51dff52011-05-19 16:55:47 +00001957 (void) FormatLocaleString(buffer,MaxTextExtent,"colorspace=%s\n",
cristy042ee782011-04-22 18:48:30 +00001958 CommandOptionToMnemonic(MagickColorspaceOptions,image->colorspace));
cristy3ed852e2009-09-05 21:47:34 +00001959 (void) WriteBlobString(image,buffer);
1960 }
1961 if (compression != UndefinedCompression)
1962 {
cristyb51dff52011-05-19 16:55:47 +00001963 (void) FormatLocaleString(buffer,MaxTextExtent,"compression=%s "
cristy042ee782011-04-22 18:48:30 +00001964 "quality=%.20g\n",CommandOptionToMnemonic(MagickCompressOptions,
cristye8c25f92010-06-03 00:53:06 +00001965 compression),(double) image->quality);
cristy3ed852e2009-09-05 21:47:34 +00001966 (void) WriteBlobString(image,buffer);
1967 }
1968 if (image->units != UndefinedResolution)
1969 {
cristyb51dff52011-05-19 16:55:47 +00001970 (void) FormatLocaleString(buffer,MaxTextExtent,"units=%s\n",
cristy042ee782011-04-22 18:48:30 +00001971 CommandOptionToMnemonic(MagickResolutionOptions,image->units));
cristy3ed852e2009-09-05 21:47:34 +00001972 (void) WriteBlobString(image,buffer);
1973 }
1974 if ((image->x_resolution != 0) || (image->y_resolution != 0))
1975 {
cristyb51dff52011-05-19 16:55:47 +00001976 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye7f51092010-01-17 00:39:37 +00001977 "resolution=%gx%g\n",image->x_resolution,image->y_resolution);
cristy3ed852e2009-09-05 21:47:34 +00001978 (void) WriteBlobString(image,buffer);
1979 }
1980 if ((image->page.width != 0) || (image->page.height != 0))
1981 {
cristyb51dff52011-05-19 16:55:47 +00001982 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00001983 "page=%.20gx%.20g%+.20g%+.20g\n",(double) image->page.width,(double)
1984 image->page.height,(double) image->page.x,(double) image->page.y);
cristy3ed852e2009-09-05 21:47:34 +00001985 (void) WriteBlobString(image,buffer);
1986 }
1987 else
1988 if ((image->page.x != 0) || (image->page.y != 0))
1989 {
cristyb51dff52011-05-19 16:55:47 +00001990 (void) FormatLocaleString(buffer,MaxTextExtent,"page=%+ld%+ld\n",
cristyf2faecf2010-05-28 19:19:36 +00001991 (long) image->page.x,(long) image->page.y);
cristy3ed852e2009-09-05 21:47:34 +00001992 (void) WriteBlobString(image,buffer);
1993 }
1994 if ((image->tile_offset.x != 0) || (image->tile_offset.y != 0))
1995 {
cristyb51dff52011-05-19 16:55:47 +00001996 (void) FormatLocaleString(buffer,MaxTextExtent,"tile-offset=%+ld%+ld\n",
cristyf2faecf2010-05-28 19:19:36 +00001997 (long) image->tile_offset.x,(long) image->tile_offset.y);
cristy3ed852e2009-09-05 21:47:34 +00001998 (void) WriteBlobString(image,buffer);
1999 }
2000 if ((GetNextImageInList(image) != (Image *) NULL) ||
2001 (GetPreviousImageInList(image) != (Image *) NULL))
2002 {
2003 if (image->scene == 0)
cristyb51dff52011-05-19 16:55:47 +00002004 (void) FormatLocaleString(buffer,MaxTextExtent,"iterations=%.20g "
cristye8c25f92010-06-03 00:53:06 +00002005 "delay=%.20g ticks-per-second=%.20g\n",(double) image->iterations,
2006 (double) image->delay,(double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002007 else
cristyb51dff52011-05-19 16:55:47 +00002008 (void) FormatLocaleString(buffer,MaxTextExtent,"scene=%.20g "
cristye8c25f92010-06-03 00:53:06 +00002009 "iterations=%.20g delay=%.20g ticks-per-second=%.20g\n",(double)
2010 image->scene,(double) image->iterations,(double) image->delay,
2011 (double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002012 (void) WriteBlobString(image,buffer);
2013 }
2014 else
2015 {
2016 if (image->scene != 0)
2017 {
cristyb51dff52011-05-19 16:55:47 +00002018 (void) FormatLocaleString(buffer,MaxTextExtent,"scene=%.20g\n",
cristye8c25f92010-06-03 00:53:06 +00002019 (double) image->scene);
cristy3ed852e2009-09-05 21:47:34 +00002020 (void) WriteBlobString(image,buffer);
2021 }
2022 if (image->iterations != 0)
2023 {
cristyb51dff52011-05-19 16:55:47 +00002024 (void) FormatLocaleString(buffer,MaxTextExtent,"iterations=%.20g\n",
cristye8c25f92010-06-03 00:53:06 +00002025 (double) image->iterations);
cristy3ed852e2009-09-05 21:47:34 +00002026 (void) WriteBlobString(image,buffer);
2027 }
2028 if (image->delay != 0)
2029 {
cristyb51dff52011-05-19 16:55:47 +00002030 (void) FormatLocaleString(buffer,MaxTextExtent,"delay=%.20g\n",
cristye8c25f92010-06-03 00:53:06 +00002031 (double) image->delay);
cristy3ed852e2009-09-05 21:47:34 +00002032 (void) WriteBlobString(image,buffer);
2033 }
2034 if (image->ticks_per_second != UndefinedTicksPerSecond)
2035 {
cristyb51dff52011-05-19 16:55:47 +00002036 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00002037 "ticks-per-second=%.20g\n",(double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002038 (void) WriteBlobString(image,buffer);
2039 }
2040 }
2041 if (image->gravity != UndefinedGravity)
2042 {
cristyb51dff52011-05-19 16:55:47 +00002043 (void) FormatLocaleString(buffer,MaxTextExtent,"gravity=%s\n",
cristy042ee782011-04-22 18:48:30 +00002044 CommandOptionToMnemonic(MagickGravityOptions,image->gravity));
cristy3ed852e2009-09-05 21:47:34 +00002045 (void) WriteBlobString(image,buffer);
2046 }
2047 if (image->dispose != UndefinedDispose)
2048 {
cristyb51dff52011-05-19 16:55:47 +00002049 (void) FormatLocaleString(buffer,MaxTextExtent,"dispose=%s\n",
cristy042ee782011-04-22 18:48:30 +00002050 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
cristy3ed852e2009-09-05 21:47:34 +00002051 (void) WriteBlobString(image,buffer);
2052 }
2053 if (image->rendering_intent != UndefinedIntent)
2054 {
cristyb51dff52011-05-19 16:55:47 +00002055 (void) FormatLocaleString(buffer,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00002056 "rendering-intent=%s\n",
cristy042ee782011-04-22 18:48:30 +00002057 CommandOptionToMnemonic(MagickIntentOptions,image->rendering_intent));
cristy3ed852e2009-09-05 21:47:34 +00002058 (void) WriteBlobString(image,buffer);
2059 }
2060 if (image->gamma != 0.0)
2061 {
cristyb51dff52011-05-19 16:55:47 +00002062 (void) FormatLocaleString(buffer,MaxTextExtent,"gamma=%g\n",
cristy3ed852e2009-09-05 21:47:34 +00002063 image->gamma);
2064 (void) WriteBlobString(image,buffer);
2065 }
2066 if (image->chromaticity.white_point.x != 0.0)
2067 {
2068 /*
2069 Note chomaticity points.
2070 */
cristyb51dff52011-05-19 16:55:47 +00002071 (void) FormatLocaleString(buffer,MaxTextExtent,"red-primary=%g,"
cristye7f51092010-01-17 00:39:37 +00002072 "%g green-primary=%g,%g blue-primary=%g,%g\n",
cristy3ed852e2009-09-05 21:47:34 +00002073 image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
2074 image->chromaticity.green_primary.x,
2075 image->chromaticity.green_primary.y,
2076 image->chromaticity.blue_primary.x,
2077 image->chromaticity.blue_primary.y);
2078 (void) WriteBlobString(image,buffer);
cristyb51dff52011-05-19 16:55:47 +00002079 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye7f51092010-01-17 00:39:37 +00002080 "white-point=%g,%g\n",image->chromaticity.white_point.x,
cristy8cd5b312010-01-07 01:10:24 +00002081 image->chromaticity.white_point.y);
cristy3ed852e2009-09-05 21:47:34 +00002082 (void) WriteBlobString(image,buffer);
2083 }
2084 if (image->orientation != UndefinedOrientation)
2085 {
cristyb51dff52011-05-19 16:55:47 +00002086 (void) FormatLocaleString(buffer,MaxTextExtent,"orientation=%s\n",
cristy042ee782011-04-22 18:48:30 +00002087 CommandOptionToMnemonic(MagickOrientationOptions,image->orientation));
cristy3ed852e2009-09-05 21:47:34 +00002088 (void) WriteBlobString(image,buffer);
2089 }
2090 if (image->profiles != (void *) NULL)
2091 {
2092 const char
2093 *name;
2094
2095 const StringInfo
2096 *profile;
2097
2098 /*
2099 Write image profiles.
2100 */
2101 ResetImageProfileIterator(image);
2102 name=GetNextImageProfile(image);
2103 while (name != (const char *) NULL)
2104 {
2105 profile=GetImageProfile(image,name);
2106 if (profile != (StringInfo *) NULL)
2107 {
cristyb51dff52011-05-19 16:55:47 +00002108 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00002109 "profile:%s=%.20g\n",name,(double)
2110 GetStringInfoLength(profile));
cristy3ed852e2009-09-05 21:47:34 +00002111 (void) WriteBlobString(image,buffer);
2112 }
2113 name=GetNextImageProfile(image);
2114 }
2115 }
2116 if (image->montage != (char *) NULL)
2117 {
cristyb51dff52011-05-19 16:55:47 +00002118 (void) FormatLocaleString(buffer,MaxTextExtent,"montage=%s\n",
cristy3ed852e2009-09-05 21:47:34 +00002119 image->montage);
2120 (void) WriteBlobString(image,buffer);
2121 }
2122 if (quantum_info->format == FloatingPointQuantumFormat)
cristy0c2fcca2009-10-16 01:37:20 +00002123 (void) SetImageProperty(image,"quantum:format","floating-point");
cristy3ed852e2009-09-05 21:47:34 +00002124 ResetImagePropertyIterator(image);
2125 property=GetNextImageProperty(image);
2126 while (property != (const char *) NULL)
2127 {
cristyb51dff52011-05-19 16:55:47 +00002128 (void) FormatLocaleString(buffer,MaxTextExtent,"%s=",property);
cristy3ed852e2009-09-05 21:47:34 +00002129 (void) WriteBlobString(image,buffer);
2130 value=GetImageProperty(image,property);
2131 if (value != (const char *) NULL)
2132 {
cristybb503372010-05-27 20:51:26 +00002133 for (i=0; i < (ssize_t) strlen(value); i++)
cristy3ed852e2009-09-05 21:47:34 +00002134 if (isspace((int) ((unsigned char) value[i])) != 0)
2135 break;
cristybb503372010-05-27 20:51:26 +00002136 if (i <= (ssize_t) strlen(value))
cristy3ed852e2009-09-05 21:47:34 +00002137 (void) WriteBlobByte(image,'{');
2138 (void) WriteBlob(image,strlen(value),(const unsigned char *) value);
cristybb503372010-05-27 20:51:26 +00002139 if (i <= (ssize_t) strlen(value))
cristy3ed852e2009-09-05 21:47:34 +00002140 (void) WriteBlobByte(image,'}');
2141 }
2142 (void) WriteBlobByte(image,'\n');
2143 property=GetNextImageProperty(image);
2144 }
2145 (void) WriteBlobString(image,"\f\n:\032");
2146 if (image->montage != (char *) NULL)
2147 {
2148 /*
2149 Write montage tile directory.
2150 */
2151 if (image->directory != (char *) NULL)
2152 (void) WriteBlob(image,strlen(image->directory),(unsigned char *)
2153 image->directory);
2154 (void) WriteBlobByte(image,'\0');
2155 }
2156 if (image->profiles != (void *) NULL)
2157 {
2158 const char
2159 *name;
2160
2161 const StringInfo
2162 *profile;
2163
2164 /*
2165 Generic profile.
2166 */
2167 ResetImageProfileIterator(image);
2168 name=GetNextImageProfile(image);
2169 while (name != (const char *) NULL)
2170 {
2171 profile=GetImageProfile(image,name);
2172 (void) WriteBlob(image,GetStringInfoLength(profile),
2173 GetStringInfoDatum(profile));
2174 name=GetNextImageProfile(image);
2175 }
2176 }
2177 if (image->storage_class == PseudoClass)
2178 {
2179 size_t
2180 packet_size;
2181
2182 unsigned char
2183 *colormap,
2184 *q;
2185
2186 /*
2187 Allocate colormap.
2188 */
2189 packet_size=(size_t) (3*quantum_info->depth/8);
2190 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
2191 packet_size*sizeof(*colormap));
2192 if (colormap == (unsigned char *) NULL)
2193 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2194 /*
2195 Write colormap to file.
2196 */
2197 q=colormap;
cristybb503372010-05-27 20:51:26 +00002198 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00002199 {
2200 switch (quantum_info->depth)
2201 {
2202 default:
2203 ThrowWriterException(CorruptImageError,"ImageDepthNotSupported");
2204 case 32:
2205 {
cristy4cb162a2010-05-30 03:04:47 +00002206 register unsigned int
cristy3ed852e2009-09-05 21:47:34 +00002207 pixel;
2208
2209 pixel=ScaleQuantumToLong(image->colormap[i].red);
2210 q=PopLongPixel(MSBEndian,pixel,q);
2211 pixel=ScaleQuantumToLong(image->colormap[i].green);
2212 q=PopLongPixel(MSBEndian,pixel,q);
2213 pixel=ScaleQuantumToLong(image->colormap[i].blue);
2214 q=PopLongPixel(MSBEndian,pixel,q);
2215 break;
2216 }
2217 case 16:
2218 {
2219 register unsigned short
2220 pixel;
2221
2222 pixel=ScaleQuantumToShort(image->colormap[i].red);
2223 q=PopShortPixel(MSBEndian,pixel,q);
2224 pixel=ScaleQuantumToShort(image->colormap[i].green);
2225 q=PopShortPixel(MSBEndian,pixel,q);
2226 pixel=ScaleQuantumToShort(image->colormap[i].blue);
2227 q=PopShortPixel(MSBEndian,pixel,q);
2228 break;
2229 }
2230 case 8:
2231 {
2232 register unsigned char
2233 pixel;
2234
2235 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].red);
2236 q=PopCharPixel(pixel,q);
2237 pixel=(unsigned char) ScaleQuantumToChar(
2238 image->colormap[i].green);
2239 q=PopCharPixel(pixel,q);
2240 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].blue);
2241 q=PopCharPixel(pixel,q);
2242 break;
2243 }
2244 }
2245 }
2246 (void) WriteBlob(image,packet_size*image->colors,colormap);
2247 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
2248 }
2249 /*
2250 Write image pixels to file.
2251 */
cristy330af6c2010-12-21 14:36:06 +00002252 status=MagickTrue;
2253 switch (compression)
2254 {
2255#if defined(MAGICKCORE_BZLIB_DELEGATE)
2256 case BZipCompression:
2257 {
2258 (void) ResetMagickMemory(&bzip_info,0,sizeof(bzip_info));
2259 bzip_info.bzalloc=AcquireBZIPMemory;
2260 bzip_info.bzfree=RelinquishBZIPMemory;
2261 code=BZ2_bzCompressInit(&bzip_info,(int) (image->quality ==
2262 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,
2263 9)),(int) image_info->verbose,0);
2264 if (code != BZ_OK)
2265 status=MagickFalse;
2266 break;
2267 }
2268#endif
2269#if defined(MAGICKCORE_LZMA_DELEGATE)
2270 case LZMACompression:
2271 {
cristy330af6c2010-12-21 14:36:06 +00002272 (void) ResetMagickMemory(&allocator,0,sizeof(allocator));
2273 allocator.alloc=AcquireLZMAMemory;
2274 allocator.free=RelinquishLZMAMemory;
cristy9d72f1a2010-12-21 20:46:59 +00002275 lzma_info=initialize_lzma;
cristy330af6c2010-12-21 14:36:06 +00002276 lzma_info.allocator=&allocator;
cristy9d72f1a2010-12-21 20:46:59 +00002277 code=lzma_easy_encoder(&lzma_info,image->quality/10,LZMA_CHECK_SHA256);
2278 if (code != LZMA_OK)
2279 status=MagickTrue;
cristy330af6c2010-12-21 14:36:06 +00002280 break;
2281 }
2282#endif
2283#if defined(MAGICKCORE_ZLIB_DELEGATE)
2284 case LZWCompression:
2285 case ZipCompression:
2286 {
2287 (void) ResetMagickMemory(&zip_info,0,sizeof(zip_info));
2288 zip_info.zalloc=AcquireZIPMemory;
2289 zip_info.zfree=RelinquishZIPMemory;
2290 code=deflateInit(&zip_info,(int) (image->quality ==
2291 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9)));
2292 if (code != Z_OK)
2293 status=MagickFalse;
2294 break;
2295 }
2296#endif
2297 default:
2298 break;
2299 }
cristy3ed852e2009-09-05 21:47:34 +00002300 quantum_type=GetQuantumType(image,&image->exception);
2301 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002302 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002303 {
cristy4c08aed2011-07-01 19:47:50 +00002304 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00002305 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002306
cristybb503372010-05-27 20:51:26 +00002307 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002308 x;
2309
cristy330af6c2010-12-21 14:36:06 +00002310 if (status == MagickFalse)
2311 break;
cristy3ed852e2009-09-05 21:47:34 +00002312 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
cristy4c08aed2011-07-01 19:47:50 +00002313 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002314 break;
cristy3ed852e2009-09-05 21:47:34 +00002315 q=pixels;
2316 switch (compression)
2317 {
cristy3ed852e2009-09-05 21:47:34 +00002318#if defined(MAGICKCORE_BZLIB_DELEGATE)
2319 case BZipCompression:
2320 {
cristy3ed852e2009-09-05 21:47:34 +00002321 bzip_info.next_in=(char *) pixels;
2322 bzip_info.avail_in=(unsigned int) (packet_size*image->columns);
cristy4c08aed2011-07-01 19:47:50 +00002323 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2324 quantum_type,pixels,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002325 do
2326 {
2327 bzip_info.next_out=(char *) compress_pixels;
2328 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2329 image->columns);
2330 code=BZ2_bzCompress(&bzip_info,BZ_FLUSH);
cristy26377172010-12-20 19:01:58 +00002331 if (code != BZ_OK)
2332 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00002333 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2334 if (length != 0)
2335 {
2336 (void) WriteBlobMSBLong(image,(unsigned int) length);
2337 (void) WriteBlob(image,length,compress_pixels);
2338 }
2339 } while (bzip_info.avail_in != 0);
cristy26377172010-12-20 19:01:58 +00002340 break;
2341 }
2342#endif
2343#if defined(MAGICKCORE_LZMA_DELEGATE)
2344 case LZMACompression:
2345 {
cristy26377172010-12-20 19:01:58 +00002346 lzma_info.next_in=pixels;
cristy330af6c2010-12-21 14:36:06 +00002347 lzma_info.avail_in=packet_size*image->columns;
cristy4c08aed2011-07-01 19:47:50 +00002348 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2349 quantum_type,pixels,&image->exception);
cristy26377172010-12-20 19:01:58 +00002350 do
2351 {
2352 lzma_info.next_out=compress_pixels;
2353 lzma_info.avail_out=packet_size*image->columns;
2354 code=lzma_code(&lzma_info,LZMA_RUN);
2355 if (code != LZMA_OK)
2356 status=MagickFalse;
2357 length=(size_t) (lzma_info.next_out-compress_pixels);
2358 if (length != 0)
2359 {
2360 (void) WriteBlobMSBLong(image,(unsigned int) length);
2361 (void) WriteBlob(image,length,compress_pixels);
2362 }
2363 } while (lzma_info.avail_in != 0);
cristy26377172010-12-20 19:01:58 +00002364 break;
2365 }
2366#endif
2367#if defined(MAGICKCORE_ZLIB_DELEGATE)
2368 case LZWCompression:
2369 case ZipCompression:
2370 {
cristy26377172010-12-20 19:01:58 +00002371 zip_info.next_in=pixels;
2372 zip_info.avail_in=(uInt) (packet_size*image->columns);
cristy4c08aed2011-07-01 19:47:50 +00002373 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2374 quantum_type,pixels,&image->exception);
cristy26377172010-12-20 19:01:58 +00002375 do
2376 {
2377 zip_info.next_out=compress_pixels;
2378 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns);
2379 code=deflate(&zip_info,Z_SYNC_FLUSH);
2380 if (code != Z_OK)
2381 status=MagickFalse;
2382 length=(size_t) (zip_info.next_out-compress_pixels);
2383 if (length != 0)
2384 {
2385 (void) WriteBlobMSBLong(image,(unsigned int) length);
2386 (void) WriteBlob(image,length,compress_pixels);
2387 }
2388 } while (zip_info.avail_in != 0);
cristy3ed852e2009-09-05 21:47:34 +00002389 break;
2390 }
2391#endif
2392 case RLECompression:
2393 {
cristy4c08aed2011-07-01 19:47:50 +00002394 length=0;
2395 SetPixelInfo(image,p,&pixel);
cristyed231572011-07-14 02:18:59 +00002396 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00002397 for (x=1; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002398 {
cristy4c08aed2011-07-01 19:47:50 +00002399 SetPixelInfo(image,p,&target);
2400 if ((length < 255) &&
2401 (IsPixelInfoEquivalent(&pixel,&target) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00002402 length++;
2403 else
2404 {
cristy4c08aed2011-07-01 19:47:50 +00002405 q=PopRunlengthPacket(image,q,length,&pixel);
cristy3ed852e2009-09-05 21:47:34 +00002406 length=0;
2407 }
cristy4c08aed2011-07-01 19:47:50 +00002408 SetPixelInfo(image,p,&pixel);
cristyed231572011-07-14 02:18:59 +00002409 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002410 }
cristy4c08aed2011-07-01 19:47:50 +00002411 q=PopRunlengthPacket(image,q,length,&pixel);
cristy3ed852e2009-09-05 21:47:34 +00002412 (void) WriteBlob(image,(size_t) (q-pixels),pixels);
2413 break;
2414 }
2415 default:
2416 {
cristy4c08aed2011-07-01 19:47:50 +00002417 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2418 quantum_type,pixels,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002419 (void) WriteBlob(image,packet_size*image->columns,pixels);
2420 break;
2421 }
2422 }
cristycee97112010-05-28 00:44:52 +00002423 if (image->previous == (Image *) NULL)
2424 {
2425 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2426 image->rows);
2427 if (status == MagickFalse)
2428 break;
2429 }
cristy3ed852e2009-09-05 21:47:34 +00002430 }
cristy330af6c2010-12-21 14:36:06 +00002431 switch (compression)
2432 {
2433#if defined(MAGICKCORE_BZLIB_DELEGATE)
2434 case BZipCompression:
2435 {
2436 for ( ; ; )
2437 {
2438 if (status == MagickFalse)
2439 break;
2440 bzip_info.next_out=(char *) compress_pixels;
2441 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2442 image->columns);
2443 code=BZ2_bzCompress(&bzip_info,BZ_FINISH);
cristy330af6c2010-12-21 14:36:06 +00002444 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2445 if (length != 0)
2446 {
2447 (void) WriteBlobMSBLong(image,(unsigned int) length);
2448 (void) WriteBlob(image,length,compress_pixels);
2449 }
2450 if (code == BZ_STREAM_END)
2451 break;
2452 }
2453 code=BZ2_bzCompressEnd(&bzip_info);
2454 if (code != BZ_OK)
2455 status=MagickFalse;
2456 break;
2457 }
2458#endif
2459#if defined(MAGICKCORE_LZMA_DELEGATE)
2460 case LZMACompression:
2461 {
2462 for ( ; ; )
2463 {
2464 if (status == MagickFalse)
2465 break;
2466 lzma_info.next_out=compress_pixels;
2467 lzma_info.avail_out=packet_size*image->columns;
2468 code=lzma_code(&lzma_info,LZMA_FINISH);
cristy330af6c2010-12-21 14:36:06 +00002469 length=(size_t) (lzma_info.next_out-compress_pixels);
2470 if (length > 6)
2471 {
2472 (void) WriteBlobMSBLong(image,(unsigned int) length);
2473 (void) WriteBlob(image,length,compress_pixels);
2474 }
2475 if (code == LZMA_STREAM_END)
2476 break;
2477 }
2478 lzma_end(&lzma_info);
2479 break;
2480 }
2481#endif
2482#if defined(MAGICKCORE_ZLIB_DELEGATE)
2483 case LZWCompression:
2484 case ZipCompression:
2485 {
2486 for ( ; ; )
2487 {
2488 if (status == MagickFalse)
2489 break;
2490 zip_info.next_out=compress_pixels;
2491 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*
2492 image->columns);
2493 code=deflate(&zip_info,Z_FINISH);
cristy330af6c2010-12-21 14:36:06 +00002494 length=(size_t) (zip_info.next_out-compress_pixels);
2495 if (length > 6)
2496 {
2497 (void) WriteBlobMSBLong(image,(unsigned int) length);
2498 (void) WriteBlob(image,length,compress_pixels);
2499 }
2500 if (code == Z_STREAM_END)
2501 break;
2502 }
2503 code=deflateEnd(&zip_info);
2504 if (code != Z_OK)
2505 status=MagickFalse;
2506 break;
2507 }
2508#endif
2509 default:
2510 break;
2511 }
cristy3ed852e2009-09-05 21:47:34 +00002512 quantum_info=DestroyQuantumInfo(quantum_info);
2513 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
2514 if (GetNextImageInList(image) == (Image *) NULL)
2515 break;
2516 image=SyncNextImageInList(image);
2517 status=SetImageProgress(image,SaveImagesTag,scene++,
2518 GetImageListLength(image));
2519 if (status == MagickFalse)
2520 break;
2521 } while (image_info->adjoin != MagickFalse);
2522 (void) CloseBlob(image);
2523 return(status);
2524}