blob: ade4d7837ca10a7ed3f1b473e9e73b6a3f22051b [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% %
20% Copyright 1999-2009 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% 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"
cristy316d5172009-09-17 19:31:25 +000048#include "magick/colormap-private.h"
cristy3ed852e2009-09-05 21:47:34 +000049#include "magick/color-private.h"
50#include "magick/colorspace.h"
51#include "magick/constitute.h"
52#include "magick/exception.h"
53#include "magick/exception-private.h"
54#include "magick/hashmap.h"
55#include "magick/geometry.h"
56#include "magick/image.h"
57#include "magick/image-private.h"
58#include "magick/list.h"
59#include "magick/magick.h"
60#include "magick/memory_.h"
61#include "magick/monitor.h"
62#include "magick/monitor-private.h"
63#include "magick/option.h"
64#include "magick/pixel.h"
65#include "magick/profile.h"
66#include "magick/property.h"
67#include "magick/quantum-private.h"
68#include "magick/static.h"
69#include "magick/statistic.h"
70#include "magick/string_.h"
71#include "magick/module.h"
72#if defined(MAGICKCORE_ZLIB_DELEGATE)
73#include "zlib.h"
74#endif
75#if defined(MAGICKCORE_BZLIB_DELEGATE)
76#include "bzlib.h"
77#endif
78
79/*
80 Forward declarations.
81*/
82static MagickBooleanType
83 WriteMIFFImage(const ImageInfo *,Image *);
84
85/*
86%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87% %
88% %
89% %
90% I s M I F F %
91% %
92% %
93% %
94%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95%
96% IsMIFF() returns MagickTrue if the image format type, identified by the
97% magick string, is MIFF.
98%
99% The format of the IsMIFF method is:
100%
101% MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
102%
103% A description of each parameter follows:
104%
105% o magick: compare image format pattern against these bytes.
106%
107% o length: Specifies the length of the magick string.
108%
109*/
110static MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
111{
112 if (length < 14)
113 return(MagickFalse);
114 if (LocaleNCompare((const char *) magick,"id=ImageMagick",14) == 0)
115 return(MagickTrue);
116 return(MagickFalse);
117}
118
119/*
120%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121% %
122% %
123% %
124% R e a d M I F F I m a g e %
125% %
126% %
127% %
128%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
129%
130% ReadMIFFImage() reads a MIFF image file and returns it. It allocates the
131% memory necessary for the new Image structure and returns a pointer to the
132% new image.
133%
134% The format of the ReadMIFFImage method is:
135%
136% Image *ReadMIFFImage(const ImageInfo *image_info,
137% ExceptionInfo *exception)
138%
139% Decompression code contributed by Kyle Shorter.
140%
141% A description of each parameter follows:
142%
143% o image_info: the image info.
144%
145% o exception: return any errors or warnings in this structure.
146%
147*/
148
149#if defined(MAGICKCORE_BZLIB_DELEGATE)
150static void *AcquireBZIPMemory(void *context,int items,int size)
151{
152 (void) context;
153 return((void *) AcquireQuantumMemory((size_t) items,(size_t) size));
154}
155#endif
156
157#if defined(MAGICKCORE_ZLIB_DELEGATE)
158static voidpf AcquireZIPMemory(voidpf context,unsigned int items,
159 unsigned int size)
160{
161 (void) context;
162 return((voidpf) AcquireQuantumMemory(items,size));
163}
164#endif
165
166static inline size_t MagickMax(const size_t x,const size_t y)
167{
168 if (x > y)
169 return(x);
170 return(y);
171}
172
173static inline size_t MagickMin(const size_t x,const size_t y)
174{
175 if (x < y)
176 return(x);
177 return(y);
178}
179
180static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
181 size_t *length,PixelPacket *pixel,IndexPacket *index)
182{
183 const unsigned char
184 *p;
185
186 p=pixels;
187 if (image->storage_class == PseudoClass)
188 {
189 *index=(IndexPacket) 0;
190 switch (image->depth)
191 {
192 case 32:
193 {
194 *index=ConstrainColormapIndex(image,
195 (*p << 24) | (*(p+1) << 16) | (*(p+2) << 8) | *(p+3));
196 p+=4;
197 break;
198 }
199 case 16:
200 {
201 *index=ConstrainColormapIndex(image,(*p << 8) | *(p+1));
202 p+=2;
203 break;
204 }
205 case 8:
206 {
207 *index=ConstrainColormapIndex(image,*p);
208 p++;
209 break;
210 }
211 default:
212 (void) ThrowMagickException(&image->exception,GetMagickModule(),
213 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
214 }
215 *pixel=image->colormap[(long) *index];
216 switch (image->depth)
217 {
218 case 8:
219 {
220 unsigned char
221 quantum;
222
223 if (image->matte != MagickFalse)
224 {
225 p=PushCharPixel(p,&quantum);
226 pixel->opacity=ScaleCharToQuantum(quantum);
227 }
228 break;
229 }
230 case 16:
231 {
232 unsigned short
233 quantum;
234
235 if (image->matte != MagickFalse)
236 {
237 p=PushShortPixel(MSBEndian,p,&quantum);
238 pixel->opacity=(Quantum) (quantum >> (image->depth-
239 MAGICKCORE_QUANTUM_DEPTH));
240 }
241 break;
242 }
243 case 32:
244 {
245 unsigned long
246 quantum;
247
248 if (image->matte != MagickFalse)
249 {
250 p=PushLongPixel(MSBEndian,p,&quantum);
251 pixel->opacity=(Quantum) (quantum >> (image->depth-
252 MAGICKCORE_QUANTUM_DEPTH));
253 }
254 break;
255 }
256 default:
257 (void) ThrowMagickException(&image->exception,GetMagickModule(),
258 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
259 }
260 *length=(size_t) (*p++)+1;
261 return;
262 }
263 switch (image->depth)
264 {
265 case 8:
266 {
267 unsigned char
268 quantum;
269
270 p=PushCharPixel(p,&quantum);
271 pixel->red=ScaleCharToQuantum(quantum);
272 p=PushCharPixel(p,&quantum);
273 pixel->green=ScaleCharToQuantum(quantum);
274 p=PushCharPixel(p,&quantum);
275 pixel->blue=ScaleCharToQuantum(quantum);
276 if (image->matte != MagickFalse)
277 {
278 p=PushCharPixel(p,&quantum);
279 pixel->opacity=ScaleCharToQuantum(quantum);
280 }
281 if (image->colorspace == CMYKColorspace)
282 {
283 p=PushCharPixel(p,&quantum);
284 *index=ScaleCharToQuantum(quantum);
285 }
286 break;
287 }
288 case 16:
289 {
290 unsigned short
291 quantum;
292
293 p=PushShortPixel(MSBEndian,p,&quantum);
294 pixel->red=(Quantum) (quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH));
295 p=PushShortPixel(MSBEndian,p,&quantum);
296 pixel->green=(Quantum) (quantum >> (image->depth-
297 MAGICKCORE_QUANTUM_DEPTH));
298 p=PushShortPixel(MSBEndian,p,&quantum);
299 pixel->blue=(Quantum) (quantum >> (image->depth-
300 MAGICKCORE_QUANTUM_DEPTH));
301 if (image->matte != MagickFalse)
302 {
303 p=PushShortPixel(MSBEndian,p,&quantum);
304 pixel->opacity=(Quantum) (quantum >> (image->depth-
305 MAGICKCORE_QUANTUM_DEPTH));
306 }
307 if (image->colorspace == CMYKColorspace)
308 {
309 p=PushShortPixel(MSBEndian,p,&quantum);
310 *index=(IndexPacket) (quantum >> (image->depth-
311 MAGICKCORE_QUANTUM_DEPTH));
312 }
313 break;
314 }
315 case 32:
316 {
317 unsigned long
318 quantum;
319
320 p=PushLongPixel(MSBEndian,p,&quantum);
321 pixel->red=(Quantum) (quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH));
322 p=PushLongPixel(MSBEndian,p,&quantum);
323 pixel->green=(Quantum) (quantum >> (image->depth-
324 MAGICKCORE_QUANTUM_DEPTH));
325 p=PushLongPixel(MSBEndian,p,&quantum);
326 pixel->blue=(Quantum) (quantum >> (image->depth-
327 MAGICKCORE_QUANTUM_DEPTH));
328 if (image->matte != MagickFalse)
329 {
330 p=PushLongPixel(MSBEndian,p,&quantum);
331 pixel->opacity=(Quantum) (quantum >> (image->depth-
332 MAGICKCORE_QUANTUM_DEPTH));
333 }
334 if (image->colorspace == CMYKColorspace)
335 {
336 p=PushLongPixel(MSBEndian,p,&quantum);
337 *index=(IndexPacket) (quantum >> (image->depth-
338 MAGICKCORE_QUANTUM_DEPTH));
339 }
340 break;
341 }
342 default:
343 (void) ThrowMagickException(&image->exception,GetMagickModule(),
344 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
345 }
346 *length=(size_t) (*p++)+1;
347}
348
349#if defined(MAGICKCORE_ZLIB_DELEGATE)
350static void RelinquishZIPMemory(voidpf context,voidpf memory)
351{
352 (void) context;
353 memory=RelinquishMagickMemory(memory);
354}
355#endif
356
357#if defined(MAGICKCORE_BZLIB_DELEGATE)
358static void RelinquishBZIPMemory(void *context,void *memory)
359{
360 (void) context;
361 memory=RelinquishMagickMemory(memory);
362}
363#endif
364
365static Image *ReadMIFFImage(const ImageInfo *image_info,
366 ExceptionInfo *exception)
367{
368#define BZipMaxExtent(x) ((x)+((x)/100)+600)
369#define ZipMaxExtent(x) ((x)+(((x)+7) >> 3)+(((x)+63) >> 6)+11)
370
371#if defined(MAGICKCORE_BZLIB_DELEGATE)
372 bz_stream
373 bzip_info;
374#endif
375
376 char
377 id[MaxTextExtent],
378 keyword[MaxTextExtent],
379 *options;
380
381 const unsigned char
382 *p;
383
384 double
385 version;
386
387 GeometryInfo
388 geometry_info;
389
390 Image
391 *image;
392
393 IndexPacket
394 index;
395
396 int
397 c,
398 code;
399
400 LinkedListInfo
401 *profiles;
402
403 long
404 y;
405
406 MagickBooleanType
407 status;
408
409 MagickStatusType
410 flags;
411
412 PixelPacket
413 pixel;
414
415 QuantumFormatType
416 quantum_format;
417
418 QuantumInfo
419 *quantum_info;
420
421 QuantumType
422 quantum_type;
423
424 register long
425 i;
426
427 size_t
428 length,
429 packet_size;
430
431 ssize_t
432 count;
433
434 unsigned char
435 *compress_pixels,
436 *pixels;
437
438 unsigned long
439 colors;
440
441#if defined(MAGICKCORE_ZLIB_DELEGATE)
442 z_stream
443 zip_info;
444#endif
445
446 /*
447 Open image file.
448 */
449 assert(image_info != (const ImageInfo *) NULL);
450 assert(image_info->signature == MagickSignature);
451 if (image_info->debug != MagickFalse)
452 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
453 image_info->filename);
454 assert(exception != (ExceptionInfo *) NULL);
455 assert(exception->signature == MagickSignature);
456 image=AcquireImage(image_info);
457 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
458 if (status == MagickFalse)
459 {
460 image=DestroyImageList(image);
461 return((Image *) NULL);
462 }
463 /*
464 Decode image header; header terminates one character beyond a ':'.
465 */
466 c=ReadBlobByte(image);
467 if (c == EOF)
468 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
469 code=0;
470 *id='\0';
471 (void) ResetMagickMemory(keyword,0,sizeof(keyword));
472 version=0.0;
473 do
474 {
475 /*
476 Decode image header; header terminates one character beyond a ':'.
477 */
478 length=MaxTextExtent;
479 options=AcquireString((char *) NULL);
480 quantum_format=UndefinedQuantumFormat;
481 profiles=(LinkedListInfo *) NULL;
482 colors=0;
483 image->depth=8UL;
484 image->compression=NoCompression;
485 while ((isgraph(c) != MagickFalse) && (c != (int) ':'))
486 {
487 register char
488 *p;
489
490 if (c == (int) '{')
491 {
492 char
493 *comment;
494
495 /*
496 Read comment-- any text between { }.
497 */
498 length=MaxTextExtent;
499 comment=AcquireString((char *) NULL);
500 for (p=comment; comment != (char *) NULL; p++)
501 {
502 c=ReadBlobByte(image);
503 if ((c == EOF) || (c == (int) '}'))
504 break;
505 if ((size_t) (p-comment+1) >= length)
506 {
507 *p='\0';
508 length<<=1;
509 comment=(char *) ResizeQuantumMemory(comment,length+
510 MaxTextExtent,sizeof(*comment));
511 if (comment == (char *) NULL)
512 break;
513 p=comment+strlen(comment);
514 }
515 *p=(char) c;
516 }
517 if (comment == (char *) NULL)
518 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
519 *p='\0';
520 (void) SetImageProperty(image,"comment",comment);
521 comment=DestroyString(comment);
522 c=ReadBlobByte(image);
523 }
524 else
525 if (isalnum(c) != MagickFalse)
526 {
527 /*
528 Get the keyword.
529 */
530 p=keyword;
531 do
532 {
533 if (isspace((int) ((unsigned char) c)) != 0)
534 break;
535 if (c == (int) '=')
536 break;
537 if ((size_t) (p-keyword) < (MaxTextExtent-1))
538 *p++=(char) c;
539 c=ReadBlobByte(image);
540 } while (c != EOF);
541 *p='\0';
542 p=options;
543 while (isspace((int) ((unsigned char) c)) != 0)
544 c=ReadBlobByte(image);
545 if (c == (int) '=')
546 {
547 /*
548 Get the keyword value.
549 */
550 c=ReadBlobByte(image);
551 while ((c != (int) '}') && (c != EOF))
552 {
553 if ((size_t) (p-options+1) >= length)
554 {
555 *p='\0';
556 length<<=1;
557 options=(char *) ResizeQuantumMemory(options,length+
558 MaxTextExtent,sizeof(*options));
559 if (options == (char *) NULL)
560 break;
561 p=options+strlen(options);
562 }
563 if (options == (char *) NULL)
564 ThrowReaderException(ResourceLimitError,
565 "MemoryAllocationFailed");
566 *p++=(char) c;
567 c=ReadBlobByte(image);
568 if (*options != '{')
569 if (isspace((int) ((unsigned char) c)) != 0)
570 break;
571 }
572 }
573 *p='\0';
574 if (*options == '{')
575 (void) CopyMagickString(options,options+1,MaxTextExtent);
576 /*
577 Assign a value to the specified keyword.
578 */
579 switch (*keyword)
580 {
581 case 'b':
582 case 'B':
583 {
584 if (LocaleCompare(keyword,"background-color") == 0)
585 {
586 (void) QueryColorDatabase(options,&image->background_color,
587 exception);
588 break;
589 }
590 if (LocaleCompare(keyword,"blue-primary") == 0)
591 {
592 flags=ParseGeometry(options,&geometry_info);
593 image->chromaticity.blue_primary.x=geometry_info.rho;
594 image->chromaticity.blue_primary.y=geometry_info.sigma;
595 if ((flags & SigmaValue) == 0)
596 image->chromaticity.blue_primary.y=
597 image->chromaticity.blue_primary.x;
598 break;
599 }
600 if (LocaleCompare(keyword,"border-color") == 0)
601 {
602 (void) QueryColorDatabase(options,&image->border_color,
603 exception);
604 break;
605 }
606 (void) SetImageProperty(image,keyword,options);
607 break;
608 }
609 case 'c':
610 case 'C':
611 {
612 if (LocaleCompare(keyword,"class") == 0)
613 {
614 long
615 storage_class;
616
617 storage_class=ParseMagickOption(MagickClassOptions,
618 MagickFalse,options);
619 if (storage_class < 0)
620 break;
621 image->storage_class=(ClassType) storage_class;
622 break;
623 }
624 if (LocaleCompare(keyword,"colors") == 0)
625 {
626 colors=(unsigned long) atol(options);
627 break;
628 }
629 if (LocaleCompare(keyword,"colorspace") == 0)
630 {
631 long
632 colorspace;
633
634 colorspace=ParseMagickOption(MagickColorspaceOptions,
635 MagickFalse,options);
636 if (colorspace < 0)
637 break;
638 image->colorspace=(ColorspaceType) colorspace;
639 break;
640 }
641 if (LocaleCompare(keyword,"compression") == 0)
642 {
643 long
644 compression;
645
646 compression=ParseMagickOption(MagickCompressOptions,
647 MagickFalse,options);
648 if (compression < 0)
649 break;
650 image->compression=(CompressionType) compression;
651 break;
652 }
653 if (LocaleCompare(keyword,"columns") == 0)
654 {
655 image->columns=(unsigned long) atol(options);
656 break;
657 }
658 (void) SetImageProperty(image,keyword,options);
659 break;
660 }
661 case 'd':
662 case 'D':
663 {
664 if (LocaleCompare(keyword,"delay") == 0)
665 {
666 image->delay=(unsigned long) atol(options);
667 break;
668 }
669 if (LocaleCompare(keyword,"depth") == 0)
670 {
671 image->depth=(unsigned long) atol(options);
672 break;
673 }
674 if (LocaleCompare(keyword,"dispose") == 0)
675 {
676 long
677 dispose;
678
679 dispose=ParseMagickOption(MagickDisposeOptions,MagickFalse,
680 options);
681 if (dispose < 0)
682 break;
683 image->dispose=(DisposeType) dispose;
684 break;
685 }
686 (void) SetImageProperty(image,keyword,options);
687 break;
688 }
689 case 'e':
690 case 'E':
691 {
692 if (LocaleCompare(keyword,"endian") == 0)
693 {
694 long
695 endian;
696
697 endian=ParseMagickOption(MagickEndianOptions,MagickFalse,
698 options);
699 if (endian < 0)
700 break;
701 image->endian=(EndianType) endian;
702 break;
703 }
704 (void) SetImageProperty(image,keyword,options);
705 break;
706 }
707 case 'g':
708 case 'G':
709 {
710 if (LocaleCompare(keyword,"gamma") == 0)
711 {
712 image->gamma=atof(options);
713 break;
714 }
715 if (LocaleCompare(keyword,"gravity") == 0)
716 {
717 long
718 gravity;
719
720 gravity=ParseMagickOption(MagickGravityOptions,MagickFalse,
721 options);
722 if (gravity < 0)
723 break;
724 image->gravity=(GravityType) gravity;
725 break;
726 }
727 if (LocaleCompare(keyword,"green-primary") == 0)
728 {
729 flags=ParseGeometry(options,&geometry_info);
730 image->chromaticity.green_primary.x=geometry_info.rho;
731 image->chromaticity.green_primary.y=geometry_info.sigma;
732 if ((flags & SigmaValue) == 0)
733 image->chromaticity.green_primary.y=
734 image->chromaticity.green_primary.x;
735 break;
736 }
737 (void) SetImageProperty(image,keyword,options);
738 break;
739 }
740 case 'i':
741 case 'I':
742 {
743 if (LocaleCompare(keyword,"id") == 0)
744 {
745 (void) CopyMagickString(id,options,MaxTextExtent);
746 break;
747 }
748 if (LocaleCompare(keyword,"iterations") == 0)
749 {
750 image->iterations=(unsigned long) atol(options);
751 break;
752 }
753 (void) SetImageProperty(image,keyword,options);
754 break;
755 }
756 case 'm':
757 case 'M':
758 {
759 if (LocaleCompare(keyword,"matte") == 0)
760 {
761 long
762 matte;
763
764 matte=ParseMagickOption(MagickBooleanOptions,MagickFalse,
765 options);
766 if (matte < 0)
767 break;
768 image->matte=(MagickBooleanType) matte;
769 break;
770 }
771 if (LocaleCompare(keyword,"matte-color") == 0)
772 {
773 (void) QueryColorDatabase(options,&image->matte_color,
774 exception);
775 break;
776 }
777 if (LocaleCompare(keyword,"montage") == 0)
778 {
779 (void) CloneString(&image->montage,options);
780 break;
781 }
782 (void) SetImageProperty(image,keyword,options);
783 break;
784 }
785 case 'o':
786 case 'O':
787 {
788 if (LocaleCompare(keyword,"opaque") == 0)
789 {
790 long
791 matte;
792
793 matte=ParseMagickOption(MagickBooleanOptions,MagickFalse,
794 options);
795 if (matte < 0)
796 break;
797 image->matte=(MagickBooleanType) matte;
798 break;
799 }
800 if (LocaleCompare(keyword,"orientation") == 0)
801 {
802 long
803 orientation;
804
805 orientation=ParseMagickOption(MagickOrientationOptions,
806 MagickFalse,options);
807 if (orientation < 0)
808 break;
809 image->orientation=(OrientationType) orientation;
810 break;
811 }
812 (void) SetImageProperty(image,keyword,options);
813 break;
814 }
815 case 'p':
816 case 'P':
817 {
818 if (LocaleCompare(keyword,"page") == 0)
819 {
820 char
821 *geometry;
822
823 geometry=GetPageGeometry(options);
824 (void) ParseAbsoluteGeometry(geometry,&image->page);
825 geometry=DestroyString(geometry);
826 break;
827 }
828 if ((LocaleNCompare(keyword,"profile:",8) == 0) ||
829 (LocaleNCompare(keyword,"profile-",8) == 0))
830 {
831 StringInfo
832 *profile;
833
834 if (profiles == (LinkedListInfo *) NULL)
835 profiles=NewLinkedList(0);
836 (void) AppendValueToLinkedList(profiles,
837 AcquireString(keyword+8));
838 profile=AcquireStringInfo((size_t) atol(options));
839 (void) SetImageProfile(image,keyword+8,profile);
840 profile=DestroyStringInfo(profile);
841 break;
842 }
843 (void) SetImageProperty(image,keyword,options);
844 break;
845 }
846 case 'q':
847 case 'Q':
848 {
849 if (LocaleCompare(keyword,"quality") == 0)
850 {
851 image->quality=(unsigned long) atol(options);
852 break;
853 }
854 if ((LocaleCompare(keyword,"quantum-format") == 0) ||
855 (LocaleCompare(keyword,"quantum:format") == 0))
856 {
857 long
858 format;
859
860 format=ParseMagickOption(MagickQuantumFormatOptions,
861 MagickFalse,options);
862 if (format < 0)
863 break;
864 quantum_format=(QuantumFormatType) format;
865 break;
866 }
867 (void) SetImageProperty(image,keyword,options);
868 break;
869 }
870 case 'r':
871 case 'R':
872 {
873 if (LocaleCompare(keyword,"red-primary") == 0)
874 {
875 flags=ParseGeometry(options,&geometry_info);
876 image->chromaticity.red_primary.x=geometry_info.rho;
877 image->chromaticity.red_primary.y=geometry_info.sigma;
878 if ((flags & SigmaValue) == 0)
879 image->chromaticity.red_primary.y=
880 image->chromaticity.red_primary.x;
881 break;
882 }
883 if (LocaleCompare(keyword,"rendering-intent") == 0)
884 {
885 long
886 rendering_intent;
887
888 rendering_intent=ParseMagickOption(MagickIntentOptions,
889 MagickFalse,options);
890 if (rendering_intent < 0)
891 break;
892 image->rendering_intent=(RenderingIntent) rendering_intent;
893 break;
894 }
895 if (LocaleCompare(keyword,"resolution") == 0)
896 {
897 flags=ParseGeometry(options,&geometry_info);
898 image->x_resolution=geometry_info.rho;
899 image->y_resolution=geometry_info.sigma;
900 if ((flags & SigmaValue) == 0)
901 image->y_resolution=image->x_resolution;
902 break;
903 }
904 if (LocaleCompare(keyword,"rows") == 0)
905 {
906 image->rows=(unsigned long) atol(options);
907 break;
908 }
909 (void) SetImageProperty(image,keyword,options);
910 break;
911 }
912 case 's':
913 case 'S':
914 {
915 if (LocaleCompare(keyword,"scene") == 0)
916 {
917 image->scene=(unsigned long) atol(options);
918 break;
919 }
920 (void) SetImageProperty(image,keyword,options);
921 break;
922 }
923 case 't':
924 case 'T':
925 {
926 if (LocaleCompare(keyword,"ticks-per-second") == 0)
927 {
928 image->ticks_per_second=atol(options);
929 break;
930 }
931 if (LocaleCompare(keyword,"tile-offset") == 0)
932 {
933 char
934 *geometry;
935
936 geometry=GetPageGeometry(options);
937 (void) ParseAbsoluteGeometry(geometry,&image->tile_offset);
938 geometry=DestroyString(geometry);
939 break;
940 }
941 if (LocaleCompare(keyword,"type") == 0)
942 {
943 long
944 type;
945
946 type=ParseMagickOption(MagickTypeOptions,MagickFalse,
947 options);
948 if (type < 0)
949 break;
950 image->type=(ImageType) type;
951 break;
952 }
953 (void) SetImageProperty(image,keyword,options);
954 break;
955 }
956 case 'u':
957 case 'U':
958 {
959 if (LocaleCompare(keyword,"units") == 0)
960 {
961 long
962 units;
963
964 units=ParseMagickOption(MagickResolutionOptions,MagickFalse,
965 options);
966 if (units < 0)
967 break;
968 image->units=(ResolutionType) units;
969 break;
970 }
971 (void) SetImageProperty(image,keyword,options);
972 break;
973 }
974 case 'v':
975 case 'V':
976 {
977 if (LocaleCompare(keyword,"version") == 0)
978 {
979 version=atof(options);
980 break;
981 }
982 (void) SetImageProperty(image,keyword,options);
983 break;
984 }
985 case 'w':
986 case 'W':
987 {
988 if (LocaleCompare(keyword,"white-point") == 0)
989 {
990 flags=ParseGeometry(options,&geometry_info);
991 image->chromaticity.white_point.x=geometry_info.rho;
992 image->chromaticity.white_point.y=geometry_info.rho;
993 if ((flags & SigmaValue) != 0)
994 image->chromaticity.white_point.y=
995 image->chromaticity.white_point.x;
996 break;
997 }
998 (void) SetImageProperty(image,keyword,options);
999 break;
1000 }
1001 default:
1002 {
1003 (void) SetImageProperty(image,keyword,options);
1004 break;
1005 }
1006 }
1007 }
1008 else
1009 c=ReadBlobByte(image);
1010 while (isspace((int) ((unsigned char) c)) != 0)
1011 c=ReadBlobByte(image);
1012 }
1013 options=DestroyString(options);
1014 (void) ReadBlobByte(image);
1015 /*
1016 Verify that required image information is defined.
1017 */
1018 if ((LocaleCompare(id,"ImageMagick") != 0) ||
1019 (image->storage_class == UndefinedClass) ||
1020 (image->columns == 0) || (image->rows == 0))
1021 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1022 if (image->montage != (char *) NULL)
1023 {
1024 register char
1025 *p;
1026
1027 /*
1028 Image directory.
1029 */
1030 length=MaxTextExtent;
1031 image->directory=AcquireString((char *) NULL);
1032 p=image->directory;
1033 do
1034 {
1035 *p='\0';
1036 if ((strlen(image->directory)+MaxTextExtent) >= length)
1037 {
1038 /*
1039 Allocate more memory for the image directory.
1040 */
1041 length<<=1;
1042 image->directory=(char *) ResizeQuantumMemory(image->directory,
1043 length+MaxTextExtent,sizeof(*image->directory));
1044 if (image->directory == (char *) NULL)
1045 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1046 p=image->directory+strlen(image->directory);
1047 }
1048 c=ReadBlobByte(image);
1049 *p++=(char) c;
1050 } while (c != (int) '\0');
1051 }
1052 if (profiles != (LinkedListInfo *) NULL)
1053 {
1054 const char
1055 *name;
1056
1057 const StringInfo
1058 *profile;
1059
1060 /*
1061 Read image profiles.
1062 */
1063 ResetLinkedListIterator(profiles);
1064 name=(const char *) GetNextValueInLinkedList(profiles);
1065 while (name != (const char *) NULL)
1066 {
1067 profile=GetImageProfile(image,name);
1068 if (profile != (StringInfo *) NULL)
1069 {
1070 register unsigned char
1071 *p;
1072
1073 p=GetStringInfoDatum(profile);
1074 count=ReadBlob(image,GetStringInfoLength(profile),p);
1075 }
1076 name=(const char *) GetNextValueInLinkedList(profiles);
1077 }
1078 profiles=DestroyLinkedList(profiles,RelinquishMagickMemory);
1079 }
1080 image->depth=GetImageQuantumDepth(image,MagickFalse);
1081 if (image->storage_class == PseudoClass)
1082 {
1083 /*
1084 Create image colormap.
1085 */
1086 status=AcquireImageColormap(image,colors != 0 ? colors : 256);
1087 if (status == MagickFalse)
1088 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1089 if (colors != 0)
1090 {
1091 size_t
1092 packet_size;
1093
1094 unsigned char
1095 *colormap;
1096
1097 /*
1098 Read image colormap from file.
1099 */
1100 packet_size=(size_t) (3UL*image->depth/8UL);
1101 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
1102 packet_size*sizeof(*colormap));
1103 if (colormap == (unsigned char *) NULL)
1104 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1105 count=ReadBlob(image,packet_size*image->colors,colormap);
1106 p=colormap;
1107 switch (image->depth)
1108 {
1109 default:
1110 ThrowReaderException(CorruptImageError,
1111 "ImageDepthNotSupported");
1112 case 8:
1113 {
1114 unsigned char
1115 pixel;
1116
1117 for (i=0; i < (long) image->colors; i++)
1118 {
1119 p=PushCharPixel(p,&pixel);
1120 image->colormap[i].red=ScaleCharToQuantum(pixel);
1121 p=PushCharPixel(p,&pixel);
1122 image->colormap[i].green=ScaleCharToQuantum(pixel);
1123 p=PushCharPixel(p,&pixel);
1124 image->colormap[i].blue=ScaleCharToQuantum(pixel);
1125 }
1126 break;
1127 }
1128 case 16:
1129 {
1130 unsigned short
1131 pixel;
1132
1133 for (i=0; i < (long) image->colors; i++)
1134 {
1135 p=PushShortPixel(MSBEndian,p,&pixel);
1136 image->colormap[i].red=ScaleShortToQuantum(pixel);
1137 p=PushShortPixel(MSBEndian,p,&pixel);
1138 image->colormap[i].green=ScaleShortToQuantum(pixel);
1139 p=PushShortPixel(MSBEndian,p,&pixel);
1140 image->colormap[i].blue=ScaleShortToQuantum(pixel);
1141 }
1142 break;
1143 }
1144 case 32:
1145 {
1146 unsigned long
1147 pixel;
1148
1149 for (i=0; i < (long) image->colors; i++)
1150 {
1151 p=PushLongPixel(MSBEndian,p,&pixel);
1152 image->colormap[i].red=ScaleLongToQuantum(pixel);
1153 p=PushLongPixel(MSBEndian,p,&pixel);
1154 image->colormap[i].green=ScaleLongToQuantum(pixel);
1155 p=PushLongPixel(MSBEndian,p,&pixel);
1156 image->colormap[i].blue=ScaleLongToQuantum(pixel);
1157 }
1158 break;
1159 }
1160 }
1161 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
1162 }
1163 }
1164 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1165 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1166 break;
1167 /*
1168 Allocate image pixels.
1169 */
1170 quantum_info=AcquireQuantumInfo(image_info,image);
1171 if (quantum_info == (QuantumInfo *) NULL)
1172 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1173 if (quantum_format != UndefinedQuantumFormat)
1174 {
1175 status=SetQuantumFormat(image,quantum_info,quantum_format);
1176 if (status == MagickFalse)
1177 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1178 }
1179 packet_size=(size_t) (quantum_info->depth/8);
1180 if (image->storage_class == DirectClass)
1181 packet_size=(size_t) (3*quantum_info->depth/8);
1182 if (image->matte != MagickFalse)
1183 packet_size+=quantum_info->depth/8;
1184 if (image->colorspace == CMYKColorspace)
1185 packet_size+=quantum_info->depth/8;
1186 if (image->compression == RLECompression)
1187 packet_size++;
1188 length=image->columns;
1189 length=MagickMax(BZipMaxExtent(packet_size*image->columns),ZipMaxExtent(
1190 packet_size*image->columns));
1191 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
1192 sizeof(*compress_pixels));
1193 if (compress_pixels == (unsigned char *) NULL)
1194 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1195 /*
1196 Read image pixels.
1197 */
1198 quantum_type=RGBQuantum;
1199 if (image->matte != MagickFalse)
1200 quantum_type=RGBAQuantum;
1201 if (image->colorspace == CMYKColorspace)
1202 {
1203 quantum_type=CMYKQuantum;
1204 if (image->matte != MagickFalse)
1205 quantum_type=CMYKAQuantum;
1206 }
1207 if (image->storage_class == PseudoClass)
1208 {
1209 quantum_type=IndexQuantum;
1210 if (image->matte != MagickFalse)
1211 quantum_type=IndexAlphaQuantum;
1212 }
1213 if (image->colorspace == GRAYColorspace)
1214 {
1215 quantum_type=GrayQuantum;
1216 if (image->matte != MagickFalse)
1217 quantum_type=GrayAlphaQuantum;
1218 }
1219 pixels=GetQuantumPixels(quantum_info);
1220 index=(IndexPacket) 0;
1221 length=0;
1222 for (y=0; y < (long) image->rows; y++)
1223 {
1224 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00001225 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00001226
1227 register long
1228 x;
1229
1230 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001231 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001232
1233 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1234 if (q == (PixelPacket *) NULL)
1235 break;
1236 indexes=GetAuthenticIndexQueue(image);
1237 switch (image->compression)
1238 {
1239#if defined(MAGICKCORE_ZLIB_DELEGATE)
1240 case LZWCompression:
1241 case ZipCompression:
1242 {
1243 if (y == 0)
1244 {
1245 zip_info.zalloc=AcquireZIPMemory;
1246 zip_info.zfree=RelinquishZIPMemory;
1247 zip_info.opaque=(voidpf) NULL;
1248 code=inflateInit(&zip_info);
1249 if (code >= 0)
1250 status=MagickTrue;
1251 zip_info.avail_in=0;
1252 }
1253 zip_info.next_out=pixels;
1254 zip_info.avail_out=(uInt) (packet_size*image->columns);
1255 do
1256 {
1257 if (zip_info.avail_in == 0)
1258 {
1259 zip_info.next_in=compress_pixels;
1260 length=(size_t) ZipMaxExtent(packet_size*image->columns);
1261 if (version != 0)
1262 length=(size_t) ReadBlobMSBLong(image);
1263 zip_info.avail_in=(unsigned int) ReadBlob(image,length,
1264 zip_info.next_in);
1265 }
1266 if (inflate(&zip_info,Z_SYNC_FLUSH) == Z_STREAM_END)
1267 break;
1268 } while (zip_info.avail_out != 0);
1269 if (y == (long) (image->rows-1))
1270 {
1271 if (version == 0)
1272 {
1273 MagickOffsetType
1274 offset;
1275
1276 offset=SeekBlob(image,-((MagickOffsetType) zip_info.avail_in),
1277 SEEK_CUR);
1278 if (offset < 0)
1279 ThrowReaderException(CorruptImageError,
1280 "ImproperImageHeader");
1281 }
1282 code=inflateEnd(&zip_info);
1283 if (code >= 0)
1284 status=MagickTrue;
1285 }
1286 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1287 quantum_type,pixels,exception);
1288 break;
1289 }
1290#endif
1291#if defined(MAGICKCORE_BZLIB_DELEGATE)
1292 case BZipCompression:
1293 {
1294 if (y == 0)
1295 {
1296 bzip_info.bzalloc=AcquireBZIPMemory;
1297 bzip_info.bzfree=RelinquishBZIPMemory;
1298 bzip_info.opaque=(void *) NULL;
1299 code=BZ2_bzDecompressInit(&bzip_info,(int) image_info->verbose,
1300 MagickFalse);
1301 if (code >= 0)
1302 status=MagickTrue;
1303 bzip_info.avail_in=0;
1304 }
1305 bzip_info.next_out=(char *) pixels;
1306 bzip_info.avail_out=(unsigned int) (packet_size*image->columns);
1307 do
1308 {
1309 if (bzip_info.avail_in == 0)
1310 {
1311 bzip_info.next_in=(char *) compress_pixels;
1312 length=(size_t) BZipMaxExtent(packet_size*image->columns);
1313 if (version != 0)
1314 length=(size_t) ReadBlobMSBLong(image);
1315 bzip_info.avail_in=(unsigned int) ReadBlob(image,length,
1316 (unsigned char *) bzip_info.next_in);
1317 }
1318 if (BZ2_bzDecompress(&bzip_info) == BZ_STREAM_END)
1319 break;
1320 } while (bzip_info.avail_out != 0);
1321 if (y == (long) (image->rows-1))
1322 {
1323 if (version == 0)
1324 {
1325 MagickOffsetType
1326 offset;
1327
1328 offset=SeekBlob(image,-((MagickOffsetType)
1329 bzip_info.avail_in),SEEK_CUR);
1330 if (offset < 0)
1331 ThrowReaderException(CorruptImageError,
1332 "ImproperImageHeader");
1333 }
1334 code=BZ2_bzDecompressEnd(&bzip_info);
1335 if (code >= 0)
1336 status=MagickTrue;
1337 }
1338 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1339 quantum_type,pixels,exception);
1340 break;
1341 }
1342#endif
1343 case RLECompression:
1344 {
1345 if (y == 0)
1346 {
1347 (void) ResetMagickMemory(&pixel,0,sizeof(pixel));
1348 pixel.opacity=(Quantum) TransparentOpacity;
1349 index=(IndexPacket) 0;
1350 }
1351 for (x=0; x < (long) image->columns; x++)
1352 {
1353 if (length == 0)
1354 {
1355 count=ReadBlob(image,packet_size,pixels);
1356 PushRunlengthPacket(image,pixels,&length,&pixel,&index);
1357 }
1358 length--;
1359 if ((image->storage_class == PseudoClass) ||
1360 (image->colorspace == CMYKColorspace))
1361 indexes[x]=index;
1362 *q++=pixel;
1363 }
1364 break;
1365 }
1366 default:
1367 {
1368 count=ReadBlob(image,packet_size*image->columns,pixels);
1369 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1370 quantum_type,pixels,exception);
1371 break;
1372 }
1373 }
1374 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1375 break;
1376 }
1377 SetQuantumImageType(image,quantum_type);
1378 quantum_info=DestroyQuantumInfo(quantum_info);
1379 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
1380 if (((y != (long) image->rows)) || (status == MagickFalse))
1381 {
1382 image=DestroyImageList(image);
1383 return((Image *) NULL);
1384 }
1385 if (EOFBlob(image) != MagickFalse)
1386 {
1387 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1388 image->filename);
1389 break;
1390 }
1391 /*
1392 Proceed to next image.
1393 */
1394 if (image_info->number_scenes != 0)
1395 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1396 break;
1397 do
1398 {
1399 c=ReadBlobByte(image);
1400 } while ((isgraph(c) == MagickFalse) && (c != EOF));
1401 if (c != EOF)
1402 {
1403 /*
1404 Allocate next image structure.
1405 */
1406 AcquireNextImage(image_info,image);
1407 if (GetNextImageInList(image) == (Image *) NULL)
1408 {
1409 image=DestroyImageList(image);
1410 return((Image *) NULL);
1411 }
1412 image=SyncNextImageInList(image);
1413 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1414 GetBlobSize(image));
1415 if (status == MagickFalse)
1416 break;
1417 }
1418 } while (c != EOF);
1419 (void) CloseBlob(image);
1420 return(GetFirstImageInList(image));
1421}
1422
1423/*
1424%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1425% %
1426% %
1427% %
1428% R e g i s t e r M I F F I m a g e %
1429% %
1430% %
1431% %
1432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1433%
1434% RegisterMIFFImage() adds properties for the MIFF image format to the list of
1435% supported formats. The properties include the image format tag, a method to
1436% read and/or write the format, whether the format supports the saving of more
1437% than one frame to the same file or blob, whether the format supports native
1438% in-memory I/O, and a brief description of the format.
1439%
1440% The format of the RegisterMIFFImage method is:
1441%
1442% unsigned long RegisterMIFFImage(void)
1443%
1444*/
1445ModuleExport unsigned long RegisterMIFFImage(void)
1446{
1447 char
1448 version[MaxTextExtent];
1449
1450 MagickInfo
1451 *entry;
1452
1453 *version='\0';
1454#if defined(MagickImageCoderSignatureText)
1455 (void) CopyMagickString(version,MagickLibVersionText,MaxTextExtent);
1456#if defined(ZLIB_VERSION)
1457 (void) ConcatenateMagickString(version," with Zlib ",MaxTextExtent);
1458 (void) ConcatenateMagickString(version,ZLIB_VERSION,MaxTextExtent);
1459#endif
1460#if defined(MAGICKCORE_BZLIB_DELEGATE)
1461 (void) ConcatenateMagickString(version," and BZlib",MaxTextExtent);
1462#endif
1463#endif
1464 entry=SetMagickInfo("MIFF");
1465 entry->decoder=(DecodeImageHandler *) ReadMIFFImage;
1466 entry->encoder=(EncodeImageHandler *) WriteMIFFImage;
1467 entry->magick=(IsImageFormatHandler *) IsMIFF;
1468 entry->description=ConstantString("Magick Image File Format");
1469 if (*version != '\0')
1470 entry->version=ConstantString(version);
1471 entry->module=ConstantString("MIFF");
1472 (void) RegisterMagickInfo(entry);
1473 return(MagickImageCoderSignature);
1474}
1475
1476/*
1477%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1478% %
1479% %
1480% %
1481% U n r e g i s t e r M I F F I m a g e %
1482% %
1483% %
1484% %
1485%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1486%
1487% UnregisterMIFFImage() removes format registrations made by the MIFF module
1488% from the list of supported formats.
1489%
1490% The format of the UnregisterMIFFImage method is:
1491%
1492% UnregisterMIFFImage(void)
1493%
1494*/
1495ModuleExport void UnregisterMIFFImage(void)
1496{
1497 (void) UnregisterMagickInfo("MIFF");
1498}
1499
1500/*
1501%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1502% %
1503% %
1504% %
1505% W r i t e M I F F I m a g e %
1506% %
1507% %
1508% %
1509%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1510%
1511% WriteMIFFImage() writes a MIFF image to a file.
1512%
1513% The format of the WriteMIFFImage method is:
1514%
1515% MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
1516% Image *image)
1517%
1518% Compression code contributed by Kyle Shorter.
1519%
1520% A description of each parameter follows:
1521%
1522% o image_info: the image info.
1523%
1524% o image: the image.
1525%
1526*/
1527
1528static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
1529 size_t length,PixelPacket pixel,IndexPacket index)
1530{
1531 if (image->storage_class != DirectClass)
1532 {
1533 switch (image->depth)
1534 {
1535 case 32:
1536 {
1537 *pixels++=(unsigned char) ((unsigned long) index >> 24);
1538 *pixels++=(unsigned char) ((unsigned long) index >> 16);
1539 }
1540 case 16:
1541 *pixels++=(unsigned char) ((unsigned long) index >> 8);
1542 case 8:
1543 {
1544 *pixels++=(unsigned char) index;
1545 break;
1546 }
1547 default:
1548 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1549 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1550 }
1551 switch (image->depth)
1552 {
1553 case 32:
1554 {
1555 unsigned long
1556 value;
1557
1558 if (image->matte != MagickFalse)
1559 {
1560 value=ScaleQuantumToLong(pixel.opacity);
1561 pixels=PopLongPixel(MSBEndian,value,pixels);
1562 }
1563 break;
1564 }
1565 case 16:
1566 {
1567 unsigned short
1568 value;
1569
1570 if (image->matte != MagickFalse)
1571 {
1572 value=ScaleQuantumToShort(pixel.opacity);
1573 pixels=PopShortPixel(MSBEndian,value,pixels);
1574 }
1575 break;
1576 }
1577 case 8:
1578 {
1579 unsigned char
1580 value;
1581
1582 if (image->matte != MagickFalse)
1583 {
1584 value=(unsigned char) ScaleQuantumToChar(pixel.opacity);
1585 pixels=PopCharPixel(value,pixels);
1586 }
1587 break;
1588 }
1589 default:
1590 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1591 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1592 }
1593 *pixels++=(unsigned char) length;
1594 return(pixels);
1595 }
1596 switch (image->depth)
1597 {
1598 case 32:
1599 {
1600 unsigned long
1601 value;
1602
1603 value=ScaleQuantumToLong(pixel.red);
1604 pixels=PopLongPixel(MSBEndian,value,pixels);
1605 value=ScaleQuantumToLong(pixel.green);
1606 pixels=PopLongPixel(MSBEndian,value,pixels);
1607 value=ScaleQuantumToLong(pixel.blue);
1608 pixels=PopLongPixel(MSBEndian,value,pixels);
1609 if (image->matte != MagickFalse)
1610 {
1611 value=ScaleQuantumToLong(pixel.opacity);
1612 pixels=PopLongPixel(MSBEndian,value,pixels);
1613 }
1614 if (image->colorspace == CMYKColorspace)
1615 {
1616 value=ScaleQuantumToLong(index);
1617 pixels=PopLongPixel(MSBEndian,value,pixels);
1618 }
1619 break;
1620 }
1621 case 16:
1622 {
1623 unsigned short
1624 value;
1625
1626 value=ScaleQuantumToShort(pixel.red);
1627 pixels=PopShortPixel(MSBEndian,value,pixels);
1628 value=ScaleQuantumToShort(pixel.green);
1629 pixels=PopShortPixel(MSBEndian,value,pixels);
1630 value=ScaleQuantumToShort(pixel.blue);
1631 pixels=PopShortPixel(MSBEndian,value,pixels);
1632 if (image->matte != MagickFalse)
1633 {
1634 value=ScaleQuantumToShort(pixel.opacity);
1635 pixels=PopShortPixel(MSBEndian,value,pixels);
1636 }
1637 if (image->colorspace == CMYKColorspace)
1638 {
1639 value=ScaleQuantumToShort(index);
1640 pixels=PopShortPixel(MSBEndian,value,pixels);
1641 }
1642 break;
1643 }
1644 case 8:
1645 {
1646 unsigned char
1647 value;
1648
1649 value=(unsigned char) ScaleQuantumToChar(pixel.red);
1650 pixels=PopCharPixel(value,pixels);
1651 value=(unsigned char) ScaleQuantumToChar(pixel.green);
1652 pixels=PopCharPixel(value,pixels);
1653 value=(unsigned char) ScaleQuantumToChar(pixel.blue);
1654 pixels=PopCharPixel(value,pixels);
1655 if (image->matte != MagickFalse)
1656 {
1657 value=(unsigned char) ScaleQuantumToChar(pixel.opacity);
1658 pixels=PopCharPixel(value,pixels);
1659 }
1660 if (image->colorspace == CMYKColorspace)
1661 {
1662 value=(unsigned char) ScaleQuantumToChar(index);
1663 pixels=PopCharPixel(value,pixels);
1664 }
1665 break;
1666 }
1667 default:
1668 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1669 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1670 }
1671 *pixels++=(unsigned char) length;
1672 return(pixels);
1673}
1674
1675static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
1676 Image *image)
1677{
1678#if defined(MAGICKCORE_BZLIB_DELEGATE)
1679 bz_stream
1680 bzip_info;
1681#endif
1682
1683 char
1684 buffer[MaxTextExtent];
1685
1686 CompressionType
1687 compression;
1688
1689 const char
1690 *property,
1691 *value;
1692
1693 IndexPacket
1694 index;
1695
1696 int
1697 code;
1698
1699 long
1700 y;
1701
1702 MagickBooleanType
1703 status;
1704
1705 MagickOffsetType
1706 scene;
1707
1708 PixelPacket
1709 pixel;
1710
1711 QuantumInfo
1712 *quantum_info;
1713
1714 QuantumType
1715 quantum_type;
1716
1717 register long
1718 i;
1719
1720 size_t
1721 length,
1722 packet_size;
1723
1724 unsigned char
1725 *compress_pixels,
1726 *pixels,
1727 *q;
1728
1729#if defined(MAGICKCORE_ZLIB_DELEGATE)
1730 z_stream
1731 zip_info;
1732#endif
1733
1734 /*
1735 Open output image file.
1736 */
1737 assert(image_info != (const ImageInfo *) NULL);
1738 assert(image_info->signature == MagickSignature);
1739 assert(image != (Image *) NULL);
1740 assert(image->signature == MagickSignature);
1741 if (image->debug != MagickFalse)
1742 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1743 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1744 if (status == MagickFalse)
1745 return(status);
1746 code=0;
1747 scene=0;
1748 do
1749 {
1750 /*
1751 Allocate image pixels.
1752 */
1753 image->depth=image->depth <= 8 ? 8UL : image->depth <= 16 ? 16UL :
1754 image->depth <= 32 ? 32UL : 64UL;
1755 quantum_info=AcquireQuantumInfo(image_info,image);
1756 if (quantum_info == (QuantumInfo *) NULL)
1757 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1758 if ((image->storage_class != PseudoClass) && (image->depth >= 32) &&
1759 (quantum_info->format == UndefinedQuantumFormat) &&
1760 (IsHighDynamicRangeImage(image,&image->exception) != MagickFalse))
1761 {
1762 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1763 if (status == MagickFalse)
1764 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1765 }
1766 if ((image->storage_class == PseudoClass) &&
1767 (image->colors > (unsigned long) (GetQuantumRange(image->depth)+1)))
1768 (void) SetImageStorageClass(image,DirectClass);
1769 if (IsGrayImage(image,&image->exception) != MagickFalse)
1770 {
1771 image->storage_class=DirectClass;
1772 (void) SetImageColorspace(image,GRAYColorspace);
1773 }
1774 compression=image->compression;
1775 if (image_info->compression != UndefinedCompression)
1776 compression=image_info->compression;
1777 switch (compression)
1778 {
1779#if !defined(MAGICKCORE_ZLIB_DELEGATE)
1780 case LZWCompression:
1781 case ZipCompression: compression=NoCompression; break;
1782#endif
1783#if !defined(MAGICKCORE_BZLIB_DELEGATE)
1784 case BZipCompression: compression=NoCompression; break;
1785#endif
1786 case RLECompression:
1787 {
1788 if (quantum_info->format == FloatingPointQuantumFormat)
1789 compression=NoCompression;
1790 break;
1791 }
1792 default:
1793 break;
1794 }
1795 packet_size=(size_t) (quantum_info->depth/8);
1796 if (image->storage_class == DirectClass)
1797 packet_size=(size_t) (3*quantum_info->depth/8);
1798 if (image->matte != MagickFalse)
1799 packet_size+=quantum_info->depth/8;
1800 if (image->colorspace == CMYKColorspace)
1801 packet_size+=quantum_info->depth/8;
1802 if (compression == RLECompression)
1803 packet_size++;
1804 length=image->columns;
1805 length=MagickMax(BZipMaxExtent(packet_size*image->columns),ZipMaxExtent(
1806 packet_size*image->columns));
1807 if ((compression == BZipCompression) || (compression == ZipCompression))
1808 if (length != (size_t) ((unsigned int) length))
1809 compression=NoCompression;
1810 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
1811 sizeof(*compress_pixels));
1812 if (compress_pixels == (unsigned char *) NULL)
1813 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1814 /*
1815 Write MIFF header.
1816 */
1817 (void) WriteBlobString(image,"id=ImageMagick version=1.0\n");
1818 (void) FormatMagickString(buffer,MaxTextExtent,
1819 "class=%s colors=%lu matte=%s\n",MagickOptionToMnemonic(
1820 MagickClassOptions,image->storage_class),image->colors,
1821 MagickOptionToMnemonic(MagickBooleanOptions,(long) image->matte));
1822 (void) WriteBlobString(image,buffer);
1823 (void) FormatMagickString(buffer,MaxTextExtent,"columns=%lu rows=%lu "
1824 "depth=%lu\n",image->columns,image->rows,image->depth);
1825 (void) WriteBlobString(image,buffer);
1826 if (image->type != UndefinedType)
1827 {
1828 (void) FormatMagickString(buffer,MaxTextExtent,"type=%s\n",
1829 MagickOptionToMnemonic(MagickTypeOptions,image->type));
1830 (void) WriteBlobString(image,buffer);
1831 }
1832 if (image->colorspace != UndefinedColorspace)
1833 {
1834 (void) FormatMagickString(buffer,MaxTextExtent,"colorspace=%s\n",
1835 MagickOptionToMnemonic(MagickColorspaceOptions,image->colorspace));
1836 (void) WriteBlobString(image,buffer);
1837 }
1838 if (compression != UndefinedCompression)
1839 {
1840 (void) FormatMagickString(buffer,MaxTextExtent,"compression=%s "
1841 "quality=%lu\n",MagickOptionToMnemonic(MagickCompressOptions,
1842 compression),image->quality);
1843 (void) WriteBlobString(image,buffer);
1844 }
1845 if (image->units != UndefinedResolution)
1846 {
1847 (void) FormatMagickString(buffer,MaxTextExtent,"units=%s\n",
1848 MagickOptionToMnemonic(MagickResolutionOptions,image->units));
1849 (void) WriteBlobString(image,buffer);
1850 }
1851 if ((image->x_resolution != 0) || (image->y_resolution != 0))
1852 {
1853 (void) FormatMagickString(buffer,MaxTextExtent,"resolution=%gx%g\n",
1854 image->x_resolution,image->y_resolution);
1855 (void) WriteBlobString(image,buffer);
1856 }
1857 if ((image->page.width != 0) || (image->page.height != 0))
1858 {
1859 (void) FormatMagickString(buffer,MaxTextExtent,"page=%lux%lu%+ld%+ld\n",
1860 image->page.width,image->page.height,image->page.x,image->page.y);
1861 (void) WriteBlobString(image,buffer);
1862 }
1863 else
1864 if ((image->page.x != 0) || (image->page.y != 0))
1865 {
1866 (void) FormatMagickString(buffer,MaxTextExtent,"page=%+ld%+ld\n",
1867 image->page.x,image->page.y);
1868 (void) WriteBlobString(image,buffer);
1869 }
1870 if ((image->tile_offset.x != 0) || (image->tile_offset.y != 0))
1871 {
1872 (void) FormatMagickString(buffer,MaxTextExtent,"tile-offset=%+ld%+ld\n",
1873 image->tile_offset.x,image->tile_offset.y);
1874 (void) WriteBlobString(image,buffer);
1875 }
1876 if ((GetNextImageInList(image) != (Image *) NULL) ||
1877 (GetPreviousImageInList(image) != (Image *) NULL))
1878 {
1879 if (image->scene == 0)
1880 (void) FormatMagickString(buffer,MaxTextExtent,"iterations=%lu "
1881 "delay=%lu ticks-per-second=%lu\n",image->iterations,image->delay,
1882 image->ticks_per_second);
1883 else
1884 (void) FormatMagickString(buffer,MaxTextExtent,"scene=%lu "
1885 "iterations=%lu delay=%lu ticks-per-second=%lu\n",image->scene,
1886 image->iterations,image->delay,image->ticks_per_second);
1887 (void) WriteBlobString(image,buffer);
1888 }
1889 else
1890 {
1891 if (image->scene != 0)
1892 {
1893 (void) FormatMagickString(buffer,MaxTextExtent,"scene=%lu\n",
1894 image->scene);
1895 (void) WriteBlobString(image,buffer);
1896 }
1897 if (image->iterations != 0)
1898 {
1899 (void) FormatMagickString(buffer,MaxTextExtent,"iterations=%lu\n",
1900 image->iterations);
1901 (void) WriteBlobString(image,buffer);
1902 }
1903 if (image->delay != 0)
1904 {
1905 (void) FormatMagickString(buffer,MaxTextExtent,"delay=%lu\n",
1906 image->delay);
1907 (void) WriteBlobString(image,buffer);
1908 }
1909 if (image->ticks_per_second != UndefinedTicksPerSecond)
1910 {
1911 (void) FormatMagickString(buffer,MaxTextExtent,
1912 "ticks-per-second=%lu\n",image->ticks_per_second);
1913 (void) WriteBlobString(image,buffer);
1914 }
1915 }
1916 if (image->gravity != UndefinedGravity)
1917 {
1918 (void) FormatMagickString(buffer,MaxTextExtent,"gravity=%s\n",
1919 MagickOptionToMnemonic(MagickGravityOptions,image->gravity));
1920 (void) WriteBlobString(image,buffer);
1921 }
1922 if (image->dispose != UndefinedDispose)
1923 {
1924 (void) FormatMagickString(buffer,MaxTextExtent,"dispose=%s\n",
1925 MagickOptionToMnemonic(MagickDisposeOptions,image->dispose));
1926 (void) WriteBlobString(image,buffer);
1927 }
1928 if (image->rendering_intent != UndefinedIntent)
1929 {
1930 (void) FormatMagickString(buffer,MaxTextExtent,
1931 "rendering-intent=%s\n",
1932 MagickOptionToMnemonic(MagickIntentOptions,image->rendering_intent));
1933 (void) WriteBlobString(image,buffer);
1934 }
1935 if (image->gamma != 0.0)
1936 {
1937 (void) FormatMagickString(buffer,MaxTextExtent,"gamma=%g\n",
1938 image->gamma);
1939 (void) WriteBlobString(image,buffer);
1940 }
1941 if (image->chromaticity.white_point.x != 0.0)
1942 {
1943 /*
1944 Note chomaticity points.
1945 */
1946 (void) FormatMagickString(buffer,MaxTextExtent,"red-primary=%g,%g "
1947 "green-primary=%g,%g blue-primary=%g,%g\n",
1948 image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
1949 image->chromaticity.green_primary.x,
1950 image->chromaticity.green_primary.y,
1951 image->chromaticity.blue_primary.x,
1952 image->chromaticity.blue_primary.y);
1953 (void) WriteBlobString(image,buffer);
1954 (void) FormatMagickString(buffer,MaxTextExtent,"white-point=%g,%g\n",
1955 image->chromaticity.white_point.x,image->chromaticity.white_point.y);
1956 (void) WriteBlobString(image,buffer);
1957 }
1958 if (image->orientation != UndefinedOrientation)
1959 {
1960 (void) FormatMagickString(buffer,MaxTextExtent,"orientation=%s\n",
1961 MagickOptionToMnemonic(MagickOrientationOptions,image->orientation));
1962 (void) WriteBlobString(image,buffer);
1963 }
1964 if (image->profiles != (void *) NULL)
1965 {
1966 const char
1967 *name;
1968
1969 const StringInfo
1970 *profile;
1971
1972 /*
1973 Write image profiles.
1974 */
1975 ResetImageProfileIterator(image);
1976 name=GetNextImageProfile(image);
1977 while (name != (const char *) NULL)
1978 {
1979 profile=GetImageProfile(image,name);
1980 if (profile != (StringInfo *) NULL)
1981 {
1982 (void) FormatMagickString(buffer,MaxTextExtent,"profile:%s=%lu\n",
1983 name,(unsigned long) GetStringInfoLength(profile));
1984 (void) WriteBlobString(image,buffer);
1985 }
1986 name=GetNextImageProfile(image);
1987 }
1988 }
1989 if (image->montage != (char *) NULL)
1990 {
1991 (void) FormatMagickString(buffer,MaxTextExtent,"montage=%s\n",
1992 image->montage);
1993 (void) WriteBlobString(image,buffer);
1994 }
1995 if (quantum_info->format == FloatingPointQuantumFormat)
cristy0c2fcca2009-10-16 01:37:20 +00001996 (void) SetImageProperty(image,"quantum:format","floating-point");
cristy3ed852e2009-09-05 21:47:34 +00001997 ResetImagePropertyIterator(image);
1998 property=GetNextImageProperty(image);
1999 while (property != (const char *) NULL)
2000 {
2001 (void) FormatMagickString(buffer,MaxTextExtent,"%s=",property);
2002 (void) WriteBlobString(image,buffer);
2003 value=GetImageProperty(image,property);
2004 if (value != (const char *) NULL)
2005 {
2006 for (i=0; i < (long) strlen(value); i++)
2007 if (isspace((int) ((unsigned char) value[i])) != 0)
2008 break;
2009 if (i <= (long) strlen(value))
2010 (void) WriteBlobByte(image,'{');
2011 (void) WriteBlob(image,strlen(value),(const unsigned char *) value);
2012 if (i <= (long) strlen(value))
2013 (void) WriteBlobByte(image,'}');
2014 }
2015 (void) WriteBlobByte(image,'\n');
2016 property=GetNextImageProperty(image);
2017 }
2018 (void) WriteBlobString(image,"\f\n:\032");
2019 if (image->montage != (char *) NULL)
2020 {
2021 /*
2022 Write montage tile directory.
2023 */
2024 if (image->directory != (char *) NULL)
2025 (void) WriteBlob(image,strlen(image->directory),(unsigned char *)
2026 image->directory);
2027 (void) WriteBlobByte(image,'\0');
2028 }
2029 if (image->profiles != (void *) NULL)
2030 {
2031 const char
2032 *name;
2033
2034 const StringInfo
2035 *profile;
2036
2037 /*
2038 Generic profile.
2039 */
2040 ResetImageProfileIterator(image);
2041 name=GetNextImageProfile(image);
2042 while (name != (const char *) NULL)
2043 {
2044 profile=GetImageProfile(image,name);
2045 (void) WriteBlob(image,GetStringInfoLength(profile),
2046 GetStringInfoDatum(profile));
2047 name=GetNextImageProfile(image);
2048 }
2049 }
2050 if (image->storage_class == PseudoClass)
2051 {
2052 size_t
2053 packet_size;
2054
2055 unsigned char
2056 *colormap,
2057 *q;
2058
2059 /*
2060 Allocate colormap.
2061 */
2062 packet_size=(size_t) (3*quantum_info->depth/8);
2063 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
2064 packet_size*sizeof(*colormap));
2065 if (colormap == (unsigned char *) NULL)
2066 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2067 /*
2068 Write colormap to file.
2069 */
2070 q=colormap;
2071 for (i=0; i < (long) image->colors; i++)
2072 {
2073 switch (quantum_info->depth)
2074 {
2075 default:
2076 ThrowWriterException(CorruptImageError,"ImageDepthNotSupported");
2077 case 32:
2078 {
2079 register unsigned long
2080 pixel;
2081
2082 pixel=ScaleQuantumToLong(image->colormap[i].red);
2083 q=PopLongPixel(MSBEndian,pixel,q);
2084 pixel=ScaleQuantumToLong(image->colormap[i].green);
2085 q=PopLongPixel(MSBEndian,pixel,q);
2086 pixel=ScaleQuantumToLong(image->colormap[i].blue);
2087 q=PopLongPixel(MSBEndian,pixel,q);
2088 break;
2089 }
2090 case 16:
2091 {
2092 register unsigned short
2093 pixel;
2094
2095 pixel=ScaleQuantumToShort(image->colormap[i].red);
2096 q=PopShortPixel(MSBEndian,pixel,q);
2097 pixel=ScaleQuantumToShort(image->colormap[i].green);
2098 q=PopShortPixel(MSBEndian,pixel,q);
2099 pixel=ScaleQuantumToShort(image->colormap[i].blue);
2100 q=PopShortPixel(MSBEndian,pixel,q);
2101 break;
2102 }
2103 case 8:
2104 {
2105 register unsigned char
2106 pixel;
2107
2108 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].red);
2109 q=PopCharPixel(pixel,q);
2110 pixel=(unsigned char) ScaleQuantumToChar(
2111 image->colormap[i].green);
2112 q=PopCharPixel(pixel,q);
2113 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].blue);
2114 q=PopCharPixel(pixel,q);
2115 break;
2116 }
2117 }
2118 }
2119 (void) WriteBlob(image,packet_size*image->colors,colormap);
2120 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
2121 }
2122 /*
2123 Write image pixels to file.
2124 */
2125 quantum_type=GetQuantumType(image,&image->exception);
2126 pixels=GetQuantumPixels(quantum_info);
2127 status=MagickTrue;
2128 for (y=0; y < (long) image->rows; y++)
2129 {
2130 register const IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002131 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002132
2133 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002134 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002135
2136 register long
2137 x;
2138
2139 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2140 if (p == (const PixelPacket *) NULL)
2141 break;
2142 indexes=GetVirtualIndexQueue(image);
2143 q=pixels;
2144 switch (compression)
2145 {
2146#if defined(MAGICKCORE_ZLIB_DELEGATE)
2147 case LZWCompression:
2148 case ZipCompression:
2149 {
2150 if (y == 0)
2151 {
2152 zip_info.zalloc=AcquireZIPMemory;
2153 zip_info.zfree=RelinquishZIPMemory;
2154 zip_info.opaque=(voidpf) NULL;
2155 code=deflateInit(&zip_info,(int) (image->quality ==
2156 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,
2157 9)));
2158 if (code >= 0)
2159 status=MagickTrue;
2160 }
2161 zip_info.next_in=pixels;
2162 zip_info.avail_in=(uInt) (packet_size*image->columns);
cristy74fe8f12009-10-03 19:09:01 +00002163 (void) ExportQuantumPixels(image,(const CacheView *) NULL,
2164 quantum_info,quantum_type,pixels,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002165 do
2166 {
2167 zip_info.next_out=compress_pixels;
2168 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns);
2169 code=deflate(&zip_info,Z_SYNC_FLUSH);
2170 if (code >= 0)
2171 status=MagickTrue;
2172 length=(size_t) (zip_info.next_out-compress_pixels);
2173 if (length != 0)
2174 {
2175 (void) WriteBlobMSBLong(image,(unsigned int) length);
2176 (void) WriteBlob(image,length,compress_pixels);
2177 }
2178 } while (zip_info.avail_in != 0);
2179 if (y == (long) (image->rows-1))
2180 {
2181 for ( ; ; )
2182 {
2183 zip_info.next_out=compress_pixels;
2184 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*
2185 image->columns);
2186 code=deflate(&zip_info,Z_FINISH);
2187 length=(size_t) (zip_info.next_out-compress_pixels);
2188 if (length > 6)
2189 {
2190 (void) WriteBlobMSBLong(image,(unsigned int) length);
2191 (void) WriteBlob(image,length,compress_pixels);
2192 }
2193 if (code == Z_STREAM_END)
2194 break;
2195 }
2196 status=deflateEnd(&zip_info) == 0 ? MagickTrue : MagickFalse;
2197 }
2198 break;
2199 }
2200#endif
2201#if defined(MAGICKCORE_BZLIB_DELEGATE)
2202 case BZipCompression:
2203 {
2204 if (y == 0)
2205 {
2206 bzip_info.bzalloc=AcquireBZIPMemory;
2207 bzip_info.bzfree=RelinquishBZIPMemory;
2208 bzip_info.opaque=(void *) NULL;
2209 code=BZ2_bzCompressInit(&bzip_info,(int) (image->quality ==
2210 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,
2211 9)),
2212 (int) image_info->verbose,0);
2213 if (code >= 0)
2214 status=MagickTrue;
2215 }
2216 bzip_info.next_in=(char *) pixels;
2217 bzip_info.avail_in=(unsigned int) (packet_size*image->columns);
cristy74fe8f12009-10-03 19:09:01 +00002218 (void) ExportQuantumPixels(image,(const CacheView *) NULL,
2219 quantum_info,quantum_type,pixels,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002220 do
2221 {
2222 bzip_info.next_out=(char *) compress_pixels;
2223 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2224 image->columns);
2225 code=BZ2_bzCompress(&bzip_info,BZ_FLUSH);
2226 if (code >= 0)
2227 status=MagickTrue;
2228 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2229 if (length != 0)
2230 {
2231 (void) WriteBlobMSBLong(image,(unsigned int) length);
2232 (void) WriteBlob(image,length,compress_pixels);
2233 }
2234 } while (bzip_info.avail_in != 0);
2235 if (y == (long) (image->rows-1))
2236 {
2237 for ( ; ; )
2238 {
2239 bzip_info.next_out=(char *) compress_pixels;
2240 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2241 image->columns);
2242 code=BZ2_bzCompress(&bzip_info,BZ_FINISH);
2243 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2244 if (length != 0)
2245 {
2246 (void) WriteBlobMSBLong(image,(unsigned int) length);
2247 (void) WriteBlob(image,length,compress_pixels);
2248 }
2249 if (code == BZ_STREAM_END)
2250 break;
2251 }
2252 status=BZ2_bzCompressEnd(&bzip_info) == 0 ? MagickTrue :
2253 MagickFalse;
2254 }
2255 break;
2256 }
2257#endif
2258 case RLECompression:
2259 {
2260 pixel=(*p);
2261 index=(IndexPacket) 0;
2262 if (indexes != (IndexPacket *) NULL)
2263 index=(*indexes);
2264 length=255;
2265 for (x=0; x < (long) image->columns; x++)
2266 {
2267 if ((length < 255) && (x < (long) (image->columns-1)) &&
2268 (IsColorEqual(p,&pixel) != MagickFalse) &&
2269 ((image->matte == MagickFalse) ||
2270 (p->opacity == pixel.opacity)) &&
2271 ((indexes == (IndexPacket *) NULL) || (index == indexes[x])))
2272 length++;
2273 else
2274 {
2275 if (x > 0)
2276 q=PopRunlengthPacket(image,q,length,pixel,index);
2277 length=0;
2278 }
2279 pixel=(*p);
2280 if (indexes != (IndexPacket *) NULL)
2281 index=indexes[x];
2282 p++;
2283 }
2284 q=PopRunlengthPacket(image,q,length,pixel,index);
2285 (void) WriteBlob(image,(size_t) (q-pixels),pixels);
2286 break;
2287 }
2288 default:
2289 {
2290 (void) ExportQuantumPixels(image,(const CacheView *) NULL,
2291 quantum_info,quantum_type,pixels,&image->exception);
2292 (void) WriteBlob(image,packet_size*image->columns,pixels);
2293 break;
2294 }
2295 }
2296 if ((image->previous == (Image *) NULL) &&
2297 (SetImageProgress(image,SaveImageTag,y,image->rows) == MagickFalse))
2298 break;
2299 }
2300 quantum_info=DestroyQuantumInfo(quantum_info);
2301 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
2302 if (GetNextImageInList(image) == (Image *) NULL)
2303 break;
2304 image=SyncNextImageInList(image);
2305 status=SetImageProgress(image,SaveImagesTag,scene++,
2306 GetImageListLength(image));
2307 if (status == MagickFalse)
2308 break;
2309 } while (image_info->adjoin != MagickFalse);
2310 (void) CloseBlob(image);
2311 return(status);
2312}