1 /*
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 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38
39 /*
40 Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/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/colorspace-private.h"
53 #include "MagickCore/constitute.h"
54 #include "MagickCore/exception.h"
55 #include "MagickCore/exception-private.h"
56 #include "MagickCore/geometry.h"
57 #include "MagickCore/image.h"
58 #include "MagickCore/image-private.h"
59 #include "MagickCore/linked-list.h"
60 #include "MagickCore/list.h"
61 #include "MagickCore/magick.h"
62 #include "MagickCore/memory_.h"
63 #include "MagickCore/memory-private.h"
64 #include "MagickCore/module.h"
65 #include "MagickCore/monitor.h"
66 #include "MagickCore/monitor-private.h"
67 #include "MagickCore/option.h"
68 #include "MagickCore/pixel.h"
69 #include "MagickCore/pixel-accessor.h"
70 #include "MagickCore/profile.h"
71 #include "MagickCore/property.h"
72 #include "MagickCore/quantum-private.h"
73 #include "MagickCore/static.h"
74 #include "MagickCore/statistic.h"
75 #include "MagickCore/string_.h"
76 #include "MagickCore/string-private.h"
77 #if defined(MAGICKCORE_BZLIB_DELEGATE)
78 #include "bzlib.h"
79 #endif
80 #if defined(MAGICKCORE_LZMA_DELEGATE)
81 #include "lzma.h"
82 #endif
83 #if defined(MAGICKCORE_ZLIB_DELEGATE)
84 #include "zlib.h"
85 #endif
86
87 /*
88 Define declarations.
89 */
90 #if !defined(LZMA_OK)
91 #define LZMA_OK 0
92 #endif
93
94 /*
95 Forward declarations.
96 */
97 static MagickBooleanType
98 WriteMIFFImage(const ImageInfo *,Image *,ExceptionInfo *);
99
100 /*
101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102 % %
103 % %
104 % %
105 % I s M I F F %
106 % %
107 % %
108 % %
109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110 %
111 % IsMIFF() returns MagickTrue if the image format type, identified by the
112 % magick string, is MIFF.
113 %
114 % The format of the IsMIFF method is:
115 %
116 % MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
117 %
118 % A description of each parameter follows:
119 %
120 % o magick: compare image format pattern against these bytes.
121 %
122 % o length: Specifies the length of the magick string.
123 %
124 */
IsMIFF(const unsigned char * magick,const size_t length)125 static MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
126 {
127 if (length < 14)
128 return(MagickFalse);
129 if (LocaleNCompare((const char *) magick,"id=ImageMagick",14) == 0)
130 return(MagickTrue);
131 return(MagickFalse);
132 }
133
134 /*
135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136 % %
137 % %
138 % %
139 % R e a d M I F F I m a g e %
140 % %
141 % %
142 % %
143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144 %
145 % ReadMIFFImage() reads a MIFF image file and returns it. It allocates the
146 % memory necessary for the new Image structure and returns a pointer to the
147 % new image.
148 %
149 % The format of the ReadMIFFImage method is:
150 %
151 % Image *ReadMIFFImage(const ImageInfo *image_info,
152 % ExceptionInfo *exception)
153 %
154 % Decompression code contributed by Kyle Shorter.
155 %
156 % A description of each parameter follows:
157 %
158 % o image_info: the image info.
159 %
160 % o exception: return any errors or warnings in this structure.
161 %
162 */
163
164 #if defined(MAGICKCORE_BZLIB_DELEGATE) || defined(MAGICKCORE_LZMA_DELEGATE) || defined(MAGICKCORE_ZLIB_DELEGATE)
AcquireCompressionMemory(void * context,const size_t items,const size_t size)165 static void *AcquireCompressionMemory(void *context,const size_t items,
166 const size_t size)
167 {
168 size_t
169 extent;
170
171 (void) context;
172 if (HeapOverflowSanityCheck(items,size) != MagickFalse)
173 return((void *) NULL);
174 extent=items*size;
175 if (extent > GetMaxMemoryRequest())
176 return((void *) NULL);
177 return(AcquireMagickMemory(extent));
178 }
179 #endif
180
181 #if defined(MAGICKCORE_BZLIB_DELEGATE)
182 static void *AcquireBZIPMemory(void *,int,int) magick_attribute((__malloc__));
183
AcquireBZIPMemory(void * context,int items,int size)184 static void *AcquireBZIPMemory(void *context,int items,int size)
185 {
186 return(AcquireCompressionMemory(context,(size_t) items,(size_t) size));
187 }
188 #endif
189
190 #if defined(MAGICKCORE_LZMA_DELEGATE)
191 static void *AcquireLZMAMemory(void *,size_t,size_t)
192 magick_attribute((__malloc__));
193
AcquireLZMAMemory(void * context,size_t items,size_t size)194 static void *AcquireLZMAMemory(void *context,size_t items,size_t size)
195 {
196 return(AcquireCompressionMemory(context,items,size));
197 }
198 #endif
199
200 #if defined(MAGICKCORE_ZLIB_DELEGATE)
201 static voidpf AcquireZIPMemory(voidpf,unsigned int,unsigned int)
202 magick_attribute((__malloc__));
203
AcquireZIPMemory(voidpf context,unsigned int items,unsigned int size)204 static voidpf AcquireZIPMemory(voidpf context,unsigned int items,
205 unsigned int size)
206 {
207 return((voidpf) AcquireCompressionMemory(context,(size_t) items,
208 (size_t) size));
209 }
210 #endif
211
PushRunlengthPacket(Image * image,const unsigned char * pixels,size_t * length,PixelInfo * pixel,ExceptionInfo * exception)212 static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
213 size_t *length,PixelInfo *pixel,ExceptionInfo *exception)
214 {
215 const unsigned char
216 *p;
217
218 p=pixels;
219 if (image->storage_class == PseudoClass)
220 {
221 pixel->index=0.0;
222 switch (image->depth)
223 {
224 case 32:
225 {
226 pixel->index=(MagickRealType) ConstrainColormapIndex(image,(ssize_t)
227 (((size_t) *p << 24) | ((size_t) *(p+1) << 16) |
228 ((size_t) *(p+2) << 8) | (size_t) *(p+3)),exception);
229 p+=4;
230 break;
231 }
232 case 16:
233 {
234 pixel->index=(MagickRealType) ConstrainColormapIndex(image,(ssize_t)
235 ((*p << 8) | *(p+1)),exception);
236 p+=2;
237 break;
238 }
239 case 8:
240 {
241 pixel->index=(MagickRealType) ConstrainColormapIndex(image,
242 (ssize_t) *p,exception);
243 p++;
244 break;
245 }
246 default:
247 (void) ThrowMagickException(exception,GetMagickModule(),
248 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
249 }
250 switch (image->depth)
251 {
252 case 8:
253 {
254 unsigned char
255 quantum;
256
257 if (image->alpha_trait != UndefinedPixelTrait)
258 {
259 p=PushCharPixel(p,&quantum);
260 pixel->alpha=(MagickRealType) ScaleCharToQuantum(quantum);
261 }
262 break;
263 }
264 case 16:
265 {
266 unsigned short
267 quantum;
268
269 if (image->alpha_trait != UndefinedPixelTrait)
270 {
271 p=PushShortPixel(MSBEndian,p,&quantum);
272 pixel->alpha=(MagickRealType) (quantum >> (image->depth-
273 MAGICKCORE_QUANTUM_DEPTH));
274 }
275 break;
276 }
277 case 32:
278 {
279 unsigned int
280 quantum;
281
282 if (image->alpha_trait != UndefinedPixelTrait)
283 {
284 p=PushLongPixel(MSBEndian,p,&quantum);
285 pixel->alpha=(MagickRealType) (quantum >> (image->depth-
286 MAGICKCORE_QUANTUM_DEPTH));
287 }
288 break;
289 }
290 default:
291 (void) ThrowMagickException(exception,GetMagickModule(),
292 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
293 }
294 *length=(size_t) (*p++)+1;
295 return;
296 }
297 switch (image->depth)
298 {
299 case 8:
300 {
301 unsigned char
302 quantum;
303
304 p=PushCharPixel(p,&quantum);
305 pixel->red=(MagickRealType) ScaleCharToQuantum(quantum);
306 pixel->green=pixel->red;
307 pixel->blue=pixel->red;
308 if (IsGrayColorspace(image->colorspace) == MagickFalse)
309 {
310 p=PushCharPixel(p,&quantum);
311 pixel->green=(MagickRealType) ScaleCharToQuantum(quantum);
312 p=PushCharPixel(p,&quantum);
313 pixel->blue=(MagickRealType) ScaleCharToQuantum(quantum);
314 }
315 if (image->colorspace == CMYKColorspace)
316 {
317 p=PushCharPixel(p,&quantum);
318 pixel->black=(MagickRealType) ScaleCharToQuantum(quantum);
319 }
320 if (image->alpha_trait != UndefinedPixelTrait)
321 {
322 p=PushCharPixel(p,&quantum);
323 pixel->alpha=(MagickRealType) ScaleCharToQuantum(quantum);
324 }
325 break;
326 }
327 case 16:
328 {
329 unsigned short
330 quantum;
331
332 p=PushShortPixel(MSBEndian,p,&quantum);
333 pixel->red=(MagickRealType) (quantum >> (image->depth-
334 MAGICKCORE_QUANTUM_DEPTH));
335 pixel->green=pixel->red;
336 pixel->blue=pixel->red;
337 if (IsGrayColorspace(image->colorspace) == MagickFalse)
338 {
339 p=PushShortPixel(MSBEndian,p,&quantum);
340 pixel->green=(MagickRealType) (quantum >> (image->depth-
341 MAGICKCORE_QUANTUM_DEPTH));
342 p=PushShortPixel(MSBEndian,p,&quantum);
343 pixel->blue=(MagickRealType) (quantum >> (image->depth-
344 MAGICKCORE_QUANTUM_DEPTH));
345 }
346 if (image->colorspace == CMYKColorspace)
347 {
348 p=PushShortPixel(MSBEndian,p,&quantum);
349 pixel->black=(MagickRealType) (quantum >> (image->depth-
350 MAGICKCORE_QUANTUM_DEPTH));
351 }
352 if (image->alpha_trait != UndefinedPixelTrait)
353 {
354 p=PushShortPixel(MSBEndian,p,&quantum);
355 pixel->alpha=(MagickRealType) (quantum >> (image->depth-
356 MAGICKCORE_QUANTUM_DEPTH));
357 }
358 break;
359 }
360 case 32:
361 {
362 unsigned int
363 quantum;
364
365 p=PushLongPixel(MSBEndian,p,&quantum);
366 pixel->red=(MagickRealType) (quantum >> (image->depth-
367 MAGICKCORE_QUANTUM_DEPTH));
368 pixel->green=pixel->red;
369 pixel->blue=pixel->red;
370 if (IsGrayColorspace(image->colorspace) == MagickFalse)
371 {
372 p=PushLongPixel(MSBEndian,p,&quantum);
373 pixel->green=(MagickRealType) (quantum >> (image->depth-
374 MAGICKCORE_QUANTUM_DEPTH));
375 p=PushLongPixel(MSBEndian,p,&quantum);
376 pixel->blue=(MagickRealType) (quantum >> (image->depth-
377 MAGICKCORE_QUANTUM_DEPTH));
378 }
379 if (image->colorspace == CMYKColorspace)
380 {
381 p=PushLongPixel(MSBEndian,p,&quantum);
382 pixel->black=(MagickRealType) (quantum >> (image->depth-
383 MAGICKCORE_QUANTUM_DEPTH));
384 }
385 if (image->alpha_trait != UndefinedPixelTrait)
386 {
387 p=PushLongPixel(MSBEndian,p,&quantum);
388 pixel->alpha=(MagickRealType) (quantum >> (image->depth-
389 MAGICKCORE_QUANTUM_DEPTH));
390 }
391 break;
392 }
393 default:
394 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
395 "ImageDepthNotSupported","`%s'",image->filename);
396 }
397 *length=(size_t) (*p++)+1;
398 }
399
400 #if defined(MAGICKCORE_BZLIB_DELEGATE)
RelinquishBZIPMemory(void * context,void * memory)401 static void RelinquishBZIPMemory(void *context,void *memory)
402 {
403 (void) context;
404 memory=RelinquishMagickMemory(memory);
405 }
406 #endif
407
408 #if defined(MAGICKCORE_LZMA_DELEGATE)
RelinquishLZMAMemory(void * context,void * memory)409 static void RelinquishLZMAMemory(void *context,void *memory)
410 {
411 (void) context;
412 memory=RelinquishMagickMemory(memory);
413 }
414 #endif
415
416 #if defined(MAGICKCORE_ZLIB_DELEGATE)
RelinquishZIPMemory(voidpf context,voidpf memory)417 static void RelinquishZIPMemory(voidpf context,voidpf memory)
418 {
419 (void) context;
420 memory=RelinquishMagickMemory(memory);
421 }
422 #endif
423
ReadMIFFImage(const ImageInfo * image_info,ExceptionInfo * exception)424 static Image *ReadMIFFImage(const ImageInfo *image_info,
425 ExceptionInfo *exception)
426 {
427 #define BZipMaxExtent(x) ((x)+((x)/100)+600)
428 #define LZMAMaxExtent(x) ((x)+((x)/3)+128)
429 #define ThrowMIFFException(exception,message) \
430 { \
431 if (quantum_info != (QuantumInfo *) NULL) \
432 quantum_info=DestroyQuantumInfo(quantum_info); \
433 if (compress_pixels != (unsigned char *) NULL) \
434 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels); \
435 ThrowReaderException((exception),(message)); \
436 }
437 #define ZipMaxExtent(x) ((x)+(((x)+7) >> 3)+(((x)+63) >> 6)+11)
438
439 #if defined(MAGICKCORE_BZLIB_DELEGATE)
440 bz_stream
441 bzip_info;
442 #endif
443
444 char
445 id[MagickPathExtent],
446 keyword[MagickPathExtent],
447 *options;
448
449 double
450 version;
451
452 GeometryInfo
453 geometry_info;
454
455 Image
456 *image;
457
458 int
459 c;
460
461 LinkedListInfo
462 *profiles;
463
464 #if defined(MAGICKCORE_LZMA_DELEGATE)
465 lzma_stream
466 initialize_lzma = LZMA_STREAM_INIT,
467 lzma_info;
468
469 lzma_allocator
470 allocator;
471 #endif
472
473 MagickBooleanType
474 status;
475
476 PixelInfo
477 pixel;
478
479 MagickStatusType
480 flags;
481
482 QuantumFormatType
483 quantum_format;
484
485 QuantumInfo
486 *quantum_info;
487
488 QuantumType
489 quantum_type;
490
491 register ssize_t
492 i;
493
494 size_t
495 compress_extent,
496 extent,
497 length,
498 packet_size;
499
500 ssize_t
501 count;
502
503 unsigned char
504 *compress_pixels,
505 *pixels;
506
507 size_t
508 colors;
509
510 ssize_t
511 y;
512
513 #if defined(MAGICKCORE_ZLIB_DELEGATE)
514 z_stream
515 zip_info;
516 #endif
517
518 /*
519 Open image file.
520 */
521 assert(image_info != (const ImageInfo *) NULL);
522 assert(image_info->signature == MagickCoreSignature);
523 if (image_info->debug != MagickFalse)
524 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
525 image_info->filename);
526 assert(exception != (ExceptionInfo *) NULL);
527 assert(exception->signature == MagickCoreSignature);
528 image=AcquireImage(image_info,exception);
529 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
530 if (status == MagickFalse)
531 {
532 image=DestroyImageList(image);
533 return((Image *) NULL);
534 }
535 /*
536 Decode image header; header terminates one character beyond a ':'.
537 */
538 c=ReadBlobByte(image);
539 if (c == EOF)
540 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
541 *id='\0';
542 compress_pixels=(unsigned char *) NULL;
543 quantum_info=(QuantumInfo *) NULL;
544 (void) memset(keyword,0,sizeof(keyword));
545 version=0.0;
546 (void) version;
547 do
548 {
549 /*
550 Decode image header; header terminates one character beyond a ':'.
551 */
552 SetGeometryInfo(&geometry_info);
553 length=MagickPathExtent;
554 options=AcquireString((char *) NULL);
555 quantum_format=UndefinedQuantumFormat;
556 profiles=(LinkedListInfo *) NULL;
557 colors=0;
558 image->depth=8UL;
559 image->compression=NoCompression;
560 while ((isgraph(c) != MagickFalse) && (c != (int) ':'))
561 {
562 register char
563 *p;
564
565 if (c == (int) '{')
566 {
567 char
568 *comment;
569
570 /*
571 Read comment-- any text between { }.
572 */
573 length=MagickPathExtent;
574 comment=AcquireString((char *) NULL);
575 for (p=comment; comment != (char *) NULL; p++)
576 {
577 c=ReadBlobByte(image);
578 if (c == (int) '\\')
579 c=ReadBlobByte(image);
580 else
581 if ((c == EOF) || (c == (int) '}'))
582 break;
583 if ((size_t) (p-comment+1) >= length)
584 {
585 *p='\0';
586 length<<=1;
587 comment=(char *) ResizeQuantumMemory(comment,length+
588 MagickPathExtent,sizeof(*comment));
589 if (comment == (char *) NULL)
590 break;
591 p=comment+strlen(comment);
592 }
593 *p=(char) c;
594 }
595 if (comment == (char *) NULL)
596 {
597 options=DestroyString(options);
598 ThrowMIFFException(ResourceLimitError,"MemoryAllocationFailed");
599 }
600 *p='\0';
601 (void) SetImageProperty(image,"comment",comment,exception);
602 comment=DestroyString(comment);
603 c=ReadBlobByte(image);
604 }
605 else
606 if (isalnum(c) != MagickFalse)
607 {
608 /*
609 Get the keyword.
610 */
611 length=MagickPathExtent-1;
612 p=keyword;
613 do
614 {
615 if (c == (int) '=')
616 break;
617 if ((size_t) (p-keyword) < (MagickPathExtent-1))
618 *p++=(char) c;
619 c=ReadBlobByte(image);
620 } while (c != EOF);
621 *p='\0';
622 p=options;
623 while ((isspace((int) ((unsigned char) c)) != 0) && (c != EOF))
624 c=ReadBlobByte(image);
625 if (c == (int) '=')
626 {
627 /*
628 Get the keyword value.
629 */
630 c=ReadBlobByte(image);
631 while ((c != (int) '}') && (c != EOF))
632 {
633 if ((size_t) (p-options+1) >= length)
634 {
635 *p='\0';
636 length<<=1;
637 options=(char *) ResizeQuantumMemory(options,length+
638 MagickPathExtent,sizeof(*options));
639 if (options == (char *) NULL)
640 break;
641 p=options+strlen(options);
642 }
643 *p++=(char) c;
644 c=ReadBlobByte(image);
645 if (c == '\\')
646 {
647 c=ReadBlobByte(image);
648 if (c == (int) '}')
649 {
650 *p++=(char) c;
651 c=ReadBlobByte(image);
652 }
653 }
654 if (*options != '{')
655 if (isspace((int) ((unsigned char) c)) != 0)
656 break;
657 }
658 if (options == (char *) NULL)
659 ThrowMIFFException(ResourceLimitError,
660 "MemoryAllocationFailed");
661 }
662 *p='\0';
663 if (*options == '{')
664 (void) CopyMagickString(options,options+1,strlen(options));
665 /*
666 Assign a value to the specified keyword.
667 */
668 switch (*keyword)
669 {
670 case 'a':
671 case 'A':
672 {
673 if (LocaleCompare(keyword,"alpha-trait") == 0)
674 {
675 ssize_t
676 alpha_trait;
677
678 alpha_trait=ParseCommandOption(MagickPixelTraitOptions,
679 MagickFalse,options);
680 if (alpha_trait < 0)
681 break;
682 image->alpha_trait=(PixelTrait) alpha_trait;
683 break;
684 }
685 (void) SetImageProperty(image,keyword,options,exception);
686 break;
687 }
688 case 'b':
689 case 'B':
690 {
691 if (LocaleCompare(keyword,"background-color") == 0)
692 {
693 (void) QueryColorCompliance(options,AllCompliance,
694 &image->background_color,exception);
695 break;
696 }
697 if (LocaleCompare(keyword,"blue-primary") == 0)
698 {
699 flags=ParseGeometry(options,&geometry_info);
700 image->chromaticity.blue_primary.x=geometry_info.rho;
701 image->chromaticity.blue_primary.y=geometry_info.sigma;
702 if ((flags & SigmaValue) == 0)
703 image->chromaticity.blue_primary.y=
704 image->chromaticity.blue_primary.x;
705 break;
706 }
707 if (LocaleCompare(keyword,"border-color") == 0)
708 {
709 (void) QueryColorCompliance(options,AllCompliance,
710 &image->border_color,exception);
711 break;
712 }
713 (void) SetImageProperty(image,keyword,options,exception);
714 break;
715 }
716 case 'c':
717 case 'C':
718 {
719 if (LocaleCompare(keyword,"class") == 0)
720 {
721 ssize_t
722 storage_class;
723
724 storage_class=ParseCommandOption(MagickClassOptions,
725 MagickFalse,options);
726 if (storage_class < 0)
727 break;
728 image->storage_class=(ClassType) storage_class;
729 break;
730 }
731 if (LocaleCompare(keyword,"colors") == 0)
732 {
733 colors=StringToUnsignedLong(options);
734 break;
735 }
736 if (LocaleCompare(keyword,"colorspace") == 0)
737 {
738 ssize_t
739 colorspace;
740
741 colorspace=ParseCommandOption(MagickColorspaceOptions,
742 MagickFalse,options);
743 if (colorspace < 0)
744 break;
745 image->colorspace=(ColorspaceType) colorspace;
746 break;
747 }
748 if (LocaleCompare(keyword,"compression") == 0)
749 {
750 ssize_t
751 compression;
752
753 compression=ParseCommandOption(MagickCompressOptions,
754 MagickFalse,options);
755 if (compression < 0)
756 break;
757 image->compression=(CompressionType) compression;
758 break;
759 }
760 if (LocaleCompare(keyword,"columns") == 0)
761 {
762 image->columns=StringToUnsignedLong(options);
763 break;
764 }
765 (void) SetImageProperty(image,keyword,options,exception);
766 break;
767 }
768 case 'd':
769 case 'D':
770 {
771 if (LocaleCompare(keyword,"delay") == 0)
772 {
773 image->delay=StringToUnsignedLong(options);
774 break;
775 }
776 if (LocaleCompare(keyword,"depth") == 0)
777 {
778 image->depth=StringToUnsignedLong(options);
779 break;
780 }
781 if (LocaleCompare(keyword,"dispose") == 0)
782 {
783 ssize_t
784 dispose;
785
786 dispose=ParseCommandOption(MagickDisposeOptions,MagickFalse,
787 options);
788 if (dispose < 0)
789 break;
790 image->dispose=(DisposeType) dispose;
791 break;
792 }
793 (void) SetImageProperty(image,keyword,options,exception);
794 break;
795 }
796 case 'e':
797 case 'E':
798 {
799 if (LocaleCompare(keyword,"endian") == 0)
800 {
801 ssize_t
802 endian;
803
804 endian=ParseCommandOption(MagickEndianOptions,MagickFalse,
805 options);
806 if (endian < 0)
807 break;
808 image->endian=(EndianType) endian;
809 break;
810 }
811 (void) SetImageProperty(image,keyword,options,exception);
812 break;
813 }
814 case 'g':
815 case 'G':
816 {
817 if (LocaleCompare(keyword,"gamma") == 0)
818 {
819 image->gamma=StringToDouble(options,(char **) NULL);
820 break;
821 }
822 if (LocaleCompare(keyword,"gravity") == 0)
823 {
824 ssize_t
825 gravity;
826
827 gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,
828 options);
829 if (gravity < 0)
830 break;
831 image->gravity=(GravityType) gravity;
832 break;
833 }
834 if (LocaleCompare(keyword,"green-primary") == 0)
835 {
836 flags=ParseGeometry(options,&geometry_info);
837 image->chromaticity.green_primary.x=geometry_info.rho;
838 image->chromaticity.green_primary.y=geometry_info.sigma;
839 if ((flags & SigmaValue) == 0)
840 image->chromaticity.green_primary.y=
841 image->chromaticity.green_primary.x;
842 break;
843 }
844 (void) SetImageProperty(image,keyword,options,exception);
845 break;
846 }
847 case 'i':
848 case 'I':
849 {
850 if (LocaleCompare(keyword,"id") == 0)
851 {
852 (void) CopyMagickString(id,options,MagickPathExtent);
853 break;
854 }
855 if (LocaleCompare(keyword,"iterations") == 0)
856 {
857 image->iterations=StringToUnsignedLong(options);
858 break;
859 }
860 (void) SetImageProperty(image,keyword,options,exception);
861 break;
862 }
863 case 'm':
864 case 'M':
865 {
866 if (LocaleCompare(keyword,"matte") == 0)
867 {
868 ssize_t
869 matte;
870
871 matte=ParseCommandOption(MagickBooleanOptions,MagickFalse,
872 options);
873 if (matte < 0)
874 break;
875 image->alpha_trait=matte == 0 ? UndefinedPixelTrait :
876 BlendPixelTrait;
877 break;
878 }
879 if (LocaleCompare(keyword,"mattecolor") == 0)
880 {
881 (void) QueryColorCompliance(options,AllCompliance,
882 &image->matte_color,exception);
883 break;
884 }
885 if (LocaleCompare(keyword,"montage") == 0)
886 {
887 (void) CloneString(&image->montage,options);
888 break;
889 }
890 (void) SetImageProperty(image,keyword,options,exception);
891 break;
892 }
893 case 'o':
894 case 'O':
895 {
896 if (LocaleCompare(keyword,"orientation") == 0)
897 {
898 ssize_t
899 orientation;
900
901 orientation=ParseCommandOption(MagickOrientationOptions,
902 MagickFalse,options);
903 if (orientation < 0)
904 break;
905 image->orientation=(OrientationType) orientation;
906 break;
907 }
908 (void) SetImageProperty(image,keyword,options,exception);
909 break;
910 }
911 case 'p':
912 case 'P':
913 {
914 if (LocaleCompare(keyword,"page") == 0)
915 {
916 char
917 *geometry;
918
919 geometry=GetPageGeometry(options);
920 (void) ParseAbsoluteGeometry(geometry,&image->page);
921 geometry=DestroyString(geometry);
922 break;
923 }
924 if (LocaleCompare(keyword,"pixel-intensity") == 0)
925 {
926 ssize_t
927 intensity;
928
929 intensity=ParseCommandOption(MagickPixelIntensityOptions,
930 MagickFalse,options);
931 if (intensity < 0)
932 break;
933 image->intensity=(PixelIntensityMethod) intensity;
934 break;
935 }
936 if (LocaleCompare(keyword,"profile") == 0)
937 {
938 if (profiles == (LinkedListInfo *) NULL)
939 profiles=NewLinkedList(0);
940 (void) AppendValueToLinkedList(profiles,
941 AcquireString(options));
942 break;
943 }
944 (void) SetImageProperty(image,keyword,options,exception);
945 break;
946 }
947 case 'q':
948 case 'Q':
949 {
950 if (LocaleCompare(keyword,"quality") == 0)
951 {
952 image->quality=StringToUnsignedLong(options);
953 break;
954 }
955 if ((LocaleCompare(keyword,"quantum-format") == 0) ||
956 (LocaleCompare(keyword,"quantum:format") == 0))
957 {
958 ssize_t
959 format;
960
961 format=ParseCommandOption(MagickQuantumFormatOptions,
962 MagickFalse,options);
963 if (format < 0)
964 break;
965 quantum_format=(QuantumFormatType) format;
966 break;
967 }
968 (void) SetImageProperty(image,keyword,options,exception);
969 break;
970 }
971 case 'r':
972 case 'R':
973 {
974 if (LocaleCompare(keyword,"red-primary") == 0)
975 {
976 flags=ParseGeometry(options,&geometry_info);
977 image->chromaticity.red_primary.x=geometry_info.rho;
978 image->chromaticity.red_primary.y=geometry_info.sigma;
979 if ((flags & SigmaValue) == 0)
980 image->chromaticity.red_primary.y=
981 image->chromaticity.red_primary.x;
982 break;
983 }
984 if (LocaleCompare(keyword,"rendering-intent") == 0)
985 {
986 ssize_t
987 rendering_intent;
988
989 rendering_intent=ParseCommandOption(MagickIntentOptions,
990 MagickFalse,options);
991 if (rendering_intent < 0)
992 break;
993 image->rendering_intent=(RenderingIntent) rendering_intent;
994 break;
995 }
996 if (LocaleCompare(keyword,"resolution") == 0)
997 {
998 flags=ParseGeometry(options,&geometry_info);
999 image->resolution.x=geometry_info.rho;
1000 image->resolution.y=geometry_info.sigma;
1001 if ((flags & SigmaValue) == 0)
1002 image->resolution.y=image->resolution.x;
1003 break;
1004 }
1005 if (LocaleCompare(keyword,"rows") == 0)
1006 {
1007 image->rows=StringToUnsignedLong(options);
1008 break;
1009 }
1010 (void) SetImageProperty(image,keyword,options,exception);
1011 break;
1012 }
1013 case 's':
1014 case 'S':
1015 {
1016 if (LocaleCompare(keyword,"scene") == 0)
1017 {
1018 image->scene=StringToUnsignedLong(options);
1019 break;
1020 }
1021 (void) SetImageProperty(image,keyword,options,exception);
1022 break;
1023 }
1024 case 't':
1025 case 'T':
1026 {
1027 if (LocaleCompare(keyword,"ticks-per-second") == 0)
1028 {
1029 image->ticks_per_second=(ssize_t) StringToLong(options);
1030 break;
1031 }
1032 if (LocaleCompare(keyword,"tile-offset") == 0)
1033 {
1034 char
1035 *geometry;
1036
1037 geometry=GetPageGeometry(options);
1038 (void) ParseAbsoluteGeometry(geometry,&image->tile_offset);
1039 geometry=DestroyString(geometry);
1040 break;
1041 }
1042 if (LocaleCompare(keyword,"type") == 0)
1043 {
1044 ssize_t
1045 type;
1046
1047 type=ParseCommandOption(MagickTypeOptions,MagickFalse,
1048 options);
1049 if (type < 0)
1050 break;
1051 image->type=(ImageType) type;
1052 break;
1053 }
1054 (void) SetImageProperty(image,keyword,options,exception);
1055 break;
1056 }
1057 case 'u':
1058 case 'U':
1059 {
1060 if (LocaleCompare(keyword,"units") == 0)
1061 {
1062 ssize_t
1063 units;
1064
1065 units=ParseCommandOption(MagickResolutionOptions,
1066 MagickFalse,options);
1067 if (units < 0)
1068 break;
1069 image->units=(ResolutionType) units;
1070 break;
1071 }
1072 (void) SetImageProperty(image,keyword,options,exception);
1073 break;
1074 }
1075 case 'v':
1076 case 'V':
1077 {
1078 if (LocaleCompare(keyword,"version") == 0)
1079 {
1080 version=StringToDouble(options,(char **) NULL);
1081 break;
1082 }
1083 (void) SetImageProperty(image,keyword,options,exception);
1084 break;
1085 }
1086 case 'w':
1087 case 'W':
1088 {
1089 if (LocaleCompare(keyword,"white-point") == 0)
1090 {
1091 flags=ParseGeometry(options,&geometry_info);
1092 image->chromaticity.white_point.x=geometry_info.rho;
1093 image->chromaticity.white_point.y=geometry_info.sigma;
1094 if ((flags & SigmaValue) == 0)
1095 image->chromaticity.white_point.y=
1096 image->chromaticity.white_point.x;
1097 break;
1098 }
1099 (void) SetImageProperty(image,keyword,options,exception);
1100 break;
1101 }
1102 default:
1103 {
1104 (void) SetImageProperty(image,keyword,options,exception);
1105 break;
1106 }
1107 }
1108 }
1109 else
1110 c=ReadBlobByte(image);
1111 while (isspace((int) ((unsigned char) c)) != 0)
1112 c=ReadBlobByte(image);
1113 }
1114 options=DestroyString(options);
1115 (void) ReadBlobByte(image);
1116 /*
1117 Verify that required image information is defined.
1118 */
1119 if ((LocaleCompare(id,"ImageMagick") != 0) ||
1120 (image->storage_class == UndefinedClass) ||
1121 (image->compression == UndefinedCompression) ||
1122 (image->colorspace == UndefinedColorspace) ||
1123 (image->columns == 0) || (image->rows == 0) ||
1124 (image->depth == 0) || (image->depth > 64))
1125 {
1126 if (profiles != (LinkedListInfo *) NULL)
1127 profiles=DestroyLinkedList(profiles,RelinquishMagickMemory);
1128 if (image->previous == (Image *) NULL)
1129 ThrowMIFFException(CorruptImageError,"ImproperImageHeader");
1130 DeleteImageFromList(&image);
1131 (void) ThrowMagickException(exception,GetMagickModule(),
1132 CorruptImageError,"ImproperImageHeader","`%s'",image->filename);
1133 break;
1134 }
1135 if (image->montage != (char *) NULL)
1136 {
1137 register char
1138 *p;
1139
1140 /*
1141 Image directory.
1142 */
1143 extent=MagickPathExtent;
1144 image->directory=AcquireString((char *) NULL);
1145 p=image->directory;
1146 length=0;
1147 do
1148 {
1149 *p='\0';
1150 if ((length+MagickPathExtent) >= extent)
1151 {
1152 /*
1153 Allocate more memory for the image directory.
1154 */
1155 extent<<=1;
1156 image->directory=(char *) ResizeQuantumMemory(image->directory,
1157 extent+MagickPathExtent,sizeof(*image->directory));
1158 if (image->directory == (char *) NULL)
1159 ThrowMIFFException(CorruptImageError,"UnableToReadImageData");
1160 p=image->directory+length;
1161 }
1162 c=ReadBlobByte(image);
1163 if (c == EOF)
1164 break;
1165 *p++=(char) c;
1166 length++;
1167 } while (c != (int) '\0');
1168 }
1169 if (profiles != (LinkedListInfo *) NULL)
1170 {
1171 const char
1172 *name;
1173
1174 StringInfo
1175 *profile;
1176
1177 /*
1178 Read image profiles.
1179 */
1180 ResetLinkedListIterator(profiles);
1181 name=(const char *) GetNextValueInLinkedList(profiles);
1182 while (name != (const char *) NULL)
1183 {
1184 length=ReadBlobMSBLong(image);
1185 if ((MagickSizeType) length > GetBlobSize(image))
1186 break;
1187 profile=AcquireStringInfo(length);
1188 if (profile == (StringInfo *) NULL)
1189 break;
1190 count=ReadBlob(image,length,GetStringInfoDatum(profile));
1191 if (count != (ssize_t) length)
1192 {
1193 profile=DestroyStringInfo(profile);
1194 break;
1195 }
1196 status=SetImageProfile(image,name,profile,exception);
1197 profile=DestroyStringInfo(profile);
1198 if (status == MagickFalse)
1199 break;
1200 name=(const char *) GetNextValueInLinkedList(profiles);
1201 }
1202 profiles=DestroyLinkedList(profiles,RelinquishMagickMemory);
1203 }
1204 image->depth=GetImageQuantumDepth(image,MagickFalse);
1205 if (image->storage_class == PseudoClass)
1206 {
1207 unsigned char
1208 *colormap;
1209
1210 /*
1211 Create image colormap.
1212 */
1213 packet_size=(size_t) (3UL*image->depth/8UL);
1214 if ((MagickSizeType) colors > GetBlobSize(image))
1215 ThrowMIFFException(CorruptImageError,"InsufficientImageDataInFile");
1216 if (((MagickSizeType) packet_size*colors) > GetBlobSize(image))
1217 ThrowMIFFException(CorruptImageError,"InsufficientImageDataInFile");
1218 status=AcquireImageColormap(image,colors != 0 ? colors : 256,exception);
1219 if (status == MagickFalse)
1220 ThrowMIFFException(ResourceLimitError,"MemoryAllocationFailed");
1221 if (colors != 0)
1222 {
1223 const unsigned char
1224 *p;
1225
1226 /*
1227 Read image colormap from file.
1228 */
1229 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
1230 packet_size*sizeof(*colormap));
1231 if (colormap == (unsigned char *) NULL)
1232 ThrowMIFFException(ResourceLimitError,"MemoryAllocationFailed");
1233 count=ReadBlob(image,packet_size*image->colors,colormap);
1234 p=colormap;
1235 switch (image->depth)
1236 {
1237 default:
1238 {
1239 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
1240 ThrowMIFFException(CorruptImageError,"ImageDepthNotSupported");
1241 break;
1242 }
1243 case 8:
1244 {
1245 unsigned char
1246 char_pixel;
1247
1248 for (i=0; i < (ssize_t) image->colors; i++)
1249 {
1250 p=PushCharPixel(p,&char_pixel);
1251 image->colormap[i].red=(MagickRealType)
1252 ScaleCharToQuantum(char_pixel);
1253 p=PushCharPixel(p,&char_pixel);
1254 image->colormap[i].green=(MagickRealType)
1255 ScaleCharToQuantum(char_pixel);
1256 p=PushCharPixel(p,&char_pixel);
1257 image->colormap[i].blue=(MagickRealType)
1258 ScaleCharToQuantum(char_pixel);
1259 }
1260 break;
1261 }
1262 case 16:
1263 {
1264 unsigned short
1265 short_pixel;
1266
1267 for (i=0; i < (ssize_t) image->colors; i++)
1268 {
1269 p=PushShortPixel(MSBEndian,p,&short_pixel);
1270 image->colormap[i].red=(MagickRealType)
1271 ScaleShortToQuantum(short_pixel);
1272 p=PushShortPixel(MSBEndian,p,&short_pixel);
1273 image->colormap[i].green=(MagickRealType)
1274 ScaleShortToQuantum(short_pixel);
1275 p=PushShortPixel(MSBEndian,p,&short_pixel);
1276 image->colormap[i].blue=(MagickRealType)
1277 ScaleShortToQuantum(short_pixel);
1278 }
1279 break;
1280 }
1281 case 32:
1282 {
1283 unsigned int
1284 long_pixel;
1285
1286 for (i=0; i < (ssize_t) image->colors; i++)
1287 {
1288 p=PushLongPixel(MSBEndian,p,&long_pixel);
1289 image->colormap[i].red=(MagickRealType)
1290 ScaleLongToQuantum(long_pixel);
1291 p=PushLongPixel(MSBEndian,p,&long_pixel);
1292 image->colormap[i].green=(MagickRealType)
1293 ScaleLongToQuantum(long_pixel);
1294 p=PushLongPixel(MSBEndian,p,&long_pixel);
1295 image->colormap[i].blue=(MagickRealType)
1296 ScaleLongToQuantum(long_pixel);
1297 }
1298 break;
1299 }
1300 }
1301 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
1302 }
1303 }
1304 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1305 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1306 break;
1307 status=SetImageExtent(image,image->columns,image->rows,exception);
1308 if (status == MagickFalse)
1309 return(DestroyImageList(image));
1310 status=ResetImagePixels(image,exception);
1311 if (status == MagickFalse)
1312 return(DestroyImageList(image));
1313 /*
1314 Allocate image pixels.
1315 */
1316 quantum_info=AcquireQuantumInfo(image_info,image);
1317 if (quantum_info == (QuantumInfo *) NULL)
1318 ThrowMIFFException(ResourceLimitError,"MemoryAllocationFailed");
1319 if (quantum_format != UndefinedQuantumFormat)
1320 {
1321 status=SetQuantumFormat(image,quantum_info,quantum_format);
1322 if (status == MagickFalse)
1323 ThrowMIFFException(ResourceLimitError,"MemoryAllocationFailed");
1324 }
1325 packet_size=(size_t) (quantum_info->depth/8);
1326 if (image->storage_class == DirectClass)
1327 packet_size=(size_t) (3*quantum_info->depth/8);
1328 if (IsGrayColorspace(image->colorspace) != MagickFalse)
1329 packet_size=quantum_info->depth/8;
1330 if (image->alpha_trait != UndefinedPixelTrait)
1331 packet_size+=quantum_info->depth/8;
1332 if (image->colorspace == CMYKColorspace)
1333 packet_size+=quantum_info->depth/8;
1334 if (image->compression == RLECompression)
1335 packet_size++;
1336 compress_extent=MagickMax(MagickMax(BZipMaxExtent(packet_size*
1337 image->columns),LZMAMaxExtent(packet_size*image->columns)),
1338 ZipMaxExtent(packet_size*image->columns));
1339 if (compress_extent < (packet_size*image->columns))
1340 ThrowMIFFException(ResourceLimitError,"MemoryAllocationFailed");
1341 compress_pixels=(unsigned char *) AcquireQuantumMemory(compress_extent,
1342 sizeof(*compress_pixels));
1343 if (compress_pixels == (unsigned char *) NULL)
1344 ThrowMIFFException(ResourceLimitError,"MemoryAllocationFailed");
1345 /*
1346 Read image pixels.
1347 */
1348 quantum_type=RGBQuantum;
1349 if (image->alpha_trait != UndefinedPixelTrait)
1350 quantum_type=RGBAQuantum;
1351 if (image->colorspace == CMYKColorspace)
1352 {
1353 quantum_type=CMYKQuantum;
1354 if (image->alpha_trait != UndefinedPixelTrait)
1355 quantum_type=CMYKAQuantum;
1356 }
1357 if (IsGrayColorspace(image->colorspace) != MagickFalse)
1358 {
1359 quantum_type=GrayQuantum;
1360 if (image->alpha_trait != UndefinedPixelTrait)
1361 quantum_type=GrayAlphaQuantum;
1362 }
1363 if (image->storage_class == PseudoClass)
1364 {
1365 quantum_type=IndexQuantum;
1366 if (image->alpha_trait != UndefinedPixelTrait)
1367 quantum_type=IndexAlphaQuantum;
1368 }
1369 status=MagickTrue;
1370 GetPixelInfo(image,&pixel);
1371 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1372 (void) memset(&bzip_info,0,sizeof(bzip_info));
1373 #endif
1374 #if defined(MAGICKCORE_LZMA_DELEGATE)
1375 (void) memset(&allocator,0,sizeof(allocator));
1376 #endif
1377 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1378 (void) memset(&zip_info,0,sizeof(zip_info));
1379 #endif
1380 switch (image->compression)
1381 {
1382 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1383 case BZipCompression:
1384 {
1385 int
1386 code;
1387
1388 bzip_info.bzalloc=AcquireBZIPMemory;
1389 bzip_info.bzfree=RelinquishBZIPMemory;
1390 bzip_info.opaque=(void *) image;
1391 code=BZ2_bzDecompressInit(&bzip_info,(int) image_info->verbose,
1392 MagickFalse);
1393 if (code != BZ_OK)
1394 status=MagickFalse;
1395 break;
1396 }
1397 #endif
1398 #if defined(MAGICKCORE_LZMA_DELEGATE)
1399 case LZMACompression:
1400 {
1401 int
1402 code;
1403
1404 allocator.alloc=AcquireLZMAMemory;
1405 allocator.free=RelinquishLZMAMemory;
1406 allocator.opaque=(void *) image;
1407 lzma_info=initialize_lzma;
1408 lzma_info.allocator=(&allocator);
1409 code=lzma_auto_decoder(&lzma_info,(uint64_t) -1,0);
1410 if (code != LZMA_OK)
1411 status=MagickFalse;
1412 break;
1413 }
1414 #endif
1415 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1416 case LZWCompression:
1417 case ZipCompression:
1418 {
1419 int
1420 code;
1421
1422 zip_info.zalloc=AcquireZIPMemory;
1423 zip_info.zfree=RelinquishZIPMemory;
1424 zip_info.opaque=(voidpf) image;
1425 code=inflateInit(&zip_info);
1426 if (code != Z_OK)
1427 status=MagickFalse;
1428 break;
1429 }
1430 #endif
1431 case RLECompression:
1432 break;
1433 default:
1434 break;
1435 }
1436 pixels=(unsigned char *) GetQuantumPixels(quantum_info);
1437 length=0;
1438 for (y=0; y < (ssize_t) image->rows; y++)
1439 {
1440 register ssize_t
1441 x;
1442
1443 register Quantum
1444 *magick_restrict q;
1445
1446 if (status == MagickFalse)
1447 break;
1448 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1449 if (q == (Quantum *) NULL)
1450 break;
1451 extent=0;
1452 switch (image->compression)
1453 {
1454 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1455 case BZipCompression:
1456 {
1457 bzip_info.next_out=(char *) pixels;
1458 bzip_info.avail_out=(unsigned int) (packet_size*image->columns);
1459 do
1460 {
1461 int
1462 code;
1463
1464 if (bzip_info.avail_in == 0)
1465 {
1466 bzip_info.next_in=(char *) compress_pixels;
1467 length=(size_t) BZipMaxExtent(packet_size*image->columns);
1468 if (version != 0.0)
1469 length=(size_t) ReadBlobMSBLong(image);
1470 if (length <= compress_extent)
1471 bzip_info.avail_in=(unsigned int) ReadBlob(image,length,
1472 (unsigned char *) bzip_info.next_in);
1473 if ((length > compress_extent) ||
1474 ((size_t) bzip_info.avail_in != length))
1475 {
1476 (void) BZ2_bzDecompressEnd(&bzip_info);
1477 ThrowMIFFException(CorruptImageError,
1478 "UnableToReadImageData");
1479 }
1480 }
1481 code=BZ2_bzDecompress(&bzip_info);
1482 if ((code != BZ_OK) && (code != BZ_STREAM_END))
1483 {
1484 status=MagickFalse;
1485 break;
1486 }
1487 if (code == BZ_STREAM_END)
1488 break;
1489 } while (bzip_info.avail_out != 0);
1490 extent=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1491 quantum_type,pixels,exception);
1492 break;
1493 }
1494 #endif
1495 #if defined(MAGICKCORE_LZMA_DELEGATE)
1496 case LZMACompression:
1497 {
1498 lzma_info.next_out=pixels;
1499 lzma_info.avail_out=packet_size*image->columns;
1500 do
1501 {
1502 int
1503 code;
1504
1505 if (lzma_info.avail_in == 0)
1506 {
1507 lzma_info.next_in=compress_pixels;
1508 length=(size_t) ReadBlobMSBLong(image);
1509 if (length <= compress_extent)
1510 lzma_info.avail_in=(unsigned int) ReadBlob(image,length,
1511 (unsigned char *) lzma_info.next_in);
1512 if ((length > compress_extent) ||
1513 (lzma_info.avail_in != length))
1514 {
1515 lzma_end(&lzma_info);
1516 ThrowMIFFException(CorruptImageError,
1517 "UnableToReadImageData");
1518 }
1519 }
1520 code=lzma_code(&lzma_info,LZMA_RUN);
1521 if ((code != LZMA_OK) && (code != LZMA_STREAM_END))
1522 {
1523 status=MagickFalse;
1524 break;
1525 }
1526 if (code == LZMA_STREAM_END)
1527 break;
1528 } while (lzma_info.avail_out != 0);
1529 extent=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1530 quantum_type,pixels,exception);
1531 break;
1532 }
1533 #endif
1534 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1535 case LZWCompression:
1536 case ZipCompression:
1537 {
1538 zip_info.next_out=pixels;
1539 zip_info.avail_out=(uInt) (packet_size*image->columns);
1540 do
1541 {
1542 int
1543 code;
1544
1545 if (zip_info.avail_in == 0)
1546 {
1547 zip_info.next_in=compress_pixels;
1548 length=(size_t) ZipMaxExtent(packet_size*image->columns);
1549 if (version != 0.0)
1550 length=(size_t) ReadBlobMSBLong(image);
1551 if (length <= compress_extent)
1552 zip_info.avail_in=(unsigned int) ReadBlob(image,length,
1553 zip_info.next_in);
1554 if ((length > compress_extent) ||
1555 ((size_t) zip_info.avail_in != length))
1556 {
1557 (void) inflateEnd(&zip_info);
1558 ThrowMIFFException(CorruptImageError,
1559 "UnableToReadImageData");
1560 }
1561 }
1562 code=inflate(&zip_info,Z_SYNC_FLUSH);
1563 if ((code != Z_OK) && (code != Z_STREAM_END))
1564 {
1565 status=MagickFalse;
1566 break;
1567 }
1568 if (code == Z_STREAM_END)
1569 break;
1570 } while (zip_info.avail_out != 0);
1571 extent=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1572 quantum_type,pixels,exception);
1573 break;
1574 }
1575 #endif
1576 case RLECompression:
1577 {
1578 for (x=0; x < (ssize_t) image->columns; x++)
1579 {
1580 if (length == 0)
1581 {
1582 count=ReadBlob(image,packet_size,pixels);
1583 if (count != (ssize_t) packet_size)
1584 ThrowMIFFException(CorruptImageError,"UnableToReadImageData");
1585 PushRunlengthPacket(image,pixels,&length,&pixel,exception);
1586 }
1587 length--;
1588 if (image->storage_class == PseudoClass)
1589 SetPixelIndex(image,ClampToQuantum(pixel.index),q);
1590 else
1591 {
1592 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1593 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1594 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1595 if (image->colorspace == CMYKColorspace)
1596 SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1597 }
1598 if (image->alpha_trait != UndefinedPixelTrait)
1599 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1600 q+=GetPixelChannels(image);
1601 }
1602 extent=(size_t) x;
1603 break;
1604 }
1605 default:
1606 {
1607 count=ReadBlob(image,packet_size*image->columns,pixels);
1608 if (count != (ssize_t) (packet_size*image->columns))
1609 ThrowMIFFException(CorruptImageError,"UnableToReadImageData");
1610 extent=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1611 quantum_type,pixels,exception);
1612 break;
1613 }
1614 }
1615 if (extent < image->columns)
1616 break;
1617 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1618 break;
1619 }
1620 SetQuantumImageType(image,quantum_type);
1621 switch (image->compression)
1622 {
1623 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1624 case BZipCompression:
1625 {
1626 int
1627 code;
1628
1629 if (version == 0.0)
1630 {
1631 MagickOffsetType
1632 offset;
1633
1634 offset=SeekBlob(image,-((MagickOffsetType) bzip_info.avail_in),
1635 SEEK_CUR);
1636 if (offset < 0)
1637 {
1638 (void) BZ2_bzDecompressEnd(&bzip_info);
1639 ThrowMIFFException(CorruptImageError,"ImproperImageHeader");
1640 }
1641 }
1642 code=BZ2_bzDecompressEnd(&bzip_info);
1643 if (code != BZ_OK)
1644 status=MagickFalse;
1645 break;
1646 }
1647 #endif
1648 #if defined(MAGICKCORE_LZMA_DELEGATE)
1649 case LZMACompression:
1650 {
1651 int
1652 code;
1653
1654 code=lzma_code(&lzma_info,LZMA_FINISH);
1655 if ((code != LZMA_STREAM_END) && (code != LZMA_OK))
1656 status=MagickFalse;
1657 lzma_end(&lzma_info);
1658 break;
1659 }
1660 #endif
1661 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1662 case LZWCompression:
1663 case ZipCompression:
1664 {
1665 int
1666 code;
1667
1668 if (version == 0.0)
1669 {
1670 MagickOffsetType
1671 offset;
1672
1673 offset=SeekBlob(image,-((MagickOffsetType) zip_info.avail_in),
1674 SEEK_CUR);
1675 if (offset < 0)
1676 {
1677 (void) inflateEnd(&zip_info);
1678 ThrowMIFFException(CorruptImageError,"ImproperImageHeader");
1679 }
1680 }
1681 code=inflateEnd(&zip_info);
1682 if (code != Z_OK)
1683 status=MagickFalse;
1684 break;
1685 }
1686 #endif
1687 default:
1688 break;
1689 }
1690 quantum_info=DestroyQuantumInfo(quantum_info);
1691 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
1692 if (((y != (ssize_t) image->rows)) || (status == MagickFalse))
1693 {
1694 image=DestroyImageList(image);
1695 return((Image *) NULL);
1696 }
1697 if (EOFBlob(image) != MagickFalse)
1698 {
1699 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1700 image->filename);
1701 break;
1702 }
1703 /*
1704 Proceed to next image.
1705 */
1706 if (image_info->number_scenes != 0)
1707 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1708 break;
1709 do
1710 {
1711 c=ReadBlobByte(image);
1712 } while ((isgraph(c) == MagickFalse) && (c != EOF));
1713 if (c != EOF)
1714 {
1715 /*
1716 Allocate next image structure.
1717 */
1718 AcquireNextImage(image_info,image,exception);
1719 if (GetNextImageInList(image) == (Image *) NULL)
1720 {
1721 status=MagickFalse;
1722 break;
1723 }
1724 image=SyncNextImageInList(image);
1725 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1726 GetBlobSize(image));
1727 if (status == MagickFalse)
1728 break;
1729 }
1730 } while (c != EOF);
1731 (void) CloseBlob(image);
1732 if (status == MagickFalse)
1733 return(DestroyImageList(image));
1734 return(GetFirstImageInList(image));
1735 }
1736
1737 /*
1738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1739 % %
1740 % %
1741 % %
1742 % R e g i s t e r M I F F I m a g e %
1743 % %
1744 % %
1745 % %
1746 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1747 %
1748 % RegisterMIFFImage() adds properties for the MIFF image format to the list of
1749 % supported formats. The properties include the image format tag, a method to
1750 % read and/or write the format, whether the format supports the saving of more
1751 % than one frame to the same file or blob, whether the format supports native
1752 % in-memory I/O, and a brief description of the format.
1753 %
1754 % The format of the RegisterMIFFImage method is:
1755 %
1756 % size_t RegisterMIFFImage(void)
1757 %
1758 */
RegisterMIFFImage(void)1759 ModuleExport size_t RegisterMIFFImage(void)
1760 {
1761 char
1762 version[MagickPathExtent];
1763
1764 MagickInfo
1765 *entry;
1766
1767 *version='\0';
1768 #if defined(MagickImageCoderSignatureText)
1769 (void) CopyMagickString(version,MagickLibVersionText,MagickPathExtent);
1770 #if defined(ZLIB_VERSION)
1771 (void) ConcatenateMagickString(version," with Zlib ",MagickPathExtent);
1772 (void) ConcatenateMagickString(version,ZLIB_VERSION,MagickPathExtent);
1773 #endif
1774 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1775 (void) ConcatenateMagickString(version," and BZlib",MagickPathExtent);
1776 #endif
1777 #endif
1778 entry=AcquireMagickInfo("MIFF","MIFF","Magick Image File Format");
1779 entry->decoder=(DecodeImageHandler *) ReadMIFFImage;
1780 entry->encoder=(EncodeImageHandler *) WriteMIFFImage;
1781 entry->magick=(IsImageFormatHandler *) IsMIFF;
1782 entry->flags|=CoderDecoderSeekableStreamFlag;
1783 if (*version != '\0')
1784 entry->version=ConstantString(version);
1785 (void) RegisterMagickInfo(entry);
1786 return(MagickImageCoderSignature);
1787 }
1788
1789 /*
1790 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1791 % %
1792 % %
1793 % %
1794 % U n r e g i s t e r M I F F I m a g e %
1795 % %
1796 % %
1797 % %
1798 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1799 %
1800 % UnregisterMIFFImage() removes format registrations made by the MIFF module
1801 % from the list of supported formats.
1802 %
1803 % The format of the UnregisterMIFFImage method is:
1804 %
1805 % UnregisterMIFFImage(void)
1806 %
1807 */
UnregisterMIFFImage(void)1808 ModuleExport void UnregisterMIFFImage(void)
1809 {
1810 (void) UnregisterMagickInfo("MIFF");
1811 }
1812
1813 /*
1814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1815 % %
1816 % %
1817 % %
1818 % W r i t e M I F F I m a g e %
1819 % %
1820 % %
1821 % %
1822 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1823 %
1824 % WriteMIFFImage() writes a MIFF image to a file.
1825 %
1826 % The format of the WriteMIFFImage method is:
1827 %
1828 % MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
1829 % Image *image,ExceptionInfo *exception)
1830 %
1831 % Compression code contributed by Kyle Shorter.
1832 %
1833 % A description of each parameter follows:
1834 %
1835 % o image_info: the image info.
1836 %
1837 % o image: the image.
1838 %
1839 % o exception: return any errors or warnings in this structure.
1840 %
1841 */
1842
PopRunlengthPacket(Image * image,unsigned char * pixels,size_t length,PixelInfo * pixel,ExceptionInfo * exception)1843 static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
1844 size_t length,PixelInfo *pixel,ExceptionInfo *exception)
1845 {
1846 if (image->storage_class != DirectClass)
1847 {
1848 unsigned int
1849 value;
1850
1851 value=(unsigned int) ClampToQuantum(pixel->index);
1852 switch (image->depth)
1853 {
1854 case 32:
1855 {
1856 *pixels++=(unsigned char) (value >> 24);
1857 *pixels++=(unsigned char) (value >> 16);
1858 }
1859 case 16:
1860 *pixels++=(unsigned char) (value >> 8);
1861 case 8:
1862 {
1863 *pixels++=(unsigned char) value;
1864 break;
1865 }
1866 default:
1867 (void) ThrowMagickException(exception,GetMagickModule(),
1868 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1869 }
1870 switch (image->depth)
1871 {
1872 case 32:
1873 {
1874 unsigned int
1875 long_value;
1876
1877 if (image->alpha_trait != UndefinedPixelTrait)
1878 {
1879 long_value=ScaleQuantumToLong(ClampToQuantum(pixel->alpha));
1880 pixels=PopLongPixel(MSBEndian,long_value,pixels);
1881 }
1882 break;
1883 }
1884 case 16:
1885 {
1886 unsigned short
1887 short_value;
1888
1889 if (image->alpha_trait != UndefinedPixelTrait)
1890 {
1891 short_value=ScaleQuantumToShort(ClampToQuantum(pixel->alpha));
1892 pixels=PopShortPixel(MSBEndian,short_value,pixels);
1893 }
1894 break;
1895 }
1896 case 8:
1897 {
1898 unsigned char
1899 char_value;
1900
1901 if (image->alpha_trait != UndefinedPixelTrait)
1902 {
1903 char_value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1904 pixel->alpha));
1905 pixels=PopCharPixel(char_value,pixels);
1906 }
1907 break;
1908 }
1909 default:
1910 (void) ThrowMagickException(exception,GetMagickModule(),
1911 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1912 }
1913 *pixels++=(unsigned char) length;
1914 return(pixels);
1915 }
1916 switch (image->depth)
1917 {
1918 case 32:
1919 {
1920 unsigned int
1921 value;
1922
1923 value=ScaleQuantumToLong(ClampToQuantum(pixel->red));
1924 pixels=PopLongPixel(MSBEndian,value,pixels);
1925 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1926 {
1927 value=ScaleQuantumToLong(ClampToQuantum(pixel->green));
1928 pixels=PopLongPixel(MSBEndian,value,pixels);
1929 value=ScaleQuantumToLong(ClampToQuantum(pixel->blue));
1930 pixels=PopLongPixel(MSBEndian,value,pixels);
1931 }
1932 if (image->colorspace == CMYKColorspace)
1933 {
1934 value=ScaleQuantumToLong(ClampToQuantum(pixel->black));
1935 pixels=PopLongPixel(MSBEndian,value,pixels);
1936 }
1937 if (image->alpha_trait != UndefinedPixelTrait)
1938 {
1939 value=ScaleQuantumToLong(ClampToQuantum(pixel->alpha));
1940 pixels=PopLongPixel(MSBEndian,value,pixels);
1941 }
1942 break;
1943 }
1944 case 16:
1945 {
1946 unsigned short
1947 value;
1948
1949 value=ScaleQuantumToShort(ClampToQuantum(pixel->red));
1950 pixels=PopShortPixel(MSBEndian,value,pixels);
1951 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1952 {
1953 value=ScaleQuantumToShort(ClampToQuantum(pixel->green));
1954 pixels=PopShortPixel(MSBEndian,value,pixels);
1955 value=ScaleQuantumToShort(ClampToQuantum(pixel->blue));
1956 pixels=PopShortPixel(MSBEndian,value,pixels);
1957 }
1958 if (image->colorspace == CMYKColorspace)
1959 {
1960 value=ScaleQuantumToShort(ClampToQuantum(pixel->black));
1961 pixels=PopShortPixel(MSBEndian,value,pixels);
1962 }
1963 if (image->alpha_trait != UndefinedPixelTrait)
1964 {
1965 value=ScaleQuantumToShort(ClampToQuantum(pixel->alpha));
1966 pixels=PopShortPixel(MSBEndian,value,pixels);
1967 }
1968 break;
1969 }
1970 case 8:
1971 {
1972 unsigned char
1973 value;
1974
1975 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->red));
1976 pixels=PopCharPixel(value,pixels);
1977 if (IsGrayColorspace(image->colorspace) == MagickFalse)
1978 {
1979 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1980 pixel->green));
1981 pixels=PopCharPixel(value,pixels);
1982 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->blue));
1983 pixels=PopCharPixel(value,pixels);
1984 }
1985 if (image->colorspace == CMYKColorspace)
1986 {
1987 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1988 pixel->black));
1989 pixels=PopCharPixel(value,pixels);
1990 }
1991 if (image->alpha_trait != UndefinedPixelTrait)
1992 {
1993 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1994 pixel->alpha));
1995 pixels=PopCharPixel(value,pixels);
1996 }
1997 break;
1998 }
1999 default:
2000 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
2001 "ImageDepthNotSupported","`%s'",image->filename);
2002 }
2003 *pixels++=(unsigned char) length;
2004 return(pixels);
2005 }
2006
WriteMIFFImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)2007 static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
2008 Image *image,ExceptionInfo *exception)
2009 {
2010 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2011 bz_stream
2012 bzip_info;
2013 #endif
2014
2015 char
2016 buffer[MagickPathExtent];
2017
2018 CompressionType
2019 compression;
2020
2021 const char
2022 *property,
2023 *value;
2024
2025 #if defined(MAGICKCORE_LZMA_DELEGATE)
2026 lzma_allocator
2027 allocator;
2028
2029 lzma_stream
2030 initialize_lzma = LZMA_STREAM_INIT,
2031 lzma_info;
2032 #endif
2033
2034 MagickBooleanType
2035 status;
2036
2037 MagickOffsetType
2038 scene;
2039
2040 PixelInfo
2041 pixel,
2042 target;
2043
2044 QuantumInfo
2045 *quantum_info;
2046
2047 QuantumType
2048 quantum_type;
2049
2050 register ssize_t
2051 i;
2052
2053 size_t
2054 imageListLength,
2055 length,
2056 packet_size;
2057
2058 ssize_t
2059 y;
2060
2061 unsigned char
2062 *compress_pixels,
2063 *pixels,
2064 *q;
2065
2066 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2067 z_stream
2068 zip_info;
2069 #endif
2070
2071 /*
2072 Open output image file.
2073 */
2074 assert(image_info != (const ImageInfo *) NULL);
2075 assert(image_info->signature == MagickCoreSignature);
2076 assert(image != (Image *) NULL);
2077 assert(image->signature == MagickCoreSignature);
2078 if (image->debug != MagickFalse)
2079 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2080 assert(exception != (ExceptionInfo *) NULL);
2081 assert(exception->signature == MagickCoreSignature);
2082 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2083 if (status == MagickFalse)
2084 return(status);
2085 scene=0;
2086 imageListLength=GetImageListLength(image);
2087 do
2088 {
2089 /*
2090 Allocate image pixels.
2091 */
2092 if ((image->storage_class == PseudoClass) &&
2093 (image->colors > (size_t) (GetQuantumRange(image->depth)+1)))
2094 (void) SetImageStorageClass(image,DirectClass,exception);
2095 image->depth=image->depth <= 8 ? 8UL : image->depth <= 16 ? 16UL :
2096 image->depth <= 32 ? 32UL : 64UL;
2097 quantum_info=AcquireQuantumInfo(image_info,image);
2098 if (quantum_info == (QuantumInfo *) NULL)
2099 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2100 if ((image->storage_class != PseudoClass) && (image->depth >= 16) &&
2101 (quantum_info->format == UndefinedQuantumFormat) &&
2102 (IsHighDynamicRangeImage(image,exception) != MagickFalse))
2103 {
2104 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2105 if (status == MagickFalse)
2106 {
2107 quantum_info=DestroyQuantumInfo(quantum_info);
2108 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2109 }
2110 }
2111 else
2112 if (image->depth < 16)
2113 (void) DeleteImageProperty(image,"quantum:format");
2114 compression=UndefinedCompression;
2115 if (image_info->compression != UndefinedCompression)
2116 compression=image_info->compression;
2117 switch (compression)
2118 {
2119 #if !defined(MAGICKCORE_LZMA_DELEGATE)
2120 case LZMACompression: compression=NoCompression; break;
2121 #endif
2122 #if !defined(MAGICKCORE_ZLIB_DELEGATE)
2123 case LZWCompression:
2124 case ZipCompression: compression=NoCompression; break;
2125 #endif
2126 #if !defined(MAGICKCORE_BZLIB_DELEGATE)
2127 case BZipCompression: compression=NoCompression; break;
2128 #endif
2129 case RLECompression:
2130 {
2131 if (quantum_info->format == FloatingPointQuantumFormat)
2132 compression=NoCompression;
2133 GetPixelInfo(image,&target);
2134 break;
2135 }
2136 default:
2137 break;
2138 }
2139 packet_size=(size_t) (quantum_info->depth/8);
2140 if (image->storage_class == DirectClass)
2141 packet_size=(size_t) (3*quantum_info->depth/8);
2142 if (IsGrayColorspace(image->colorspace) != MagickFalse)
2143 packet_size=(size_t) (quantum_info->depth/8);
2144 if (image->alpha_trait != UndefinedPixelTrait)
2145 packet_size+=quantum_info->depth/8;
2146 if (image->colorspace == CMYKColorspace)
2147 packet_size+=quantum_info->depth/8;
2148 if (compression == RLECompression)
2149 packet_size++;
2150 length=MagickMax(BZipMaxExtent(packet_size*image->columns),ZipMaxExtent(
2151 packet_size*image->columns));
2152 if ((compression == BZipCompression) || (compression == ZipCompression))
2153 if (length != (size_t) ((unsigned int) length))
2154 compression=NoCompression;
2155 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
2156 sizeof(*compress_pixels));
2157 if (compress_pixels == (unsigned char *) NULL)
2158 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2159 /*
2160 Write MIFF header.
2161 */
2162 (void) WriteBlobString(image,"id=ImageMagick version=1.0\n");
2163 (void) FormatLocaleString(buffer,MagickPathExtent,
2164 "class=%s colors=%.20g alpha-trait=%s\n",CommandOptionToMnemonic(
2165 MagickClassOptions,image->storage_class),(double) image->colors,
2166 CommandOptionToMnemonic(MagickPixelTraitOptions,(ssize_t)
2167 image->alpha_trait));
2168 (void) WriteBlobString(image,buffer);
2169 if (image->alpha_trait != UndefinedPixelTrait)
2170 (void) WriteBlobString(image,"matte=True\n");
2171 (void) FormatLocaleString(buffer,MagickPathExtent,
2172 "columns=%.20g rows=%.20g depth=%.20g\n",(double) image->columns,
2173 (double) image->rows,(double) image->depth);
2174 (void) WriteBlobString(image,buffer);
2175 if (image->type != UndefinedType)
2176 {
2177 (void) FormatLocaleString(buffer,MagickPathExtent,"type=%s\n",
2178 CommandOptionToMnemonic(MagickTypeOptions,image->type));
2179 (void) WriteBlobString(image,buffer);
2180 }
2181 if (image->colorspace != UndefinedColorspace)
2182 {
2183 (void) FormatLocaleString(buffer,MagickPathExtent,"colorspace=%s\n",
2184 CommandOptionToMnemonic(MagickColorspaceOptions,image->colorspace));
2185 (void) WriteBlobString(image,buffer);
2186 }
2187 if (image->intensity != UndefinedPixelIntensityMethod)
2188 {
2189 (void) FormatLocaleString(buffer,MagickPathExtent,
2190 "pixel-intensity=%s\n",CommandOptionToMnemonic(
2191 MagickPixelIntensityOptions,image->intensity));
2192 (void) WriteBlobString(image,buffer);
2193 }
2194 if (image->endian != UndefinedEndian)
2195 {
2196 (void) FormatLocaleString(buffer,MagickPathExtent,"endian=%s\n",
2197 CommandOptionToMnemonic(MagickEndianOptions,image->endian));
2198 (void) WriteBlobString(image,buffer);
2199 }
2200 if (compression != UndefinedCompression)
2201 {
2202 (void) FormatLocaleString(buffer,MagickPathExtent,"compression=%s "
2203 "quality=%.20g\n",CommandOptionToMnemonic(MagickCompressOptions,
2204 compression),(double) image->quality);
2205 (void) WriteBlobString(image,buffer);
2206 }
2207 if (image->units != UndefinedResolution)
2208 {
2209 (void) FormatLocaleString(buffer,MagickPathExtent,"units=%s\n",
2210 CommandOptionToMnemonic(MagickResolutionOptions,image->units));
2211 (void) WriteBlobString(image,buffer);
2212 }
2213 if ((image->resolution.x != 0) || (image->resolution.y != 0))
2214 {
2215 (void) FormatLocaleString(buffer,MagickPathExtent,
2216 "resolution=%gx%g\n",image->resolution.x,image->resolution.y);
2217 (void) WriteBlobString(image,buffer);
2218 }
2219 if ((image->page.width != 0) || (image->page.height != 0))
2220 {
2221 (void) FormatLocaleString(buffer,MagickPathExtent,
2222 "page=%.20gx%.20g%+.20g%+.20g\n",(double) image->page.width,(double)
2223 image->page.height,(double) image->page.x,(double) image->page.y);
2224 (void) WriteBlobString(image,buffer);
2225 }
2226 else
2227 if ((image->page.x != 0) || (image->page.y != 0))
2228 {
2229 (void) FormatLocaleString(buffer,MagickPathExtent,"page=%+ld%+ld\n",
2230 (long) image->page.x,(long) image->page.y);
2231 (void) WriteBlobString(image,buffer);
2232 }
2233 if ((image->tile_offset.x != 0) || (image->tile_offset.y != 0))
2234 {
2235 (void) FormatLocaleString(buffer,MagickPathExtent,
2236 "tile-offset=%+ld%+ld\n",(long) image->tile_offset.x,(long)
2237 image->tile_offset.y);
2238 (void) WriteBlobString(image,buffer);
2239 }
2240 if ((GetNextImageInList(image) != (Image *) NULL) ||
2241 (GetPreviousImageInList(image) != (Image *) NULL))
2242 {
2243 if (image->scene == 0)
2244 (void) FormatLocaleString(buffer,MagickPathExtent,"iterations=%.20g "
2245 "delay=%.20g ticks-per-second=%.20g\n",(double) image->iterations,
2246 (double) image->delay,(double) image->ticks_per_second);
2247 else
2248 (void) FormatLocaleString(buffer,MagickPathExtent,"scene=%.20g "
2249 "iterations=%.20g delay=%.20g ticks-per-second=%.20g\n",(double)
2250 image->scene,(double) image->iterations,(double) image->delay,
2251 (double) image->ticks_per_second);
2252 (void) WriteBlobString(image,buffer);
2253 }
2254 else
2255 {
2256 if (image->scene != 0)
2257 {
2258 (void) FormatLocaleString(buffer,MagickPathExtent,"scene=%.20g\n",
2259 (double) image->scene);
2260 (void) WriteBlobString(image,buffer);
2261 }
2262 if (image->iterations != 0)
2263 {
2264 (void) FormatLocaleString(buffer,MagickPathExtent,
2265 "iterations=%.20g\n",(double) image->iterations);
2266 (void) WriteBlobString(image,buffer);
2267 }
2268 if (image->delay != 0)
2269 {
2270 (void) FormatLocaleString(buffer,MagickPathExtent,"delay=%.20g\n",
2271 (double) image->delay);
2272 (void) WriteBlobString(image,buffer);
2273 }
2274 if (image->ticks_per_second != UndefinedTicksPerSecond)
2275 {
2276 (void) FormatLocaleString(buffer,MagickPathExtent,
2277 "ticks-per-second=%.20g\n",(double) image->ticks_per_second);
2278 (void) WriteBlobString(image,buffer);
2279 }
2280 }
2281 if (image->gravity != UndefinedGravity)
2282 {
2283 (void) FormatLocaleString(buffer,MagickPathExtent,"gravity=%s\n",
2284 CommandOptionToMnemonic(MagickGravityOptions,image->gravity));
2285 (void) WriteBlobString(image,buffer);
2286 }
2287 if (image->dispose != UndefinedDispose)
2288 {
2289 (void) FormatLocaleString(buffer,MagickPathExtent,"dispose=%s\n",
2290 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
2291 (void) WriteBlobString(image,buffer);
2292 }
2293 if (image->rendering_intent != UndefinedIntent)
2294 {
2295 (void) FormatLocaleString(buffer,MagickPathExtent,
2296 "rendering-intent=%s\n",CommandOptionToMnemonic(MagickIntentOptions,
2297 image->rendering_intent));
2298 (void) WriteBlobString(image,buffer);
2299 }
2300 if (image->gamma != 0.0)
2301 {
2302 (void) FormatLocaleString(buffer,MagickPathExtent,"gamma=%g\n",
2303 image->gamma);
2304 (void) WriteBlobString(image,buffer);
2305 }
2306 if (image->chromaticity.white_point.x != 0.0)
2307 {
2308 /*
2309 Note chomaticity points.
2310 */
2311 (void) FormatLocaleString(buffer,MagickPathExtent,"red-primary=%g,"
2312 "%g green-primary=%g,%g blue-primary=%g,%g\n",
2313 image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
2314 image->chromaticity.green_primary.x,
2315 image->chromaticity.green_primary.y,
2316 image->chromaticity.blue_primary.x,
2317 image->chromaticity.blue_primary.y);
2318 (void) WriteBlobString(image,buffer);
2319 (void) FormatLocaleString(buffer,MagickPathExtent,
2320 "white-point=%g,%g\n",image->chromaticity.white_point.x,
2321 image->chromaticity.white_point.y);
2322 (void) WriteBlobString(image,buffer);
2323 }
2324 if (image->orientation != UndefinedOrientation)
2325 {
2326 (void) FormatLocaleString(buffer,MagickPathExtent,"orientation=%s\n",
2327 CommandOptionToMnemonic(MagickOrientationOptions,image->orientation));
2328 (void) WriteBlobString(image,buffer);
2329 }
2330 if (image->profiles != (void *) NULL)
2331 {
2332 const char
2333 *name;
2334
2335 const StringInfo
2336 *profile;
2337
2338 /*
2339 Write image profile names.
2340 */
2341 ResetImageProfileIterator(image);
2342 for (name=GetNextImageProfile(image); name != (const char *) NULL; )
2343 {
2344 profile=GetImageProfile(image,name);
2345 if (profile != (StringInfo *) NULL)
2346 {
2347 (void) FormatLocaleString(buffer,MagickPathExtent,"profile=%s\n",
2348 name);
2349 (void) WriteBlobString(image,buffer);
2350 }
2351 name=GetNextImageProfile(image);
2352 }
2353 }
2354 if (image->montage != (char *) NULL)
2355 {
2356 (void) FormatLocaleString(buffer,MagickPathExtent,"montage=%s\n",
2357 image->montage);
2358 (void) WriteBlobString(image,buffer);
2359 }
2360 if (quantum_info->format == FloatingPointQuantumFormat)
2361 (void) SetImageProperty(image,"quantum:format","floating-point",
2362 exception);
2363 ResetImagePropertyIterator(image);
2364 property=GetNextImageProperty(image);
2365 while (property != (const char *) NULL)
2366 {
2367 (void) FormatLocaleString(buffer,MagickPathExtent,"%s=",property);
2368 (void) WriteBlobString(image,buffer);
2369 value=GetImageProperty(image,property,exception);
2370 if (value != (const char *) NULL)
2371 {
2372 length=strlen(value);
2373 for (i=0; i < (ssize_t) length; i++)
2374 if ((isspace((int) ((unsigned char) value[i])) != 0) ||
2375 (value[i] == '}'))
2376 break;
2377 if ((i == (ssize_t) length) && (i != 0))
2378 (void) WriteBlob(image,length,(const unsigned char *) value);
2379 else
2380 {
2381 (void) WriteBlobByte(image,'{');
2382 if (strchr(value,'}') == (char *) NULL)
2383 (void) WriteBlob(image,length,(const unsigned char *) value);
2384 else
2385 for (i=0; i < (ssize_t) length; i++)
2386 {
2387 if (value[i] == (int) '}')
2388 (void) WriteBlobByte(image,'\\');
2389 (void) WriteBlobByte(image,(unsigned char) value[i]);
2390 }
2391 (void) WriteBlobByte(image,'}');
2392 }
2393 }
2394 (void) WriteBlobByte(image,'\n');
2395 property=GetNextImageProperty(image);
2396 }
2397 (void) WriteBlobString(image,"\f\n:\032");
2398 if (image->montage != (char *) NULL)
2399 {
2400 /*
2401 Write montage tile directory.
2402 */
2403 if (image->directory != (char *) NULL)
2404 (void) WriteBlob(image,strlen(image->directory),(unsigned char *)
2405 image->directory);
2406 (void) WriteBlobByte(image,'\0');
2407 }
2408 if (image->profiles != 0)
2409 {
2410 const char
2411 *name;
2412
2413 const StringInfo
2414 *profile;
2415
2416 /*
2417 Write image profile blob.
2418 */
2419 ResetImageProfileIterator(image);
2420 name=GetNextImageProfile(image);
2421 while (name != (const char *) NULL)
2422 {
2423 profile=GetImageProfile(image,name);
2424 (void) WriteBlobMSBLong(image,(unsigned int)
2425 GetStringInfoLength(profile));
2426 (void) WriteBlob(image,GetStringInfoLength(profile),
2427 GetStringInfoDatum(profile));
2428 name=GetNextImageProfile(image);
2429 }
2430 }
2431 if (image->storage_class == PseudoClass)
2432 {
2433 size_t
2434 colormap_size;
2435
2436 unsigned char
2437 *colormap;
2438
2439 /*
2440 Allocate colormap.
2441 */
2442 colormap_size=(size_t) (3*quantum_info->depth/8);
2443 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
2444 colormap_size*sizeof(*colormap));
2445 if (colormap == (unsigned char *) NULL)
2446 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2447 /*
2448 Write colormap to file.
2449 */
2450 q=colormap;
2451 for (i=0; i < (ssize_t) image->colors; i++)
2452 {
2453 switch (quantum_info->depth)
2454 {
2455 default:
2456 ThrowWriterException(CorruptImageError,"ImageDepthNotSupported");
2457 case 32:
2458 {
2459 register unsigned int
2460 long_pixel;
2461
2462 long_pixel=ScaleQuantumToLong((Quantum)
2463 image->colormap[i].red);
2464 q=PopLongPixel(MSBEndian,long_pixel,q);
2465 long_pixel=ScaleQuantumToLong((Quantum)
2466 image->colormap[i].green);
2467 q=PopLongPixel(MSBEndian,long_pixel,q);
2468 long_pixel=ScaleQuantumToLong((Quantum)
2469 image->colormap[i].blue);
2470 q=PopLongPixel(MSBEndian,long_pixel,q);
2471 break;
2472 }
2473 case 16:
2474 {
2475 register unsigned short
2476 short_pixel;
2477
2478 short_pixel=ScaleQuantumToShort((Quantum)
2479 image->colormap[i].red);
2480 q=PopShortPixel(MSBEndian,short_pixel,q);
2481 short_pixel=ScaleQuantumToShort((Quantum)
2482 image->colormap[i].green);
2483 q=PopShortPixel(MSBEndian,short_pixel,q);
2484 short_pixel=ScaleQuantumToShort((Quantum)
2485 image->colormap[i].blue);
2486 q=PopShortPixel(MSBEndian,short_pixel,q);
2487 break;
2488 }
2489 case 8:
2490 {
2491 register unsigned char
2492 char_pixel;
2493
2494 char_pixel=(unsigned char) ScaleQuantumToChar((Quantum)
2495 image->colormap[i].red);
2496 q=PopCharPixel(char_pixel,q);
2497 char_pixel=(unsigned char) ScaleQuantumToChar((Quantum)
2498 image->colormap[i].green);
2499 q=PopCharPixel(char_pixel,q);
2500 char_pixel=(unsigned char) ScaleQuantumToChar((Quantum)
2501 image->colormap[i].blue);
2502 q=PopCharPixel(char_pixel,q);
2503 break;
2504 }
2505 }
2506 }
2507 (void) WriteBlob(image,colormap_size*image->colors,colormap);
2508 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
2509 }
2510 /*
2511 Write image pixels to file.
2512 */
2513 status=MagickTrue;
2514 switch (compression)
2515 {
2516 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2517 case BZipCompression:
2518 {
2519 int
2520 code;
2521
2522 (void) memset(&bzip_info,0,sizeof(bzip_info));
2523 bzip_info.bzalloc=AcquireBZIPMemory;
2524 bzip_info.bzfree=RelinquishBZIPMemory;
2525 bzip_info.opaque=(void *) NULL;
2526 code=BZ2_bzCompressInit(&bzip_info,(int) (image->quality ==
2527 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9)),
2528 (int) image_info->verbose,0);
2529 if (code != BZ_OK)
2530 status=MagickFalse;
2531 break;
2532 }
2533 #endif
2534 #if defined(MAGICKCORE_LZMA_DELEGATE)
2535 case LZMACompression:
2536 {
2537 int
2538 code;
2539
2540 allocator.alloc=AcquireLZMAMemory;
2541 allocator.free=RelinquishLZMAMemory;
2542 allocator.opaque=(void *) NULL;
2543 lzma_info=initialize_lzma;
2544 lzma_info.allocator=&allocator;
2545 code=lzma_easy_encoder(&lzma_info,(uint32_t) (image->quality/10),
2546 LZMA_CHECK_SHA256);
2547 if (code != LZMA_OK)
2548 status=MagickTrue;
2549 break;
2550 }
2551 #endif
2552 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2553 case LZWCompression:
2554 case ZipCompression:
2555 {
2556 int
2557 code;
2558
2559 zip_info.zalloc=AcquireZIPMemory;
2560 zip_info.zfree=RelinquishZIPMemory;
2561 zip_info.opaque=(void *) NULL;
2562 code=deflateInit(&zip_info,(int) (image->quality ==
2563 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9)));
2564 if (code != Z_OK)
2565 status=MagickFalse;
2566 break;
2567 }
2568 #endif
2569 default:
2570 break;
2571 }
2572 quantum_type=GetQuantumType(image,exception);
2573 pixels=(unsigned char *) GetQuantumPixels(quantum_info);
2574 for (y=0; y < (ssize_t) image->rows; y++)
2575 {
2576 register const Quantum
2577 *magick_restrict p;
2578
2579 register ssize_t
2580 x;
2581
2582 if (status == MagickFalse)
2583 break;
2584 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2585 if (p == (const Quantum *) NULL)
2586 break;
2587 q=pixels;
2588 switch (compression)
2589 {
2590 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2591 case BZipCompression:
2592 {
2593 bzip_info.next_in=(char *) pixels;
2594 bzip_info.avail_in=(unsigned int) (packet_size*image->columns);
2595 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2596 quantum_type,pixels,exception);
2597 do
2598 {
2599 int
2600 code;
2601
2602 bzip_info.next_out=(char *) compress_pixels;
2603 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2604 image->columns);
2605 code=BZ2_bzCompress(&bzip_info,BZ_FLUSH);
2606 if (code < 0)
2607 status=MagickFalse;
2608 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2609 if (length != 0)
2610 {
2611 (void) WriteBlobMSBLong(image,(unsigned int) length);
2612 (void) WriteBlob(image,length,compress_pixels);
2613 }
2614 } while (bzip_info.avail_in != 0);
2615 break;
2616 }
2617 #endif
2618 #if defined(MAGICKCORE_LZMA_DELEGATE)
2619 case LZMACompression:
2620 {
2621 lzma_info.next_in=pixels;
2622 lzma_info.avail_in=packet_size*image->columns;
2623 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2624 quantum_type,pixels,exception);
2625 do
2626 {
2627 int
2628 code;
2629
2630 lzma_info.next_out=compress_pixels;
2631 lzma_info.avail_out=LZMAMaxExtent(packet_size*image->columns);
2632 code=lzma_code(&lzma_info,LZMA_RUN);
2633 if (code != LZMA_OK)
2634 status=MagickFalse;
2635 length=(size_t) (lzma_info.next_out-compress_pixels);
2636 if (length != 0)
2637 {
2638 (void) WriteBlobMSBLong(image,(unsigned int) length);
2639 (void) WriteBlob(image,length,compress_pixels);
2640 }
2641 } while (lzma_info.avail_in != 0);
2642 break;
2643 }
2644 #endif
2645 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2646 case LZWCompression:
2647 case ZipCompression:
2648 {
2649 zip_info.next_in=pixels;
2650 zip_info.avail_in=(uInt) (packet_size*image->columns);
2651 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2652 quantum_type,pixels,exception);
2653 do
2654 {
2655 int
2656 code;
2657
2658 zip_info.next_out=compress_pixels;
2659 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns);
2660 code=deflate(&zip_info,Z_SYNC_FLUSH);
2661 if (code != Z_OK)
2662 status=MagickFalse;
2663 length=(size_t) (zip_info.next_out-compress_pixels);
2664 if (length != 0)
2665 {
2666 (void) WriteBlobMSBLong(image,(unsigned int) length);
2667 (void) WriteBlob(image,length,compress_pixels);
2668 }
2669 } while (zip_info.avail_in != 0);
2670 break;
2671 }
2672 #endif
2673 case RLECompression:
2674 {
2675 length=0;
2676 GetPixelInfoPixel(image,p,&pixel);
2677 p+=GetPixelChannels(image);
2678 for (x=1; x < (ssize_t) image->columns; x++)
2679 {
2680 GetPixelInfoPixel(image,p,&target);
2681 if ((length < 255) &&
2682 (IsPixelInfoEquivalent(&pixel,&target) != MagickFalse))
2683 length++;
2684 else
2685 {
2686 q=PopRunlengthPacket(image,q,length,&pixel,exception);
2687 length=0;
2688 }
2689 GetPixelInfoPixel(image,p,&pixel);
2690 p+=GetPixelChannels(image);
2691 }
2692 q=PopRunlengthPacket(image,q,length,&pixel,exception);
2693 (void) WriteBlob(image,(size_t) (q-pixels),pixels);
2694 break;
2695 }
2696 default:
2697 {
2698 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2699 quantum_type,pixels,exception);
2700 (void) WriteBlob(image,packet_size*image->columns,pixels);
2701 break;
2702 }
2703 }
2704 if (image->previous == (Image *) NULL)
2705 {
2706 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2707 image->rows);
2708 if (status == MagickFalse)
2709 break;
2710 }
2711 }
2712 switch (compression)
2713 {
2714 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2715 case BZipCompression:
2716 {
2717 int
2718 code;
2719
2720 for ( ; ; )
2721 {
2722 if (status == MagickFalse)
2723 break;
2724 bzip_info.next_out=(char *) compress_pixels;
2725 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2726 image->columns);
2727 code=BZ2_bzCompress(&bzip_info,BZ_FINISH);
2728 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2729 if (length != 0)
2730 {
2731 (void) WriteBlobMSBLong(image,(unsigned int) length);
2732 (void) WriteBlob(image,length,compress_pixels);
2733 }
2734 if (code == BZ_STREAM_END)
2735 break;
2736 }
2737 code=BZ2_bzCompressEnd(&bzip_info);
2738 if (code != BZ_OK)
2739 status=MagickFalse;
2740 break;
2741 }
2742 #endif
2743 #if defined(MAGICKCORE_LZMA_DELEGATE)
2744 case LZMACompression:
2745 {
2746 int
2747 code;
2748
2749 for ( ; ; )
2750 {
2751 if (status == MagickFalse)
2752 break;
2753 lzma_info.next_out=compress_pixels;
2754 lzma_info.avail_out=packet_size*image->columns;
2755 code=lzma_code(&lzma_info,LZMA_FINISH);
2756 length=(size_t) (lzma_info.next_out-compress_pixels);
2757 if (length > 6)
2758 {
2759 (void) WriteBlobMSBLong(image,(unsigned int) length);
2760 (void) WriteBlob(image,length,compress_pixels);
2761 }
2762 if (code == LZMA_STREAM_END)
2763 break;
2764 }
2765 lzma_end(&lzma_info);
2766 break;
2767 }
2768 #endif
2769 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2770 case LZWCompression:
2771 case ZipCompression:
2772 {
2773 int
2774 code;
2775
2776 for ( ; ; )
2777 {
2778 if (status == MagickFalse)
2779 break;
2780 zip_info.next_out=compress_pixels;
2781 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns);
2782 code=deflate(&zip_info,Z_FINISH);
2783 length=(size_t) (zip_info.next_out-compress_pixels);
2784 if (length > 6)
2785 {
2786 (void) WriteBlobMSBLong(image,(unsigned int) length);
2787 (void) WriteBlob(image,length,compress_pixels);
2788 }
2789 if (code == Z_STREAM_END)
2790 break;
2791 }
2792 code=deflateEnd(&zip_info);
2793 if (code != Z_OK)
2794 status=MagickFalse;
2795 break;
2796 }
2797 #endif
2798 default:
2799 break;
2800 }
2801 quantum_info=DestroyQuantumInfo(quantum_info);
2802 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
2803 if (GetNextImageInList(image) == (Image *) NULL)
2804 break;
2805 image=SyncNextImageInList(image);
2806 status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);
2807 if (status == MagickFalse)
2808 break;
2809 } while (image_info->adjoin != MagickFalse);
2810 (void) CloseBlob(image);
2811 return(status);
2812 }
2813