blob: 12976b64f137354de1aadf72cea59db7ab87ae4c [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*/
42#include "magick/studio.h"
cristy5a2ca482009-10-14 18:24:56 +000043#include "magick/attribute.h"
cristy3ed852e2009-09-05 21:47:34 +000044#include "magick/blob.h"
45#include "magick/blob-private.h"
46#include "magick/cache.h"
47#include "magick/color.h"
cristy3ed852e2009-09-05 21:47:34 +000048#include "magick/color-private.h"
cristye7e40552010-04-24 21:34:22 +000049#include "magick/colormap.h"
50#include "magick/colormap-private.h"
cristy3ed852e2009-09-05 21:47:34 +000051#include "magick/colorspace.h"
52#include "magick/constitute.h"
53#include "magick/exception.h"
54#include "magick/exception-private.h"
55#include "magick/hashmap.h"
56#include "magick/geometry.h"
57#include "magick/image.h"
58#include "magick/image-private.h"
59#include "magick/list.h"
60#include "magick/magick.h"
61#include "magick/memory_.h"
cristyf2f27272009-12-17 14:48:46 +000062#include "magick/module.h"
cristy3ed852e2009-09-05 21:47:34 +000063#include "magick/monitor.h"
64#include "magick/monitor-private.h"
65#include "magick/option.h"
66#include "magick/pixel.h"
67#include "magick/profile.h"
68#include "magick/property.h"
69#include "magick/quantum-private.h"
70#include "magick/static.h"
71#include "magick/statistic.h"
72#include "magick/string_.h"
cristyf2f27272009-12-17 14:48:46 +000073#include "magick/string-private.h"
cristy3ed852e2009-09-05 21:47:34 +000074#if defined(MAGICKCORE_BZLIB_DELEGATE)
75#include "bzlib.h"
76#endif
cristy26377172010-12-20 19:01:58 +000077#if defined(MAGICKCORE_LZMA_DELEGATE)
78#include "lzma.h"
79#endif
80#if defined(MAGICKCORE_ZLIB_DELEGATE)
81#include "zlib.h"
82#endif
cristy3ed852e2009-09-05 21:47:34 +000083
84/*
cristya7a341e2010-12-22 20:28:51 +000085 Define declarations.
86*/
87#if !defined(LZMA_OK)
88#define LZMA_OK 0
89#endif
90
91/*
cristy3ed852e2009-09-05 21:47:34 +000092 Forward declarations.
93*/
94static MagickBooleanType
95 WriteMIFFImage(const ImageInfo *,Image *);
96
97/*
98%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
99% %
100% %
101% %
102% I s M I F F %
103% %
104% %
105% %
106%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
107%
108% IsMIFF() returns MagickTrue if the image format type, identified by the
109% magick string, is MIFF.
110%
111% The format of the IsMIFF method is:
112%
113% MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
114%
115% A description of each parameter follows:
116%
117% o magick: compare image format pattern against these bytes.
118%
119% o length: Specifies the length of the magick string.
120%
121*/
122static MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
123{
124 if (length < 14)
125 return(MagickFalse);
126 if (LocaleNCompare((const char *) magick,"id=ImageMagick",14) == 0)
127 return(MagickTrue);
128 return(MagickFalse);
129}
130
131/*
132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133% %
134% %
135% %
136% R e a d M I F F I m a g e %
137% %
138% %
139% %
140%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141%
142% ReadMIFFImage() reads a MIFF image file and returns it. It allocates the
143% memory necessary for the new Image structure and returns a pointer to the
144% new image.
145%
146% The format of the ReadMIFFImage method is:
147%
148% Image *ReadMIFFImage(const ImageInfo *image_info,
149% ExceptionInfo *exception)
150%
151% Decompression code contributed by Kyle Shorter.
152%
153% A description of each parameter follows:
154%
155% o image_info: the image info.
156%
157% o exception: return any errors or warnings in this structure.
158%
159*/
160
161#if defined(MAGICKCORE_BZLIB_DELEGATE)
162static void *AcquireBZIPMemory(void *context,int items,int size)
163{
164 (void) context;
165 return((void *) AcquireQuantumMemory((size_t) items,(size_t) size));
166}
167#endif
168
cristy4b46dba2010-12-20 19:18:20 +0000169#if defined(MAGICKCORE_LZMA_DELEGATE)
170static void *AcquireLZMAMemory(void *context,size_t items,size_t size)
171{
172 (void) context;
173 return((void *) AcquireQuantumMemory((size_t) items,(size_t) size));
174}
175#endif
176
cristy3ed852e2009-09-05 21:47:34 +0000177#if defined(MAGICKCORE_ZLIB_DELEGATE)
178static voidpf AcquireZIPMemory(voidpf context,unsigned int items,
179 unsigned int size)
180{
181 (void) context;
182 return((voidpf) AcquireQuantumMemory(items,size));
183}
184#endif
185
186static inline size_t MagickMax(const size_t x,const size_t y)
187{
188 if (x > y)
189 return(x);
190 return(y);
191}
192
193static inline size_t MagickMin(const size_t x,const size_t y)
194{
195 if (x < y)
196 return(x);
197 return(y);
198}
199
200static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
201 size_t *length,PixelPacket *pixel,IndexPacket *index)
202{
203 const unsigned char
204 *p;
205
206 p=pixels;
207 if (image->storage_class == PseudoClass)
208 {
209 *index=(IndexPacket) 0;
210 switch (image->depth)
211 {
212 case 32:
213 {
214 *index=ConstrainColormapIndex(image,
215 (*p << 24) | (*(p+1) << 16) | (*(p+2) << 8) | *(p+3));
216 p+=4;
217 break;
218 }
219 case 16:
220 {
221 *index=ConstrainColormapIndex(image,(*p << 8) | *(p+1));
222 p+=2;
223 break;
224 }
225 case 8:
226 {
227 *index=ConstrainColormapIndex(image,*p);
228 p++;
229 break;
230 }
231 default:
232 (void) ThrowMagickException(&image->exception,GetMagickModule(),
233 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
234 }
cristybb503372010-05-27 20:51:26 +0000235 *pixel=image->colormap[(ssize_t) *index];
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);
246 pixel->opacity=ScaleCharToQuantum(quantum);
247 }
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);
258 pixel->opacity=(Quantum) (quantum >> (image->depth-
259 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);
271 pixel->opacity=(Quantum) (quantum >> (image->depth-
272 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);
291 pixel->red=ScaleCharToQuantum(quantum);
292 p=PushCharPixel(p,&quantum);
293 pixel->green=ScaleCharToQuantum(quantum);
294 p=PushCharPixel(p,&quantum);
295 pixel->blue=ScaleCharToQuantum(quantum);
296 if (image->matte != MagickFalse)
297 {
298 p=PushCharPixel(p,&quantum);
299 pixel->opacity=ScaleCharToQuantum(quantum);
300 }
301 if (image->colorspace == CMYKColorspace)
302 {
303 p=PushCharPixel(p,&quantum);
304 *index=ScaleCharToQuantum(quantum);
305 }
306 break;
307 }
308 case 16:
309 {
310 unsigned short
311 quantum;
312
313 p=PushShortPixel(MSBEndian,p,&quantum);
314 pixel->red=(Quantum) (quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH));
315 p=PushShortPixel(MSBEndian,p,&quantum);
316 pixel->green=(Quantum) (quantum >> (image->depth-
317 MAGICKCORE_QUANTUM_DEPTH));
318 p=PushShortPixel(MSBEndian,p,&quantum);
319 pixel->blue=(Quantum) (quantum >> (image->depth-
320 MAGICKCORE_QUANTUM_DEPTH));
321 if (image->matte != MagickFalse)
322 {
323 p=PushShortPixel(MSBEndian,p,&quantum);
324 pixel->opacity=(Quantum) (quantum >> (image->depth-
325 MAGICKCORE_QUANTUM_DEPTH));
326 }
327 if (image->colorspace == CMYKColorspace)
328 {
329 p=PushShortPixel(MSBEndian,p,&quantum);
330 *index=(IndexPacket) (quantum >> (image->depth-
331 MAGICKCORE_QUANTUM_DEPTH));
332 }
333 break;
334 }
335 case 32:
336 {
cristy4cb162a2010-05-30 03:04:47 +0000337 unsigned int
cristy3ed852e2009-09-05 21:47:34 +0000338 quantum;
339
340 p=PushLongPixel(MSBEndian,p,&quantum);
341 pixel->red=(Quantum) (quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH));
342 p=PushLongPixel(MSBEndian,p,&quantum);
343 pixel->green=(Quantum) (quantum >> (image->depth-
344 MAGICKCORE_QUANTUM_DEPTH));
345 p=PushLongPixel(MSBEndian,p,&quantum);
346 pixel->blue=(Quantum) (quantum >> (image->depth-
347 MAGICKCORE_QUANTUM_DEPTH));
348 if (image->matte != MagickFalse)
349 {
350 p=PushLongPixel(MSBEndian,p,&quantum);
351 pixel->opacity=(Quantum) (quantum >> (image->depth-
352 MAGICKCORE_QUANTUM_DEPTH));
353 }
354 if (image->colorspace == CMYKColorspace)
355 {
356 p=PushLongPixel(MSBEndian,p,&quantum);
357 *index=(IndexPacket) (quantum >> (image->depth-
358 MAGICKCORE_QUANTUM_DEPTH));
359 }
360 break;
361 }
362 default:
363 (void) ThrowMagickException(&image->exception,GetMagickModule(),
364 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
365 }
366 *length=(size_t) (*p++)+1;
367}
368
cristy4b46dba2010-12-20 19:18:20 +0000369#if defined(MAGICKCORE_BZLIB_DELEGATE)
370static void RelinquishBZIPMemory(void *context,void *memory)
cristy3ed852e2009-09-05 21:47:34 +0000371{
372 (void) context;
373 memory=RelinquishMagickMemory(memory);
374}
375#endif
376
cristy4b46dba2010-12-20 19:18:20 +0000377#if defined(MAGICKCORE_LZMA_DELEGATE)
378static void RelinquishLZMAMemory(void *context,void *memory)
379{
380 (void) context;
381 memory=RelinquishMagickMemory(memory);
382}
383#endif
384
385#if defined(MAGICKCORE_ZLIB_DELEGATE)
386static void RelinquishZIPMemory(voidpf context,voidpf memory)
cristy3ed852e2009-09-05 21:47:34 +0000387{
388 (void) context;
389 memory=RelinquishMagickMemory(memory);
390}
391#endif
392
393static Image *ReadMIFFImage(const ImageInfo *image_info,
394 ExceptionInfo *exception)
395{
396#define BZipMaxExtent(x) ((x)+((x)/100)+600)
cristy26377172010-12-20 19:01:58 +0000397#define LZMAMaxExtent(x) ((x)+((x)/3)+128)
cristy3ed852e2009-09-05 21:47:34 +0000398#define ZipMaxExtent(x) ((x)+(((x)+7) >> 3)+(((x)+63) >> 6)+11)
399
400#if defined(MAGICKCORE_BZLIB_DELEGATE)
401 bz_stream
402 bzip_info;
403#endif
404
405 char
406 id[MaxTextExtent],
407 keyword[MaxTextExtent],
408 *options;
409
410 const unsigned char
411 *p;
412
413 double
414 version;
415
416 GeometryInfo
417 geometry_info;
418
419 Image
420 *image;
421
422 IndexPacket
423 index;
424
425 int
426 c,
427 code;
428
cristy26377172010-12-20 19:01:58 +0000429#if defined(MAGICKCORE_LZMA_DELEGATE)
430 lzma_stream
cristy330af6c2010-12-21 14:36:06 +0000431 initialize_lzma = LZMA_STREAM_INIT,
432 lzma_info;
cristy4b46dba2010-12-20 19:18:20 +0000433
434 lzma_allocator
435 allocator;
cristy26377172010-12-20 19:01:58 +0000436#endif
437
cristy3ed852e2009-09-05 21:47:34 +0000438 LinkedListInfo
439 *profiles;
440
cristy3ed852e2009-09-05 21:47:34 +0000441 MagickBooleanType
442 status;
443
444 MagickStatusType
445 flags;
446
447 PixelPacket
448 pixel;
449
450 QuantumFormatType
451 quantum_format;
452
453 QuantumInfo
454 *quantum_info;
455
456 QuantumType
457 quantum_type;
458
cristybb503372010-05-27 20:51:26 +0000459 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000460 i;
461
462 size_t
463 length,
464 packet_size;
465
466 ssize_t
467 count;
468
469 unsigned char
470 *compress_pixels,
471 *pixels;
472
cristybb503372010-05-27 20:51:26 +0000473 size_t
cristy3ed852e2009-09-05 21:47:34 +0000474 colors;
475
cristy26377172010-12-20 19:01:58 +0000476 ssize_t
477 y;
478
cristy3ed852e2009-09-05 21:47:34 +0000479#if defined(MAGICKCORE_ZLIB_DELEGATE)
480 z_stream
481 zip_info;
482#endif
483
484 /*
485 Open image file.
486 */
487 assert(image_info != (const ImageInfo *) NULL);
488 assert(image_info->signature == MagickSignature);
489 if (image_info->debug != MagickFalse)
490 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
491 image_info->filename);
492 assert(exception != (ExceptionInfo *) NULL);
493 assert(exception->signature == MagickSignature);
494 image=AcquireImage(image_info);
495 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
496 if (status == MagickFalse)
497 {
498 image=DestroyImageList(image);
499 return((Image *) NULL);
500 }
501 /*
502 Decode image header; header terminates one character beyond a ':'.
503 */
504 c=ReadBlobByte(image);
505 if (c == EOF)
506 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
507 code=0;
508 *id='\0';
509 (void) ResetMagickMemory(keyword,0,sizeof(keyword));
510 version=0.0;
511 do
512 {
513 /*
514 Decode image header; header terminates one character beyond a ':'.
515 */
516 length=MaxTextExtent;
517 options=AcquireString((char *) NULL);
518 quantum_format=UndefinedQuantumFormat;
519 profiles=(LinkedListInfo *) NULL;
520 colors=0;
521 image->depth=8UL;
522 image->compression=NoCompression;
523 while ((isgraph(c) != MagickFalse) && (c != (int) ':'))
524 {
525 register char
526 *p;
527
528 if (c == (int) '{')
529 {
530 char
531 *comment;
532
533 /*
534 Read comment-- any text between { }.
535 */
536 length=MaxTextExtent;
537 comment=AcquireString((char *) NULL);
538 for (p=comment; comment != (char *) NULL; p++)
539 {
540 c=ReadBlobByte(image);
541 if ((c == EOF) || (c == (int) '}'))
542 break;
543 if ((size_t) (p-comment+1) >= length)
544 {
545 *p='\0';
546 length<<=1;
547 comment=(char *) ResizeQuantumMemory(comment,length+
548 MaxTextExtent,sizeof(*comment));
549 if (comment == (char *) NULL)
550 break;
551 p=comment+strlen(comment);
552 }
553 *p=(char) c;
554 }
555 if (comment == (char *) NULL)
556 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
557 *p='\0';
558 (void) SetImageProperty(image,"comment",comment);
559 comment=DestroyString(comment);
560 c=ReadBlobByte(image);
561 }
562 else
563 if (isalnum(c) != MagickFalse)
564 {
565 /*
566 Get the keyword.
567 */
568 p=keyword;
569 do
570 {
cristy3ed852e2009-09-05 21:47:34 +0000571 if (c == (int) '=')
572 break;
573 if ((size_t) (p-keyword) < (MaxTextExtent-1))
574 *p++=(char) c;
575 c=ReadBlobByte(image);
576 } while (c != EOF);
577 *p='\0';
578 p=options;
cristy93505cf2010-08-10 21:37:49 +0000579 while ((isspace((int) ((unsigned char) c)) != 0) && (c != EOF))
cristy3ed852e2009-09-05 21:47:34 +0000580 c=ReadBlobByte(image);
581 if (c == (int) '=')
582 {
583 /*
584 Get the keyword value.
585 */
586 c=ReadBlobByte(image);
587 while ((c != (int) '}') && (c != EOF))
588 {
589 if ((size_t) (p-options+1) >= length)
590 {
591 *p='\0';
592 length<<=1;
593 options=(char *) ResizeQuantumMemory(options,length+
594 MaxTextExtent,sizeof(*options));
595 if (options == (char *) NULL)
596 break;
597 p=options+strlen(options);
598 }
599 if (options == (char *) NULL)
600 ThrowReaderException(ResourceLimitError,
601 "MemoryAllocationFailed");
602 *p++=(char) c;
603 c=ReadBlobByte(image);
604 if (*options != '{')
605 if (isspace((int) ((unsigned char) c)) != 0)
606 break;
607 }
608 }
609 *p='\0';
610 if (*options == '{')
611 (void) CopyMagickString(options,options+1,MaxTextExtent);
612 /*
613 Assign a value to the specified keyword.
614 */
615 switch (*keyword)
616 {
617 case 'b':
618 case 'B':
619 {
620 if (LocaleCompare(keyword,"background-color") == 0)
621 {
622 (void) QueryColorDatabase(options,&image->background_color,
623 exception);
624 break;
625 }
626 if (LocaleCompare(keyword,"blue-primary") == 0)
627 {
628 flags=ParseGeometry(options,&geometry_info);
629 image->chromaticity.blue_primary.x=geometry_info.rho;
630 image->chromaticity.blue_primary.y=geometry_info.sigma;
631 if ((flags & SigmaValue) == 0)
632 image->chromaticity.blue_primary.y=
633 image->chromaticity.blue_primary.x;
634 break;
635 }
636 if (LocaleCompare(keyword,"border-color") == 0)
637 {
638 (void) QueryColorDatabase(options,&image->border_color,
639 exception);
640 break;
641 }
642 (void) SetImageProperty(image,keyword,options);
643 break;
644 }
645 case 'c':
646 case 'C':
647 {
648 if (LocaleCompare(keyword,"class") == 0)
649 {
cristybb503372010-05-27 20:51:26 +0000650 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000651 storage_class;
652
cristy042ee782011-04-22 18:48:30 +0000653 storage_class=ParseCommandOption(MagickClassOptions,
cristy3ed852e2009-09-05 21:47:34 +0000654 MagickFalse,options);
655 if (storage_class < 0)
656 break;
657 image->storage_class=(ClassType) storage_class;
658 break;
659 }
660 if (LocaleCompare(keyword,"colors") == 0)
661 {
cristye27293e2009-12-18 02:53:20 +0000662 colors=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000663 break;
664 }
665 if (LocaleCompare(keyword,"colorspace") == 0)
666 {
cristybb503372010-05-27 20:51:26 +0000667 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000668 colorspace;
669
cristy042ee782011-04-22 18:48:30 +0000670 colorspace=ParseCommandOption(MagickColorspaceOptions,
cristy3ed852e2009-09-05 21:47:34 +0000671 MagickFalse,options);
672 if (colorspace < 0)
673 break;
674 image->colorspace=(ColorspaceType) colorspace;
675 break;
676 }
677 if (LocaleCompare(keyword,"compression") == 0)
678 {
cristybb503372010-05-27 20:51:26 +0000679 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000680 compression;
681
cristy042ee782011-04-22 18:48:30 +0000682 compression=ParseCommandOption(MagickCompressOptions,
cristy3ed852e2009-09-05 21:47:34 +0000683 MagickFalse,options);
684 if (compression < 0)
685 break;
686 image->compression=(CompressionType) compression;
687 break;
688 }
689 if (LocaleCompare(keyword,"columns") == 0)
690 {
cristye27293e2009-12-18 02:53:20 +0000691 image->columns=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000692 break;
693 }
694 (void) SetImageProperty(image,keyword,options);
695 break;
696 }
697 case 'd':
698 case 'D':
699 {
700 if (LocaleCompare(keyword,"delay") == 0)
701 {
cristye27293e2009-12-18 02:53:20 +0000702 image->delay=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000703 break;
704 }
705 if (LocaleCompare(keyword,"depth") == 0)
706 {
cristye27293e2009-12-18 02:53:20 +0000707 image->depth=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000708 break;
709 }
710 if (LocaleCompare(keyword,"dispose") == 0)
711 {
cristybb503372010-05-27 20:51:26 +0000712 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000713 dispose;
714
cristy042ee782011-04-22 18:48:30 +0000715 dispose=ParseCommandOption(MagickDisposeOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000716 options);
717 if (dispose < 0)
718 break;
719 image->dispose=(DisposeType) dispose;
720 break;
721 }
722 (void) SetImageProperty(image,keyword,options);
723 break;
724 }
725 case 'e':
726 case 'E':
727 {
728 if (LocaleCompare(keyword,"endian") == 0)
729 {
cristybb503372010-05-27 20:51:26 +0000730 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000731 endian;
732
cristy042ee782011-04-22 18:48:30 +0000733 endian=ParseCommandOption(MagickEndianOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000734 options);
735 if (endian < 0)
736 break;
737 image->endian=(EndianType) endian;
738 break;
739 }
740 (void) SetImageProperty(image,keyword,options);
741 break;
742 }
743 case 'g':
744 case 'G':
745 {
746 if (LocaleCompare(keyword,"gamma") == 0)
747 {
cristyf2f27272009-12-17 14:48:46 +0000748 image->gamma=StringToDouble(options);
cristy3ed852e2009-09-05 21:47:34 +0000749 break;
750 }
751 if (LocaleCompare(keyword,"gravity") == 0)
752 {
cristybb503372010-05-27 20:51:26 +0000753 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000754 gravity;
755
cristy042ee782011-04-22 18:48:30 +0000756 gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000757 options);
758 if (gravity < 0)
759 break;
760 image->gravity=(GravityType) gravity;
761 break;
762 }
763 if (LocaleCompare(keyword,"green-primary") == 0)
764 {
765 flags=ParseGeometry(options,&geometry_info);
766 image->chromaticity.green_primary.x=geometry_info.rho;
767 image->chromaticity.green_primary.y=geometry_info.sigma;
768 if ((flags & SigmaValue) == 0)
769 image->chromaticity.green_primary.y=
770 image->chromaticity.green_primary.x;
771 break;
772 }
773 (void) SetImageProperty(image,keyword,options);
774 break;
775 }
776 case 'i':
777 case 'I':
778 {
779 if (LocaleCompare(keyword,"id") == 0)
780 {
781 (void) CopyMagickString(id,options,MaxTextExtent);
782 break;
783 }
784 if (LocaleCompare(keyword,"iterations") == 0)
785 {
cristye27293e2009-12-18 02:53:20 +0000786 image->iterations=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000787 break;
788 }
789 (void) SetImageProperty(image,keyword,options);
790 break;
791 }
792 case 'm':
793 case 'M':
794 {
795 if (LocaleCompare(keyword,"matte") == 0)
796 {
cristybb503372010-05-27 20:51:26 +0000797 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000798 matte;
799
cristy042ee782011-04-22 18:48:30 +0000800 matte=ParseCommandOption(MagickBooleanOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000801 options);
802 if (matte < 0)
803 break;
804 image->matte=(MagickBooleanType) matte;
805 break;
806 }
807 if (LocaleCompare(keyword,"matte-color") == 0)
808 {
809 (void) QueryColorDatabase(options,&image->matte_color,
810 exception);
811 break;
812 }
813 if (LocaleCompare(keyword,"montage") == 0)
814 {
815 (void) CloneString(&image->montage,options);
816 break;
817 }
818 (void) SetImageProperty(image,keyword,options);
819 break;
820 }
821 case 'o':
822 case 'O':
823 {
824 if (LocaleCompare(keyword,"opaque") == 0)
825 {
cristybb503372010-05-27 20:51:26 +0000826 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000827 matte;
828
cristy042ee782011-04-22 18:48:30 +0000829 matte=ParseCommandOption(MagickBooleanOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000830 options);
831 if (matte < 0)
832 break;
833 image->matte=(MagickBooleanType) matte;
834 break;
835 }
836 if (LocaleCompare(keyword,"orientation") == 0)
837 {
cristybb503372010-05-27 20:51:26 +0000838 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000839 orientation;
840
cristy042ee782011-04-22 18:48:30 +0000841 orientation=ParseCommandOption(MagickOrientationOptions,
cristy3ed852e2009-09-05 21:47:34 +0000842 MagickFalse,options);
843 if (orientation < 0)
844 break;
845 image->orientation=(OrientationType) orientation;
846 break;
847 }
848 (void) SetImageProperty(image,keyword,options);
849 break;
850 }
851 case 'p':
852 case 'P':
853 {
854 if (LocaleCompare(keyword,"page") == 0)
855 {
856 char
857 *geometry;
858
859 geometry=GetPageGeometry(options);
860 (void) ParseAbsoluteGeometry(geometry,&image->page);
861 geometry=DestroyString(geometry);
862 break;
863 }
864 if ((LocaleNCompare(keyword,"profile:",8) == 0) ||
865 (LocaleNCompare(keyword,"profile-",8) == 0))
866 {
867 StringInfo
868 *profile;
869
870 if (profiles == (LinkedListInfo *) NULL)
871 profiles=NewLinkedList(0);
872 (void) AppendValueToLinkedList(profiles,
873 AcquireString(keyword+8));
cristyf2f27272009-12-17 14:48:46 +0000874 profile=AcquireStringInfo((size_t) StringToLong(options));
cristy3ed852e2009-09-05 21:47:34 +0000875 (void) SetImageProfile(image,keyword+8,profile);
876 profile=DestroyStringInfo(profile);
877 break;
878 }
879 (void) SetImageProperty(image,keyword,options);
880 break;
881 }
882 case 'q':
883 case 'Q':
884 {
885 if (LocaleCompare(keyword,"quality") == 0)
886 {
cristye27293e2009-12-18 02:53:20 +0000887 image->quality=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000888 break;
889 }
890 if ((LocaleCompare(keyword,"quantum-format") == 0) ||
891 (LocaleCompare(keyword,"quantum:format") == 0))
892 {
cristybb503372010-05-27 20:51:26 +0000893 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000894 format;
895
cristy042ee782011-04-22 18:48:30 +0000896 format=ParseCommandOption(MagickQuantumFormatOptions,
cristy3ed852e2009-09-05 21:47:34 +0000897 MagickFalse,options);
898 if (format < 0)
899 break;
900 quantum_format=(QuantumFormatType) format;
901 break;
902 }
903 (void) SetImageProperty(image,keyword,options);
904 break;
905 }
906 case 'r':
907 case 'R':
908 {
909 if (LocaleCompare(keyword,"red-primary") == 0)
910 {
911 flags=ParseGeometry(options,&geometry_info);
912 image->chromaticity.red_primary.x=geometry_info.rho;
913 image->chromaticity.red_primary.y=geometry_info.sigma;
914 if ((flags & SigmaValue) == 0)
915 image->chromaticity.red_primary.y=
916 image->chromaticity.red_primary.x;
917 break;
918 }
919 if (LocaleCompare(keyword,"rendering-intent") == 0)
920 {
cristybb503372010-05-27 20:51:26 +0000921 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000922 rendering_intent;
923
cristy042ee782011-04-22 18:48:30 +0000924 rendering_intent=ParseCommandOption(MagickIntentOptions,
cristy3ed852e2009-09-05 21:47:34 +0000925 MagickFalse,options);
926 if (rendering_intent < 0)
927 break;
928 image->rendering_intent=(RenderingIntent) rendering_intent;
929 break;
930 }
931 if (LocaleCompare(keyword,"resolution") == 0)
932 {
933 flags=ParseGeometry(options,&geometry_info);
934 image->x_resolution=geometry_info.rho;
935 image->y_resolution=geometry_info.sigma;
936 if ((flags & SigmaValue) == 0)
937 image->y_resolution=image->x_resolution;
938 break;
939 }
940 if (LocaleCompare(keyword,"rows") == 0)
941 {
cristye27293e2009-12-18 02:53:20 +0000942 image->rows=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000943 break;
944 }
945 (void) SetImageProperty(image,keyword,options);
946 break;
947 }
948 case 's':
949 case 'S':
950 {
951 if (LocaleCompare(keyword,"scene") == 0)
952 {
cristye27293e2009-12-18 02:53:20 +0000953 image->scene=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000954 break;
955 }
956 (void) SetImageProperty(image,keyword,options);
957 break;
958 }
959 case 't':
960 case 'T':
961 {
962 if (LocaleCompare(keyword,"ticks-per-second") == 0)
963 {
cristy15893a42010-11-20 18:57:15 +0000964 image->ticks_per_second=(ssize_t) StringToLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000965 break;
966 }
967 if (LocaleCompare(keyword,"tile-offset") == 0)
968 {
969 char
970 *geometry;
971
972 geometry=GetPageGeometry(options);
973 (void) ParseAbsoluteGeometry(geometry,&image->tile_offset);
974 geometry=DestroyString(geometry);
975 break;
976 }
977 if (LocaleCompare(keyword,"type") == 0)
978 {
cristybb503372010-05-27 20:51:26 +0000979 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000980 type;
981
cristy042ee782011-04-22 18:48:30 +0000982 type=ParseCommandOption(MagickTypeOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000983 options);
984 if (type < 0)
985 break;
986 image->type=(ImageType) type;
987 break;
988 }
989 (void) SetImageProperty(image,keyword,options);
990 break;
991 }
992 case 'u':
993 case 'U':
994 {
995 if (LocaleCompare(keyword,"units") == 0)
996 {
cristybb503372010-05-27 20:51:26 +0000997 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000998 units;
999
cristy042ee782011-04-22 18:48:30 +00001000 units=ParseCommandOption(MagickResolutionOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +00001001 options);
1002 if (units < 0)
1003 break;
1004 image->units=(ResolutionType) units;
1005 break;
1006 }
1007 (void) SetImageProperty(image,keyword,options);
1008 break;
1009 }
1010 case 'v':
1011 case 'V':
1012 {
1013 if (LocaleCompare(keyword,"version") == 0)
1014 {
cristyf2f27272009-12-17 14:48:46 +00001015 version=StringToDouble(options);
cristy3ed852e2009-09-05 21:47:34 +00001016 break;
1017 }
1018 (void) SetImageProperty(image,keyword,options);
1019 break;
1020 }
1021 case 'w':
1022 case 'W':
1023 {
1024 if (LocaleCompare(keyword,"white-point") == 0)
1025 {
1026 flags=ParseGeometry(options,&geometry_info);
1027 image->chromaticity.white_point.x=geometry_info.rho;
1028 image->chromaticity.white_point.y=geometry_info.rho;
1029 if ((flags & SigmaValue) != 0)
1030 image->chromaticity.white_point.y=
1031 image->chromaticity.white_point.x;
1032 break;
1033 }
1034 (void) SetImageProperty(image,keyword,options);
1035 break;
1036 }
1037 default:
1038 {
1039 (void) SetImageProperty(image,keyword,options);
1040 break;
1041 }
1042 }
1043 }
1044 else
1045 c=ReadBlobByte(image);
1046 while (isspace((int) ((unsigned char) c)) != 0)
1047 c=ReadBlobByte(image);
1048 }
1049 options=DestroyString(options);
1050 (void) ReadBlobByte(image);
1051 /*
1052 Verify that required image information is defined.
1053 */
1054 if ((LocaleCompare(id,"ImageMagick") != 0) ||
1055 (image->storage_class == UndefinedClass) ||
1056 (image->columns == 0) || (image->rows == 0))
1057 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1058 if (image->montage != (char *) NULL)
1059 {
1060 register char
1061 *p;
1062
1063 /*
1064 Image directory.
1065 */
1066 length=MaxTextExtent;
1067 image->directory=AcquireString((char *) NULL);
1068 p=image->directory;
1069 do
1070 {
1071 *p='\0';
1072 if ((strlen(image->directory)+MaxTextExtent) >= length)
1073 {
1074 /*
1075 Allocate more memory for the image directory.
1076 */
1077 length<<=1;
1078 image->directory=(char *) ResizeQuantumMemory(image->directory,
1079 length+MaxTextExtent,sizeof(*image->directory));
1080 if (image->directory == (char *) NULL)
1081 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1082 p=image->directory+strlen(image->directory);
1083 }
1084 c=ReadBlobByte(image);
1085 *p++=(char) c;
1086 } while (c != (int) '\0');
1087 }
1088 if (profiles != (LinkedListInfo *) NULL)
1089 {
1090 const char
1091 *name;
1092
1093 const StringInfo
1094 *profile;
1095
1096 /*
1097 Read image profiles.
1098 */
1099 ResetLinkedListIterator(profiles);
1100 name=(const char *) GetNextValueInLinkedList(profiles);
1101 while (name != (const char *) NULL)
1102 {
1103 profile=GetImageProfile(image,name);
1104 if (profile != (StringInfo *) NULL)
1105 {
1106 register unsigned char
1107 *p;
1108
1109 p=GetStringInfoDatum(profile);
1110 count=ReadBlob(image,GetStringInfoLength(profile),p);
cristyda16f162011-02-19 23:52:17 +00001111 (void) count;
cristy3ed852e2009-09-05 21:47:34 +00001112 }
1113 name=(const char *) GetNextValueInLinkedList(profiles);
1114 }
1115 profiles=DestroyLinkedList(profiles,RelinquishMagickMemory);
1116 }
1117 image->depth=GetImageQuantumDepth(image,MagickFalse);
1118 if (image->storage_class == PseudoClass)
1119 {
1120 /*
1121 Create image colormap.
1122 */
1123 status=AcquireImageColormap(image,colors != 0 ? colors : 256);
1124 if (status == MagickFalse)
1125 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1126 if (colors != 0)
1127 {
1128 size_t
1129 packet_size;
1130
1131 unsigned char
1132 *colormap;
1133
1134 /*
1135 Read image colormap from file.
1136 */
1137 packet_size=(size_t) (3UL*image->depth/8UL);
1138 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
1139 packet_size*sizeof(*colormap));
1140 if (colormap == (unsigned char *) NULL)
1141 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1142 count=ReadBlob(image,packet_size*image->colors,colormap);
1143 p=colormap;
1144 switch (image->depth)
1145 {
1146 default:
1147 ThrowReaderException(CorruptImageError,
1148 "ImageDepthNotSupported");
1149 case 8:
1150 {
1151 unsigned char
1152 pixel;
1153
cristybb503372010-05-27 20:51:26 +00001154 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001155 {
1156 p=PushCharPixel(p,&pixel);
1157 image->colormap[i].red=ScaleCharToQuantum(pixel);
1158 p=PushCharPixel(p,&pixel);
1159 image->colormap[i].green=ScaleCharToQuantum(pixel);
1160 p=PushCharPixel(p,&pixel);
1161 image->colormap[i].blue=ScaleCharToQuantum(pixel);
1162 }
1163 break;
1164 }
1165 case 16:
1166 {
1167 unsigned short
1168 pixel;
1169
cristybb503372010-05-27 20:51:26 +00001170 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001171 {
1172 p=PushShortPixel(MSBEndian,p,&pixel);
1173 image->colormap[i].red=ScaleShortToQuantum(pixel);
1174 p=PushShortPixel(MSBEndian,p,&pixel);
1175 image->colormap[i].green=ScaleShortToQuantum(pixel);
1176 p=PushShortPixel(MSBEndian,p,&pixel);
1177 image->colormap[i].blue=ScaleShortToQuantum(pixel);
1178 }
1179 break;
1180 }
1181 case 32:
1182 {
cristy4cb162a2010-05-30 03:04:47 +00001183 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001184 pixel;
1185
cristybb503372010-05-27 20:51:26 +00001186 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001187 {
1188 p=PushLongPixel(MSBEndian,p,&pixel);
1189 image->colormap[i].red=ScaleLongToQuantum(pixel);
1190 p=PushLongPixel(MSBEndian,p,&pixel);
1191 image->colormap[i].green=ScaleLongToQuantum(pixel);
1192 p=PushLongPixel(MSBEndian,p,&pixel);
1193 image->colormap[i].blue=ScaleLongToQuantum(pixel);
1194 }
1195 break;
1196 }
1197 }
1198 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
1199 }
1200 }
1201 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1202 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1203 break;
1204 /*
1205 Allocate image pixels.
1206 */
1207 quantum_info=AcquireQuantumInfo(image_info,image);
1208 if (quantum_info == (QuantumInfo *) NULL)
1209 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1210 if (quantum_format != UndefinedQuantumFormat)
1211 {
1212 status=SetQuantumFormat(image,quantum_info,quantum_format);
1213 if (status == MagickFalse)
1214 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1215 }
1216 packet_size=(size_t) (quantum_info->depth/8);
1217 if (image->storage_class == DirectClass)
1218 packet_size=(size_t) (3*quantum_info->depth/8);
1219 if (image->matte != MagickFalse)
1220 packet_size+=quantum_info->depth/8;
1221 if (image->colorspace == CMYKColorspace)
1222 packet_size+=quantum_info->depth/8;
1223 if (image->compression == RLECompression)
1224 packet_size++;
1225 length=image->columns;
cristy26377172010-12-20 19:01:58 +00001226 length=MagickMax(MagickMax(BZipMaxExtent(packet_size*image->columns),
1227 LZMAMaxExtent(packet_size*image->columns)),ZipMaxExtent(packet_size*
1228 image->columns));
cristy3ed852e2009-09-05 21:47:34 +00001229 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
1230 sizeof(*compress_pixels));
1231 if (compress_pixels == (unsigned char *) NULL)
1232 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1233 /*
1234 Read image pixels.
1235 */
1236 quantum_type=RGBQuantum;
1237 if (image->matte != MagickFalse)
1238 quantum_type=RGBAQuantum;
1239 if (image->colorspace == CMYKColorspace)
1240 {
1241 quantum_type=CMYKQuantum;
1242 if (image->matte != MagickFalse)
1243 quantum_type=CMYKAQuantum;
1244 }
1245 if (image->storage_class == PseudoClass)
1246 {
1247 quantum_type=IndexQuantum;
1248 if (image->matte != MagickFalse)
1249 quantum_type=IndexAlphaQuantum;
1250 }
1251 if (image->colorspace == GRAYColorspace)
1252 {
1253 quantum_type=GrayQuantum;
1254 if (image->matte != MagickFalse)
1255 quantum_type=GrayAlphaQuantum;
1256 }
cristy330af6c2010-12-21 14:36:06 +00001257 status=MagickTrue;
1258 switch (image->compression)
1259 {
1260#if defined(MAGICKCORE_BZLIB_DELEGATE)
1261 case BZipCompression:
1262 {
1263 (void) ResetMagickMemory(&bzip_info,0,sizeof(bzip_info));
1264 bzip_info.bzalloc=AcquireBZIPMemory;
1265 bzip_info.bzfree=RelinquishBZIPMemory;
1266 bzip_info.opaque=(void *) NULL;
1267 code=BZ2_bzDecompressInit(&bzip_info,(int) image_info->verbose,
1268 MagickFalse);
1269 if (code != BZ_OK)
1270 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001271 break;
1272 }
1273#endif
1274#if defined(MAGICKCORE_LZMA_DELEGATE)
1275 case LZMACompression:
1276 {
cristy9d72f1a2010-12-21 20:46:59 +00001277 (void) ResetMagickMemory(&allocator,0,sizeof(allocator));
1278 allocator.alloc=AcquireLZMAMemory;
1279 allocator.free=RelinquishLZMAMemory;
cristy330af6c2010-12-21 14:36:06 +00001280 lzma_info=initialize_lzma;
cristy9d72f1a2010-12-21 20:46:59 +00001281 lzma_info.allocator=(&allocator);
cristy330af6c2010-12-21 14:36:06 +00001282 code=lzma_auto_decoder(&lzma_info,-1,0);
1283 if (code != LZMA_OK)
1284 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001285 break;
1286 }
1287#endif
1288#if defined(MAGICKCORE_ZLIB_DELEGATE)
1289 case LZWCompression:
1290 case ZipCompression:
1291 {
1292 (void) ResetMagickMemory(&zip_info,0,sizeof(zip_info));
1293 zip_info.zalloc=AcquireZIPMemory;
1294 zip_info.zfree=RelinquishZIPMemory;
1295 zip_info.opaque=(voidpf) NULL;
1296 code=inflateInit(&zip_info);
1297 if (code != Z_OK)
1298 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001299 break;
1300 }
1301#endif
1302 case RLECompression:
1303 {
1304 (void) ResetMagickMemory(&pixel,0,sizeof(pixel));
1305 pixel.opacity=(Quantum) TransparentOpacity;
1306 index=(IndexPacket) 0;
1307 break;
1308 }
1309 default:
1310 break;
1311 }
cristy3ed852e2009-09-05 21:47:34 +00001312 pixels=GetQuantumPixels(quantum_info);
1313 index=(IndexPacket) 0;
1314 length=0;
cristybb503372010-05-27 20:51:26 +00001315 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001316 {
1317 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00001318 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00001319
cristybb503372010-05-27 20:51:26 +00001320 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001321 x;
1322
1323 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001324 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001325
cristy330af6c2010-12-21 14:36:06 +00001326 if (status == MagickFalse)
1327 break;
cristy3ed852e2009-09-05 21:47:34 +00001328 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1329 if (q == (PixelPacket *) NULL)
1330 break;
1331 indexes=GetAuthenticIndexQueue(image);
1332 switch (image->compression)
1333 {
cristy3ed852e2009-09-05 21:47:34 +00001334#if defined(MAGICKCORE_BZLIB_DELEGATE)
1335 case BZipCompression:
1336 {
cristy3ed852e2009-09-05 21:47:34 +00001337 bzip_info.next_out=(char *) pixels;
1338 bzip_info.avail_out=(unsigned int) (packet_size*image->columns);
1339 do
1340 {
1341 if (bzip_info.avail_in == 0)
1342 {
1343 bzip_info.next_in=(char *) compress_pixels;
1344 length=(size_t) BZipMaxExtent(packet_size*image->columns);
1345 if (version != 0)
1346 length=(size_t) ReadBlobMSBLong(image);
1347 bzip_info.avail_in=(unsigned int) ReadBlob(image,length,
1348 (unsigned char *) bzip_info.next_in);
1349 }
1350 if (BZ2_bzDecompress(&bzip_info) == BZ_STREAM_END)
1351 break;
1352 } while (bzip_info.avail_out != 0);
cristy26377172010-12-20 19:01:58 +00001353 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1354 quantum_type,pixels,exception);
1355 break;
1356 }
1357#endif
1358#if defined(MAGICKCORE_LZMA_DELEGATE)
1359 case LZMACompression:
1360 {
cristy26377172010-12-20 19:01:58 +00001361 lzma_info.next_out=pixels;
cristy330af6c2010-12-21 14:36:06 +00001362 lzma_info.avail_out=packet_size*image->columns;
cristy26377172010-12-20 19:01:58 +00001363 do
1364 {
1365 if (lzma_info.avail_in == 0)
1366 {
1367 lzma_info.next_in=compress_pixels;
1368 length=(size_t) ReadBlobMSBLong(image);
1369 lzma_info.avail_in=(unsigned int) ReadBlob(image,length,
1370 (unsigned char *) lzma_info.next_in);
1371 }
1372 code=lzma_code(&lzma_info,LZMA_RUN);
cristy330af6c2010-12-21 14:36:06 +00001373 if (code < 0)
1374 {
1375 status=MagickFalse;
1376 break;
1377 }
1378 if (code == LZMA_STREAM_END)
cristy26377172010-12-20 19:01:58 +00001379 break;
1380 } while (lzma_info.avail_out != 0);
cristy26377172010-12-20 19:01:58 +00001381 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1382 quantum_type,pixels,exception);
1383 break;
1384 }
1385#endif
1386#if defined(MAGICKCORE_ZLIB_DELEGATE)
1387 case LZWCompression:
1388 case ZipCompression:
1389 {
cristy26377172010-12-20 19:01:58 +00001390 zip_info.next_out=pixels;
1391 zip_info.avail_out=(uInt) (packet_size*image->columns);
1392 do
1393 {
1394 if (zip_info.avail_in == 0)
1395 {
1396 zip_info.next_in=compress_pixels;
1397 length=(size_t) ZipMaxExtent(packet_size*image->columns);
1398 if (version != 0)
1399 length=(size_t) ReadBlobMSBLong(image);
1400 zip_info.avail_in=(unsigned int) ReadBlob(image,length,
1401 zip_info.next_in);
1402 }
1403 if (inflate(&zip_info,Z_SYNC_FLUSH) == Z_STREAM_END)
1404 break;
1405 } while (zip_info.avail_out != 0);
cristy3ed852e2009-09-05 21:47:34 +00001406 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1407 quantum_type,pixels,exception);
1408 break;
1409 }
1410#endif
1411 case RLECompression:
1412 {
cristybb503372010-05-27 20:51:26 +00001413 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001414 {
1415 if (length == 0)
1416 {
1417 count=ReadBlob(image,packet_size,pixels);
1418 PushRunlengthPacket(image,pixels,&length,&pixel,&index);
1419 }
1420 length--;
1421 if ((image->storage_class == PseudoClass) ||
1422 (image->colorspace == CMYKColorspace))
cristyaff6d802011-04-26 01:46:31 +00001423 SetIndexPixelComponent(indexes+x,index);
cristy9fff7b42011-04-29 01:09:31 +00001424 SetRedPixelComponent(q,pixel.red);
1425 SetGreenPixelComponent(q,pixel.green);
1426 SetBluePixelComponent(q,pixel.blue);
1427 SetOpacityPixelComponent(q,pixel.opacity);
1428 q++;
cristy3ed852e2009-09-05 21:47:34 +00001429 }
1430 break;
1431 }
1432 default:
1433 {
1434 count=ReadBlob(image,packet_size*image->columns,pixels);
1435 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1436 quantum_type,pixels,exception);
1437 break;
1438 }
1439 }
1440 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1441 break;
1442 }
1443 SetQuantumImageType(image,quantum_type);
cristy330af6c2010-12-21 14:36:06 +00001444 switch (image->compression)
1445 {
1446#if defined(MAGICKCORE_BZLIB_DELEGATE)
1447 case BZipCompression:
1448 {
1449 if (version == 0)
1450 {
1451 MagickOffsetType
1452 offset;
1453
1454 offset=SeekBlob(image,-((MagickOffsetType)
1455 bzip_info.avail_in),SEEK_CUR);
1456 if (offset < 0)
1457 ThrowReaderException(CorruptImageError,
1458 "ImproperImageHeader");
1459 }
1460 code=BZ2_bzDecompressEnd(&bzip_info);
1461 if (code != BZ_OK)
1462 status=MagickFalse;
1463 break;
1464 }
1465#endif
1466#if defined(MAGICKCORE_LZMA_DELEGATE)
1467 case LZMACompression:
1468 {
cristy3b788a02010-12-27 15:59:54 +00001469 code=lzma_code(&lzma_info,LZMA_FINISH);
1470 if ((code != LZMA_STREAM_END) && (code != LZMA_OK))
cristyb977da52010-12-22 15:55:53 +00001471 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001472 lzma_end(&lzma_info);
1473 break;
1474 }
1475#endif
1476#if defined(MAGICKCORE_ZLIB_DELEGATE)
1477 case LZWCompression:
1478 case ZipCompression:
1479 {
1480 if (version == 0)
1481 {
1482 MagickOffsetType
1483 offset;
1484
1485 offset=SeekBlob(image,-((MagickOffsetType) zip_info.avail_in),
1486 SEEK_CUR);
1487 if (offset < 0)
1488 ThrowReaderException(CorruptImageError,
1489 "ImproperImageHeader");
1490 }
1491 code=inflateEnd(&zip_info);
1492 if (code != LZMA_OK)
1493 status=MagickFalse;
1494 break;
1495 }
1496#endif
1497 default:
1498 break;
1499 }
cristy3ed852e2009-09-05 21:47:34 +00001500 quantum_info=DestroyQuantumInfo(quantum_info);
1501 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
cristybb503372010-05-27 20:51:26 +00001502 if (((y != (ssize_t) image->rows)) || (status == MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001503 {
1504 image=DestroyImageList(image);
1505 return((Image *) NULL);
1506 }
1507 if (EOFBlob(image) != MagickFalse)
1508 {
1509 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1510 image->filename);
1511 break;
1512 }
1513 /*
1514 Proceed to next image.
1515 */
1516 if (image_info->number_scenes != 0)
1517 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1518 break;
1519 do
1520 {
1521 c=ReadBlobByte(image);
1522 } while ((isgraph(c) == MagickFalse) && (c != EOF));
1523 if (c != EOF)
1524 {
1525 /*
1526 Allocate next image structure.
1527 */
1528 AcquireNextImage(image_info,image);
1529 if (GetNextImageInList(image) == (Image *) NULL)
1530 {
1531 image=DestroyImageList(image);
1532 return((Image *) NULL);
1533 }
1534 image=SyncNextImageInList(image);
1535 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1536 GetBlobSize(image));
1537 if (status == MagickFalse)
1538 break;
1539 }
1540 } while (c != EOF);
1541 (void) CloseBlob(image);
1542 return(GetFirstImageInList(image));
1543}
1544
1545/*
1546%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1547% %
1548% %
1549% %
1550% R e g i s t e r M I F F I m a g e %
1551% %
1552% %
1553% %
1554%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1555%
1556% RegisterMIFFImage() adds properties for the MIFF image format to the list of
1557% supported formats. The properties include the image format tag, a method to
1558% read and/or write the format, whether the format supports the saving of more
1559% than one frame to the same file or blob, whether the format supports native
1560% in-memory I/O, and a brief description of the format.
1561%
1562% The format of the RegisterMIFFImage method is:
1563%
cristybb503372010-05-27 20:51:26 +00001564% size_t RegisterMIFFImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001565%
1566*/
cristybb503372010-05-27 20:51:26 +00001567ModuleExport size_t RegisterMIFFImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001568{
1569 char
1570 version[MaxTextExtent];
1571
1572 MagickInfo
1573 *entry;
1574
1575 *version='\0';
1576#if defined(MagickImageCoderSignatureText)
1577 (void) CopyMagickString(version,MagickLibVersionText,MaxTextExtent);
1578#if defined(ZLIB_VERSION)
1579 (void) ConcatenateMagickString(version," with Zlib ",MaxTextExtent);
1580 (void) ConcatenateMagickString(version,ZLIB_VERSION,MaxTextExtent);
1581#endif
1582#if defined(MAGICKCORE_BZLIB_DELEGATE)
1583 (void) ConcatenateMagickString(version," and BZlib",MaxTextExtent);
1584#endif
1585#endif
1586 entry=SetMagickInfo("MIFF");
1587 entry->decoder=(DecodeImageHandler *) ReadMIFFImage;
1588 entry->encoder=(EncodeImageHandler *) WriteMIFFImage;
1589 entry->magick=(IsImageFormatHandler *) IsMIFF;
cristyffaf9782011-04-13 19:50:51 +00001590 entry->seekable_stream=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00001591 entry->description=ConstantString("Magick Image File Format");
1592 if (*version != '\0')
1593 entry->version=ConstantString(version);
1594 entry->module=ConstantString("MIFF");
1595 (void) RegisterMagickInfo(entry);
1596 return(MagickImageCoderSignature);
1597}
1598
1599/*
1600%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1601% %
1602% %
1603% %
1604% U n r e g i s t e r M I F F I m a g e %
1605% %
1606% %
1607% %
1608%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1609%
1610% UnregisterMIFFImage() removes format registrations made by the MIFF module
1611% from the list of supported formats.
1612%
1613% The format of the UnregisterMIFFImage method is:
1614%
1615% UnregisterMIFFImage(void)
1616%
1617*/
1618ModuleExport void UnregisterMIFFImage(void)
1619{
1620 (void) UnregisterMagickInfo("MIFF");
1621}
1622
1623/*
1624%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1625% %
1626% %
1627% %
1628% W r i t e M I F F I m a g e %
1629% %
1630% %
1631% %
1632%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1633%
1634% WriteMIFFImage() writes a MIFF image to a file.
1635%
1636% The format of the WriteMIFFImage method is:
1637%
1638% MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
1639% Image *image)
1640%
1641% Compression code contributed by Kyle Shorter.
1642%
1643% A description of each parameter follows:
1644%
1645% o image_info: the image info.
1646%
1647% o image: the image.
1648%
1649*/
1650
1651static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
1652 size_t length,PixelPacket pixel,IndexPacket index)
1653{
1654 if (image->storage_class != DirectClass)
1655 {
1656 switch (image->depth)
1657 {
1658 case 32:
1659 {
cristybb503372010-05-27 20:51:26 +00001660 *pixels++=(unsigned char) ((size_t) index >> 24);
1661 *pixels++=(unsigned char) ((size_t) index >> 16);
cristy3ed852e2009-09-05 21:47:34 +00001662 }
1663 case 16:
cristybb503372010-05-27 20:51:26 +00001664 *pixels++=(unsigned char) ((size_t) index >> 8);
cristy3ed852e2009-09-05 21:47:34 +00001665 case 8:
1666 {
1667 *pixels++=(unsigned char) index;
1668 break;
1669 }
1670 default:
1671 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1672 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1673 }
1674 switch (image->depth)
1675 {
1676 case 32:
1677 {
cristy4cb162a2010-05-30 03:04:47 +00001678 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001679 value;
1680
1681 if (image->matte != MagickFalse)
1682 {
1683 value=ScaleQuantumToLong(pixel.opacity);
1684 pixels=PopLongPixel(MSBEndian,value,pixels);
1685 }
1686 break;
1687 }
1688 case 16:
1689 {
1690 unsigned short
1691 value;
1692
1693 if (image->matte != MagickFalse)
1694 {
1695 value=ScaleQuantumToShort(pixel.opacity);
1696 pixels=PopShortPixel(MSBEndian,value,pixels);
1697 }
1698 break;
1699 }
1700 case 8:
1701 {
1702 unsigned char
1703 value;
1704
1705 if (image->matte != MagickFalse)
1706 {
1707 value=(unsigned char) ScaleQuantumToChar(pixel.opacity);
1708 pixels=PopCharPixel(value,pixels);
1709 }
1710 break;
1711 }
1712 default:
1713 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1714 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1715 }
1716 *pixels++=(unsigned char) length;
1717 return(pixels);
1718 }
1719 switch (image->depth)
1720 {
1721 case 32:
1722 {
cristy4cb162a2010-05-30 03:04:47 +00001723 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001724 value;
1725
1726 value=ScaleQuantumToLong(pixel.red);
1727 pixels=PopLongPixel(MSBEndian,value,pixels);
1728 value=ScaleQuantumToLong(pixel.green);
1729 pixels=PopLongPixel(MSBEndian,value,pixels);
1730 value=ScaleQuantumToLong(pixel.blue);
1731 pixels=PopLongPixel(MSBEndian,value,pixels);
1732 if (image->matte != MagickFalse)
1733 {
1734 value=ScaleQuantumToLong(pixel.opacity);
1735 pixels=PopLongPixel(MSBEndian,value,pixels);
1736 }
1737 if (image->colorspace == CMYKColorspace)
1738 {
1739 value=ScaleQuantumToLong(index);
1740 pixels=PopLongPixel(MSBEndian,value,pixels);
1741 }
1742 break;
1743 }
1744 case 16:
1745 {
1746 unsigned short
1747 value;
1748
1749 value=ScaleQuantumToShort(pixel.red);
1750 pixels=PopShortPixel(MSBEndian,value,pixels);
1751 value=ScaleQuantumToShort(pixel.green);
1752 pixels=PopShortPixel(MSBEndian,value,pixels);
1753 value=ScaleQuantumToShort(pixel.blue);
1754 pixels=PopShortPixel(MSBEndian,value,pixels);
1755 if (image->matte != MagickFalse)
1756 {
1757 value=ScaleQuantumToShort(pixel.opacity);
1758 pixels=PopShortPixel(MSBEndian,value,pixels);
1759 }
1760 if (image->colorspace == CMYKColorspace)
1761 {
1762 value=ScaleQuantumToShort(index);
1763 pixels=PopShortPixel(MSBEndian,value,pixels);
1764 }
1765 break;
1766 }
1767 case 8:
1768 {
1769 unsigned char
1770 value;
1771
1772 value=(unsigned char) ScaleQuantumToChar(pixel.red);
1773 pixels=PopCharPixel(value,pixels);
1774 value=(unsigned char) ScaleQuantumToChar(pixel.green);
1775 pixels=PopCharPixel(value,pixels);
1776 value=(unsigned char) ScaleQuantumToChar(pixel.blue);
1777 pixels=PopCharPixel(value,pixels);
1778 if (image->matte != MagickFalse)
1779 {
1780 value=(unsigned char) ScaleQuantumToChar(pixel.opacity);
1781 pixels=PopCharPixel(value,pixels);
1782 }
1783 if (image->colorspace == CMYKColorspace)
1784 {
1785 value=(unsigned char) ScaleQuantumToChar(index);
1786 pixels=PopCharPixel(value,pixels);
1787 }
1788 break;
1789 }
1790 default:
1791 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1792 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1793 }
1794 *pixels++=(unsigned char) length;
1795 return(pixels);
1796}
1797
1798static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
1799 Image *image)
1800{
1801#if defined(MAGICKCORE_BZLIB_DELEGATE)
1802 bz_stream
1803 bzip_info;
1804#endif
1805
1806 char
1807 buffer[MaxTextExtent];
1808
1809 CompressionType
1810 compression;
1811
1812 const char
1813 *property,
1814 *value;
1815
1816 IndexPacket
1817 index;
1818
1819 int
1820 code;
1821
cristy26377172010-12-20 19:01:58 +00001822#if defined(MAGICKCORE_LZMA_DELEGATE)
cristy4b46dba2010-12-20 19:18:20 +00001823 lzma_allocator
1824 allocator;
1825
cristy26377172010-12-20 19:01:58 +00001826 lzma_stream
cristy330af6c2010-12-21 14:36:06 +00001827 initialize_lzma = LZMA_STREAM_INIT,
1828 lzma_info;
cristy26377172010-12-20 19:01:58 +00001829#endif
cristy3ed852e2009-09-05 21:47:34 +00001830
1831 MagickBooleanType
1832 status;
1833
1834 MagickOffsetType
1835 scene;
1836
1837 PixelPacket
1838 pixel;
1839
1840 QuantumInfo
1841 *quantum_info;
1842
1843 QuantumType
1844 quantum_type;
1845
cristybb503372010-05-27 20:51:26 +00001846 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001847 i;
1848
1849 size_t
1850 length,
1851 packet_size;
1852
cristy26377172010-12-20 19:01:58 +00001853 ssize_t
1854 y;
1855
cristy3ed852e2009-09-05 21:47:34 +00001856 unsigned char
1857 *compress_pixels,
1858 *pixels,
1859 *q;
1860
1861#if defined(MAGICKCORE_ZLIB_DELEGATE)
1862 z_stream
1863 zip_info;
1864#endif
1865
1866 /*
1867 Open output image file.
1868 */
1869 assert(image_info != (const ImageInfo *) NULL);
1870 assert(image_info->signature == MagickSignature);
1871 assert(image != (Image *) NULL);
1872 assert(image->signature == MagickSignature);
1873 if (image->debug != MagickFalse)
1874 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1875 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1876 if (status == MagickFalse)
1877 return(status);
1878 code=0;
1879 scene=0;
1880 do
1881 {
1882 /*
1883 Allocate image pixels.
1884 */
1885 image->depth=image->depth <= 8 ? 8UL : image->depth <= 16 ? 16UL :
1886 image->depth <= 32 ? 32UL : 64UL;
1887 quantum_info=AcquireQuantumInfo(image_info,image);
1888 if (quantum_info == (QuantumInfo *) NULL)
1889 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1890 if ((image->storage_class != PseudoClass) && (image->depth >= 32) &&
1891 (quantum_info->format == UndefinedQuantumFormat) &&
1892 (IsHighDynamicRangeImage(image,&image->exception) != MagickFalse))
1893 {
1894 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1895 if (status == MagickFalse)
1896 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1897 }
1898 if ((image->storage_class == PseudoClass) &&
cristybb503372010-05-27 20:51:26 +00001899 (image->colors > (size_t) (GetQuantumRange(image->depth)+1)))
cristy3ed852e2009-09-05 21:47:34 +00001900 (void) SetImageStorageClass(image,DirectClass);
1901 if (IsGrayImage(image,&image->exception) != MagickFalse)
1902 {
1903 image->storage_class=DirectClass;
1904 (void) SetImageColorspace(image,GRAYColorspace);
1905 }
1906 compression=image->compression;
1907 if (image_info->compression != UndefinedCompression)
1908 compression=image_info->compression;
1909 switch (compression)
1910 {
1911#if !defined(MAGICKCORE_ZLIB_DELEGATE)
cristy26377172010-12-20 19:01:58 +00001912 case LZMACompression: compression=NoCompression; break;
1913#endif
1914#if !defined(MAGICKCORE_ZLIB_DELEGATE)
cristy3ed852e2009-09-05 21:47:34 +00001915 case LZWCompression:
1916 case ZipCompression: compression=NoCompression; break;
1917#endif
1918#if !defined(MAGICKCORE_BZLIB_DELEGATE)
1919 case BZipCompression: compression=NoCompression; break;
1920#endif
1921 case RLECompression:
1922 {
1923 if (quantum_info->format == FloatingPointQuantumFormat)
1924 compression=NoCompression;
1925 break;
1926 }
1927 default:
1928 break;
1929 }
1930 packet_size=(size_t) (quantum_info->depth/8);
1931 if (image->storage_class == DirectClass)
1932 packet_size=(size_t) (3*quantum_info->depth/8);
1933 if (image->matte != MagickFalse)
1934 packet_size+=quantum_info->depth/8;
1935 if (image->colorspace == CMYKColorspace)
1936 packet_size+=quantum_info->depth/8;
1937 if (compression == RLECompression)
1938 packet_size++;
1939 length=image->columns;
1940 length=MagickMax(BZipMaxExtent(packet_size*image->columns),ZipMaxExtent(
1941 packet_size*image->columns));
1942 if ((compression == BZipCompression) || (compression == ZipCompression))
1943 if (length != (size_t) ((unsigned int) length))
1944 compression=NoCompression;
1945 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
1946 sizeof(*compress_pixels));
1947 if (compress_pixels == (unsigned char *) NULL)
1948 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1949 /*
1950 Write MIFF header.
1951 */
1952 (void) WriteBlobString(image,"id=ImageMagick version=1.0\n");
1953 (void) FormatMagickString(buffer,MaxTextExtent,
cristy042ee782011-04-22 18:48:30 +00001954 "class=%s colors=%.20g matte=%s\n",CommandOptionToMnemonic(
cristye8c25f92010-06-03 00:53:06 +00001955 MagickClassOptions,image->storage_class),(double) image->colors,
cristy042ee782011-04-22 18:48:30 +00001956 CommandOptionToMnemonic(MagickBooleanOptions,(ssize_t) image->matte));
cristy3ed852e2009-09-05 21:47:34 +00001957 (void) WriteBlobString(image,buffer);
cristye8c25f92010-06-03 00:53:06 +00001958 (void) FormatMagickString(buffer,MaxTextExtent,"columns=%.20g rows=%.20g "
1959 "depth=%.20g\n",(double) image->columns,(double) image->rows,(double)
1960 image->depth);
cristy3ed852e2009-09-05 21:47:34 +00001961 (void) WriteBlobString(image,buffer);
cristy5f1c1ff2010-12-23 21:38:06 +00001962 if (image->type != UndefinedType)
cristy3ed852e2009-09-05 21:47:34 +00001963 {
1964 (void) FormatMagickString(buffer,MaxTextExtent,"type=%s\n",
cristy042ee782011-04-22 18:48:30 +00001965 CommandOptionToMnemonic(MagickTypeOptions,image->type));
cristy3ed852e2009-09-05 21:47:34 +00001966 (void) WriteBlobString(image,buffer);
1967 }
1968 if (image->colorspace != UndefinedColorspace)
1969 {
1970 (void) FormatMagickString(buffer,MaxTextExtent,"colorspace=%s\n",
cristy042ee782011-04-22 18:48:30 +00001971 CommandOptionToMnemonic(MagickColorspaceOptions,image->colorspace));
cristy3ed852e2009-09-05 21:47:34 +00001972 (void) WriteBlobString(image,buffer);
1973 }
1974 if (compression != UndefinedCompression)
1975 {
1976 (void) FormatMagickString(buffer,MaxTextExtent,"compression=%s "
cristy042ee782011-04-22 18:48:30 +00001977 "quality=%.20g\n",CommandOptionToMnemonic(MagickCompressOptions,
cristye8c25f92010-06-03 00:53:06 +00001978 compression),(double) image->quality);
cristy3ed852e2009-09-05 21:47:34 +00001979 (void) WriteBlobString(image,buffer);
1980 }
1981 if (image->units != UndefinedResolution)
1982 {
1983 (void) FormatMagickString(buffer,MaxTextExtent,"units=%s\n",
cristy042ee782011-04-22 18:48:30 +00001984 CommandOptionToMnemonic(MagickResolutionOptions,image->units));
cristy3ed852e2009-09-05 21:47:34 +00001985 (void) WriteBlobString(image,buffer);
1986 }
1987 if ((image->x_resolution != 0) || (image->y_resolution != 0))
1988 {
cristy8cd5b312010-01-07 01:10:24 +00001989 (void) FormatMagickString(buffer,MaxTextExtent,
cristye7f51092010-01-17 00:39:37 +00001990 "resolution=%gx%g\n",image->x_resolution,image->y_resolution);
cristy3ed852e2009-09-05 21:47:34 +00001991 (void) WriteBlobString(image,buffer);
1992 }
1993 if ((image->page.width != 0) || (image->page.height != 0))
1994 {
cristye8c25f92010-06-03 00:53:06 +00001995 (void) FormatMagickString(buffer,MaxTextExtent,
1996 "page=%.20gx%.20g%+.20g%+.20g\n",(double) image->page.width,(double)
1997 image->page.height,(double) image->page.x,(double) image->page.y);
cristy3ed852e2009-09-05 21:47:34 +00001998 (void) WriteBlobString(image,buffer);
1999 }
2000 else
2001 if ((image->page.x != 0) || (image->page.y != 0))
2002 {
2003 (void) FormatMagickString(buffer,MaxTextExtent,"page=%+ld%+ld\n",
cristyf2faecf2010-05-28 19:19:36 +00002004 (long) image->page.x,(long) image->page.y);
cristy3ed852e2009-09-05 21:47:34 +00002005 (void) WriteBlobString(image,buffer);
2006 }
2007 if ((image->tile_offset.x != 0) || (image->tile_offset.y != 0))
2008 {
2009 (void) FormatMagickString(buffer,MaxTextExtent,"tile-offset=%+ld%+ld\n",
cristyf2faecf2010-05-28 19:19:36 +00002010 (long) image->tile_offset.x,(long) image->tile_offset.y);
cristy3ed852e2009-09-05 21:47:34 +00002011 (void) WriteBlobString(image,buffer);
2012 }
2013 if ((GetNextImageInList(image) != (Image *) NULL) ||
2014 (GetPreviousImageInList(image) != (Image *) NULL))
2015 {
2016 if (image->scene == 0)
cristye8c25f92010-06-03 00:53:06 +00002017 (void) FormatMagickString(buffer,MaxTextExtent,"iterations=%.20g "
2018 "delay=%.20g ticks-per-second=%.20g\n",(double) image->iterations,
2019 (double) image->delay,(double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002020 else
cristye8c25f92010-06-03 00:53:06 +00002021 (void) FormatMagickString(buffer,MaxTextExtent,"scene=%.20g "
2022 "iterations=%.20g delay=%.20g ticks-per-second=%.20g\n",(double)
2023 image->scene,(double) image->iterations,(double) image->delay,
2024 (double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002025 (void) WriteBlobString(image,buffer);
2026 }
2027 else
2028 {
2029 if (image->scene != 0)
2030 {
cristye8c25f92010-06-03 00:53:06 +00002031 (void) FormatMagickString(buffer,MaxTextExtent,"scene=%.20g\n",
2032 (double) image->scene);
cristy3ed852e2009-09-05 21:47:34 +00002033 (void) WriteBlobString(image,buffer);
2034 }
2035 if (image->iterations != 0)
2036 {
cristye8c25f92010-06-03 00:53:06 +00002037 (void) FormatMagickString(buffer,MaxTextExtent,"iterations=%.20g\n",
2038 (double) image->iterations);
cristy3ed852e2009-09-05 21:47:34 +00002039 (void) WriteBlobString(image,buffer);
2040 }
2041 if (image->delay != 0)
2042 {
cristye8c25f92010-06-03 00:53:06 +00002043 (void) FormatMagickString(buffer,MaxTextExtent,"delay=%.20g\n",
2044 (double) image->delay);
cristy3ed852e2009-09-05 21:47:34 +00002045 (void) WriteBlobString(image,buffer);
2046 }
2047 if (image->ticks_per_second != UndefinedTicksPerSecond)
2048 {
2049 (void) FormatMagickString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00002050 "ticks-per-second=%.20g\n",(double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002051 (void) WriteBlobString(image,buffer);
2052 }
2053 }
2054 if (image->gravity != UndefinedGravity)
2055 {
2056 (void) FormatMagickString(buffer,MaxTextExtent,"gravity=%s\n",
cristy042ee782011-04-22 18:48:30 +00002057 CommandOptionToMnemonic(MagickGravityOptions,image->gravity));
cristy3ed852e2009-09-05 21:47:34 +00002058 (void) WriteBlobString(image,buffer);
2059 }
2060 if (image->dispose != UndefinedDispose)
2061 {
2062 (void) FormatMagickString(buffer,MaxTextExtent,"dispose=%s\n",
cristy042ee782011-04-22 18:48:30 +00002063 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
cristy3ed852e2009-09-05 21:47:34 +00002064 (void) WriteBlobString(image,buffer);
2065 }
2066 if (image->rendering_intent != UndefinedIntent)
2067 {
2068 (void) FormatMagickString(buffer,MaxTextExtent,
2069 "rendering-intent=%s\n",
cristy042ee782011-04-22 18:48:30 +00002070 CommandOptionToMnemonic(MagickIntentOptions,image->rendering_intent));
cristy3ed852e2009-09-05 21:47:34 +00002071 (void) WriteBlobString(image,buffer);
2072 }
2073 if (image->gamma != 0.0)
2074 {
cristye7f51092010-01-17 00:39:37 +00002075 (void) FormatMagickString(buffer,MaxTextExtent,"gamma=%g\n",
cristy3ed852e2009-09-05 21:47:34 +00002076 image->gamma);
2077 (void) WriteBlobString(image,buffer);
2078 }
2079 if (image->chromaticity.white_point.x != 0.0)
2080 {
2081 /*
2082 Note chomaticity points.
2083 */
cristye7f51092010-01-17 00:39:37 +00002084 (void) FormatMagickString(buffer,MaxTextExtent,"red-primary=%g,"
2085 "%g green-primary=%g,%g blue-primary=%g,%g\n",
cristy3ed852e2009-09-05 21:47:34 +00002086 image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
2087 image->chromaticity.green_primary.x,
2088 image->chromaticity.green_primary.y,
2089 image->chromaticity.blue_primary.x,
2090 image->chromaticity.blue_primary.y);
2091 (void) WriteBlobString(image,buffer);
cristy8cd5b312010-01-07 01:10:24 +00002092 (void) FormatMagickString(buffer,MaxTextExtent,
cristye7f51092010-01-17 00:39:37 +00002093 "white-point=%g,%g\n",image->chromaticity.white_point.x,
cristy8cd5b312010-01-07 01:10:24 +00002094 image->chromaticity.white_point.y);
cristy3ed852e2009-09-05 21:47:34 +00002095 (void) WriteBlobString(image,buffer);
2096 }
2097 if (image->orientation != UndefinedOrientation)
2098 {
2099 (void) FormatMagickString(buffer,MaxTextExtent,"orientation=%s\n",
cristy042ee782011-04-22 18:48:30 +00002100 CommandOptionToMnemonic(MagickOrientationOptions,image->orientation));
cristy3ed852e2009-09-05 21:47:34 +00002101 (void) WriteBlobString(image,buffer);
2102 }
2103 if (image->profiles != (void *) NULL)
2104 {
2105 const char
2106 *name;
2107
2108 const StringInfo
2109 *profile;
2110
2111 /*
2112 Write image profiles.
2113 */
2114 ResetImageProfileIterator(image);
2115 name=GetNextImageProfile(image);
2116 while (name != (const char *) NULL)
2117 {
2118 profile=GetImageProfile(image,name);
2119 if (profile != (StringInfo *) NULL)
2120 {
cristye8c25f92010-06-03 00:53:06 +00002121 (void) FormatMagickString(buffer,MaxTextExtent,
2122 "profile:%s=%.20g\n",name,(double)
2123 GetStringInfoLength(profile));
cristy3ed852e2009-09-05 21:47:34 +00002124 (void) WriteBlobString(image,buffer);
2125 }
2126 name=GetNextImageProfile(image);
2127 }
2128 }
2129 if (image->montage != (char *) NULL)
2130 {
2131 (void) FormatMagickString(buffer,MaxTextExtent,"montage=%s\n",
2132 image->montage);
2133 (void) WriteBlobString(image,buffer);
2134 }
2135 if (quantum_info->format == FloatingPointQuantumFormat)
cristy0c2fcca2009-10-16 01:37:20 +00002136 (void) SetImageProperty(image,"quantum:format","floating-point");
cristy3ed852e2009-09-05 21:47:34 +00002137 ResetImagePropertyIterator(image);
2138 property=GetNextImageProperty(image);
2139 while (property != (const char *) NULL)
2140 {
2141 (void) FormatMagickString(buffer,MaxTextExtent,"%s=",property);
2142 (void) WriteBlobString(image,buffer);
2143 value=GetImageProperty(image,property);
2144 if (value != (const char *) NULL)
2145 {
cristybb503372010-05-27 20:51:26 +00002146 for (i=0; i < (ssize_t) strlen(value); i++)
cristy3ed852e2009-09-05 21:47:34 +00002147 if (isspace((int) ((unsigned char) value[i])) != 0)
2148 break;
cristybb503372010-05-27 20:51:26 +00002149 if (i <= (ssize_t) strlen(value))
cristy3ed852e2009-09-05 21:47:34 +00002150 (void) WriteBlobByte(image,'{');
2151 (void) WriteBlob(image,strlen(value),(const unsigned char *) value);
cristybb503372010-05-27 20:51:26 +00002152 if (i <= (ssize_t) strlen(value))
cristy3ed852e2009-09-05 21:47:34 +00002153 (void) WriteBlobByte(image,'}');
2154 }
2155 (void) WriteBlobByte(image,'\n');
2156 property=GetNextImageProperty(image);
2157 }
2158 (void) WriteBlobString(image,"\f\n:\032");
2159 if (image->montage != (char *) NULL)
2160 {
2161 /*
2162 Write montage tile directory.
2163 */
2164 if (image->directory != (char *) NULL)
2165 (void) WriteBlob(image,strlen(image->directory),(unsigned char *)
2166 image->directory);
2167 (void) WriteBlobByte(image,'\0');
2168 }
2169 if (image->profiles != (void *) NULL)
2170 {
2171 const char
2172 *name;
2173
2174 const StringInfo
2175 *profile;
2176
2177 /*
2178 Generic profile.
2179 */
2180 ResetImageProfileIterator(image);
2181 name=GetNextImageProfile(image);
2182 while (name != (const char *) NULL)
2183 {
2184 profile=GetImageProfile(image,name);
2185 (void) WriteBlob(image,GetStringInfoLength(profile),
2186 GetStringInfoDatum(profile));
2187 name=GetNextImageProfile(image);
2188 }
2189 }
2190 if (image->storage_class == PseudoClass)
2191 {
2192 size_t
2193 packet_size;
2194
2195 unsigned char
2196 *colormap,
2197 *q;
2198
2199 /*
2200 Allocate colormap.
2201 */
2202 packet_size=(size_t) (3*quantum_info->depth/8);
2203 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
2204 packet_size*sizeof(*colormap));
2205 if (colormap == (unsigned char *) NULL)
2206 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2207 /*
2208 Write colormap to file.
2209 */
2210 q=colormap;
cristybb503372010-05-27 20:51:26 +00002211 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00002212 {
2213 switch (quantum_info->depth)
2214 {
2215 default:
2216 ThrowWriterException(CorruptImageError,"ImageDepthNotSupported");
2217 case 32:
2218 {
cristy4cb162a2010-05-30 03:04:47 +00002219 register unsigned int
cristy3ed852e2009-09-05 21:47:34 +00002220 pixel;
2221
2222 pixel=ScaleQuantumToLong(image->colormap[i].red);
2223 q=PopLongPixel(MSBEndian,pixel,q);
2224 pixel=ScaleQuantumToLong(image->colormap[i].green);
2225 q=PopLongPixel(MSBEndian,pixel,q);
2226 pixel=ScaleQuantumToLong(image->colormap[i].blue);
2227 q=PopLongPixel(MSBEndian,pixel,q);
2228 break;
2229 }
2230 case 16:
2231 {
2232 register unsigned short
2233 pixel;
2234
2235 pixel=ScaleQuantumToShort(image->colormap[i].red);
2236 q=PopShortPixel(MSBEndian,pixel,q);
2237 pixel=ScaleQuantumToShort(image->colormap[i].green);
2238 q=PopShortPixel(MSBEndian,pixel,q);
2239 pixel=ScaleQuantumToShort(image->colormap[i].blue);
2240 q=PopShortPixel(MSBEndian,pixel,q);
2241 break;
2242 }
2243 case 8:
2244 {
2245 register unsigned char
2246 pixel;
2247
2248 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].red);
2249 q=PopCharPixel(pixel,q);
2250 pixel=(unsigned char) ScaleQuantumToChar(
2251 image->colormap[i].green);
2252 q=PopCharPixel(pixel,q);
2253 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].blue);
2254 q=PopCharPixel(pixel,q);
2255 break;
2256 }
2257 }
2258 }
2259 (void) WriteBlob(image,packet_size*image->colors,colormap);
2260 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
2261 }
2262 /*
2263 Write image pixels to file.
2264 */
cristy330af6c2010-12-21 14:36:06 +00002265 status=MagickTrue;
2266 switch (compression)
2267 {
2268#if defined(MAGICKCORE_BZLIB_DELEGATE)
2269 case BZipCompression:
2270 {
2271 (void) ResetMagickMemory(&bzip_info,0,sizeof(bzip_info));
2272 bzip_info.bzalloc=AcquireBZIPMemory;
2273 bzip_info.bzfree=RelinquishBZIPMemory;
2274 code=BZ2_bzCompressInit(&bzip_info,(int) (image->quality ==
2275 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,
2276 9)),(int) image_info->verbose,0);
2277 if (code != BZ_OK)
2278 status=MagickFalse;
2279 break;
2280 }
2281#endif
2282#if defined(MAGICKCORE_LZMA_DELEGATE)
2283 case LZMACompression:
2284 {
cristy330af6c2010-12-21 14:36:06 +00002285 (void) ResetMagickMemory(&allocator,0,sizeof(allocator));
2286 allocator.alloc=AcquireLZMAMemory;
2287 allocator.free=RelinquishLZMAMemory;
cristy9d72f1a2010-12-21 20:46:59 +00002288 lzma_info=initialize_lzma;
cristy330af6c2010-12-21 14:36:06 +00002289 lzma_info.allocator=&allocator;
cristy9d72f1a2010-12-21 20:46:59 +00002290 code=lzma_easy_encoder(&lzma_info,image->quality/10,LZMA_CHECK_SHA256);
2291 if (code != LZMA_OK)
2292 status=MagickTrue;
cristy330af6c2010-12-21 14:36:06 +00002293 break;
2294 }
2295#endif
2296#if defined(MAGICKCORE_ZLIB_DELEGATE)
2297 case LZWCompression:
2298 case ZipCompression:
2299 {
2300 (void) ResetMagickMemory(&zip_info,0,sizeof(zip_info));
2301 zip_info.zalloc=AcquireZIPMemory;
2302 zip_info.zfree=RelinquishZIPMemory;
2303 code=deflateInit(&zip_info,(int) (image->quality ==
2304 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9)));
2305 if (code != Z_OK)
2306 status=MagickFalse;
2307 break;
2308 }
2309#endif
2310 default:
2311 break;
2312 }
cristy3ed852e2009-09-05 21:47:34 +00002313 quantum_type=GetQuantumType(image,&image->exception);
2314 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002315 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002316 {
2317 register const IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002318 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002319
2320 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002321 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002322
cristybb503372010-05-27 20:51:26 +00002323 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002324 x;
2325
cristy330af6c2010-12-21 14:36:06 +00002326 if (status == MagickFalse)
2327 break;
cristy3ed852e2009-09-05 21:47:34 +00002328 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2329 if (p == (const PixelPacket *) NULL)
2330 break;
2331 indexes=GetVirtualIndexQueue(image);
2332 q=pixels;
2333 switch (compression)
2334 {
cristy3ed852e2009-09-05 21:47:34 +00002335#if defined(MAGICKCORE_BZLIB_DELEGATE)
2336 case BZipCompression:
2337 {
cristy3ed852e2009-09-05 21:47:34 +00002338 bzip_info.next_in=(char *) pixels;
2339 bzip_info.avail_in=(unsigned int) (packet_size*image->columns);
cristy74fe8f12009-10-03 19:09:01 +00002340 (void) ExportQuantumPixels(image,(const CacheView *) NULL,
2341 quantum_info,quantum_type,pixels,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002342 do
2343 {
2344 bzip_info.next_out=(char *) compress_pixels;
2345 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2346 image->columns);
2347 code=BZ2_bzCompress(&bzip_info,BZ_FLUSH);
cristy26377172010-12-20 19:01:58 +00002348 if (code != BZ_OK)
2349 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00002350 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2351 if (length != 0)
2352 {
2353 (void) WriteBlobMSBLong(image,(unsigned int) length);
2354 (void) WriteBlob(image,length,compress_pixels);
2355 }
2356 } while (bzip_info.avail_in != 0);
cristy26377172010-12-20 19:01:58 +00002357 break;
2358 }
2359#endif
2360#if defined(MAGICKCORE_LZMA_DELEGATE)
2361 case LZMACompression:
2362 {
cristy26377172010-12-20 19:01:58 +00002363 lzma_info.next_in=pixels;
cristy330af6c2010-12-21 14:36:06 +00002364 lzma_info.avail_in=packet_size*image->columns;
cristy26377172010-12-20 19:01:58 +00002365 (void) ExportQuantumPixels(image,(const CacheView *) NULL,
2366 quantum_info,quantum_type,pixels,&image->exception);
2367 do
2368 {
2369 lzma_info.next_out=compress_pixels;
2370 lzma_info.avail_out=packet_size*image->columns;
2371 code=lzma_code(&lzma_info,LZMA_RUN);
2372 if (code != LZMA_OK)
2373 status=MagickFalse;
2374 length=(size_t) (lzma_info.next_out-compress_pixels);
2375 if (length != 0)
2376 {
2377 (void) WriteBlobMSBLong(image,(unsigned int) length);
2378 (void) WriteBlob(image,length,compress_pixels);
2379 }
2380 } while (lzma_info.avail_in != 0);
cristy26377172010-12-20 19:01:58 +00002381 break;
2382 }
2383#endif
2384#if defined(MAGICKCORE_ZLIB_DELEGATE)
2385 case LZWCompression:
2386 case ZipCompression:
2387 {
cristy26377172010-12-20 19:01:58 +00002388 zip_info.next_in=pixels;
2389 zip_info.avail_in=(uInt) (packet_size*image->columns);
2390 (void) ExportQuantumPixels(image,(const CacheView *) NULL,
2391 quantum_info,quantum_type,pixels,&image->exception);
2392 do
2393 {
2394 zip_info.next_out=compress_pixels;
2395 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns);
2396 code=deflate(&zip_info,Z_SYNC_FLUSH);
2397 if (code != Z_OK)
2398 status=MagickFalse;
2399 length=(size_t) (zip_info.next_out-compress_pixels);
2400 if (length != 0)
2401 {
2402 (void) WriteBlobMSBLong(image,(unsigned int) length);
2403 (void) WriteBlob(image,length,compress_pixels);
2404 }
2405 } while (zip_info.avail_in != 0);
cristy3ed852e2009-09-05 21:47:34 +00002406 break;
2407 }
2408#endif
2409 case RLECompression:
2410 {
2411 pixel=(*p);
2412 index=(IndexPacket) 0;
2413 if (indexes != (IndexPacket *) NULL)
2414 index=(*indexes);
2415 length=255;
cristybb503372010-05-27 20:51:26 +00002416 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002417 {
cristybb503372010-05-27 20:51:26 +00002418 if ((length < 255) && (x < (ssize_t) (image->columns-1)) &&
cristy3ed852e2009-09-05 21:47:34 +00002419 (IsColorEqual(p,&pixel) != MagickFalse) &&
2420 ((image->matte == MagickFalse) ||
cristyd05ecd12011-04-22 20:44:42 +00002421 (GetOpacityPixelComponent(p) == pixel.opacity)) &&
cristy9fff7b42011-04-29 01:09:31 +00002422 ((indexes == (IndexPacket *) NULL) ||
2423 (index == GetIndexPixelComponent(indexes+x))))
cristy3ed852e2009-09-05 21:47:34 +00002424 length++;
2425 else
2426 {
2427 if (x > 0)
2428 q=PopRunlengthPacket(image,q,length,pixel,index);
2429 length=0;
2430 }
2431 pixel=(*p);
2432 if (indexes != (IndexPacket *) NULL)
cristyaff6d802011-04-26 01:46:31 +00002433 index=GetIndexPixelComponent(indexes+x);
cristy3ed852e2009-09-05 21:47:34 +00002434 p++;
2435 }
2436 q=PopRunlengthPacket(image,q,length,pixel,index);
2437 (void) WriteBlob(image,(size_t) (q-pixels),pixels);
2438 break;
2439 }
2440 default:
2441 {
2442 (void) ExportQuantumPixels(image,(const CacheView *) NULL,
2443 quantum_info,quantum_type,pixels,&image->exception);
2444 (void) WriteBlob(image,packet_size*image->columns,pixels);
2445 break;
2446 }
2447 }
cristycee97112010-05-28 00:44:52 +00002448 if (image->previous == (Image *) NULL)
2449 {
2450 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2451 image->rows);
2452 if (status == MagickFalse)
2453 break;
2454 }
cristy3ed852e2009-09-05 21:47:34 +00002455 }
cristy330af6c2010-12-21 14:36:06 +00002456 switch (compression)
2457 {
2458#if defined(MAGICKCORE_BZLIB_DELEGATE)
2459 case BZipCompression:
2460 {
2461 for ( ; ; )
2462 {
2463 if (status == MagickFalse)
2464 break;
2465 bzip_info.next_out=(char *) compress_pixels;
2466 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2467 image->columns);
2468 code=BZ2_bzCompress(&bzip_info,BZ_FINISH);
2469 if (code != BZ_OK)
2470 status=MagickFalse;
2471 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2472 if (length != 0)
2473 {
2474 (void) WriteBlobMSBLong(image,(unsigned int) length);
2475 (void) WriteBlob(image,length,compress_pixels);
2476 }
2477 if (code == BZ_STREAM_END)
2478 break;
2479 }
2480 code=BZ2_bzCompressEnd(&bzip_info);
2481 if (code != BZ_OK)
2482 status=MagickFalse;
2483 break;
2484 }
2485#endif
2486#if defined(MAGICKCORE_LZMA_DELEGATE)
2487 case LZMACompression:
2488 {
2489 for ( ; ; )
2490 {
2491 if (status == MagickFalse)
2492 break;
2493 lzma_info.next_out=compress_pixels;
2494 lzma_info.avail_out=packet_size*image->columns;
2495 code=lzma_code(&lzma_info,LZMA_FINISH);
2496 if (code != LZMA_OK)
2497 status=MagickFalse;
2498 length=(size_t) (lzma_info.next_out-compress_pixels);
2499 if (length > 6)
2500 {
2501 (void) WriteBlobMSBLong(image,(unsigned int) length);
2502 (void) WriteBlob(image,length,compress_pixels);
2503 }
2504 if (code == LZMA_STREAM_END)
2505 break;
2506 }
2507 lzma_end(&lzma_info);
2508 break;
2509 }
2510#endif
2511#if defined(MAGICKCORE_ZLIB_DELEGATE)
2512 case LZWCompression:
2513 case ZipCompression:
2514 {
2515 for ( ; ; )
2516 {
2517 if (status == MagickFalse)
2518 break;
2519 zip_info.next_out=compress_pixels;
2520 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*
2521 image->columns);
2522 code=deflate(&zip_info,Z_FINISH);
2523 if (code != Z_OK)
2524 status=MagickFalse;
2525 length=(size_t) (zip_info.next_out-compress_pixels);
2526 if (length > 6)
2527 {
2528 (void) WriteBlobMSBLong(image,(unsigned int) length);
2529 (void) WriteBlob(image,length,compress_pixels);
2530 }
2531 if (code == Z_STREAM_END)
2532 break;
2533 }
2534 code=deflateEnd(&zip_info);
2535 if (code != Z_OK)
2536 status=MagickFalse;
2537 break;
2538 }
2539#endif
2540 default:
2541 break;
2542 }
cristy3ed852e2009-09-05 21:47:34 +00002543 quantum_info=DestroyQuantumInfo(quantum_info);
2544 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
2545 if (GetNextImageInList(image) == (Image *) NULL)
2546 break;
2547 image=SyncNextImageInList(image);
2548 status=SetImageProgress(image,SaveImagesTag,scene++,
2549 GetImageListLength(image));
2550 if (status == MagickFalse)
2551 break;
2552 } while (image_info->adjoin != MagickFalse);
2553 (void) CloseBlob(image);
2554 return(status);
2555}