blob: dcbcfbd1f7b853c55ef13b1b48c5fe450abf5599 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% M M IIIII FFFFF FFFFF %
7% MM MM I F F %
8% M M M I FFF FFF %
9% M M I F F %
10% M M IIIII F F %
11% %
12% %
13% Read/Write MIFF Image Format %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy7e41fe82010-12-04 23:12:08 +000020% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/attribute.h"
44#include "MagickCore/blob.h"
45#include "MagickCore/blob-private.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/color.h"
48#include "MagickCore/color-private.h"
49#include "MagickCore/colormap.h"
50#include "MagickCore/colormap-private.h"
51#include "MagickCore/colorspace.h"
52#include "MagickCore/constitute.h"
53#include "MagickCore/exception.h"
54#include "MagickCore/exception-private.h"
55#include "MagickCore/hashmap.h"
56#include "MagickCore/geometry.h"
57#include "MagickCore/image.h"
58#include "MagickCore/image-private.h"
59#include "MagickCore/list.h"
60#include "MagickCore/magick.h"
61#include "MagickCore/memory_.h"
62#include "MagickCore/module.h"
63#include "MagickCore/monitor.h"
64#include "MagickCore/monitor-private.h"
65#include "MagickCore/option.h"
66#include "MagickCore/pixel.h"
67#include "MagickCore/pixel-accessor.h"
68#include "MagickCore/profile.h"
69#include "MagickCore/property.h"
70#include "MagickCore/quantum-private.h"
71#include "MagickCore/static.h"
72#include "MagickCore/statistic.h"
73#include "MagickCore/string_.h"
74#include "MagickCore/string-private.h"
cristy3ed852e2009-09-05 21:47:34 +000075#if defined(MAGICKCORE_BZLIB_DELEGATE)
76#include "bzlib.h"
77#endif
cristy26377172010-12-20 19:01:58 +000078#if defined(MAGICKCORE_LZMA_DELEGATE)
79#include "lzma.h"
80#endif
81#if defined(MAGICKCORE_ZLIB_DELEGATE)
82#include "zlib.h"
83#endif
cristy3ed852e2009-09-05 21:47:34 +000084
85/*
cristya7a341e2010-12-22 20:28:51 +000086 Define declarations.
87*/
88#if !defined(LZMA_OK)
89#define LZMA_OK 0
90#endif
91
92/*
cristy3ed852e2009-09-05 21:47:34 +000093 Forward declarations.
94*/
95static MagickBooleanType
cristy1e178e72011-08-28 19:44:34 +000096 WriteMIFFImage(const ImageInfo *,Image *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +000097
98/*
99%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
100% %
101% %
102% %
103% I s M I F F %
104% %
105% %
106% %
107%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108%
109% IsMIFF() returns MagickTrue if the image format type, identified by the
110% magick string, is MIFF.
111%
112% The format of the IsMIFF method is:
113%
114% MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
115%
116% A description of each parameter follows:
117%
118% o magick: compare image format pattern against these bytes.
119%
120% o length: Specifies the length of the magick string.
121%
122*/
123static MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length)
124{
125 if (length < 14)
126 return(MagickFalse);
127 if (LocaleNCompare((const char *) magick,"id=ImageMagick",14) == 0)
128 return(MagickTrue);
129 return(MagickFalse);
130}
131
132/*
133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
134% %
135% %
136% %
137% R e a d M I F F I m a g e %
138% %
139% %
140% %
141%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142%
143% ReadMIFFImage() reads a MIFF image file and returns it. It allocates the
144% memory necessary for the new Image structure and returns a pointer to the
145% new image.
146%
147% The format of the ReadMIFFImage method is:
148%
149% Image *ReadMIFFImage(const ImageInfo *image_info,
150% ExceptionInfo *exception)
151%
152% Decompression code contributed by Kyle Shorter.
153%
154% A description of each parameter follows:
155%
156% o image_info: the image info.
157%
158% o exception: return any errors or warnings in this structure.
159%
160*/
161
162#if defined(MAGICKCORE_BZLIB_DELEGATE)
163static void *AcquireBZIPMemory(void *context,int items,int size)
164{
165 (void) context;
166 return((void *) AcquireQuantumMemory((size_t) items,(size_t) size));
167}
168#endif
169
cristy4b46dba2010-12-20 19:18:20 +0000170#if defined(MAGICKCORE_LZMA_DELEGATE)
171static void *AcquireLZMAMemory(void *context,size_t items,size_t size)
172{
173 (void) context;
174 return((void *) AcquireQuantumMemory((size_t) items,(size_t) size));
175}
176#endif
177
cristy3ed852e2009-09-05 21:47:34 +0000178#if defined(MAGICKCORE_ZLIB_DELEGATE)
179static voidpf AcquireZIPMemory(voidpf context,unsigned int items,
180 unsigned int size)
181{
182 (void) context;
183 return((voidpf) AcquireQuantumMemory(items,size));
184}
185#endif
186
187static inline size_t MagickMax(const size_t x,const size_t y)
188{
189 if (x > y)
190 return(x);
191 return(y);
192}
193
194static inline size_t MagickMin(const size_t x,const size_t y)
195{
196 if (x < y)
197 return(x);
198 return(y);
199}
200
201static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
cristy4c08aed2011-07-01 19:47:50 +0000202 size_t *length,PixelInfo *pixel)
cristy3ed852e2009-09-05 21:47:34 +0000203{
204 const unsigned char
205 *p;
206
207 p=pixels;
208 if (image->storage_class == PseudoClass)
209 {
cristy4c08aed2011-07-01 19:47:50 +0000210 pixel->index=0;
cristy3ed852e2009-09-05 21:47:34 +0000211 switch (image->depth)
212 {
213 case 32:
214 {
cristy4c08aed2011-07-01 19:47:50 +0000215 pixel->index=ConstrainColormapIndex(image,
cristy3ed852e2009-09-05 21:47:34 +0000216 (*p << 24) | (*(p+1) << 16) | (*(p+2) << 8) | *(p+3));
217 p+=4;
218 break;
219 }
220 case 16:
221 {
cristy4c08aed2011-07-01 19:47:50 +0000222 pixel->index=ConstrainColormapIndex(image,(*p << 8) | *(p+1));
cristy3ed852e2009-09-05 21:47:34 +0000223 p+=2;
224 break;
225 }
226 case 8:
227 {
cristy4c08aed2011-07-01 19:47:50 +0000228 pixel->index=ConstrainColormapIndex(image,*p);
cristy3ed852e2009-09-05 21:47:34 +0000229 p++;
230 break;
231 }
232 default:
233 (void) ThrowMagickException(&image->exception,GetMagickModule(),
234 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
235 }
cristy3ed852e2009-09-05 21:47:34 +0000236 switch (image->depth)
237 {
238 case 8:
239 {
240 unsigned char
241 quantum;
242
243 if (image->matte != MagickFalse)
244 {
245 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000246 pixel->alpha=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000247 }
248 break;
249 }
250 case 16:
251 {
252 unsigned short
253 quantum;
254
255 if (image->matte != MagickFalse)
256 {
257 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000258 pixel->alpha=(Quantum) (quantum >> (image->depth-
cristy3ed852e2009-09-05 21:47:34 +0000259 MAGICKCORE_QUANTUM_DEPTH));
260 }
261 break;
262 }
263 case 32:
264 {
cristy4cb162a2010-05-30 03:04:47 +0000265 unsigned int
cristy3ed852e2009-09-05 21:47:34 +0000266 quantum;
267
268 if (image->matte != MagickFalse)
269 {
270 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000271 pixel->alpha=(Quantum) (quantum >> (image->depth-
cristy3ed852e2009-09-05 21:47:34 +0000272 MAGICKCORE_QUANTUM_DEPTH));
273 }
274 break;
275 }
276 default:
277 (void) ThrowMagickException(&image->exception,GetMagickModule(),
278 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
279 }
280 *length=(size_t) (*p++)+1;
281 return;
282 }
283 switch (image->depth)
284 {
285 case 8:
286 {
287 unsigned char
288 quantum;
289
290 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000291 pixel->red=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000292 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000293 pixel->green=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000294 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000295 pixel->blue=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000296 if (image->colorspace == CMYKColorspace)
297 {
298 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000299 pixel->black=ScaleCharToQuantum(quantum);
300 }
301 if (image->matte != MagickFalse)
302 {
303 p=PushCharPixel(p,&quantum);
304 pixel->alpha=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000305 }
306 break;
307 }
308 case 16:
309 {
310 unsigned short
311 quantum;
312
313 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000314 pixel->red=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000315 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000316 pixel->green=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristyfbbafc92011-05-05 01:22:11 +0000317 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000318 pixel->blue=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000319 if (image->colorspace == CMYKColorspace)
320 {
321 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000322 pixel->black=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
323 }
324 if (image->matte != MagickFalse)
325 {
326 p=PushShortPixel(MSBEndian,p,&quantum);
327 pixel->alpha=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000328 }
329 break;
330 }
331 case 32:
332 {
cristy4cb162a2010-05-30 03:04:47 +0000333 unsigned int
cristy3ed852e2009-09-05 21:47:34 +0000334 quantum;
335
336 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000337 pixel->red=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000338 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000339 pixel->green=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristyfbbafc92011-05-05 01:22:11 +0000340 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000341 pixel->blue=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000342 if (image->colorspace == CMYKColorspace)
343 {
344 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000345 pixel->black=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
346 }
347 if (image->matte != MagickFalse)
348 {
349 p=PushLongPixel(MSBEndian,p,&quantum);
350 pixel->alpha=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000351 }
352 break;
353 }
354 default:
355 (void) ThrowMagickException(&image->exception,GetMagickModule(),
356 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
357 }
358 *length=(size_t) (*p++)+1;
359}
360
cristy4b46dba2010-12-20 19:18:20 +0000361#if defined(MAGICKCORE_BZLIB_DELEGATE)
362static void RelinquishBZIPMemory(void *context,void *memory)
cristy3ed852e2009-09-05 21:47:34 +0000363{
364 (void) context;
365 memory=RelinquishMagickMemory(memory);
366}
367#endif
368
cristy4b46dba2010-12-20 19:18:20 +0000369#if defined(MAGICKCORE_LZMA_DELEGATE)
370static void RelinquishLZMAMemory(void *context,void *memory)
371{
372 (void) context;
373 memory=RelinquishMagickMemory(memory);
374}
375#endif
376
377#if defined(MAGICKCORE_ZLIB_DELEGATE)
378static void RelinquishZIPMemory(voidpf context,voidpf memory)
cristy3ed852e2009-09-05 21:47:34 +0000379{
380 (void) context;
381 memory=RelinquishMagickMemory(memory);
382}
383#endif
384
385static Image *ReadMIFFImage(const ImageInfo *image_info,
386 ExceptionInfo *exception)
387{
388#define BZipMaxExtent(x) ((x)+((x)/100)+600)
cristy26377172010-12-20 19:01:58 +0000389#define LZMAMaxExtent(x) ((x)+((x)/3)+128)
cristy3ed852e2009-09-05 21:47:34 +0000390#define ZipMaxExtent(x) ((x)+(((x)+7) >> 3)+(((x)+63) >> 6)+11)
391
392#if defined(MAGICKCORE_BZLIB_DELEGATE)
393 bz_stream
394 bzip_info;
395#endif
396
397 char
398 id[MaxTextExtent],
399 keyword[MaxTextExtent],
400 *options;
401
402 const unsigned char
403 *p;
404
405 double
406 version;
407
408 GeometryInfo
409 geometry_info;
410
411 Image
412 *image;
413
cristy3ed852e2009-09-05 21:47:34 +0000414 int
415 c,
416 code;
417
cristy26377172010-12-20 19:01:58 +0000418#if defined(MAGICKCORE_LZMA_DELEGATE)
419 lzma_stream
cristy330af6c2010-12-21 14:36:06 +0000420 initialize_lzma = LZMA_STREAM_INIT,
421 lzma_info;
cristy4b46dba2010-12-20 19:18:20 +0000422
423 lzma_allocator
424 allocator;
cristy26377172010-12-20 19:01:58 +0000425#endif
426
cristy3ed852e2009-09-05 21:47:34 +0000427 LinkedListInfo
428 *profiles;
429
cristy3ed852e2009-09-05 21:47:34 +0000430 MagickBooleanType
431 status;
432
cristy4c08aed2011-07-01 19:47:50 +0000433 PixelInfo
434 pixel;
435
cristy3ed852e2009-09-05 21:47:34 +0000436 MagickStatusType
437 flags;
438
cristy3ed852e2009-09-05 21:47:34 +0000439 QuantumFormatType
440 quantum_format;
441
442 QuantumInfo
443 *quantum_info;
444
445 QuantumType
446 quantum_type;
447
cristybb503372010-05-27 20:51:26 +0000448 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000449 i;
450
451 size_t
452 length,
453 packet_size;
454
455 ssize_t
456 count;
457
458 unsigned char
459 *compress_pixels,
460 *pixels;
461
cristybb503372010-05-27 20:51:26 +0000462 size_t
cristy3ed852e2009-09-05 21:47:34 +0000463 colors;
464
cristy26377172010-12-20 19:01:58 +0000465 ssize_t
466 y;
467
cristy3ed852e2009-09-05 21:47:34 +0000468#if defined(MAGICKCORE_ZLIB_DELEGATE)
469 z_stream
470 zip_info;
471#endif
472
473 /*
474 Open image file.
475 */
476 assert(image_info != (const ImageInfo *) NULL);
477 assert(image_info->signature == MagickSignature);
478 if (image_info->debug != MagickFalse)
479 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
480 image_info->filename);
481 assert(exception != (ExceptionInfo *) NULL);
482 assert(exception->signature == MagickSignature);
cristy9950d572011-10-01 18:22:35 +0000483 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000484 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
485 if (status == MagickFalse)
486 {
487 image=DestroyImageList(image);
488 return((Image *) NULL);
489 }
490 /*
491 Decode image header; header terminates one character beyond a ':'.
492 */
493 c=ReadBlobByte(image);
494 if (c == EOF)
495 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
496 code=0;
497 *id='\0';
498 (void) ResetMagickMemory(keyword,0,sizeof(keyword));
499 version=0.0;
500 do
501 {
502 /*
503 Decode image header; header terminates one character beyond a ':'.
504 */
505 length=MaxTextExtent;
506 options=AcquireString((char *) NULL);
507 quantum_format=UndefinedQuantumFormat;
508 profiles=(LinkedListInfo *) NULL;
509 colors=0;
510 image->depth=8UL;
511 image->compression=NoCompression;
512 while ((isgraph(c) != MagickFalse) && (c != (int) ':'))
513 {
514 register char
515 *p;
516
517 if (c == (int) '{')
518 {
519 char
520 *comment;
521
522 /*
523 Read comment-- any text between { }.
524 */
525 length=MaxTextExtent;
526 comment=AcquireString((char *) NULL);
527 for (p=comment; comment != (char *) NULL; p++)
528 {
529 c=ReadBlobByte(image);
530 if ((c == EOF) || (c == (int) '}'))
531 break;
532 if ((size_t) (p-comment+1) >= length)
533 {
534 *p='\0';
535 length<<=1;
536 comment=(char *) ResizeQuantumMemory(comment,length+
537 MaxTextExtent,sizeof(*comment));
538 if (comment == (char *) NULL)
539 break;
540 p=comment+strlen(comment);
541 }
542 *p=(char) c;
543 }
544 if (comment == (char *) NULL)
545 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
546 *p='\0';
547 (void) SetImageProperty(image,"comment",comment);
548 comment=DestroyString(comment);
549 c=ReadBlobByte(image);
550 }
551 else
552 if (isalnum(c) != MagickFalse)
553 {
554 /*
555 Get the keyword.
556 */
557 p=keyword;
558 do
559 {
cristy3ed852e2009-09-05 21:47:34 +0000560 if (c == (int) '=')
561 break;
562 if ((size_t) (p-keyword) < (MaxTextExtent-1))
563 *p++=(char) c;
564 c=ReadBlobByte(image);
565 } while (c != EOF);
566 *p='\0';
567 p=options;
cristy93505cf2010-08-10 21:37:49 +0000568 while ((isspace((int) ((unsigned char) c)) != 0) && (c != EOF))
cristy3ed852e2009-09-05 21:47:34 +0000569 c=ReadBlobByte(image);
570 if (c == (int) '=')
571 {
572 /*
573 Get the keyword value.
574 */
575 c=ReadBlobByte(image);
576 while ((c != (int) '}') && (c != EOF))
577 {
578 if ((size_t) (p-options+1) >= length)
579 {
580 *p='\0';
581 length<<=1;
582 options=(char *) ResizeQuantumMemory(options,length+
583 MaxTextExtent,sizeof(*options));
584 if (options == (char *) NULL)
585 break;
586 p=options+strlen(options);
587 }
588 if (options == (char *) NULL)
589 ThrowReaderException(ResourceLimitError,
590 "MemoryAllocationFailed");
591 *p++=(char) c;
592 c=ReadBlobByte(image);
593 if (*options != '{')
594 if (isspace((int) ((unsigned char) c)) != 0)
595 break;
596 }
597 }
598 *p='\0';
599 if (*options == '{')
600 (void) CopyMagickString(options,options+1,MaxTextExtent);
601 /*
602 Assign a value to the specified keyword.
603 */
604 switch (*keyword)
605 {
606 case 'b':
607 case 'B':
608 {
609 if (LocaleCompare(keyword,"background-color") == 0)
610 {
cristy9950d572011-10-01 18:22:35 +0000611 (void) QueryColorCompliance(options,AllCompliance,
612 &image->background_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000613 break;
614 }
615 if (LocaleCompare(keyword,"blue-primary") == 0)
616 {
617 flags=ParseGeometry(options,&geometry_info);
618 image->chromaticity.blue_primary.x=geometry_info.rho;
619 image->chromaticity.blue_primary.y=geometry_info.sigma;
620 if ((flags & SigmaValue) == 0)
621 image->chromaticity.blue_primary.y=
622 image->chromaticity.blue_primary.x;
623 break;
624 }
625 if (LocaleCompare(keyword,"border-color") == 0)
626 {
cristy9950d572011-10-01 18:22:35 +0000627 (void) QueryColorCompliance(options,AllCompliance,
628 &image->border_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000629 break;
630 }
631 (void) SetImageProperty(image,keyword,options);
632 break;
633 }
634 case 'c':
635 case 'C':
636 {
637 if (LocaleCompare(keyword,"class") == 0)
638 {
cristybb503372010-05-27 20:51:26 +0000639 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000640 storage_class;
641
cristy042ee782011-04-22 18:48:30 +0000642 storage_class=ParseCommandOption(MagickClassOptions,
cristy3ed852e2009-09-05 21:47:34 +0000643 MagickFalse,options);
644 if (storage_class < 0)
645 break;
646 image->storage_class=(ClassType) storage_class;
647 break;
648 }
649 if (LocaleCompare(keyword,"colors") == 0)
650 {
cristye27293e2009-12-18 02:53:20 +0000651 colors=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000652 break;
653 }
654 if (LocaleCompare(keyword,"colorspace") == 0)
655 {
cristybb503372010-05-27 20:51:26 +0000656 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000657 colorspace;
658
cristy042ee782011-04-22 18:48:30 +0000659 colorspace=ParseCommandOption(MagickColorspaceOptions,
cristy3ed852e2009-09-05 21:47:34 +0000660 MagickFalse,options);
661 if (colorspace < 0)
662 break;
663 image->colorspace=(ColorspaceType) colorspace;
664 break;
665 }
666 if (LocaleCompare(keyword,"compression") == 0)
667 {
cristybb503372010-05-27 20:51:26 +0000668 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000669 compression;
670
cristy042ee782011-04-22 18:48:30 +0000671 compression=ParseCommandOption(MagickCompressOptions,
cristy3ed852e2009-09-05 21:47:34 +0000672 MagickFalse,options);
673 if (compression < 0)
674 break;
675 image->compression=(CompressionType) compression;
676 break;
677 }
678 if (LocaleCompare(keyword,"columns") == 0)
679 {
cristye27293e2009-12-18 02:53:20 +0000680 image->columns=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000681 break;
682 }
683 (void) SetImageProperty(image,keyword,options);
684 break;
685 }
686 case 'd':
687 case 'D':
688 {
689 if (LocaleCompare(keyword,"delay") == 0)
690 {
cristye27293e2009-12-18 02:53:20 +0000691 image->delay=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000692 break;
693 }
694 if (LocaleCompare(keyword,"depth") == 0)
695 {
cristye27293e2009-12-18 02:53:20 +0000696 image->depth=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000697 break;
698 }
699 if (LocaleCompare(keyword,"dispose") == 0)
700 {
cristybb503372010-05-27 20:51:26 +0000701 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000702 dispose;
703
cristy042ee782011-04-22 18:48:30 +0000704 dispose=ParseCommandOption(MagickDisposeOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000705 options);
706 if (dispose < 0)
707 break;
708 image->dispose=(DisposeType) dispose;
709 break;
710 }
711 (void) SetImageProperty(image,keyword,options);
712 break;
713 }
714 case 'e':
715 case 'E':
716 {
717 if (LocaleCompare(keyword,"endian") == 0)
718 {
cristybb503372010-05-27 20:51:26 +0000719 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000720 endian;
721
cristy042ee782011-04-22 18:48:30 +0000722 endian=ParseCommandOption(MagickEndianOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000723 options);
724 if (endian < 0)
725 break;
726 image->endian=(EndianType) endian;
727 break;
728 }
729 (void) SetImageProperty(image,keyword,options);
730 break;
731 }
732 case 'g':
733 case 'G':
734 {
735 if (LocaleCompare(keyword,"gamma") == 0)
736 {
cristyc1acd842011-05-19 23:05:47 +0000737 image->gamma=InterpretLocaleValue(options,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000738 break;
739 }
740 if (LocaleCompare(keyword,"gravity") == 0)
741 {
cristybb503372010-05-27 20:51:26 +0000742 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000743 gravity;
744
cristy042ee782011-04-22 18:48:30 +0000745 gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000746 options);
747 if (gravity < 0)
748 break;
749 image->gravity=(GravityType) gravity;
750 break;
751 }
752 if (LocaleCompare(keyword,"green-primary") == 0)
753 {
754 flags=ParseGeometry(options,&geometry_info);
755 image->chromaticity.green_primary.x=geometry_info.rho;
756 image->chromaticity.green_primary.y=geometry_info.sigma;
757 if ((flags & SigmaValue) == 0)
758 image->chromaticity.green_primary.y=
759 image->chromaticity.green_primary.x;
760 break;
761 }
762 (void) SetImageProperty(image,keyword,options);
763 break;
764 }
765 case 'i':
766 case 'I':
767 {
768 if (LocaleCompare(keyword,"id") == 0)
769 {
770 (void) CopyMagickString(id,options,MaxTextExtent);
771 break;
772 }
773 if (LocaleCompare(keyword,"iterations") == 0)
774 {
cristye27293e2009-12-18 02:53:20 +0000775 image->iterations=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000776 break;
777 }
778 (void) SetImageProperty(image,keyword,options);
779 break;
780 }
781 case 'm':
782 case 'M':
783 {
784 if (LocaleCompare(keyword,"matte") == 0)
785 {
cristybb503372010-05-27 20:51:26 +0000786 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000787 matte;
788
cristy042ee782011-04-22 18:48:30 +0000789 matte=ParseCommandOption(MagickBooleanOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000790 options);
791 if (matte < 0)
792 break;
793 image->matte=(MagickBooleanType) matte;
794 break;
795 }
796 if (LocaleCompare(keyword,"matte-color") == 0)
797 {
cristy9950d572011-10-01 18:22:35 +0000798 (void) QueryColorCompliance(options,AllCompliance,
799 &image->matte_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000800 break;
801 }
802 if (LocaleCompare(keyword,"montage") == 0)
803 {
804 (void) CloneString(&image->montage,options);
805 break;
806 }
807 (void) SetImageProperty(image,keyword,options);
808 break;
809 }
810 case 'o':
811 case 'O':
812 {
813 if (LocaleCompare(keyword,"opaque") == 0)
814 {
cristybb503372010-05-27 20:51:26 +0000815 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000816 matte;
817
cristy042ee782011-04-22 18:48:30 +0000818 matte=ParseCommandOption(MagickBooleanOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000819 options);
820 if (matte < 0)
821 break;
822 image->matte=(MagickBooleanType) matte;
823 break;
824 }
825 if (LocaleCompare(keyword,"orientation") == 0)
826 {
cristybb503372010-05-27 20:51:26 +0000827 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000828 orientation;
829
cristy042ee782011-04-22 18:48:30 +0000830 orientation=ParseCommandOption(MagickOrientationOptions,
cristy3ed852e2009-09-05 21:47:34 +0000831 MagickFalse,options);
832 if (orientation < 0)
833 break;
834 image->orientation=(OrientationType) orientation;
835 break;
836 }
837 (void) SetImageProperty(image,keyword,options);
838 break;
839 }
840 case 'p':
841 case 'P':
842 {
843 if (LocaleCompare(keyword,"page") == 0)
844 {
845 char
846 *geometry;
847
848 geometry=GetPageGeometry(options);
849 (void) ParseAbsoluteGeometry(geometry,&image->page);
850 geometry=DestroyString(geometry);
851 break;
852 }
853 if ((LocaleNCompare(keyword,"profile:",8) == 0) ||
854 (LocaleNCompare(keyword,"profile-",8) == 0))
855 {
856 StringInfo
857 *profile;
858
859 if (profiles == (LinkedListInfo *) NULL)
860 profiles=NewLinkedList(0);
861 (void) AppendValueToLinkedList(profiles,
862 AcquireString(keyword+8));
cristy63f9b8e2011-09-01 13:40:50 +0000863 profile=BlobToStringInfo((const void *) NULL,(size_t)
864 StringToLong(options));
cristy49f5e9f2011-09-01 13:44:57 +0000865 if (profile == (StringInfo *) NULL)
cristy63f9b8e2011-09-01 13:40:50 +0000866 ThrowReaderException(ResourceLimitError,
867 "MemoryAllocationFailed");
cristy3ed852e2009-09-05 21:47:34 +0000868 (void) SetImageProfile(image,keyword+8,profile);
869 profile=DestroyStringInfo(profile);
870 break;
871 }
872 (void) SetImageProperty(image,keyword,options);
873 break;
874 }
875 case 'q':
876 case 'Q':
877 {
878 if (LocaleCompare(keyword,"quality") == 0)
879 {
cristye27293e2009-12-18 02:53:20 +0000880 image->quality=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000881 break;
882 }
883 if ((LocaleCompare(keyword,"quantum-format") == 0) ||
884 (LocaleCompare(keyword,"quantum:format") == 0))
885 {
cristybb503372010-05-27 20:51:26 +0000886 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000887 format;
888
cristy042ee782011-04-22 18:48:30 +0000889 format=ParseCommandOption(MagickQuantumFormatOptions,
cristy3ed852e2009-09-05 21:47:34 +0000890 MagickFalse,options);
891 if (format < 0)
892 break;
893 quantum_format=(QuantumFormatType) format;
894 break;
895 }
896 (void) SetImageProperty(image,keyword,options);
897 break;
898 }
899 case 'r':
900 case 'R':
901 {
902 if (LocaleCompare(keyword,"red-primary") == 0)
903 {
904 flags=ParseGeometry(options,&geometry_info);
905 image->chromaticity.red_primary.x=geometry_info.rho;
906 image->chromaticity.red_primary.y=geometry_info.sigma;
907 if ((flags & SigmaValue) == 0)
908 image->chromaticity.red_primary.y=
909 image->chromaticity.red_primary.x;
910 break;
911 }
912 if (LocaleCompare(keyword,"rendering-intent") == 0)
913 {
cristybb503372010-05-27 20:51:26 +0000914 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000915 rendering_intent;
916
cristy042ee782011-04-22 18:48:30 +0000917 rendering_intent=ParseCommandOption(MagickIntentOptions,
cristy3ed852e2009-09-05 21:47:34 +0000918 MagickFalse,options);
919 if (rendering_intent < 0)
920 break;
921 image->rendering_intent=(RenderingIntent) rendering_intent;
922 break;
923 }
924 if (LocaleCompare(keyword,"resolution") == 0)
925 {
926 flags=ParseGeometry(options,&geometry_info);
927 image->x_resolution=geometry_info.rho;
928 image->y_resolution=geometry_info.sigma;
929 if ((flags & SigmaValue) == 0)
930 image->y_resolution=image->x_resolution;
931 break;
932 }
933 if (LocaleCompare(keyword,"rows") == 0)
934 {
cristye27293e2009-12-18 02:53:20 +0000935 image->rows=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000936 break;
937 }
938 (void) SetImageProperty(image,keyword,options);
939 break;
940 }
941 case 's':
942 case 'S':
943 {
944 if (LocaleCompare(keyword,"scene") == 0)
945 {
cristye27293e2009-12-18 02:53:20 +0000946 image->scene=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000947 break;
948 }
949 (void) SetImageProperty(image,keyword,options);
950 break;
951 }
952 case 't':
953 case 'T':
954 {
955 if (LocaleCompare(keyword,"ticks-per-second") == 0)
956 {
cristy15893a42010-11-20 18:57:15 +0000957 image->ticks_per_second=(ssize_t) StringToLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000958 break;
959 }
960 if (LocaleCompare(keyword,"tile-offset") == 0)
961 {
962 char
963 *geometry;
964
965 geometry=GetPageGeometry(options);
966 (void) ParseAbsoluteGeometry(geometry,&image->tile_offset);
967 geometry=DestroyString(geometry);
968 break;
969 }
970 if (LocaleCompare(keyword,"type") == 0)
971 {
cristybb503372010-05-27 20:51:26 +0000972 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000973 type;
974
cristy042ee782011-04-22 18:48:30 +0000975 type=ParseCommandOption(MagickTypeOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000976 options);
977 if (type < 0)
978 break;
979 image->type=(ImageType) type;
980 break;
981 }
982 (void) SetImageProperty(image,keyword,options);
983 break;
984 }
985 case 'u':
986 case 'U':
987 {
988 if (LocaleCompare(keyword,"units") == 0)
989 {
cristybb503372010-05-27 20:51:26 +0000990 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000991 units;
992
cristyfbbafc92011-05-05 01:22:11 +0000993 units=ParseCommandOption(MagickResolutionOptions,
994 MagickFalse,options);
cristy3ed852e2009-09-05 21:47:34 +0000995 if (units < 0)
996 break;
997 image->units=(ResolutionType) units;
998 break;
999 }
1000 (void) SetImageProperty(image,keyword,options);
1001 break;
1002 }
1003 case 'v':
1004 case 'V':
1005 {
1006 if (LocaleCompare(keyword,"version") == 0)
1007 {
cristyc1acd842011-05-19 23:05:47 +00001008 version=InterpretLocaleValue(options,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +00001009 break;
1010 }
1011 (void) SetImageProperty(image,keyword,options);
1012 break;
1013 }
1014 case 'w':
1015 case 'W':
1016 {
1017 if (LocaleCompare(keyword,"white-point") == 0)
1018 {
1019 flags=ParseGeometry(options,&geometry_info);
1020 image->chromaticity.white_point.x=geometry_info.rho;
1021 image->chromaticity.white_point.y=geometry_info.rho;
1022 if ((flags & SigmaValue) != 0)
1023 image->chromaticity.white_point.y=
1024 image->chromaticity.white_point.x;
1025 break;
1026 }
1027 (void) SetImageProperty(image,keyword,options);
1028 break;
1029 }
1030 default:
1031 {
1032 (void) SetImageProperty(image,keyword,options);
1033 break;
1034 }
1035 }
1036 }
1037 else
1038 c=ReadBlobByte(image);
1039 while (isspace((int) ((unsigned char) c)) != 0)
1040 c=ReadBlobByte(image);
1041 }
1042 options=DestroyString(options);
1043 (void) ReadBlobByte(image);
1044 /*
1045 Verify that required image information is defined.
1046 */
1047 if ((LocaleCompare(id,"ImageMagick") != 0) ||
1048 (image->storage_class == UndefinedClass) ||
1049 (image->columns == 0) || (image->rows == 0))
1050 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1051 if (image->montage != (char *) NULL)
1052 {
1053 register char
1054 *p;
1055
1056 /*
1057 Image directory.
1058 */
1059 length=MaxTextExtent;
1060 image->directory=AcquireString((char *) NULL);
1061 p=image->directory;
1062 do
1063 {
1064 *p='\0';
1065 if ((strlen(image->directory)+MaxTextExtent) >= length)
1066 {
1067 /*
1068 Allocate more memory for the image directory.
1069 */
1070 length<<=1;
1071 image->directory=(char *) ResizeQuantumMemory(image->directory,
1072 length+MaxTextExtent,sizeof(*image->directory));
1073 if (image->directory == (char *) NULL)
1074 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1075 p=image->directory+strlen(image->directory);
1076 }
1077 c=ReadBlobByte(image);
1078 *p++=(char) c;
1079 } while (c != (int) '\0');
1080 }
1081 if (profiles != (LinkedListInfo *) NULL)
1082 {
1083 const char
1084 *name;
1085
1086 const StringInfo
1087 *profile;
1088
1089 /*
1090 Read image profiles.
1091 */
1092 ResetLinkedListIterator(profiles);
1093 name=(const char *) GetNextValueInLinkedList(profiles);
1094 while (name != (const char *) NULL)
1095 {
1096 profile=GetImageProfile(image,name);
1097 if (profile != (StringInfo *) NULL)
1098 {
1099 register unsigned char
1100 *p;
1101
1102 p=GetStringInfoDatum(profile);
1103 count=ReadBlob(image,GetStringInfoLength(profile),p);
cristyda16f162011-02-19 23:52:17 +00001104 (void) count;
cristy3ed852e2009-09-05 21:47:34 +00001105 }
1106 name=(const char *) GetNextValueInLinkedList(profiles);
1107 }
1108 profiles=DestroyLinkedList(profiles,RelinquishMagickMemory);
1109 }
1110 image->depth=GetImageQuantumDepth(image,MagickFalse);
1111 if (image->storage_class == PseudoClass)
1112 {
1113 /*
1114 Create image colormap.
1115 */
cristy018f07f2011-09-04 21:15:19 +00001116 status=AcquireImageColormap(image,colors != 0 ? colors : 256,exception);
cristy3ed852e2009-09-05 21:47:34 +00001117 if (status == MagickFalse)
1118 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1119 if (colors != 0)
1120 {
1121 size_t
1122 packet_size;
1123
1124 unsigned char
1125 *colormap;
1126
1127 /*
1128 Read image colormap from file.
1129 */
1130 packet_size=(size_t) (3UL*image->depth/8UL);
1131 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
1132 packet_size*sizeof(*colormap));
1133 if (colormap == (unsigned char *) NULL)
1134 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1135 count=ReadBlob(image,packet_size*image->colors,colormap);
1136 p=colormap;
1137 switch (image->depth)
1138 {
1139 default:
1140 ThrowReaderException(CorruptImageError,
1141 "ImageDepthNotSupported");
1142 case 8:
1143 {
1144 unsigned char
1145 pixel;
1146
cristybb503372010-05-27 20:51:26 +00001147 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001148 {
1149 p=PushCharPixel(p,&pixel);
1150 image->colormap[i].red=ScaleCharToQuantum(pixel);
1151 p=PushCharPixel(p,&pixel);
1152 image->colormap[i].green=ScaleCharToQuantum(pixel);
1153 p=PushCharPixel(p,&pixel);
1154 image->colormap[i].blue=ScaleCharToQuantum(pixel);
1155 }
1156 break;
1157 }
1158 case 16:
1159 {
1160 unsigned short
1161 pixel;
1162
cristybb503372010-05-27 20:51:26 +00001163 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001164 {
1165 p=PushShortPixel(MSBEndian,p,&pixel);
1166 image->colormap[i].red=ScaleShortToQuantum(pixel);
1167 p=PushShortPixel(MSBEndian,p,&pixel);
1168 image->colormap[i].green=ScaleShortToQuantum(pixel);
1169 p=PushShortPixel(MSBEndian,p,&pixel);
1170 image->colormap[i].blue=ScaleShortToQuantum(pixel);
1171 }
1172 break;
1173 }
1174 case 32:
1175 {
cristy4cb162a2010-05-30 03:04:47 +00001176 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001177 pixel;
1178
cristybb503372010-05-27 20:51:26 +00001179 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001180 {
1181 p=PushLongPixel(MSBEndian,p,&pixel);
1182 image->colormap[i].red=ScaleLongToQuantum(pixel);
1183 p=PushLongPixel(MSBEndian,p,&pixel);
1184 image->colormap[i].green=ScaleLongToQuantum(pixel);
1185 p=PushLongPixel(MSBEndian,p,&pixel);
1186 image->colormap[i].blue=ScaleLongToQuantum(pixel);
1187 }
1188 break;
1189 }
1190 }
1191 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
1192 }
1193 }
1194 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1195 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1196 break;
1197 /*
1198 Allocate image pixels.
1199 */
1200 quantum_info=AcquireQuantumInfo(image_info,image);
1201 if (quantum_info == (QuantumInfo *) NULL)
1202 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1203 if (quantum_format != UndefinedQuantumFormat)
1204 {
1205 status=SetQuantumFormat(image,quantum_info,quantum_format);
1206 if (status == MagickFalse)
1207 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1208 }
1209 packet_size=(size_t) (quantum_info->depth/8);
1210 if (image->storage_class == DirectClass)
1211 packet_size=(size_t) (3*quantum_info->depth/8);
cristyc4a6f8a2011-09-21 22:36:11 +00001212 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
1213 (image->type == GrayscaleMatteType))
cristy0a30e182011-09-01 01:43:15 +00001214 packet_size=quantum_info->depth/8;
cristy3ed852e2009-09-05 21:47:34 +00001215 if (image->matte != MagickFalse)
1216 packet_size+=quantum_info->depth/8;
1217 if (image->colorspace == CMYKColorspace)
1218 packet_size+=quantum_info->depth/8;
1219 if (image->compression == RLECompression)
1220 packet_size++;
1221 length=image->columns;
cristy26377172010-12-20 19:01:58 +00001222 length=MagickMax(MagickMax(BZipMaxExtent(packet_size*image->columns),
1223 LZMAMaxExtent(packet_size*image->columns)),ZipMaxExtent(packet_size*
1224 image->columns));
cristy3ed852e2009-09-05 21:47:34 +00001225 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
1226 sizeof(*compress_pixels));
1227 if (compress_pixels == (unsigned char *) NULL)
1228 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1229 /*
1230 Read image pixels.
1231 */
1232 quantum_type=RGBQuantum;
1233 if (image->matte != MagickFalse)
1234 quantum_type=RGBAQuantum;
1235 if (image->colorspace == CMYKColorspace)
1236 {
1237 quantum_type=CMYKQuantum;
1238 if (image->matte != MagickFalse)
1239 quantum_type=CMYKAQuantum;
1240 }
1241 if (image->storage_class == PseudoClass)
1242 {
1243 quantum_type=IndexQuantum;
1244 if (image->matte != MagickFalse)
1245 quantum_type=IndexAlphaQuantum;
1246 }
cristyc4a6f8a2011-09-21 22:36:11 +00001247 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
1248 (image->type == GrayscaleMatteType))
cristy3ed852e2009-09-05 21:47:34 +00001249 {
1250 quantum_type=GrayQuantum;
1251 if (image->matte != MagickFalse)
1252 quantum_type=GrayAlphaQuantum;
1253 }
cristy330af6c2010-12-21 14:36:06 +00001254 status=MagickTrue;
1255 switch (image->compression)
1256 {
1257#if defined(MAGICKCORE_BZLIB_DELEGATE)
1258 case BZipCompression:
1259 {
1260 (void) ResetMagickMemory(&bzip_info,0,sizeof(bzip_info));
1261 bzip_info.bzalloc=AcquireBZIPMemory;
1262 bzip_info.bzfree=RelinquishBZIPMemory;
1263 bzip_info.opaque=(void *) NULL;
1264 code=BZ2_bzDecompressInit(&bzip_info,(int) image_info->verbose,
1265 MagickFalse);
1266 if (code != BZ_OK)
1267 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001268 break;
1269 }
1270#endif
1271#if defined(MAGICKCORE_LZMA_DELEGATE)
1272 case LZMACompression:
1273 {
cristy9d72f1a2010-12-21 20:46:59 +00001274 (void) ResetMagickMemory(&allocator,0,sizeof(allocator));
1275 allocator.alloc=AcquireLZMAMemory;
1276 allocator.free=RelinquishLZMAMemory;
cristy330af6c2010-12-21 14:36:06 +00001277 lzma_info=initialize_lzma;
cristy9d72f1a2010-12-21 20:46:59 +00001278 lzma_info.allocator=(&allocator);
cristy330af6c2010-12-21 14:36:06 +00001279 code=lzma_auto_decoder(&lzma_info,-1,0);
1280 if (code != LZMA_OK)
1281 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001282 break;
1283 }
1284#endif
1285#if defined(MAGICKCORE_ZLIB_DELEGATE)
1286 case LZWCompression:
1287 case ZipCompression:
1288 {
1289 (void) ResetMagickMemory(&zip_info,0,sizeof(zip_info));
1290 zip_info.zalloc=AcquireZIPMemory;
1291 zip_info.zfree=RelinquishZIPMemory;
1292 zip_info.opaque=(voidpf) NULL;
1293 code=inflateInit(&zip_info);
1294 if (code != Z_OK)
1295 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001296 break;
1297 }
1298#endif
1299 case RLECompression:
1300 {
cristy4c08aed2011-07-01 19:47:50 +00001301 GetPixelInfo(image,&pixel);
cristy330af6c2010-12-21 14:36:06 +00001302 break;
1303 }
1304 default:
1305 break;
1306 }
cristy3ed852e2009-09-05 21:47:34 +00001307 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001308 length=0;
cristybb503372010-05-27 20:51:26 +00001309 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001310 {
cristybb503372010-05-27 20:51:26 +00001311 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001312 x;
1313
cristy4c08aed2011-07-01 19:47:50 +00001314 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00001315 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001316
cristy330af6c2010-12-21 14:36:06 +00001317 if (status == MagickFalse)
1318 break;
cristy3ed852e2009-09-05 21:47:34 +00001319 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00001320 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001321 break;
cristy3ed852e2009-09-05 21:47:34 +00001322 switch (image->compression)
1323 {
cristy3ed852e2009-09-05 21:47:34 +00001324#if defined(MAGICKCORE_BZLIB_DELEGATE)
1325 case BZipCompression:
1326 {
cristy3ed852e2009-09-05 21:47:34 +00001327 bzip_info.next_out=(char *) pixels;
1328 bzip_info.avail_out=(unsigned int) (packet_size*image->columns);
1329 do
1330 {
1331 if (bzip_info.avail_in == 0)
1332 {
1333 bzip_info.next_in=(char *) compress_pixels;
1334 length=(size_t) BZipMaxExtent(packet_size*image->columns);
1335 if (version != 0)
1336 length=(size_t) ReadBlobMSBLong(image);
1337 bzip_info.avail_in=(unsigned int) ReadBlob(image,length,
1338 (unsigned char *) bzip_info.next_in);
1339 }
1340 if (BZ2_bzDecompress(&bzip_info) == BZ_STREAM_END)
1341 break;
1342 } while (bzip_info.avail_out != 0);
cristy26377172010-12-20 19:01:58 +00001343 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1344 quantum_type,pixels,exception);
1345 break;
1346 }
1347#endif
1348#if defined(MAGICKCORE_LZMA_DELEGATE)
1349 case LZMACompression:
1350 {
cristy26377172010-12-20 19:01:58 +00001351 lzma_info.next_out=pixels;
cristy330af6c2010-12-21 14:36:06 +00001352 lzma_info.avail_out=packet_size*image->columns;
cristy26377172010-12-20 19:01:58 +00001353 do
1354 {
1355 if (lzma_info.avail_in == 0)
1356 {
1357 lzma_info.next_in=compress_pixels;
1358 length=(size_t) ReadBlobMSBLong(image);
1359 lzma_info.avail_in=(unsigned int) ReadBlob(image,length,
1360 (unsigned char *) lzma_info.next_in);
1361 }
1362 code=lzma_code(&lzma_info,LZMA_RUN);
cristy330af6c2010-12-21 14:36:06 +00001363 if (code < 0)
1364 {
1365 status=MagickFalse;
1366 break;
1367 }
1368 if (code == LZMA_STREAM_END)
cristy26377172010-12-20 19:01:58 +00001369 break;
1370 } while (lzma_info.avail_out != 0);
cristy26377172010-12-20 19:01:58 +00001371 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1372 quantum_type,pixels,exception);
1373 break;
1374 }
1375#endif
1376#if defined(MAGICKCORE_ZLIB_DELEGATE)
1377 case LZWCompression:
1378 case ZipCompression:
1379 {
cristy26377172010-12-20 19:01:58 +00001380 zip_info.next_out=pixels;
1381 zip_info.avail_out=(uInt) (packet_size*image->columns);
1382 do
1383 {
1384 if (zip_info.avail_in == 0)
1385 {
1386 zip_info.next_in=compress_pixels;
1387 length=(size_t) ZipMaxExtent(packet_size*image->columns);
1388 if (version != 0)
1389 length=(size_t) ReadBlobMSBLong(image);
1390 zip_info.avail_in=(unsigned int) ReadBlob(image,length,
1391 zip_info.next_in);
1392 }
1393 if (inflate(&zip_info,Z_SYNC_FLUSH) == Z_STREAM_END)
1394 break;
1395 } while (zip_info.avail_out != 0);
cristy3ed852e2009-09-05 21:47:34 +00001396 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1397 quantum_type,pixels,exception);
1398 break;
1399 }
1400#endif
1401 case RLECompression:
1402 {
cristybb503372010-05-27 20:51:26 +00001403 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001404 {
1405 if (length == 0)
1406 {
1407 count=ReadBlob(image,packet_size,pixels);
cristy4c08aed2011-07-01 19:47:50 +00001408 PushRunlengthPacket(image,pixels,&length,&pixel);
cristy3ed852e2009-09-05 21:47:34 +00001409 }
1410 length--;
cristy4c08aed2011-07-01 19:47:50 +00001411 if (image->storage_class == PseudoClass)
cristy94b11832011-09-08 19:46:03 +00001412 SetPixelIndex(image,ClampToQuantum(pixel.index),q);
cristy4c08aed2011-07-01 19:47:50 +00001413 else
1414 {
cristy94b11832011-09-08 19:46:03 +00001415 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1416 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1417 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
cristy4c08aed2011-07-01 19:47:50 +00001418 if (image->colorspace == CMYKColorspace)
cristy94b11832011-09-08 19:46:03 +00001419 SetPixelBlack(image,ClampToQuantum(pixel.black),q);
cristy4c08aed2011-07-01 19:47:50 +00001420 }
1421 if (image->matte != MagickFalse)
cristy94b11832011-09-08 19:46:03 +00001422 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
cristyed231572011-07-14 02:18:59 +00001423 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001424 }
1425 break;
1426 }
1427 default:
1428 {
1429 count=ReadBlob(image,packet_size*image->columns,pixels);
1430 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1431 quantum_type,pixels,exception);
1432 break;
1433 }
1434 }
1435 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1436 break;
1437 }
1438 SetQuantumImageType(image,quantum_type);
cristy330af6c2010-12-21 14:36:06 +00001439 switch (image->compression)
1440 {
1441#if defined(MAGICKCORE_BZLIB_DELEGATE)
1442 case BZipCompression:
1443 {
1444 if (version == 0)
1445 {
1446 MagickOffsetType
1447 offset;
1448
1449 offset=SeekBlob(image,-((MagickOffsetType)
1450 bzip_info.avail_in),SEEK_CUR);
1451 if (offset < 0)
1452 ThrowReaderException(CorruptImageError,
1453 "ImproperImageHeader");
1454 }
1455 code=BZ2_bzDecompressEnd(&bzip_info);
1456 if (code != BZ_OK)
1457 status=MagickFalse;
1458 break;
1459 }
1460#endif
1461#if defined(MAGICKCORE_LZMA_DELEGATE)
1462 case LZMACompression:
1463 {
cristy3b788a02010-12-27 15:59:54 +00001464 code=lzma_code(&lzma_info,LZMA_FINISH);
1465 if ((code != LZMA_STREAM_END) && (code != LZMA_OK))
cristyb977da52010-12-22 15:55:53 +00001466 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001467 lzma_end(&lzma_info);
1468 break;
1469 }
1470#endif
1471#if defined(MAGICKCORE_ZLIB_DELEGATE)
1472 case LZWCompression:
1473 case ZipCompression:
1474 {
1475 if (version == 0)
1476 {
1477 MagickOffsetType
1478 offset;
1479
1480 offset=SeekBlob(image,-((MagickOffsetType) zip_info.avail_in),
1481 SEEK_CUR);
1482 if (offset < 0)
1483 ThrowReaderException(CorruptImageError,
1484 "ImproperImageHeader");
1485 }
1486 code=inflateEnd(&zip_info);
1487 if (code != LZMA_OK)
1488 status=MagickFalse;
1489 break;
1490 }
1491#endif
1492 default:
1493 break;
1494 }
cristy3ed852e2009-09-05 21:47:34 +00001495 quantum_info=DestroyQuantumInfo(quantum_info);
1496 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
cristybb503372010-05-27 20:51:26 +00001497 if (((y != (ssize_t) image->rows)) || (status == MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001498 {
1499 image=DestroyImageList(image);
1500 return((Image *) NULL);
1501 }
1502 if (EOFBlob(image) != MagickFalse)
1503 {
1504 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1505 image->filename);
1506 break;
1507 }
1508 /*
1509 Proceed to next image.
1510 */
1511 if (image_info->number_scenes != 0)
1512 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1513 break;
1514 do
1515 {
1516 c=ReadBlobByte(image);
1517 } while ((isgraph(c) == MagickFalse) && (c != EOF));
1518 if (c != EOF)
1519 {
1520 /*
1521 Allocate next image structure.
1522 */
cristy9950d572011-10-01 18:22:35 +00001523 AcquireNextImage(image_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001524 if (GetNextImageInList(image) == (Image *) NULL)
1525 {
1526 image=DestroyImageList(image);
1527 return((Image *) NULL);
1528 }
1529 image=SyncNextImageInList(image);
1530 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1531 GetBlobSize(image));
1532 if (status == MagickFalse)
1533 break;
1534 }
1535 } while (c != EOF);
1536 (void) CloseBlob(image);
1537 return(GetFirstImageInList(image));
1538}
1539
1540/*
1541%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1542% %
1543% %
1544% %
1545% R e g i s t e r M I F F I m a g e %
1546% %
1547% %
1548% %
1549%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1550%
1551% RegisterMIFFImage() adds properties for the MIFF image format to the list of
1552% supported formats. The properties include the image format tag, a method to
1553% read and/or write the format, whether the format supports the saving of more
1554% than one frame to the same file or blob, whether the format supports native
1555% in-memory I/O, and a brief description of the format.
1556%
1557% The format of the RegisterMIFFImage method is:
1558%
cristybb503372010-05-27 20:51:26 +00001559% size_t RegisterMIFFImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001560%
1561*/
cristybb503372010-05-27 20:51:26 +00001562ModuleExport size_t RegisterMIFFImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001563{
1564 char
1565 version[MaxTextExtent];
1566
1567 MagickInfo
1568 *entry;
1569
1570 *version='\0';
1571#if defined(MagickImageCoderSignatureText)
1572 (void) CopyMagickString(version,MagickLibVersionText,MaxTextExtent);
1573#if defined(ZLIB_VERSION)
1574 (void) ConcatenateMagickString(version," with Zlib ",MaxTextExtent);
1575 (void) ConcatenateMagickString(version,ZLIB_VERSION,MaxTextExtent);
1576#endif
1577#if defined(MAGICKCORE_BZLIB_DELEGATE)
1578 (void) ConcatenateMagickString(version," and BZlib",MaxTextExtent);
1579#endif
1580#endif
1581 entry=SetMagickInfo("MIFF");
1582 entry->decoder=(DecodeImageHandler *) ReadMIFFImage;
1583 entry->encoder=(EncodeImageHandler *) WriteMIFFImage;
1584 entry->magick=(IsImageFormatHandler *) IsMIFF;
cristyffaf9782011-04-13 19:50:51 +00001585 entry->seekable_stream=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00001586 entry->description=ConstantString("Magick Image File Format");
1587 if (*version != '\0')
1588 entry->version=ConstantString(version);
1589 entry->module=ConstantString("MIFF");
1590 (void) RegisterMagickInfo(entry);
1591 return(MagickImageCoderSignature);
1592}
1593
1594/*
1595%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1596% %
1597% %
1598% %
1599% U n r e g i s t e r M I F F I m a g e %
1600% %
1601% %
1602% %
1603%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1604%
1605% UnregisterMIFFImage() removes format registrations made by the MIFF module
1606% from the list of supported formats.
1607%
1608% The format of the UnregisterMIFFImage method is:
1609%
1610% UnregisterMIFFImage(void)
1611%
1612*/
1613ModuleExport void UnregisterMIFFImage(void)
1614{
1615 (void) UnregisterMagickInfo("MIFF");
1616}
1617
1618/*
1619%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1620% %
1621% %
1622% %
1623% W r i t e M I F F I m a g e %
1624% %
1625% %
1626% %
1627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1628%
1629% WriteMIFFImage() writes a MIFF image to a file.
1630%
1631% The format of the WriteMIFFImage method is:
1632%
1633% MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
cristy1e178e72011-08-28 19:44:34 +00001634% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001635%
1636% Compression code contributed by Kyle Shorter.
1637%
1638% A description of each parameter follows:
1639%
1640% o image_info: the image info.
1641%
1642% o image: the image.
1643%
cristy1e178e72011-08-28 19:44:34 +00001644% o exception: return any errors or warnings in this structure.
1645%
cristy3ed852e2009-09-05 21:47:34 +00001646*/
1647
1648static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
cristy4c08aed2011-07-01 19:47:50 +00001649 size_t length,PixelInfo *pixel)
cristy3ed852e2009-09-05 21:47:34 +00001650{
1651 if (image->storage_class != DirectClass)
1652 {
1653 switch (image->depth)
1654 {
1655 case 32:
1656 {
cristy4c08aed2011-07-01 19:47:50 +00001657 *pixels++=(unsigned char) ((size_t) pixel->index >> 24);
1658 *pixels++=(unsigned char) ((size_t) pixel->index >> 16);
cristy3ed852e2009-09-05 21:47:34 +00001659 }
1660 case 16:
cristy4c08aed2011-07-01 19:47:50 +00001661 *pixels++=(unsigned char) ((size_t) pixel->index >> 8);
cristy3ed852e2009-09-05 21:47:34 +00001662 case 8:
1663 {
cristy4c08aed2011-07-01 19:47:50 +00001664 *pixels++=(unsigned char) pixel->index;
cristy3ed852e2009-09-05 21:47:34 +00001665 break;
1666 }
1667 default:
1668 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1669 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1670 }
1671 switch (image->depth)
1672 {
1673 case 32:
1674 {
cristy4cb162a2010-05-30 03:04:47 +00001675 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001676 value;
1677
1678 if (image->matte != MagickFalse)
1679 {
cristy94b11832011-09-08 19:46:03 +00001680 value=ScaleQuantumToLong(ClampToQuantum(pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001681 pixels=PopLongPixel(MSBEndian,value,pixels);
1682 }
1683 break;
1684 }
1685 case 16:
1686 {
1687 unsigned short
1688 value;
1689
1690 if (image->matte != MagickFalse)
1691 {
cristy94b11832011-09-08 19:46:03 +00001692 value=ScaleQuantumToShort(ClampToQuantum(pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001693 pixels=PopShortPixel(MSBEndian,value,pixels);
1694 }
1695 break;
1696 }
1697 case 8:
1698 {
1699 unsigned char
1700 value;
1701
1702 if (image->matte != MagickFalse)
1703 {
cristy94b11832011-09-08 19:46:03 +00001704 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1705 pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001706 pixels=PopCharPixel(value,pixels);
1707 }
1708 break;
1709 }
1710 default:
1711 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1712 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1713 }
1714 *pixels++=(unsigned char) length;
1715 return(pixels);
1716 }
1717 switch (image->depth)
1718 {
1719 case 32:
1720 {
cristy4cb162a2010-05-30 03:04:47 +00001721 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001722 value;
1723
cristy94b11832011-09-08 19:46:03 +00001724 value=ScaleQuantumToLong(ClampToQuantum(pixel->red));
cristy3ed852e2009-09-05 21:47:34 +00001725 pixels=PopLongPixel(MSBEndian,value,pixels);
cristy94b11832011-09-08 19:46:03 +00001726 value=ScaleQuantumToLong(ClampToQuantum(pixel->green));
cristy3ed852e2009-09-05 21:47:34 +00001727 pixels=PopLongPixel(MSBEndian,value,pixels);
cristy94b11832011-09-08 19:46:03 +00001728 value=ScaleQuantumToLong(ClampToQuantum(pixel->blue));
cristy3ed852e2009-09-05 21:47:34 +00001729 pixels=PopLongPixel(MSBEndian,value,pixels);
cristy3ed852e2009-09-05 21:47:34 +00001730 if (image->colorspace == CMYKColorspace)
1731 {
cristy94b11832011-09-08 19:46:03 +00001732 value=ScaleQuantumToLong(ClampToQuantum(pixel->black));
cristy4c08aed2011-07-01 19:47:50 +00001733 pixels=PopLongPixel(MSBEndian,value,pixels);
1734 }
1735 if (image->matte != MagickFalse)
1736 {
cristy94b11832011-09-08 19:46:03 +00001737 value=ScaleQuantumToLong(ClampToQuantum(pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001738 pixels=PopLongPixel(MSBEndian,value,pixels);
1739 }
1740 break;
1741 }
1742 case 16:
1743 {
1744 unsigned short
1745 value;
1746
cristy94b11832011-09-08 19:46:03 +00001747 value=ScaleQuantumToShort(ClampToQuantum(pixel->red));
cristy3ed852e2009-09-05 21:47:34 +00001748 pixels=PopShortPixel(MSBEndian,value,pixels);
cristy94b11832011-09-08 19:46:03 +00001749 value=ScaleQuantumToShort(ClampToQuantum(pixel->green));
cristy3ed852e2009-09-05 21:47:34 +00001750 pixels=PopShortPixel(MSBEndian,value,pixels);
cristy94b11832011-09-08 19:46:03 +00001751 value=ScaleQuantumToShort(ClampToQuantum(pixel->blue));
cristy3ed852e2009-09-05 21:47:34 +00001752 pixels=PopShortPixel(MSBEndian,value,pixels);
cristy3ed852e2009-09-05 21:47:34 +00001753 if (image->colorspace == CMYKColorspace)
1754 {
cristy94b11832011-09-08 19:46:03 +00001755 value=ScaleQuantumToShort(ClampToQuantum(pixel->black));
cristy4c08aed2011-07-01 19:47:50 +00001756 pixels=PopShortPixel(MSBEndian,value,pixels);
1757 }
1758 if (image->matte != MagickFalse)
1759 {
cristy94b11832011-09-08 19:46:03 +00001760 value=ScaleQuantumToShort(ClampToQuantum(pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001761 pixels=PopShortPixel(MSBEndian,value,pixels);
1762 }
1763 break;
1764 }
1765 case 8:
1766 {
1767 unsigned char
1768 value;
1769
cristy94b11832011-09-08 19:46:03 +00001770 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->red));
cristy3ed852e2009-09-05 21:47:34 +00001771 pixels=PopCharPixel(value,pixels);
cristy94b11832011-09-08 19:46:03 +00001772 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->green));
cristy3ed852e2009-09-05 21:47:34 +00001773 pixels=PopCharPixel(value,pixels);
cristy94b11832011-09-08 19:46:03 +00001774 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->blue));
cristy3ed852e2009-09-05 21:47:34 +00001775 pixels=PopCharPixel(value,pixels);
cristy3ed852e2009-09-05 21:47:34 +00001776 if (image->colorspace == CMYKColorspace)
1777 {
cristy94b11832011-09-08 19:46:03 +00001778 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1779 pixel->black));
cristy4c08aed2011-07-01 19:47:50 +00001780 pixels=PopCharPixel(value,pixels);
1781 }
1782 if (image->matte != MagickFalse)
1783 {
cristy94b11832011-09-08 19:46:03 +00001784 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1785 pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001786 pixels=PopCharPixel(value,pixels);
1787 }
1788 break;
1789 }
1790 default:
1791 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1792 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1793 }
1794 *pixels++=(unsigned char) length;
1795 return(pixels);
1796}
1797
1798static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
cristy1e178e72011-08-28 19:44:34 +00001799 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001800{
1801#if defined(MAGICKCORE_BZLIB_DELEGATE)
1802 bz_stream
1803 bzip_info;
1804#endif
1805
1806 char
1807 buffer[MaxTextExtent];
1808
1809 CompressionType
1810 compression;
1811
1812 const char
1813 *property,
1814 *value;
1815
cristy3ed852e2009-09-05 21:47:34 +00001816 int
1817 code;
1818
cristy26377172010-12-20 19:01:58 +00001819#if defined(MAGICKCORE_LZMA_DELEGATE)
cristy4b46dba2010-12-20 19:18:20 +00001820 lzma_allocator
1821 allocator;
1822
cristy26377172010-12-20 19:01:58 +00001823 lzma_stream
cristy330af6c2010-12-21 14:36:06 +00001824 initialize_lzma = LZMA_STREAM_INIT,
1825 lzma_info;
cristy26377172010-12-20 19:01:58 +00001826#endif
cristy3ed852e2009-09-05 21:47:34 +00001827
1828 MagickBooleanType
1829 status;
1830
1831 MagickOffsetType
1832 scene;
1833
cristy4c08aed2011-07-01 19:47:50 +00001834 PixelInfo
1835 pixel,
1836 target;
cristy3ed852e2009-09-05 21:47:34 +00001837
1838 QuantumInfo
1839 *quantum_info;
1840
1841 QuantumType
1842 quantum_type;
1843
cristybb503372010-05-27 20:51:26 +00001844 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001845 i;
1846
1847 size_t
1848 length,
1849 packet_size;
1850
cristy26377172010-12-20 19:01:58 +00001851 ssize_t
1852 y;
1853
cristy3ed852e2009-09-05 21:47:34 +00001854 unsigned char
1855 *compress_pixels,
1856 *pixels,
1857 *q;
1858
1859#if defined(MAGICKCORE_ZLIB_DELEGATE)
1860 z_stream
1861 zip_info;
1862#endif
1863
1864 /*
1865 Open output image file.
1866 */
1867 assert(image_info != (const ImageInfo *) NULL);
1868 assert(image_info->signature == MagickSignature);
1869 assert(image != (Image *) NULL);
1870 assert(image->signature == MagickSignature);
1871 if (image->debug != MagickFalse)
1872 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy3a37efd2011-08-28 20:31:03 +00001873 assert(exception != (ExceptionInfo *) NULL);
1874 assert(exception->signature == MagickSignature);
cristy1e178e72011-08-28 19:44:34 +00001875 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy3ed852e2009-09-05 21:47:34 +00001876 if (status == MagickFalse)
1877 return(status);
1878 code=0;
1879 scene=0;
1880 do
1881 {
1882 /*
1883 Allocate image pixels.
1884 */
1885 image->depth=image->depth <= 8 ? 8UL : image->depth <= 16 ? 16UL :
1886 image->depth <= 32 ? 32UL : 64UL;
1887 quantum_info=AcquireQuantumInfo(image_info,image);
1888 if (quantum_info == (QuantumInfo *) NULL)
1889 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1890 if ((image->storage_class != PseudoClass) && (image->depth >= 32) &&
1891 (quantum_info->format == UndefinedQuantumFormat) &&
cristy1e178e72011-08-28 19:44:34 +00001892 (IsHighDynamicRangeImage(image,exception) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001893 {
1894 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1895 if (status == MagickFalse)
1896 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1897 }
1898 if ((image->storage_class == PseudoClass) &&
cristybb503372010-05-27 20:51:26 +00001899 (image->colors > (size_t) (GetQuantumRange(image->depth)+1)))
cristy1e178e72011-08-28 19:44:34 +00001900 (void) SetImageStorageClass(image,DirectClass,exception);
cristy669e5c72011-09-12 12:01:33 +00001901 if (IsImageGray(image,exception) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001902 {
cristy1e178e72011-08-28 19:44:34 +00001903 (void) SetImageStorageClass(image,DirectClass,exception);
1904 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +00001905 }
1906 compression=image->compression;
1907 if (image_info->compression != UndefinedCompression)
1908 compression=image_info->compression;
1909 switch (compression)
1910 {
1911#if !defined(MAGICKCORE_ZLIB_DELEGATE)
cristy26377172010-12-20 19:01:58 +00001912 case LZMACompression: compression=NoCompression; break;
1913#endif
1914#if !defined(MAGICKCORE_ZLIB_DELEGATE)
cristy3ed852e2009-09-05 21:47:34 +00001915 case LZWCompression:
1916 case ZipCompression: compression=NoCompression; break;
1917#endif
1918#if !defined(MAGICKCORE_BZLIB_DELEGATE)
1919 case BZipCompression: compression=NoCompression; break;
1920#endif
1921 case RLECompression:
1922 {
1923 if (quantum_info->format == FloatingPointQuantumFormat)
1924 compression=NoCompression;
cristy4c08aed2011-07-01 19:47:50 +00001925 GetPixelInfo(image,&target);
cristy3ed852e2009-09-05 21:47:34 +00001926 break;
1927 }
1928 default:
1929 break;
1930 }
1931 packet_size=(size_t) (quantum_info->depth/8);
1932 if (image->storage_class == DirectClass)
1933 packet_size=(size_t) (3*quantum_info->depth/8);
cristy669e5c72011-09-12 12:01:33 +00001934 if (IsImageGray(image,exception) != MagickFalse)
cristy0a30e182011-09-01 01:43:15 +00001935 packet_size=(size_t) (quantum_info->depth/8);
cristy3ed852e2009-09-05 21:47:34 +00001936 if (image->matte != MagickFalse)
1937 packet_size+=quantum_info->depth/8;
1938 if (image->colorspace == CMYKColorspace)
1939 packet_size+=quantum_info->depth/8;
1940 if (compression == RLECompression)
1941 packet_size++;
1942 length=image->columns;
1943 length=MagickMax(BZipMaxExtent(packet_size*image->columns),ZipMaxExtent(
1944 packet_size*image->columns));
1945 if ((compression == BZipCompression) || (compression == ZipCompression))
1946 if (length != (size_t) ((unsigned int) length))
1947 compression=NoCompression;
1948 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
1949 sizeof(*compress_pixels));
1950 if (compress_pixels == (unsigned char *) NULL)
1951 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1952 /*
1953 Write MIFF header.
1954 */
1955 (void) WriteBlobString(image,"id=ImageMagick version=1.0\n");
cristyb51dff52011-05-19 16:55:47 +00001956 (void) FormatLocaleString(buffer,MaxTextExtent,
cristy042ee782011-04-22 18:48:30 +00001957 "class=%s colors=%.20g matte=%s\n",CommandOptionToMnemonic(
cristye8c25f92010-06-03 00:53:06 +00001958 MagickClassOptions,image->storage_class),(double) image->colors,
cristy042ee782011-04-22 18:48:30 +00001959 CommandOptionToMnemonic(MagickBooleanOptions,(ssize_t) image->matte));
cristy3ed852e2009-09-05 21:47:34 +00001960 (void) WriteBlobString(image,buffer);
cristyb51dff52011-05-19 16:55:47 +00001961 (void) FormatLocaleString(buffer,MaxTextExtent,"columns=%.20g rows=%.20g "
cristye8c25f92010-06-03 00:53:06 +00001962 "depth=%.20g\n",(double) image->columns,(double) image->rows,(double)
1963 image->depth);
cristy3ed852e2009-09-05 21:47:34 +00001964 (void) WriteBlobString(image,buffer);
cristy5f1c1ff2010-12-23 21:38:06 +00001965 if (image->type != UndefinedType)
cristy3ed852e2009-09-05 21:47:34 +00001966 {
cristyb51dff52011-05-19 16:55:47 +00001967 (void) FormatLocaleString(buffer,MaxTextExtent,"type=%s\n",
cristy042ee782011-04-22 18:48:30 +00001968 CommandOptionToMnemonic(MagickTypeOptions,image->type));
cristy3ed852e2009-09-05 21:47:34 +00001969 (void) WriteBlobString(image,buffer);
1970 }
1971 if (image->colorspace != UndefinedColorspace)
1972 {
cristyb51dff52011-05-19 16:55:47 +00001973 (void) FormatLocaleString(buffer,MaxTextExtent,"colorspace=%s\n",
cristy042ee782011-04-22 18:48:30 +00001974 CommandOptionToMnemonic(MagickColorspaceOptions,image->colorspace));
cristy3ed852e2009-09-05 21:47:34 +00001975 (void) WriteBlobString(image,buffer);
1976 }
1977 if (compression != UndefinedCompression)
1978 {
cristyb51dff52011-05-19 16:55:47 +00001979 (void) FormatLocaleString(buffer,MaxTextExtent,"compression=%s "
cristy042ee782011-04-22 18:48:30 +00001980 "quality=%.20g\n",CommandOptionToMnemonic(MagickCompressOptions,
cristye8c25f92010-06-03 00:53:06 +00001981 compression),(double) image->quality);
cristy3ed852e2009-09-05 21:47:34 +00001982 (void) WriteBlobString(image,buffer);
1983 }
1984 if (image->units != UndefinedResolution)
1985 {
cristyb51dff52011-05-19 16:55:47 +00001986 (void) FormatLocaleString(buffer,MaxTextExtent,"units=%s\n",
cristy042ee782011-04-22 18:48:30 +00001987 CommandOptionToMnemonic(MagickResolutionOptions,image->units));
cristy3ed852e2009-09-05 21:47:34 +00001988 (void) WriteBlobString(image,buffer);
1989 }
1990 if ((image->x_resolution != 0) || (image->y_resolution != 0))
1991 {
cristyb51dff52011-05-19 16:55:47 +00001992 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye7f51092010-01-17 00:39:37 +00001993 "resolution=%gx%g\n",image->x_resolution,image->y_resolution);
cristy3ed852e2009-09-05 21:47:34 +00001994 (void) WriteBlobString(image,buffer);
1995 }
1996 if ((image->page.width != 0) || (image->page.height != 0))
1997 {
cristyb51dff52011-05-19 16:55:47 +00001998 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00001999 "page=%.20gx%.20g%+.20g%+.20g\n",(double) image->page.width,(double)
2000 image->page.height,(double) image->page.x,(double) image->page.y);
cristy3ed852e2009-09-05 21:47:34 +00002001 (void) WriteBlobString(image,buffer);
2002 }
2003 else
2004 if ((image->page.x != 0) || (image->page.y != 0))
2005 {
cristyb51dff52011-05-19 16:55:47 +00002006 (void) FormatLocaleString(buffer,MaxTextExtent,"page=%+ld%+ld\n",
cristyf2faecf2010-05-28 19:19:36 +00002007 (long) image->page.x,(long) image->page.y);
cristy3ed852e2009-09-05 21:47:34 +00002008 (void) WriteBlobString(image,buffer);
2009 }
2010 if ((image->tile_offset.x != 0) || (image->tile_offset.y != 0))
2011 {
cristyb51dff52011-05-19 16:55:47 +00002012 (void) FormatLocaleString(buffer,MaxTextExtent,"tile-offset=%+ld%+ld\n",
cristyf2faecf2010-05-28 19:19:36 +00002013 (long) image->tile_offset.x,(long) image->tile_offset.y);
cristy3ed852e2009-09-05 21:47:34 +00002014 (void) WriteBlobString(image,buffer);
2015 }
2016 if ((GetNextImageInList(image) != (Image *) NULL) ||
2017 (GetPreviousImageInList(image) != (Image *) NULL))
2018 {
2019 if (image->scene == 0)
cristyb51dff52011-05-19 16:55:47 +00002020 (void) FormatLocaleString(buffer,MaxTextExtent,"iterations=%.20g "
cristye8c25f92010-06-03 00:53:06 +00002021 "delay=%.20g ticks-per-second=%.20g\n",(double) image->iterations,
2022 (double) image->delay,(double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002023 else
cristyb51dff52011-05-19 16:55:47 +00002024 (void) FormatLocaleString(buffer,MaxTextExtent,"scene=%.20g "
cristye8c25f92010-06-03 00:53:06 +00002025 "iterations=%.20g delay=%.20g ticks-per-second=%.20g\n",(double)
2026 image->scene,(double) image->iterations,(double) image->delay,
2027 (double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002028 (void) WriteBlobString(image,buffer);
2029 }
2030 else
2031 {
2032 if (image->scene != 0)
2033 {
cristyb51dff52011-05-19 16:55:47 +00002034 (void) FormatLocaleString(buffer,MaxTextExtent,"scene=%.20g\n",
cristye8c25f92010-06-03 00:53:06 +00002035 (double) image->scene);
cristy3ed852e2009-09-05 21:47:34 +00002036 (void) WriteBlobString(image,buffer);
2037 }
2038 if (image->iterations != 0)
2039 {
cristyb51dff52011-05-19 16:55:47 +00002040 (void) FormatLocaleString(buffer,MaxTextExtent,"iterations=%.20g\n",
cristye8c25f92010-06-03 00:53:06 +00002041 (double) image->iterations);
cristy3ed852e2009-09-05 21:47:34 +00002042 (void) WriteBlobString(image,buffer);
2043 }
2044 if (image->delay != 0)
2045 {
cristyb51dff52011-05-19 16:55:47 +00002046 (void) FormatLocaleString(buffer,MaxTextExtent,"delay=%.20g\n",
cristye8c25f92010-06-03 00:53:06 +00002047 (double) image->delay);
cristy3ed852e2009-09-05 21:47:34 +00002048 (void) WriteBlobString(image,buffer);
2049 }
2050 if (image->ticks_per_second != UndefinedTicksPerSecond)
2051 {
cristyb51dff52011-05-19 16:55:47 +00002052 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00002053 "ticks-per-second=%.20g\n",(double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002054 (void) WriteBlobString(image,buffer);
2055 }
2056 }
2057 if (image->gravity != UndefinedGravity)
2058 {
cristyb51dff52011-05-19 16:55:47 +00002059 (void) FormatLocaleString(buffer,MaxTextExtent,"gravity=%s\n",
cristy042ee782011-04-22 18:48:30 +00002060 CommandOptionToMnemonic(MagickGravityOptions,image->gravity));
cristy3ed852e2009-09-05 21:47:34 +00002061 (void) WriteBlobString(image,buffer);
2062 }
2063 if (image->dispose != UndefinedDispose)
2064 {
cristyb51dff52011-05-19 16:55:47 +00002065 (void) FormatLocaleString(buffer,MaxTextExtent,"dispose=%s\n",
cristy042ee782011-04-22 18:48:30 +00002066 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
cristy3ed852e2009-09-05 21:47:34 +00002067 (void) WriteBlobString(image,buffer);
2068 }
2069 if (image->rendering_intent != UndefinedIntent)
2070 {
cristy0a30e182011-09-01 01:43:15 +00002071 (void) FormatLocaleString(buffer,MaxTextExtent,"rendering-intent=%s\n",
2072 CommandOptionToMnemonic(MagickIntentOptions,image->rendering_intent));
cristy3ed852e2009-09-05 21:47:34 +00002073 (void) WriteBlobString(image,buffer);
2074 }
2075 if (image->gamma != 0.0)
2076 {
cristyb51dff52011-05-19 16:55:47 +00002077 (void) FormatLocaleString(buffer,MaxTextExtent,"gamma=%g\n",
cristy3ed852e2009-09-05 21:47:34 +00002078 image->gamma);
2079 (void) WriteBlobString(image,buffer);
2080 }
2081 if (image->chromaticity.white_point.x != 0.0)
2082 {
2083 /*
2084 Note chomaticity points.
2085 */
cristyb51dff52011-05-19 16:55:47 +00002086 (void) FormatLocaleString(buffer,MaxTextExtent,"red-primary=%g,"
cristye7f51092010-01-17 00:39:37 +00002087 "%g green-primary=%g,%g blue-primary=%g,%g\n",
cristy3ed852e2009-09-05 21:47:34 +00002088 image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
2089 image->chromaticity.green_primary.x,
2090 image->chromaticity.green_primary.y,
2091 image->chromaticity.blue_primary.x,
2092 image->chromaticity.blue_primary.y);
2093 (void) WriteBlobString(image,buffer);
cristyb51dff52011-05-19 16:55:47 +00002094 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye7f51092010-01-17 00:39:37 +00002095 "white-point=%g,%g\n",image->chromaticity.white_point.x,
cristy8cd5b312010-01-07 01:10:24 +00002096 image->chromaticity.white_point.y);
cristy3ed852e2009-09-05 21:47:34 +00002097 (void) WriteBlobString(image,buffer);
2098 }
2099 if (image->orientation != UndefinedOrientation)
2100 {
cristyb51dff52011-05-19 16:55:47 +00002101 (void) FormatLocaleString(buffer,MaxTextExtent,"orientation=%s\n",
cristy042ee782011-04-22 18:48:30 +00002102 CommandOptionToMnemonic(MagickOrientationOptions,image->orientation));
cristy3ed852e2009-09-05 21:47:34 +00002103 (void) WriteBlobString(image,buffer);
2104 }
2105 if (image->profiles != (void *) NULL)
2106 {
2107 const char
2108 *name;
2109
2110 const StringInfo
2111 *profile;
2112
2113 /*
2114 Write image profiles.
2115 */
2116 ResetImageProfileIterator(image);
2117 name=GetNextImageProfile(image);
2118 while (name != (const char *) NULL)
2119 {
2120 profile=GetImageProfile(image,name);
2121 if (profile != (StringInfo *) NULL)
2122 {
cristyb51dff52011-05-19 16:55:47 +00002123 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00002124 "profile:%s=%.20g\n",name,(double)
2125 GetStringInfoLength(profile));
cristy3ed852e2009-09-05 21:47:34 +00002126 (void) WriteBlobString(image,buffer);
2127 }
2128 name=GetNextImageProfile(image);
2129 }
2130 }
2131 if (image->montage != (char *) NULL)
2132 {
cristyb51dff52011-05-19 16:55:47 +00002133 (void) FormatLocaleString(buffer,MaxTextExtent,"montage=%s\n",
cristy3ed852e2009-09-05 21:47:34 +00002134 image->montage);
2135 (void) WriteBlobString(image,buffer);
2136 }
2137 if (quantum_info->format == FloatingPointQuantumFormat)
cristy0c2fcca2009-10-16 01:37:20 +00002138 (void) SetImageProperty(image,"quantum:format","floating-point");
cristy3ed852e2009-09-05 21:47:34 +00002139 ResetImagePropertyIterator(image);
2140 property=GetNextImageProperty(image);
2141 while (property != (const char *) NULL)
2142 {
cristyb51dff52011-05-19 16:55:47 +00002143 (void) FormatLocaleString(buffer,MaxTextExtent,"%s=",property);
cristy3ed852e2009-09-05 21:47:34 +00002144 (void) WriteBlobString(image,buffer);
2145 value=GetImageProperty(image,property);
2146 if (value != (const char *) NULL)
2147 {
cristybb503372010-05-27 20:51:26 +00002148 for (i=0; i < (ssize_t) strlen(value); i++)
cristy3ed852e2009-09-05 21:47:34 +00002149 if (isspace((int) ((unsigned char) value[i])) != 0)
2150 break;
cristybb503372010-05-27 20:51:26 +00002151 if (i <= (ssize_t) strlen(value))
cristy3ed852e2009-09-05 21:47:34 +00002152 (void) WriteBlobByte(image,'{');
2153 (void) WriteBlob(image,strlen(value),(const unsigned char *) value);
cristybb503372010-05-27 20:51:26 +00002154 if (i <= (ssize_t) strlen(value))
cristy3ed852e2009-09-05 21:47:34 +00002155 (void) WriteBlobByte(image,'}');
2156 }
2157 (void) WriteBlobByte(image,'\n');
2158 property=GetNextImageProperty(image);
2159 }
2160 (void) WriteBlobString(image,"\f\n:\032");
2161 if (image->montage != (char *) NULL)
2162 {
2163 /*
2164 Write montage tile directory.
2165 */
2166 if (image->directory != (char *) NULL)
2167 (void) WriteBlob(image,strlen(image->directory),(unsigned char *)
2168 image->directory);
2169 (void) WriteBlobByte(image,'\0');
2170 }
2171 if (image->profiles != (void *) NULL)
2172 {
2173 const char
2174 *name;
2175
2176 const StringInfo
2177 *profile;
2178
2179 /*
2180 Generic profile.
2181 */
2182 ResetImageProfileIterator(image);
2183 name=GetNextImageProfile(image);
2184 while (name != (const char *) NULL)
2185 {
2186 profile=GetImageProfile(image,name);
2187 (void) WriteBlob(image,GetStringInfoLength(profile),
2188 GetStringInfoDatum(profile));
2189 name=GetNextImageProfile(image);
2190 }
2191 }
2192 if (image->storage_class == PseudoClass)
2193 {
2194 size_t
2195 packet_size;
2196
2197 unsigned char
2198 *colormap,
2199 *q;
2200
2201 /*
2202 Allocate colormap.
2203 */
2204 packet_size=(size_t) (3*quantum_info->depth/8);
2205 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
2206 packet_size*sizeof(*colormap));
2207 if (colormap == (unsigned char *) NULL)
2208 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2209 /*
2210 Write colormap to file.
2211 */
2212 q=colormap;
cristybb503372010-05-27 20:51:26 +00002213 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00002214 {
2215 switch (quantum_info->depth)
2216 {
2217 default:
2218 ThrowWriterException(CorruptImageError,"ImageDepthNotSupported");
2219 case 32:
2220 {
cristy4cb162a2010-05-30 03:04:47 +00002221 register unsigned int
cristy3ed852e2009-09-05 21:47:34 +00002222 pixel;
2223
2224 pixel=ScaleQuantumToLong(image->colormap[i].red);
2225 q=PopLongPixel(MSBEndian,pixel,q);
2226 pixel=ScaleQuantumToLong(image->colormap[i].green);
2227 q=PopLongPixel(MSBEndian,pixel,q);
2228 pixel=ScaleQuantumToLong(image->colormap[i].blue);
2229 q=PopLongPixel(MSBEndian,pixel,q);
2230 break;
2231 }
2232 case 16:
2233 {
2234 register unsigned short
2235 pixel;
2236
2237 pixel=ScaleQuantumToShort(image->colormap[i].red);
2238 q=PopShortPixel(MSBEndian,pixel,q);
2239 pixel=ScaleQuantumToShort(image->colormap[i].green);
2240 q=PopShortPixel(MSBEndian,pixel,q);
2241 pixel=ScaleQuantumToShort(image->colormap[i].blue);
2242 q=PopShortPixel(MSBEndian,pixel,q);
2243 break;
2244 }
2245 case 8:
2246 {
2247 register unsigned char
2248 pixel;
2249
2250 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].red);
2251 q=PopCharPixel(pixel,q);
2252 pixel=(unsigned char) ScaleQuantumToChar(
2253 image->colormap[i].green);
2254 q=PopCharPixel(pixel,q);
2255 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].blue);
2256 q=PopCharPixel(pixel,q);
2257 break;
2258 }
2259 }
2260 }
2261 (void) WriteBlob(image,packet_size*image->colors,colormap);
2262 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
2263 }
2264 /*
2265 Write image pixels to file.
2266 */
cristy330af6c2010-12-21 14:36:06 +00002267 status=MagickTrue;
2268 switch (compression)
2269 {
2270#if defined(MAGICKCORE_BZLIB_DELEGATE)
2271 case BZipCompression:
2272 {
2273 (void) ResetMagickMemory(&bzip_info,0,sizeof(bzip_info));
2274 bzip_info.bzalloc=AcquireBZIPMemory;
2275 bzip_info.bzfree=RelinquishBZIPMemory;
2276 code=BZ2_bzCompressInit(&bzip_info,(int) (image->quality ==
2277 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,
2278 9)),(int) image_info->verbose,0);
2279 if (code != BZ_OK)
2280 status=MagickFalse;
2281 break;
2282 }
2283#endif
2284#if defined(MAGICKCORE_LZMA_DELEGATE)
2285 case LZMACompression:
2286 {
cristy330af6c2010-12-21 14:36:06 +00002287 (void) ResetMagickMemory(&allocator,0,sizeof(allocator));
2288 allocator.alloc=AcquireLZMAMemory;
2289 allocator.free=RelinquishLZMAMemory;
cristy9d72f1a2010-12-21 20:46:59 +00002290 lzma_info=initialize_lzma;
cristy330af6c2010-12-21 14:36:06 +00002291 lzma_info.allocator=&allocator;
cristy9d72f1a2010-12-21 20:46:59 +00002292 code=lzma_easy_encoder(&lzma_info,image->quality/10,LZMA_CHECK_SHA256);
2293 if (code != LZMA_OK)
2294 status=MagickTrue;
cristy330af6c2010-12-21 14:36:06 +00002295 break;
2296 }
2297#endif
2298#if defined(MAGICKCORE_ZLIB_DELEGATE)
2299 case LZWCompression:
2300 case ZipCompression:
2301 {
2302 (void) ResetMagickMemory(&zip_info,0,sizeof(zip_info));
2303 zip_info.zalloc=AcquireZIPMemory;
2304 zip_info.zfree=RelinquishZIPMemory;
2305 code=deflateInit(&zip_info,(int) (image->quality ==
2306 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9)));
2307 if (code != Z_OK)
2308 status=MagickFalse;
2309 break;
2310 }
2311#endif
2312 default:
2313 break;
2314 }
cristy1e178e72011-08-28 19:44:34 +00002315 quantum_type=GetQuantumType(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002316 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002317 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002318 {
cristy4c08aed2011-07-01 19:47:50 +00002319 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00002320 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002321
cristybb503372010-05-27 20:51:26 +00002322 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002323 x;
2324
cristy330af6c2010-12-21 14:36:06 +00002325 if (status == MagickFalse)
2326 break;
cristy1e178e72011-08-28 19:44:34 +00002327 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002328 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002329 break;
cristy3ed852e2009-09-05 21:47:34 +00002330 q=pixels;
2331 switch (compression)
2332 {
cristy3ed852e2009-09-05 21:47:34 +00002333#if defined(MAGICKCORE_BZLIB_DELEGATE)
2334 case BZipCompression:
2335 {
cristy3ed852e2009-09-05 21:47:34 +00002336 bzip_info.next_in=(char *) pixels;
2337 bzip_info.avail_in=(unsigned int) (packet_size*image->columns);
cristy4c08aed2011-07-01 19:47:50 +00002338 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002339 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002340 do
2341 {
2342 bzip_info.next_out=(char *) compress_pixels;
2343 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2344 image->columns);
2345 code=BZ2_bzCompress(&bzip_info,BZ_FLUSH);
cristy26377172010-12-20 19:01:58 +00002346 if (code != BZ_OK)
2347 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00002348 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2349 if (length != 0)
2350 {
2351 (void) WriteBlobMSBLong(image,(unsigned int) length);
2352 (void) WriteBlob(image,length,compress_pixels);
2353 }
2354 } while (bzip_info.avail_in != 0);
cristy26377172010-12-20 19:01:58 +00002355 break;
2356 }
2357#endif
2358#if defined(MAGICKCORE_LZMA_DELEGATE)
2359 case LZMACompression:
2360 {
cristy26377172010-12-20 19:01:58 +00002361 lzma_info.next_in=pixels;
cristy330af6c2010-12-21 14:36:06 +00002362 lzma_info.avail_in=packet_size*image->columns;
cristy4c08aed2011-07-01 19:47:50 +00002363 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002364 quantum_type,pixels,exception);
cristy26377172010-12-20 19:01:58 +00002365 do
2366 {
2367 lzma_info.next_out=compress_pixels;
2368 lzma_info.avail_out=packet_size*image->columns;
2369 code=lzma_code(&lzma_info,LZMA_RUN);
2370 if (code != LZMA_OK)
2371 status=MagickFalse;
2372 length=(size_t) (lzma_info.next_out-compress_pixels);
2373 if (length != 0)
2374 {
2375 (void) WriteBlobMSBLong(image,(unsigned int) length);
2376 (void) WriteBlob(image,length,compress_pixels);
2377 }
2378 } while (lzma_info.avail_in != 0);
cristy26377172010-12-20 19:01:58 +00002379 break;
2380 }
2381#endif
2382#if defined(MAGICKCORE_ZLIB_DELEGATE)
2383 case LZWCompression:
2384 case ZipCompression:
2385 {
cristy26377172010-12-20 19:01:58 +00002386 zip_info.next_in=pixels;
2387 zip_info.avail_in=(uInt) (packet_size*image->columns);
cristy4c08aed2011-07-01 19:47:50 +00002388 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002389 quantum_type,pixels,exception);
cristy26377172010-12-20 19:01:58 +00002390 do
2391 {
2392 zip_info.next_out=compress_pixels;
2393 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns);
2394 code=deflate(&zip_info,Z_SYNC_FLUSH);
2395 if (code != Z_OK)
2396 status=MagickFalse;
2397 length=(size_t) (zip_info.next_out-compress_pixels);
2398 if (length != 0)
2399 {
2400 (void) WriteBlobMSBLong(image,(unsigned int) length);
2401 (void) WriteBlob(image,length,compress_pixels);
2402 }
2403 } while (zip_info.avail_in != 0);
cristy3ed852e2009-09-05 21:47:34 +00002404 break;
2405 }
2406#endif
2407 case RLECompression:
2408 {
cristy4c08aed2011-07-01 19:47:50 +00002409 length=0;
2410 SetPixelInfo(image,p,&pixel);
cristyed231572011-07-14 02:18:59 +00002411 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00002412 for (x=1; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002413 {
cristy4c08aed2011-07-01 19:47:50 +00002414 SetPixelInfo(image,p,&target);
2415 if ((length < 255) &&
2416 (IsPixelInfoEquivalent(&pixel,&target) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00002417 length++;
2418 else
2419 {
cristy4c08aed2011-07-01 19:47:50 +00002420 q=PopRunlengthPacket(image,q,length,&pixel);
cristy3ed852e2009-09-05 21:47:34 +00002421 length=0;
2422 }
cristy4c08aed2011-07-01 19:47:50 +00002423 SetPixelInfo(image,p,&pixel);
cristyed231572011-07-14 02:18:59 +00002424 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002425 }
cristy4c08aed2011-07-01 19:47:50 +00002426 q=PopRunlengthPacket(image,q,length,&pixel);
cristy3ed852e2009-09-05 21:47:34 +00002427 (void) WriteBlob(image,(size_t) (q-pixels),pixels);
2428 break;
2429 }
2430 default:
2431 {
cristy4c08aed2011-07-01 19:47:50 +00002432 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002433 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002434 (void) WriteBlob(image,packet_size*image->columns,pixels);
2435 break;
2436 }
2437 }
cristycee97112010-05-28 00:44:52 +00002438 if (image->previous == (Image *) NULL)
2439 {
2440 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2441 image->rows);
2442 if (status == MagickFalse)
2443 break;
2444 }
cristy3ed852e2009-09-05 21:47:34 +00002445 }
cristy330af6c2010-12-21 14:36:06 +00002446 switch (compression)
2447 {
2448#if defined(MAGICKCORE_BZLIB_DELEGATE)
2449 case BZipCompression:
2450 {
2451 for ( ; ; )
2452 {
2453 if (status == MagickFalse)
2454 break;
2455 bzip_info.next_out=(char *) compress_pixels;
2456 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2457 image->columns);
2458 code=BZ2_bzCompress(&bzip_info,BZ_FINISH);
cristy330af6c2010-12-21 14:36:06 +00002459 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2460 if (length != 0)
2461 {
2462 (void) WriteBlobMSBLong(image,(unsigned int) length);
2463 (void) WriteBlob(image,length,compress_pixels);
2464 }
2465 if (code == BZ_STREAM_END)
2466 break;
2467 }
2468 code=BZ2_bzCompressEnd(&bzip_info);
2469 if (code != BZ_OK)
2470 status=MagickFalse;
2471 break;
2472 }
2473#endif
2474#if defined(MAGICKCORE_LZMA_DELEGATE)
2475 case LZMACompression:
2476 {
2477 for ( ; ; )
2478 {
2479 if (status == MagickFalse)
2480 break;
2481 lzma_info.next_out=compress_pixels;
2482 lzma_info.avail_out=packet_size*image->columns;
2483 code=lzma_code(&lzma_info,LZMA_FINISH);
cristy330af6c2010-12-21 14:36:06 +00002484 length=(size_t) (lzma_info.next_out-compress_pixels);
2485 if (length > 6)
2486 {
2487 (void) WriteBlobMSBLong(image,(unsigned int) length);
2488 (void) WriteBlob(image,length,compress_pixels);
2489 }
2490 if (code == LZMA_STREAM_END)
2491 break;
2492 }
2493 lzma_end(&lzma_info);
2494 break;
2495 }
2496#endif
2497#if defined(MAGICKCORE_ZLIB_DELEGATE)
2498 case LZWCompression:
2499 case ZipCompression:
2500 {
2501 for ( ; ; )
2502 {
2503 if (status == MagickFalse)
2504 break;
2505 zip_info.next_out=compress_pixels;
2506 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*
2507 image->columns);
2508 code=deflate(&zip_info,Z_FINISH);
cristy330af6c2010-12-21 14:36:06 +00002509 length=(size_t) (zip_info.next_out-compress_pixels);
2510 if (length > 6)
2511 {
2512 (void) WriteBlobMSBLong(image,(unsigned int) length);
2513 (void) WriteBlob(image,length,compress_pixels);
2514 }
2515 if (code == Z_STREAM_END)
2516 break;
2517 }
2518 code=deflateEnd(&zip_info);
2519 if (code != Z_OK)
2520 status=MagickFalse;
2521 break;
2522 }
2523#endif
2524 default:
2525 break;
2526 }
cristy3ed852e2009-09-05 21:47:34 +00002527 quantum_info=DestroyQuantumInfo(quantum_info);
2528 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
2529 if (GetNextImageInList(image) == (Image *) NULL)
2530 break;
2531 image=SyncNextImageInList(image);
2532 status=SetImageProgress(image,SaveImagesTag,scene++,
2533 GetImageListLength(image));
2534 if (status == MagickFalse)
2535 break;
2536 } while (image_info->adjoin != MagickFalse);
2537 (void) CloseBlob(image);
2538 return(status);
2539}