blob: e351362402f7c1134f04f628c5b471815a8844dc [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% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 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,
cristyc82a27b2011-10-21 01:07:16 +0000202 size_t *length,PixelInfo *pixel,ExceptionInfo *exception)
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,
cristyc82a27b2011-10-21 01:07:16 +0000216 (*p << 24) | (*(p+1) << 16) | (*(p+2) << 8) | *(p+3),exception);
cristy3ed852e2009-09-05 21:47:34 +0000217 p+=4;
218 break;
219 }
220 case 16:
221 {
cristyc82a27b2011-10-21 01:07:16 +0000222 pixel->index=ConstrainColormapIndex(image,(*p << 8) | *(p+1),
223 exception);
cristy3ed852e2009-09-05 21:47:34 +0000224 p+=2;
225 break;
226 }
227 case 8:
228 {
cristyc82a27b2011-10-21 01:07:16 +0000229 pixel->index=ConstrainColormapIndex(image,*p,exception);
cristy3ed852e2009-09-05 21:47:34 +0000230 p++;
231 break;
232 }
233 default:
cristyc82a27b2011-10-21 01:07:16 +0000234 (void) ThrowMagickException(exception,GetMagickModule(),
cristy3ed852e2009-09-05 21:47:34 +0000235 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
236 }
cristy3ed852e2009-09-05 21:47:34 +0000237 switch (image->depth)
238 {
239 case 8:
240 {
241 unsigned char
242 quantum;
243
244 if (image->matte != MagickFalse)
245 {
246 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000247 pixel->alpha=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000248 }
249 break;
250 }
251 case 16:
252 {
253 unsigned short
254 quantum;
255
256 if (image->matte != MagickFalse)
257 {
258 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000259 pixel->alpha=(Quantum) (quantum >> (image->depth-
cristy3ed852e2009-09-05 21:47:34 +0000260 MAGICKCORE_QUANTUM_DEPTH));
261 }
262 break;
263 }
264 case 32:
265 {
cristy4cb162a2010-05-30 03:04:47 +0000266 unsigned int
cristy3ed852e2009-09-05 21:47:34 +0000267 quantum;
268
269 if (image->matte != MagickFalse)
270 {
271 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000272 pixel->alpha=(Quantum) (quantum >> (image->depth-
cristy3ed852e2009-09-05 21:47:34 +0000273 MAGICKCORE_QUANTUM_DEPTH));
274 }
275 break;
276 }
277 default:
cristyc82a27b2011-10-21 01:07:16 +0000278 (void) ThrowMagickException(exception,GetMagickModule(),
cristy3ed852e2009-09-05 21:47:34 +0000279 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
280 }
281 *length=(size_t) (*p++)+1;
282 return;
283 }
284 switch (image->depth)
285 {
286 case 8:
287 {
288 unsigned char
289 quantum;
290
291 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000292 pixel->red=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000293 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000294 pixel->green=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000295 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000296 pixel->blue=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000297 if (image->colorspace == CMYKColorspace)
298 {
299 p=PushCharPixel(p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000300 pixel->black=ScaleCharToQuantum(quantum);
301 }
302 if (image->matte != MagickFalse)
303 {
304 p=PushCharPixel(p,&quantum);
305 pixel->alpha=ScaleCharToQuantum(quantum);
cristy3ed852e2009-09-05 21:47:34 +0000306 }
307 break;
308 }
309 case 16:
310 {
311 unsigned short
312 quantum;
313
314 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000315 pixel->red=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000316 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000317 pixel->green=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristyfbbafc92011-05-05 01:22:11 +0000318 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000319 pixel->blue=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000320 if (image->colorspace == CMYKColorspace)
321 {
322 p=PushShortPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000323 pixel->black=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
324 }
325 if (image->matte != MagickFalse)
326 {
327 p=PushShortPixel(MSBEndian,p,&quantum);
328 pixel->alpha=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000329 }
330 break;
331 }
332 case 32:
333 {
cristy4cb162a2010-05-30 03:04:47 +0000334 unsigned int
cristy3ed852e2009-09-05 21:47:34 +0000335 quantum;
336
337 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000338 pixel->red=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000339 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000340 pixel->green=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristyfbbafc92011-05-05 01:22:11 +0000341 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000342 pixel->blue=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000343 if (image->colorspace == CMYKColorspace)
344 {
345 p=PushLongPixel(MSBEndian,p,&quantum);
cristy4c08aed2011-07-01 19:47:50 +0000346 pixel->black=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
347 }
348 if (image->matte != MagickFalse)
349 {
350 p=PushLongPixel(MSBEndian,p,&quantum);
351 pixel->alpha=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
cristy3ed852e2009-09-05 21:47:34 +0000352 }
353 break;
354 }
355 default:
cristyc82a27b2011-10-21 01:07:16 +0000356 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
357 "ImageDepthNotSupported","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +0000358 }
359 *length=(size_t) (*p++)+1;
360}
361
cristy4b46dba2010-12-20 19:18:20 +0000362#if defined(MAGICKCORE_BZLIB_DELEGATE)
363static void RelinquishBZIPMemory(void *context,void *memory)
cristy3ed852e2009-09-05 21:47:34 +0000364{
365 (void) context;
366 memory=RelinquishMagickMemory(memory);
367}
368#endif
369
cristy4b46dba2010-12-20 19:18:20 +0000370#if defined(MAGICKCORE_LZMA_DELEGATE)
371static void RelinquishLZMAMemory(void *context,void *memory)
372{
373 (void) context;
374 memory=RelinquishMagickMemory(memory);
375}
376#endif
377
378#if defined(MAGICKCORE_ZLIB_DELEGATE)
379static void RelinquishZIPMemory(voidpf context,voidpf memory)
cristy3ed852e2009-09-05 21:47:34 +0000380{
381 (void) context;
382 memory=RelinquishMagickMemory(memory);
383}
384#endif
385
386static Image *ReadMIFFImage(const ImageInfo *image_info,
387 ExceptionInfo *exception)
388{
389#define BZipMaxExtent(x) ((x)+((x)/100)+600)
cristy26377172010-12-20 19:01:58 +0000390#define LZMAMaxExtent(x) ((x)+((x)/3)+128)
cristy3ed852e2009-09-05 21:47:34 +0000391#define ZipMaxExtent(x) ((x)+(((x)+7) >> 3)+(((x)+63) >> 6)+11)
392
393#if defined(MAGICKCORE_BZLIB_DELEGATE)
394 bz_stream
395 bzip_info;
396#endif
397
398 char
399 id[MaxTextExtent],
400 keyword[MaxTextExtent],
401 *options;
402
403 const unsigned char
404 *p;
405
406 double
407 version;
408
409 GeometryInfo
410 geometry_info;
411
412 Image
413 *image;
414
cristy3ed852e2009-09-05 21:47:34 +0000415 int
cristy3a99dcf2011-12-17 01:29:40 +0000416 c;
cristy3ed852e2009-09-05 21:47:34 +0000417
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");
cristy3ed852e2009-09-05 21:47:34 +0000496 *id='\0';
497 (void) ResetMagickMemory(keyword,0,sizeof(keyword));
498 version=0.0;
499 do
500 {
501 /*
502 Decode image header; header terminates one character beyond a ':'.
503 */
504 length=MaxTextExtent;
505 options=AcquireString((char *) NULL);
506 quantum_format=UndefinedQuantumFormat;
507 profiles=(LinkedListInfo *) NULL;
508 colors=0;
509 image->depth=8UL;
510 image->compression=NoCompression;
511 while ((isgraph(c) != MagickFalse) && (c != (int) ':'))
512 {
513 register char
514 *p;
515
516 if (c == (int) '{')
517 {
518 char
519 *comment;
520
521 /*
522 Read comment-- any text between { }.
523 */
524 length=MaxTextExtent;
525 comment=AcquireString((char *) NULL);
526 for (p=comment; comment != (char *) NULL; p++)
527 {
528 c=ReadBlobByte(image);
529 if ((c == EOF) || (c == (int) '}'))
530 break;
531 if ((size_t) (p-comment+1) >= length)
532 {
533 *p='\0';
534 length<<=1;
535 comment=(char *) ResizeQuantumMemory(comment,length+
536 MaxTextExtent,sizeof(*comment));
537 if (comment == (char *) NULL)
538 break;
539 p=comment+strlen(comment);
540 }
541 *p=(char) c;
542 }
543 if (comment == (char *) NULL)
544 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
545 *p='\0';
cristyd15e6592011-10-15 00:13:06 +0000546 (void) SetImageProperty(image,"comment",comment,exception);
cristy3ed852e2009-09-05 21:47:34 +0000547 comment=DestroyString(comment);
548 c=ReadBlobByte(image);
549 }
550 else
551 if (isalnum(c) != MagickFalse)
552 {
553 /*
554 Get the keyword.
555 */
556 p=keyword;
557 do
558 {
cristy3ed852e2009-09-05 21:47:34 +0000559 if (c == (int) '=')
560 break;
561 if ((size_t) (p-keyword) < (MaxTextExtent-1))
562 *p++=(char) c;
563 c=ReadBlobByte(image);
564 } while (c != EOF);
565 *p='\0';
566 p=options;
cristy93505cf2010-08-10 21:37:49 +0000567 while ((isspace((int) ((unsigned char) c)) != 0) && (c != EOF))
cristy3ed852e2009-09-05 21:47:34 +0000568 c=ReadBlobByte(image);
569 if (c == (int) '=')
570 {
571 /*
572 Get the keyword value.
573 */
574 c=ReadBlobByte(image);
575 while ((c != (int) '}') && (c != EOF))
576 {
577 if ((size_t) (p-options+1) >= length)
578 {
579 *p='\0';
580 length<<=1;
581 options=(char *) ResizeQuantumMemory(options,length+
582 MaxTextExtent,sizeof(*options));
583 if (options == (char *) NULL)
584 break;
585 p=options+strlen(options);
586 }
587 if (options == (char *) NULL)
588 ThrowReaderException(ResourceLimitError,
589 "MemoryAllocationFailed");
590 *p++=(char) c;
591 c=ReadBlobByte(image);
592 if (*options != '{')
593 if (isspace((int) ((unsigned char) c)) != 0)
594 break;
595 }
596 }
597 *p='\0';
598 if (*options == '{')
599 (void) CopyMagickString(options,options+1,MaxTextExtent);
600 /*
601 Assign a value to the specified keyword.
602 */
603 switch (*keyword)
604 {
605 case 'b':
606 case 'B':
607 {
608 if (LocaleCompare(keyword,"background-color") == 0)
609 {
cristy9950d572011-10-01 18:22:35 +0000610 (void) QueryColorCompliance(options,AllCompliance,
611 &image->background_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000612 break;
613 }
614 if (LocaleCompare(keyword,"blue-primary") == 0)
615 {
616 flags=ParseGeometry(options,&geometry_info);
617 image->chromaticity.blue_primary.x=geometry_info.rho;
618 image->chromaticity.blue_primary.y=geometry_info.sigma;
619 if ((flags & SigmaValue) == 0)
620 image->chromaticity.blue_primary.y=
621 image->chromaticity.blue_primary.x;
622 break;
623 }
624 if (LocaleCompare(keyword,"border-color") == 0)
625 {
cristy9950d572011-10-01 18:22:35 +0000626 (void) QueryColorCompliance(options,AllCompliance,
627 &image->border_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000628 break;
629 }
cristyd15e6592011-10-15 00:13:06 +0000630 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000631 break;
632 }
633 case 'c':
634 case 'C':
635 {
636 if (LocaleCompare(keyword,"class") == 0)
637 {
cristybb503372010-05-27 20:51:26 +0000638 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000639 storage_class;
640
cristy042ee782011-04-22 18:48:30 +0000641 storage_class=ParseCommandOption(MagickClassOptions,
cristy3ed852e2009-09-05 21:47:34 +0000642 MagickFalse,options);
643 if (storage_class < 0)
644 break;
645 image->storage_class=(ClassType) storage_class;
646 break;
647 }
648 if (LocaleCompare(keyword,"colors") == 0)
649 {
cristye27293e2009-12-18 02:53:20 +0000650 colors=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000651 break;
652 }
653 if (LocaleCompare(keyword,"colorspace") == 0)
654 {
cristybb503372010-05-27 20:51:26 +0000655 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000656 colorspace;
657
cristy042ee782011-04-22 18:48:30 +0000658 colorspace=ParseCommandOption(MagickColorspaceOptions,
cristy3ed852e2009-09-05 21:47:34 +0000659 MagickFalse,options);
660 if (colorspace < 0)
661 break;
662 image->colorspace=(ColorspaceType) colorspace;
663 break;
664 }
665 if (LocaleCompare(keyword,"compression") == 0)
666 {
cristybb503372010-05-27 20:51:26 +0000667 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000668 compression;
669
cristy042ee782011-04-22 18:48:30 +0000670 compression=ParseCommandOption(MagickCompressOptions,
cristy3ed852e2009-09-05 21:47:34 +0000671 MagickFalse,options);
672 if (compression < 0)
673 break;
674 image->compression=(CompressionType) compression;
675 break;
676 }
677 if (LocaleCompare(keyword,"columns") == 0)
678 {
cristye27293e2009-12-18 02:53:20 +0000679 image->columns=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000680 break;
681 }
cristyd15e6592011-10-15 00:13:06 +0000682 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000683 break;
684 }
685 case 'd':
686 case 'D':
687 {
688 if (LocaleCompare(keyword,"delay") == 0)
689 {
cristye27293e2009-12-18 02:53:20 +0000690 image->delay=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000691 break;
692 }
693 if (LocaleCompare(keyword,"depth") == 0)
694 {
cristye27293e2009-12-18 02:53:20 +0000695 image->depth=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000696 break;
697 }
698 if (LocaleCompare(keyword,"dispose") == 0)
699 {
cristybb503372010-05-27 20:51:26 +0000700 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000701 dispose;
702
cristy042ee782011-04-22 18:48:30 +0000703 dispose=ParseCommandOption(MagickDisposeOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000704 options);
705 if (dispose < 0)
706 break;
707 image->dispose=(DisposeType) dispose;
708 break;
709 }
cristyd15e6592011-10-15 00:13:06 +0000710 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000711 break;
712 }
713 case 'e':
714 case 'E':
715 {
716 if (LocaleCompare(keyword,"endian") == 0)
717 {
cristybb503372010-05-27 20:51:26 +0000718 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000719 endian;
720
cristy042ee782011-04-22 18:48:30 +0000721 endian=ParseCommandOption(MagickEndianOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000722 options);
723 if (endian < 0)
724 break;
725 image->endian=(EndianType) endian;
726 break;
727 }
cristyd15e6592011-10-15 00:13:06 +0000728 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000729 break;
730 }
731 case 'g':
732 case 'G':
733 {
734 if (LocaleCompare(keyword,"gamma") == 0)
735 {
cristydbdd0e32011-11-04 23:29:40 +0000736 image->gamma=StringToDouble(options,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000737 break;
738 }
739 if (LocaleCompare(keyword,"gravity") == 0)
740 {
cristybb503372010-05-27 20:51:26 +0000741 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000742 gravity;
743
cristy042ee782011-04-22 18:48:30 +0000744 gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000745 options);
746 if (gravity < 0)
747 break;
748 image->gravity=(GravityType) gravity;
749 break;
750 }
751 if (LocaleCompare(keyword,"green-primary") == 0)
752 {
753 flags=ParseGeometry(options,&geometry_info);
754 image->chromaticity.green_primary.x=geometry_info.rho;
755 image->chromaticity.green_primary.y=geometry_info.sigma;
756 if ((flags & SigmaValue) == 0)
757 image->chromaticity.green_primary.y=
758 image->chromaticity.green_primary.x;
759 break;
760 }
cristyd15e6592011-10-15 00:13:06 +0000761 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000762 break;
763 }
764 case 'i':
765 case 'I':
766 {
767 if (LocaleCompare(keyword,"id") == 0)
768 {
769 (void) CopyMagickString(id,options,MaxTextExtent);
770 break;
771 }
772 if (LocaleCompare(keyword,"iterations") == 0)
773 {
cristye27293e2009-12-18 02:53:20 +0000774 image->iterations=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000775 break;
776 }
cristyd15e6592011-10-15 00:13:06 +0000777 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000778 break;
779 }
780 case 'm':
781 case 'M':
782 {
783 if (LocaleCompare(keyword,"matte") == 0)
784 {
cristybb503372010-05-27 20:51:26 +0000785 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000786 matte;
787
cristy042ee782011-04-22 18:48:30 +0000788 matte=ParseCommandOption(MagickBooleanOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000789 options);
790 if (matte < 0)
791 break;
792 image->matte=(MagickBooleanType) matte;
793 break;
794 }
795 if (LocaleCompare(keyword,"matte-color") == 0)
796 {
cristy9950d572011-10-01 18:22:35 +0000797 (void) QueryColorCompliance(options,AllCompliance,
798 &image->matte_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000799 break;
800 }
801 if (LocaleCompare(keyword,"montage") == 0)
802 {
803 (void) CloneString(&image->montage,options);
804 break;
805 }
cristyd15e6592011-10-15 00:13:06 +0000806 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000807 break;
808 }
809 case 'o':
810 case 'O':
811 {
812 if (LocaleCompare(keyword,"opaque") == 0)
813 {
cristybb503372010-05-27 20:51:26 +0000814 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000815 matte;
816
cristy042ee782011-04-22 18:48:30 +0000817 matte=ParseCommandOption(MagickBooleanOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000818 options);
819 if (matte < 0)
820 break;
821 image->matte=(MagickBooleanType) matte;
822 break;
823 }
824 if (LocaleCompare(keyword,"orientation") == 0)
825 {
cristybb503372010-05-27 20:51:26 +0000826 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000827 orientation;
828
cristy042ee782011-04-22 18:48:30 +0000829 orientation=ParseCommandOption(MagickOrientationOptions,
cristy3ed852e2009-09-05 21:47:34 +0000830 MagickFalse,options);
831 if (orientation < 0)
832 break;
833 image->orientation=(OrientationType) orientation;
834 break;
835 }
cristyd15e6592011-10-15 00:13:06 +0000836 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000837 break;
838 }
839 case 'p':
840 case 'P':
841 {
842 if (LocaleCompare(keyword,"page") == 0)
843 {
844 char
845 *geometry;
846
847 geometry=GetPageGeometry(options);
848 (void) ParseAbsoluteGeometry(geometry,&image->page);
849 geometry=DestroyString(geometry);
850 break;
851 }
852 if ((LocaleNCompare(keyword,"profile:",8) == 0) ||
853 (LocaleNCompare(keyword,"profile-",8) == 0))
854 {
855 StringInfo
856 *profile;
857
858 if (profiles == (LinkedListInfo *) NULL)
859 profiles=NewLinkedList(0);
860 (void) AppendValueToLinkedList(profiles,
861 AcquireString(keyword+8));
cristy63f9b8e2011-09-01 13:40:50 +0000862 profile=BlobToStringInfo((const void *) NULL,(size_t)
863 StringToLong(options));
cristy49f5e9f2011-09-01 13:44:57 +0000864 if (profile == (StringInfo *) NULL)
cristy63f9b8e2011-09-01 13:40:50 +0000865 ThrowReaderException(ResourceLimitError,
866 "MemoryAllocationFailed");
cristyd15e6592011-10-15 00:13:06 +0000867 (void) SetImageProfile(image,keyword+8,profile,exception);
cristy3ed852e2009-09-05 21:47:34 +0000868 profile=DestroyStringInfo(profile);
869 break;
870 }
cristyd15e6592011-10-15 00:13:06 +0000871 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000872 break;
873 }
874 case 'q':
875 case 'Q':
876 {
877 if (LocaleCompare(keyword,"quality") == 0)
878 {
cristye27293e2009-12-18 02:53:20 +0000879 image->quality=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000880 break;
881 }
882 if ((LocaleCompare(keyword,"quantum-format") == 0) ||
883 (LocaleCompare(keyword,"quantum:format") == 0))
884 {
cristybb503372010-05-27 20:51:26 +0000885 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000886 format;
887
cristy042ee782011-04-22 18:48:30 +0000888 format=ParseCommandOption(MagickQuantumFormatOptions,
cristy3ed852e2009-09-05 21:47:34 +0000889 MagickFalse,options);
890 if (format < 0)
891 break;
892 quantum_format=(QuantumFormatType) format;
893 break;
894 }
cristyd15e6592011-10-15 00:13:06 +0000895 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000896 break;
897 }
898 case 'r':
899 case 'R':
900 {
901 if (LocaleCompare(keyword,"red-primary") == 0)
902 {
903 flags=ParseGeometry(options,&geometry_info);
904 image->chromaticity.red_primary.x=geometry_info.rho;
905 image->chromaticity.red_primary.y=geometry_info.sigma;
906 if ((flags & SigmaValue) == 0)
907 image->chromaticity.red_primary.y=
908 image->chromaticity.red_primary.x;
909 break;
910 }
911 if (LocaleCompare(keyword,"rendering-intent") == 0)
912 {
cristybb503372010-05-27 20:51:26 +0000913 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000914 rendering_intent;
915
cristy042ee782011-04-22 18:48:30 +0000916 rendering_intent=ParseCommandOption(MagickIntentOptions,
cristy3ed852e2009-09-05 21:47:34 +0000917 MagickFalse,options);
918 if (rendering_intent < 0)
919 break;
920 image->rendering_intent=(RenderingIntent) rendering_intent;
921 break;
922 }
923 if (LocaleCompare(keyword,"resolution") == 0)
924 {
925 flags=ParseGeometry(options,&geometry_info);
cristy2a11bef2011-10-28 18:33:11 +0000926 image->resolution.x=geometry_info.rho;
927 image->resolution.y=geometry_info.sigma;
cristy3ed852e2009-09-05 21:47:34 +0000928 if ((flags & SigmaValue) == 0)
cristy2a11bef2011-10-28 18:33:11 +0000929 image->resolution.y=image->resolution.x;
cristy3ed852e2009-09-05 21:47:34 +0000930 break;
931 }
932 if (LocaleCompare(keyword,"rows") == 0)
933 {
cristye27293e2009-12-18 02:53:20 +0000934 image->rows=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000935 break;
936 }
cristyd15e6592011-10-15 00:13:06 +0000937 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000938 break;
939 }
940 case 's':
941 case 'S':
942 {
943 if (LocaleCompare(keyword,"scene") == 0)
944 {
cristye27293e2009-12-18 02:53:20 +0000945 image->scene=StringToUnsignedLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000946 break;
947 }
cristyd15e6592011-10-15 00:13:06 +0000948 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000949 break;
950 }
951 case 't':
952 case 'T':
953 {
954 if (LocaleCompare(keyword,"ticks-per-second") == 0)
955 {
cristy15893a42010-11-20 18:57:15 +0000956 image->ticks_per_second=(ssize_t) StringToLong(options);
cristy3ed852e2009-09-05 21:47:34 +0000957 break;
958 }
959 if (LocaleCompare(keyword,"tile-offset") == 0)
960 {
961 char
962 *geometry;
963
964 geometry=GetPageGeometry(options);
965 (void) ParseAbsoluteGeometry(geometry,&image->tile_offset);
966 geometry=DestroyString(geometry);
967 break;
968 }
969 if (LocaleCompare(keyword,"type") == 0)
970 {
cristybb503372010-05-27 20:51:26 +0000971 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000972 type;
973
cristy042ee782011-04-22 18:48:30 +0000974 type=ParseCommandOption(MagickTypeOptions,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000975 options);
976 if (type < 0)
977 break;
978 image->type=(ImageType) type;
979 break;
980 }
cristyd15e6592011-10-15 00:13:06 +0000981 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +0000982 break;
983 }
984 case 'u':
985 case 'U':
986 {
987 if (LocaleCompare(keyword,"units") == 0)
988 {
cristybb503372010-05-27 20:51:26 +0000989 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000990 units;
991
cristyfbbafc92011-05-05 01:22:11 +0000992 units=ParseCommandOption(MagickResolutionOptions,
993 MagickFalse,options);
cristy3ed852e2009-09-05 21:47:34 +0000994 if (units < 0)
995 break;
996 image->units=(ResolutionType) units;
997 break;
998 }
cristyd15e6592011-10-15 00:13:06 +0000999 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +00001000 break;
1001 }
1002 case 'v':
1003 case 'V':
1004 {
1005 if (LocaleCompare(keyword,"version") == 0)
1006 {
cristydbdd0e32011-11-04 23:29:40 +00001007 version=StringToDouble(options,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +00001008 break;
1009 }
cristyd15e6592011-10-15 00:13:06 +00001010 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +00001011 break;
1012 }
1013 case 'w':
1014 case 'W':
1015 {
1016 if (LocaleCompare(keyword,"white-point") == 0)
1017 {
1018 flags=ParseGeometry(options,&geometry_info);
1019 image->chromaticity.white_point.x=geometry_info.rho;
1020 image->chromaticity.white_point.y=geometry_info.rho;
1021 if ((flags & SigmaValue) != 0)
1022 image->chromaticity.white_point.y=
1023 image->chromaticity.white_point.x;
1024 break;
1025 }
cristyd15e6592011-10-15 00:13:06 +00001026 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +00001027 break;
1028 }
1029 default:
1030 {
cristyd15e6592011-10-15 00:13:06 +00001031 (void) SetImageProperty(image,keyword,options,exception);
cristy3ed852e2009-09-05 21:47:34 +00001032 break;
1033 }
1034 }
1035 }
1036 else
1037 c=ReadBlobByte(image);
1038 while (isspace((int) ((unsigned char) c)) != 0)
1039 c=ReadBlobByte(image);
1040 }
1041 options=DestroyString(options);
1042 (void) ReadBlobByte(image);
1043 /*
1044 Verify that required image information is defined.
1045 */
1046 if ((LocaleCompare(id,"ImageMagick") != 0) ||
1047 (image->storage_class == UndefinedClass) ||
1048 (image->columns == 0) || (image->rows == 0))
1049 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1050 if (image->montage != (char *) NULL)
1051 {
1052 register char
1053 *p;
1054
1055 /*
1056 Image directory.
1057 */
1058 length=MaxTextExtent;
1059 image->directory=AcquireString((char *) NULL);
1060 p=image->directory;
1061 do
1062 {
1063 *p='\0';
1064 if ((strlen(image->directory)+MaxTextExtent) >= length)
1065 {
1066 /*
1067 Allocate more memory for the image directory.
1068 */
1069 length<<=1;
1070 image->directory=(char *) ResizeQuantumMemory(image->directory,
1071 length+MaxTextExtent,sizeof(*image->directory));
1072 if (image->directory == (char *) NULL)
1073 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1074 p=image->directory+strlen(image->directory);
1075 }
1076 c=ReadBlobByte(image);
1077 *p++=(char) c;
1078 } while (c != (int) '\0');
1079 }
1080 if (profiles != (LinkedListInfo *) NULL)
1081 {
1082 const char
1083 *name;
1084
1085 const StringInfo
1086 *profile;
1087
1088 /*
1089 Read image profiles.
1090 */
1091 ResetLinkedListIterator(profiles);
1092 name=(const char *) GetNextValueInLinkedList(profiles);
1093 while (name != (const char *) NULL)
1094 {
1095 profile=GetImageProfile(image,name);
1096 if (profile != (StringInfo *) NULL)
1097 {
1098 register unsigned char
1099 *p;
1100
1101 p=GetStringInfoDatum(profile);
1102 count=ReadBlob(image,GetStringInfoLength(profile),p);
cristyda16f162011-02-19 23:52:17 +00001103 (void) count;
cristy3ed852e2009-09-05 21:47:34 +00001104 }
1105 name=(const char *) GetNextValueInLinkedList(profiles);
1106 }
1107 profiles=DestroyLinkedList(profiles,RelinquishMagickMemory);
1108 }
1109 image->depth=GetImageQuantumDepth(image,MagickFalse);
1110 if (image->storage_class == PseudoClass)
1111 {
1112 /*
1113 Create image colormap.
1114 */
cristy018f07f2011-09-04 21:15:19 +00001115 status=AcquireImageColormap(image,colors != 0 ? colors : 256,exception);
cristy3ed852e2009-09-05 21:47:34 +00001116 if (status == MagickFalse)
1117 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1118 if (colors != 0)
1119 {
1120 size_t
1121 packet_size;
1122
1123 unsigned char
1124 *colormap;
1125
1126 /*
1127 Read image colormap from file.
1128 */
1129 packet_size=(size_t) (3UL*image->depth/8UL);
1130 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
1131 packet_size*sizeof(*colormap));
1132 if (colormap == (unsigned char *) NULL)
1133 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1134 count=ReadBlob(image,packet_size*image->colors,colormap);
1135 p=colormap;
1136 switch (image->depth)
1137 {
1138 default:
1139 ThrowReaderException(CorruptImageError,
1140 "ImageDepthNotSupported");
1141 case 8:
1142 {
1143 unsigned char
1144 pixel;
1145
cristybb503372010-05-27 20:51:26 +00001146 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001147 {
1148 p=PushCharPixel(p,&pixel);
1149 image->colormap[i].red=ScaleCharToQuantum(pixel);
1150 p=PushCharPixel(p,&pixel);
1151 image->colormap[i].green=ScaleCharToQuantum(pixel);
1152 p=PushCharPixel(p,&pixel);
1153 image->colormap[i].blue=ScaleCharToQuantum(pixel);
1154 }
1155 break;
1156 }
1157 case 16:
1158 {
1159 unsigned short
1160 pixel;
1161
cristybb503372010-05-27 20:51:26 +00001162 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001163 {
1164 p=PushShortPixel(MSBEndian,p,&pixel);
1165 image->colormap[i].red=ScaleShortToQuantum(pixel);
1166 p=PushShortPixel(MSBEndian,p,&pixel);
1167 image->colormap[i].green=ScaleShortToQuantum(pixel);
1168 p=PushShortPixel(MSBEndian,p,&pixel);
1169 image->colormap[i].blue=ScaleShortToQuantum(pixel);
1170 }
1171 break;
1172 }
1173 case 32:
1174 {
cristy4cb162a2010-05-30 03:04:47 +00001175 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001176 pixel;
1177
cristybb503372010-05-27 20:51:26 +00001178 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00001179 {
1180 p=PushLongPixel(MSBEndian,p,&pixel);
1181 image->colormap[i].red=ScaleLongToQuantum(pixel);
1182 p=PushLongPixel(MSBEndian,p,&pixel);
1183 image->colormap[i].green=ScaleLongToQuantum(pixel);
1184 p=PushLongPixel(MSBEndian,p,&pixel);
1185 image->colormap[i].blue=ScaleLongToQuantum(pixel);
1186 }
1187 break;
1188 }
1189 }
1190 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
1191 }
1192 }
1193 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1194 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1195 break;
1196 /*
1197 Allocate image pixels.
1198 */
1199 quantum_info=AcquireQuantumInfo(image_info,image);
1200 if (quantum_info == (QuantumInfo *) NULL)
1201 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1202 if (quantum_format != UndefinedQuantumFormat)
1203 {
1204 status=SetQuantumFormat(image,quantum_info,quantum_format);
1205 if (status == MagickFalse)
1206 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1207 }
1208 packet_size=(size_t) (quantum_info->depth/8);
1209 if (image->storage_class == DirectClass)
1210 packet_size=(size_t) (3*quantum_info->depth/8);
cristyc4a6f8a2011-09-21 22:36:11 +00001211 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
1212 (image->type == GrayscaleMatteType))
cristy0a30e182011-09-01 01:43:15 +00001213 packet_size=quantum_info->depth/8;
cristy3ed852e2009-09-05 21:47:34 +00001214 if (image->matte != MagickFalse)
1215 packet_size+=quantum_info->depth/8;
1216 if (image->colorspace == CMYKColorspace)
1217 packet_size+=quantum_info->depth/8;
1218 if (image->compression == RLECompression)
1219 packet_size++;
1220 length=image->columns;
cristy26377172010-12-20 19:01:58 +00001221 length=MagickMax(MagickMax(BZipMaxExtent(packet_size*image->columns),
1222 LZMAMaxExtent(packet_size*image->columns)),ZipMaxExtent(packet_size*
1223 image->columns));
cristy3ed852e2009-09-05 21:47:34 +00001224 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
1225 sizeof(*compress_pixels));
1226 if (compress_pixels == (unsigned char *) NULL)
1227 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1228 /*
1229 Read image pixels.
1230 */
1231 quantum_type=RGBQuantum;
1232 if (image->matte != MagickFalse)
1233 quantum_type=RGBAQuantum;
1234 if (image->colorspace == CMYKColorspace)
1235 {
1236 quantum_type=CMYKQuantum;
1237 if (image->matte != MagickFalse)
1238 quantum_type=CMYKAQuantum;
1239 }
1240 if (image->storage_class == PseudoClass)
1241 {
1242 quantum_type=IndexQuantum;
1243 if (image->matte != MagickFalse)
1244 quantum_type=IndexAlphaQuantum;
1245 }
cristyc4a6f8a2011-09-21 22:36:11 +00001246 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
1247 (image->type == GrayscaleMatteType))
cristy3ed852e2009-09-05 21:47:34 +00001248 {
1249 quantum_type=GrayQuantum;
1250 if (image->matte != MagickFalse)
1251 quantum_type=GrayAlphaQuantum;
1252 }
cristy330af6c2010-12-21 14:36:06 +00001253 status=MagickTrue;
1254 switch (image->compression)
1255 {
1256#if defined(MAGICKCORE_BZLIB_DELEGATE)
1257 case BZipCompression:
1258 {
cristy3a99dcf2011-12-17 01:29:40 +00001259 int
1260 code;
1261
cristy330af6c2010-12-21 14:36:06 +00001262 (void) ResetMagickMemory(&bzip_info,0,sizeof(bzip_info));
1263 bzip_info.bzalloc=AcquireBZIPMemory;
1264 bzip_info.bzfree=RelinquishBZIPMemory;
1265 bzip_info.opaque=(void *) NULL;
1266 code=BZ2_bzDecompressInit(&bzip_info,(int) image_info->verbose,
1267 MagickFalse);
1268 if (code != BZ_OK)
1269 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001270 break;
1271 }
1272#endif
1273#if defined(MAGICKCORE_LZMA_DELEGATE)
1274 case LZMACompression:
1275 {
cristy3a99dcf2011-12-17 01:29:40 +00001276 int
1277 code;
1278
cristy9d72f1a2010-12-21 20:46:59 +00001279 (void) ResetMagickMemory(&allocator,0,sizeof(allocator));
1280 allocator.alloc=AcquireLZMAMemory;
1281 allocator.free=RelinquishLZMAMemory;
cristy330af6c2010-12-21 14:36:06 +00001282 lzma_info=initialize_lzma;
cristy9d72f1a2010-12-21 20:46:59 +00001283 lzma_info.allocator=(&allocator);
cristy330af6c2010-12-21 14:36:06 +00001284 code=lzma_auto_decoder(&lzma_info,-1,0);
1285 if (code != LZMA_OK)
1286 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001287 break;
1288 }
1289#endif
1290#if defined(MAGICKCORE_ZLIB_DELEGATE)
1291 case LZWCompression:
1292 case ZipCompression:
1293 {
cristy3a99dcf2011-12-17 01:29:40 +00001294 int
1295 code;
1296
cristy330af6c2010-12-21 14:36:06 +00001297 (void) ResetMagickMemory(&zip_info,0,sizeof(zip_info));
1298 zip_info.zalloc=AcquireZIPMemory;
1299 zip_info.zfree=RelinquishZIPMemory;
1300 zip_info.opaque=(voidpf) NULL;
1301 code=inflateInit(&zip_info);
1302 if (code != Z_OK)
1303 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001304 break;
1305 }
1306#endif
1307 case RLECompression:
1308 {
cristy4c08aed2011-07-01 19:47:50 +00001309 GetPixelInfo(image,&pixel);
cristy330af6c2010-12-21 14:36:06 +00001310 break;
1311 }
1312 default:
1313 break;
1314 }
cristy3ed852e2009-09-05 21:47:34 +00001315 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001316 length=0;
cristybb503372010-05-27 20:51:26 +00001317 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001318 {
cristybb503372010-05-27 20:51:26 +00001319 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001320 x;
1321
cristy4c08aed2011-07-01 19:47:50 +00001322 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00001323 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001324
cristy330af6c2010-12-21 14:36:06 +00001325 if (status == MagickFalse)
1326 break;
cristy3ed852e2009-09-05 21:47:34 +00001327 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00001328 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001329 break;
cristy3ed852e2009-09-05 21:47:34 +00001330 switch (image->compression)
1331 {
cristy3ed852e2009-09-05 21:47:34 +00001332#if defined(MAGICKCORE_BZLIB_DELEGATE)
1333 case BZipCompression:
1334 {
cristy3ed852e2009-09-05 21:47:34 +00001335 bzip_info.next_out=(char *) pixels;
1336 bzip_info.avail_out=(unsigned int) (packet_size*image->columns);
1337 do
1338 {
1339 if (bzip_info.avail_in == 0)
1340 {
1341 bzip_info.next_in=(char *) compress_pixels;
1342 length=(size_t) BZipMaxExtent(packet_size*image->columns);
1343 if (version != 0)
1344 length=(size_t) ReadBlobMSBLong(image);
1345 bzip_info.avail_in=(unsigned int) ReadBlob(image,length,
1346 (unsigned char *) bzip_info.next_in);
1347 }
1348 if (BZ2_bzDecompress(&bzip_info) == BZ_STREAM_END)
1349 break;
1350 } while (bzip_info.avail_out != 0);
cristy26377172010-12-20 19:01:58 +00001351 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1352 quantum_type,pixels,exception);
1353 break;
1354 }
1355#endif
1356#if defined(MAGICKCORE_LZMA_DELEGATE)
1357 case LZMACompression:
1358 {
cristy26377172010-12-20 19:01:58 +00001359 lzma_info.next_out=pixels;
cristy330af6c2010-12-21 14:36:06 +00001360 lzma_info.avail_out=packet_size*image->columns;
cristy26377172010-12-20 19:01:58 +00001361 do
1362 {
cristy3a99dcf2011-12-17 01:29:40 +00001363 int
1364 code;
1365
cristy26377172010-12-20 19:01:58 +00001366 if (lzma_info.avail_in == 0)
1367 {
1368 lzma_info.next_in=compress_pixels;
1369 length=(size_t) ReadBlobMSBLong(image);
1370 lzma_info.avail_in=(unsigned int) ReadBlob(image,length,
1371 (unsigned char *) lzma_info.next_in);
1372 }
1373 code=lzma_code(&lzma_info,LZMA_RUN);
cristy330af6c2010-12-21 14:36:06 +00001374 if (code < 0)
1375 {
1376 status=MagickFalse;
1377 break;
1378 }
1379 if (code == LZMA_STREAM_END)
cristy26377172010-12-20 19:01:58 +00001380 break;
1381 } while (lzma_info.avail_out != 0);
cristy26377172010-12-20 19:01:58 +00001382 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1383 quantum_type,pixels,exception);
1384 break;
1385 }
1386#endif
1387#if defined(MAGICKCORE_ZLIB_DELEGATE)
1388 case LZWCompression:
1389 case ZipCompression:
1390 {
cristy26377172010-12-20 19:01:58 +00001391 zip_info.next_out=pixels;
1392 zip_info.avail_out=(uInt) (packet_size*image->columns);
1393 do
1394 {
1395 if (zip_info.avail_in == 0)
1396 {
1397 zip_info.next_in=compress_pixels;
1398 length=(size_t) ZipMaxExtent(packet_size*image->columns);
1399 if (version != 0)
1400 length=(size_t) ReadBlobMSBLong(image);
1401 zip_info.avail_in=(unsigned int) ReadBlob(image,length,
1402 zip_info.next_in);
1403 }
1404 if (inflate(&zip_info,Z_SYNC_FLUSH) == Z_STREAM_END)
1405 break;
1406 } while (zip_info.avail_out != 0);
cristy3ed852e2009-09-05 21:47:34 +00001407 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1408 quantum_type,pixels,exception);
1409 break;
1410 }
1411#endif
1412 case RLECompression:
1413 {
cristybb503372010-05-27 20:51:26 +00001414 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001415 {
1416 if (length == 0)
1417 {
1418 count=ReadBlob(image,packet_size,pixels);
cristyc82a27b2011-10-21 01:07:16 +00001419 PushRunlengthPacket(image,pixels,&length,&pixel,exception);
cristy3ed852e2009-09-05 21:47:34 +00001420 }
1421 length--;
cristy4c08aed2011-07-01 19:47:50 +00001422 if (image->storage_class == PseudoClass)
cristy94b11832011-09-08 19:46:03 +00001423 SetPixelIndex(image,ClampToQuantum(pixel.index),q);
cristy4c08aed2011-07-01 19:47:50 +00001424 else
1425 {
cristy94b11832011-09-08 19:46:03 +00001426 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1427 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1428 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
cristy4c08aed2011-07-01 19:47:50 +00001429 if (image->colorspace == CMYKColorspace)
cristy94b11832011-09-08 19:46:03 +00001430 SetPixelBlack(image,ClampToQuantum(pixel.black),q);
cristy4c08aed2011-07-01 19:47:50 +00001431 }
1432 if (image->matte != MagickFalse)
cristy94b11832011-09-08 19:46:03 +00001433 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
cristyed231572011-07-14 02:18:59 +00001434 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001435 }
1436 break;
1437 }
1438 default:
1439 {
1440 count=ReadBlob(image,packet_size*image->columns,pixels);
1441 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1442 quantum_type,pixels,exception);
1443 break;
1444 }
1445 }
1446 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1447 break;
1448 }
1449 SetQuantumImageType(image,quantum_type);
cristy330af6c2010-12-21 14:36:06 +00001450 switch (image->compression)
1451 {
1452#if defined(MAGICKCORE_BZLIB_DELEGATE)
1453 case BZipCompression:
1454 {
cristy3a99dcf2011-12-17 01:29:40 +00001455 int
1456 code;
1457
cristy330af6c2010-12-21 14:36:06 +00001458 if (version == 0)
1459 {
1460 MagickOffsetType
1461 offset;
1462
1463 offset=SeekBlob(image,-((MagickOffsetType)
1464 bzip_info.avail_in),SEEK_CUR);
1465 if (offset < 0)
1466 ThrowReaderException(CorruptImageError,
1467 "ImproperImageHeader");
1468 }
1469 code=BZ2_bzDecompressEnd(&bzip_info);
1470 if (code != BZ_OK)
1471 status=MagickFalse;
1472 break;
1473 }
1474#endif
1475#if defined(MAGICKCORE_LZMA_DELEGATE)
1476 case LZMACompression:
1477 {
cristy3a99dcf2011-12-17 01:29:40 +00001478 int
1479 code;
1480
cristy3b788a02010-12-27 15:59:54 +00001481 code=lzma_code(&lzma_info,LZMA_FINISH);
1482 if ((code != LZMA_STREAM_END) && (code != LZMA_OK))
cristyb977da52010-12-22 15:55:53 +00001483 status=MagickFalse;
cristy330af6c2010-12-21 14:36:06 +00001484 lzma_end(&lzma_info);
1485 break;
1486 }
1487#endif
1488#if defined(MAGICKCORE_ZLIB_DELEGATE)
1489 case LZWCompression:
1490 case ZipCompression:
1491 {
cristy3a99dcf2011-12-17 01:29:40 +00001492 int
1493 code;
1494
cristy330af6c2010-12-21 14:36:06 +00001495 if (version == 0)
1496 {
1497 MagickOffsetType
1498 offset;
1499
1500 offset=SeekBlob(image,-((MagickOffsetType) zip_info.avail_in),
1501 SEEK_CUR);
1502 if (offset < 0)
1503 ThrowReaderException(CorruptImageError,
1504 "ImproperImageHeader");
1505 }
1506 code=inflateEnd(&zip_info);
1507 if (code != LZMA_OK)
1508 status=MagickFalse;
1509 break;
1510 }
1511#endif
1512 default:
1513 break;
1514 }
cristy3ed852e2009-09-05 21:47:34 +00001515 quantum_info=DestroyQuantumInfo(quantum_info);
1516 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
cristybb503372010-05-27 20:51:26 +00001517 if (((y != (ssize_t) image->rows)) || (status == MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001518 {
1519 image=DestroyImageList(image);
1520 return((Image *) NULL);
1521 }
1522 if (EOFBlob(image) != MagickFalse)
1523 {
1524 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1525 image->filename);
1526 break;
1527 }
1528 /*
1529 Proceed to next image.
1530 */
1531 if (image_info->number_scenes != 0)
1532 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1533 break;
1534 do
1535 {
1536 c=ReadBlobByte(image);
1537 } while ((isgraph(c) == MagickFalse) && (c != EOF));
1538 if (c != EOF)
1539 {
1540 /*
1541 Allocate next image structure.
1542 */
cristy9950d572011-10-01 18:22:35 +00001543 AcquireNextImage(image_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001544 if (GetNextImageInList(image) == (Image *) NULL)
1545 {
1546 image=DestroyImageList(image);
1547 return((Image *) NULL);
1548 }
1549 image=SyncNextImageInList(image);
1550 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1551 GetBlobSize(image));
1552 if (status == MagickFalse)
1553 break;
1554 }
1555 } while (c != EOF);
1556 (void) CloseBlob(image);
1557 return(GetFirstImageInList(image));
1558}
1559
1560/*
1561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1562% %
1563% %
1564% %
1565% R e g i s t e r M I F F I m a g e %
1566% %
1567% %
1568% %
1569%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1570%
1571% RegisterMIFFImage() adds properties for the MIFF image format to the list of
1572% supported formats. The properties include the image format tag, a method to
1573% read and/or write the format, whether the format supports the saving of more
1574% than one frame to the same file or blob, whether the format supports native
1575% in-memory I/O, and a brief description of the format.
1576%
1577% The format of the RegisterMIFFImage method is:
1578%
cristybb503372010-05-27 20:51:26 +00001579% size_t RegisterMIFFImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001580%
1581*/
cristybb503372010-05-27 20:51:26 +00001582ModuleExport size_t RegisterMIFFImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001583{
1584 char
1585 version[MaxTextExtent];
1586
1587 MagickInfo
1588 *entry;
1589
1590 *version='\0';
1591#if defined(MagickImageCoderSignatureText)
1592 (void) CopyMagickString(version,MagickLibVersionText,MaxTextExtent);
1593#if defined(ZLIB_VERSION)
1594 (void) ConcatenateMagickString(version," with Zlib ",MaxTextExtent);
1595 (void) ConcatenateMagickString(version,ZLIB_VERSION,MaxTextExtent);
1596#endif
1597#if defined(MAGICKCORE_BZLIB_DELEGATE)
1598 (void) ConcatenateMagickString(version," and BZlib",MaxTextExtent);
1599#endif
1600#endif
1601 entry=SetMagickInfo("MIFF");
1602 entry->decoder=(DecodeImageHandler *) ReadMIFFImage;
1603 entry->encoder=(EncodeImageHandler *) WriteMIFFImage;
1604 entry->magick=(IsImageFormatHandler *) IsMIFF;
cristyffaf9782011-04-13 19:50:51 +00001605 entry->seekable_stream=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00001606 entry->description=ConstantString("Magick Image File Format");
1607 if (*version != '\0')
1608 entry->version=ConstantString(version);
1609 entry->module=ConstantString("MIFF");
1610 (void) RegisterMagickInfo(entry);
1611 return(MagickImageCoderSignature);
1612}
1613
1614/*
1615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1616% %
1617% %
1618% %
1619% U n r e g i s t e r M I F F I m a g e %
1620% %
1621% %
1622% %
1623%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1624%
1625% UnregisterMIFFImage() removes format registrations made by the MIFF module
1626% from the list of supported formats.
1627%
1628% The format of the UnregisterMIFFImage method is:
1629%
1630% UnregisterMIFFImage(void)
1631%
1632*/
1633ModuleExport void UnregisterMIFFImage(void)
1634{
1635 (void) UnregisterMagickInfo("MIFF");
1636}
1637
1638/*
1639%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1640% %
1641% %
1642% %
1643% W r i t e M I F F I m a g e %
1644% %
1645% %
1646% %
1647%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1648%
1649% WriteMIFFImage() writes a MIFF image to a file.
1650%
1651% The format of the WriteMIFFImage method is:
1652%
1653% MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
cristy1e178e72011-08-28 19:44:34 +00001654% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001655%
1656% Compression code contributed by Kyle Shorter.
1657%
1658% A description of each parameter follows:
1659%
1660% o image_info: the image info.
1661%
1662% o image: the image.
1663%
cristy1e178e72011-08-28 19:44:34 +00001664% o exception: return any errors or warnings in this structure.
1665%
cristy3ed852e2009-09-05 21:47:34 +00001666*/
1667
1668static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
cristyc82a27b2011-10-21 01:07:16 +00001669 size_t length,PixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001670{
1671 if (image->storage_class != DirectClass)
1672 {
1673 switch (image->depth)
1674 {
1675 case 32:
1676 {
cristy4c08aed2011-07-01 19:47:50 +00001677 *pixels++=(unsigned char) ((size_t) pixel->index >> 24);
1678 *pixels++=(unsigned char) ((size_t) pixel->index >> 16);
cristy3ed852e2009-09-05 21:47:34 +00001679 }
1680 case 16:
cristy4c08aed2011-07-01 19:47:50 +00001681 *pixels++=(unsigned char) ((size_t) pixel->index >> 8);
cristy3ed852e2009-09-05 21:47:34 +00001682 case 8:
1683 {
cristy4c08aed2011-07-01 19:47:50 +00001684 *pixels++=(unsigned char) pixel->index;
cristy3ed852e2009-09-05 21:47:34 +00001685 break;
1686 }
1687 default:
cristyc82a27b2011-10-21 01:07:16 +00001688 (void) ThrowMagickException(exception,GetMagickModule(),
cristy3ed852e2009-09-05 21:47:34 +00001689 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1690 }
1691 switch (image->depth)
1692 {
1693 case 32:
1694 {
cristy4cb162a2010-05-30 03:04:47 +00001695 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001696 value;
1697
1698 if (image->matte != MagickFalse)
1699 {
cristy94b11832011-09-08 19:46:03 +00001700 value=ScaleQuantumToLong(ClampToQuantum(pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001701 pixels=PopLongPixel(MSBEndian,value,pixels);
1702 }
1703 break;
1704 }
1705 case 16:
1706 {
1707 unsigned short
1708 value;
1709
1710 if (image->matte != MagickFalse)
1711 {
cristy94b11832011-09-08 19:46:03 +00001712 value=ScaleQuantumToShort(ClampToQuantum(pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001713 pixels=PopShortPixel(MSBEndian,value,pixels);
1714 }
1715 break;
1716 }
1717 case 8:
1718 {
1719 unsigned char
1720 value;
1721
1722 if (image->matte != MagickFalse)
1723 {
cristy94b11832011-09-08 19:46:03 +00001724 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1725 pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001726 pixels=PopCharPixel(value,pixels);
1727 }
1728 break;
1729 }
1730 default:
cristyc82a27b2011-10-21 01:07:16 +00001731 (void) ThrowMagickException(exception,GetMagickModule(),
cristy3ed852e2009-09-05 21:47:34 +00001732 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename);
1733 }
1734 *pixels++=(unsigned char) length;
1735 return(pixels);
1736 }
1737 switch (image->depth)
1738 {
1739 case 32:
1740 {
cristy4cb162a2010-05-30 03:04:47 +00001741 unsigned int
cristy3ed852e2009-09-05 21:47:34 +00001742 value;
1743
cristy94b11832011-09-08 19:46:03 +00001744 value=ScaleQuantumToLong(ClampToQuantum(pixel->red));
cristy3ed852e2009-09-05 21:47:34 +00001745 pixels=PopLongPixel(MSBEndian,value,pixels);
cristy94b11832011-09-08 19:46:03 +00001746 value=ScaleQuantumToLong(ClampToQuantum(pixel->green));
cristy3ed852e2009-09-05 21:47:34 +00001747 pixels=PopLongPixel(MSBEndian,value,pixels);
cristy94b11832011-09-08 19:46:03 +00001748 value=ScaleQuantumToLong(ClampToQuantum(pixel->blue));
cristy3ed852e2009-09-05 21:47:34 +00001749 pixels=PopLongPixel(MSBEndian,value,pixels);
cristy3ed852e2009-09-05 21:47:34 +00001750 if (image->colorspace == CMYKColorspace)
1751 {
cristy94b11832011-09-08 19:46:03 +00001752 value=ScaleQuantumToLong(ClampToQuantum(pixel->black));
cristy4c08aed2011-07-01 19:47:50 +00001753 pixels=PopLongPixel(MSBEndian,value,pixels);
1754 }
1755 if (image->matte != MagickFalse)
1756 {
cristy94b11832011-09-08 19:46:03 +00001757 value=ScaleQuantumToLong(ClampToQuantum(pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001758 pixels=PopLongPixel(MSBEndian,value,pixels);
1759 }
1760 break;
1761 }
1762 case 16:
1763 {
1764 unsigned short
1765 value;
1766
cristy94b11832011-09-08 19:46:03 +00001767 value=ScaleQuantumToShort(ClampToQuantum(pixel->red));
cristy3ed852e2009-09-05 21:47:34 +00001768 pixels=PopShortPixel(MSBEndian,value,pixels);
cristy94b11832011-09-08 19:46:03 +00001769 value=ScaleQuantumToShort(ClampToQuantum(pixel->green));
cristy3ed852e2009-09-05 21:47:34 +00001770 pixels=PopShortPixel(MSBEndian,value,pixels);
cristy94b11832011-09-08 19:46:03 +00001771 value=ScaleQuantumToShort(ClampToQuantum(pixel->blue));
cristy3ed852e2009-09-05 21:47:34 +00001772 pixels=PopShortPixel(MSBEndian,value,pixels);
cristy3ed852e2009-09-05 21:47:34 +00001773 if (image->colorspace == CMYKColorspace)
1774 {
cristy94b11832011-09-08 19:46:03 +00001775 value=ScaleQuantumToShort(ClampToQuantum(pixel->black));
cristy4c08aed2011-07-01 19:47:50 +00001776 pixels=PopShortPixel(MSBEndian,value,pixels);
1777 }
1778 if (image->matte != MagickFalse)
1779 {
cristy94b11832011-09-08 19:46:03 +00001780 value=ScaleQuantumToShort(ClampToQuantum(pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001781 pixels=PopShortPixel(MSBEndian,value,pixels);
1782 }
1783 break;
1784 }
1785 case 8:
1786 {
1787 unsigned char
1788 value;
1789
cristy94b11832011-09-08 19:46:03 +00001790 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->red));
cristy3ed852e2009-09-05 21:47:34 +00001791 pixels=PopCharPixel(value,pixels);
cristy94b11832011-09-08 19:46:03 +00001792 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->green));
cristy3ed852e2009-09-05 21:47:34 +00001793 pixels=PopCharPixel(value,pixels);
cristy94b11832011-09-08 19:46:03 +00001794 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->blue));
cristy3ed852e2009-09-05 21:47:34 +00001795 pixels=PopCharPixel(value,pixels);
cristy3ed852e2009-09-05 21:47:34 +00001796 if (image->colorspace == CMYKColorspace)
1797 {
cristy94b11832011-09-08 19:46:03 +00001798 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1799 pixel->black));
cristy4c08aed2011-07-01 19:47:50 +00001800 pixels=PopCharPixel(value,pixels);
1801 }
1802 if (image->matte != MagickFalse)
1803 {
cristy94b11832011-09-08 19:46:03 +00001804 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
1805 pixel->alpha));
cristy3ed852e2009-09-05 21:47:34 +00001806 pixels=PopCharPixel(value,pixels);
1807 }
1808 break;
1809 }
1810 default:
cristyc82a27b2011-10-21 01:07:16 +00001811 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
1812 "ImageDepthNotSupported","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +00001813 }
1814 *pixels++=(unsigned char) length;
1815 return(pixels);
1816}
1817
1818static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
cristy1e178e72011-08-28 19:44:34 +00001819 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001820{
1821#if defined(MAGICKCORE_BZLIB_DELEGATE)
1822 bz_stream
1823 bzip_info;
1824#endif
1825
1826 char
1827 buffer[MaxTextExtent];
1828
1829 CompressionType
1830 compression;
1831
1832 const char
1833 *property,
1834 *value;
1835
cristy26377172010-12-20 19:01:58 +00001836#if defined(MAGICKCORE_LZMA_DELEGATE)
cristy4b46dba2010-12-20 19:18:20 +00001837 lzma_allocator
1838 allocator;
1839
cristy26377172010-12-20 19:01:58 +00001840 lzma_stream
cristy330af6c2010-12-21 14:36:06 +00001841 initialize_lzma = LZMA_STREAM_INIT,
1842 lzma_info;
cristy26377172010-12-20 19:01:58 +00001843#endif
cristy3ed852e2009-09-05 21:47:34 +00001844
1845 MagickBooleanType
1846 status;
1847
1848 MagickOffsetType
1849 scene;
1850
cristy4c08aed2011-07-01 19:47:50 +00001851 PixelInfo
1852 pixel,
1853 target;
cristy3ed852e2009-09-05 21:47:34 +00001854
1855 QuantumInfo
1856 *quantum_info;
1857
1858 QuantumType
1859 quantum_type;
1860
cristybb503372010-05-27 20:51:26 +00001861 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001862 i;
1863
1864 size_t
1865 length,
1866 packet_size;
1867
cristy26377172010-12-20 19:01:58 +00001868 ssize_t
1869 y;
1870
cristy3ed852e2009-09-05 21:47:34 +00001871 unsigned char
1872 *compress_pixels,
1873 *pixels,
1874 *q;
1875
1876#if defined(MAGICKCORE_ZLIB_DELEGATE)
1877 z_stream
1878 zip_info;
1879#endif
1880
1881 /*
1882 Open output image file.
1883 */
1884 assert(image_info != (const ImageInfo *) NULL);
1885 assert(image_info->signature == MagickSignature);
1886 assert(image != (Image *) NULL);
1887 assert(image->signature == MagickSignature);
1888 if (image->debug != MagickFalse)
1889 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy3a37efd2011-08-28 20:31:03 +00001890 assert(exception != (ExceptionInfo *) NULL);
1891 assert(exception->signature == MagickSignature);
cristy1e178e72011-08-28 19:44:34 +00001892 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy3ed852e2009-09-05 21:47:34 +00001893 if (status == MagickFalse)
1894 return(status);
cristy3ed852e2009-09-05 21:47:34 +00001895 scene=0;
1896 do
1897 {
1898 /*
1899 Allocate image pixels.
1900 */
1901 image->depth=image->depth <= 8 ? 8UL : image->depth <= 16 ? 16UL :
1902 image->depth <= 32 ? 32UL : 64UL;
1903 quantum_info=AcquireQuantumInfo(image_info,image);
1904 if (quantum_info == (QuantumInfo *) NULL)
1905 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1906 if ((image->storage_class != PseudoClass) && (image->depth >= 32) &&
1907 (quantum_info->format == UndefinedQuantumFormat) &&
cristy1e178e72011-08-28 19:44:34 +00001908 (IsHighDynamicRangeImage(image,exception) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001909 {
1910 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1911 if (status == MagickFalse)
1912 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1913 }
1914 if ((image->storage_class == PseudoClass) &&
cristybb503372010-05-27 20:51:26 +00001915 (image->colors > (size_t) (GetQuantumRange(image->depth)+1)))
cristy1e178e72011-08-28 19:44:34 +00001916 (void) SetImageStorageClass(image,DirectClass,exception);
cristy669e5c72011-09-12 12:01:33 +00001917 if (IsImageGray(image,exception) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001918 {
cristy1e178e72011-08-28 19:44:34 +00001919 (void) SetImageStorageClass(image,DirectClass,exception);
1920 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +00001921 }
1922 compression=image->compression;
1923 if (image_info->compression != UndefinedCompression)
1924 compression=image_info->compression;
1925 switch (compression)
1926 {
1927#if !defined(MAGICKCORE_ZLIB_DELEGATE)
cristy26377172010-12-20 19:01:58 +00001928 case LZMACompression: compression=NoCompression; break;
1929#endif
1930#if !defined(MAGICKCORE_ZLIB_DELEGATE)
cristy3ed852e2009-09-05 21:47:34 +00001931 case LZWCompression:
1932 case ZipCompression: compression=NoCompression; break;
1933#endif
1934#if !defined(MAGICKCORE_BZLIB_DELEGATE)
1935 case BZipCompression: compression=NoCompression; break;
1936#endif
1937 case RLECompression:
1938 {
1939 if (quantum_info->format == FloatingPointQuantumFormat)
1940 compression=NoCompression;
cristy4c08aed2011-07-01 19:47:50 +00001941 GetPixelInfo(image,&target);
cristy3ed852e2009-09-05 21:47:34 +00001942 break;
1943 }
1944 default:
1945 break;
1946 }
1947 packet_size=(size_t) (quantum_info->depth/8);
1948 if (image->storage_class == DirectClass)
1949 packet_size=(size_t) (3*quantum_info->depth/8);
cristy669e5c72011-09-12 12:01:33 +00001950 if (IsImageGray(image,exception) != MagickFalse)
cristy0a30e182011-09-01 01:43:15 +00001951 packet_size=(size_t) (quantum_info->depth/8);
cristy3ed852e2009-09-05 21:47:34 +00001952 if (image->matte != MagickFalse)
1953 packet_size+=quantum_info->depth/8;
1954 if (image->colorspace == CMYKColorspace)
1955 packet_size+=quantum_info->depth/8;
1956 if (compression == RLECompression)
1957 packet_size++;
1958 length=image->columns;
1959 length=MagickMax(BZipMaxExtent(packet_size*image->columns),ZipMaxExtent(
1960 packet_size*image->columns));
1961 if ((compression == BZipCompression) || (compression == ZipCompression))
1962 if (length != (size_t) ((unsigned int) length))
1963 compression=NoCompression;
1964 compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
1965 sizeof(*compress_pixels));
1966 if (compress_pixels == (unsigned char *) NULL)
1967 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1968 /*
1969 Write MIFF header.
1970 */
1971 (void) WriteBlobString(image,"id=ImageMagick version=1.0\n");
cristyb51dff52011-05-19 16:55:47 +00001972 (void) FormatLocaleString(buffer,MaxTextExtent,
cristy042ee782011-04-22 18:48:30 +00001973 "class=%s colors=%.20g matte=%s\n",CommandOptionToMnemonic(
cristye8c25f92010-06-03 00:53:06 +00001974 MagickClassOptions,image->storage_class),(double) image->colors,
cristy042ee782011-04-22 18:48:30 +00001975 CommandOptionToMnemonic(MagickBooleanOptions,(ssize_t) image->matte));
cristy3ed852e2009-09-05 21:47:34 +00001976 (void) WriteBlobString(image,buffer);
cristyb51dff52011-05-19 16:55:47 +00001977 (void) FormatLocaleString(buffer,MaxTextExtent,"columns=%.20g rows=%.20g "
cristye8c25f92010-06-03 00:53:06 +00001978 "depth=%.20g\n",(double) image->columns,(double) image->rows,(double)
1979 image->depth);
cristy3ed852e2009-09-05 21:47:34 +00001980 (void) WriteBlobString(image,buffer);
cristy5f1c1ff2010-12-23 21:38:06 +00001981 if (image->type != UndefinedType)
cristy3ed852e2009-09-05 21:47:34 +00001982 {
cristyb51dff52011-05-19 16:55:47 +00001983 (void) FormatLocaleString(buffer,MaxTextExtent,"type=%s\n",
cristy042ee782011-04-22 18:48:30 +00001984 CommandOptionToMnemonic(MagickTypeOptions,image->type));
cristy3ed852e2009-09-05 21:47:34 +00001985 (void) WriteBlobString(image,buffer);
1986 }
1987 if (image->colorspace != UndefinedColorspace)
1988 {
cristyb51dff52011-05-19 16:55:47 +00001989 (void) FormatLocaleString(buffer,MaxTextExtent,"colorspace=%s\n",
cristy042ee782011-04-22 18:48:30 +00001990 CommandOptionToMnemonic(MagickColorspaceOptions,image->colorspace));
cristy3ed852e2009-09-05 21:47:34 +00001991 (void) WriteBlobString(image,buffer);
1992 }
1993 if (compression != UndefinedCompression)
1994 {
cristyb51dff52011-05-19 16:55:47 +00001995 (void) FormatLocaleString(buffer,MaxTextExtent,"compression=%s "
cristy042ee782011-04-22 18:48:30 +00001996 "quality=%.20g\n",CommandOptionToMnemonic(MagickCompressOptions,
cristye8c25f92010-06-03 00:53:06 +00001997 compression),(double) image->quality);
cristy3ed852e2009-09-05 21:47:34 +00001998 (void) WriteBlobString(image,buffer);
1999 }
2000 if (image->units != UndefinedResolution)
2001 {
cristyb51dff52011-05-19 16:55:47 +00002002 (void) FormatLocaleString(buffer,MaxTextExtent,"units=%s\n",
cristy042ee782011-04-22 18:48:30 +00002003 CommandOptionToMnemonic(MagickResolutionOptions,image->units));
cristy3ed852e2009-09-05 21:47:34 +00002004 (void) WriteBlobString(image,buffer);
2005 }
cristy2a11bef2011-10-28 18:33:11 +00002006 if ((image->resolution.x != 0) || (image->resolution.y != 0))
cristy3ed852e2009-09-05 21:47:34 +00002007 {
cristyb51dff52011-05-19 16:55:47 +00002008 (void) FormatLocaleString(buffer,MaxTextExtent,
cristy2a11bef2011-10-28 18:33:11 +00002009 "resolution=%gx%g\n",image->resolution.x,image->resolution.y);
cristy3ed852e2009-09-05 21:47:34 +00002010 (void) WriteBlobString(image,buffer);
2011 }
2012 if ((image->page.width != 0) || (image->page.height != 0))
2013 {
cristyb51dff52011-05-19 16:55:47 +00002014 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00002015 "page=%.20gx%.20g%+.20g%+.20g\n",(double) image->page.width,(double)
2016 image->page.height,(double) image->page.x,(double) image->page.y);
cristy3ed852e2009-09-05 21:47:34 +00002017 (void) WriteBlobString(image,buffer);
2018 }
2019 else
2020 if ((image->page.x != 0) || (image->page.y != 0))
2021 {
cristyb51dff52011-05-19 16:55:47 +00002022 (void) FormatLocaleString(buffer,MaxTextExtent,"page=%+ld%+ld\n",
cristyf2faecf2010-05-28 19:19:36 +00002023 (long) image->page.x,(long) image->page.y);
cristy3ed852e2009-09-05 21:47:34 +00002024 (void) WriteBlobString(image,buffer);
2025 }
2026 if ((image->tile_offset.x != 0) || (image->tile_offset.y != 0))
2027 {
cristyb51dff52011-05-19 16:55:47 +00002028 (void) FormatLocaleString(buffer,MaxTextExtent,"tile-offset=%+ld%+ld\n",
cristyf2faecf2010-05-28 19:19:36 +00002029 (long) image->tile_offset.x,(long) image->tile_offset.y);
cristy3ed852e2009-09-05 21:47:34 +00002030 (void) WriteBlobString(image,buffer);
2031 }
2032 if ((GetNextImageInList(image) != (Image *) NULL) ||
2033 (GetPreviousImageInList(image) != (Image *) NULL))
2034 {
2035 if (image->scene == 0)
cristyb51dff52011-05-19 16:55:47 +00002036 (void) FormatLocaleString(buffer,MaxTextExtent,"iterations=%.20g "
cristye8c25f92010-06-03 00:53:06 +00002037 "delay=%.20g ticks-per-second=%.20g\n",(double) image->iterations,
2038 (double) image->delay,(double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002039 else
cristyb51dff52011-05-19 16:55:47 +00002040 (void) FormatLocaleString(buffer,MaxTextExtent,"scene=%.20g "
cristye8c25f92010-06-03 00:53:06 +00002041 "iterations=%.20g delay=%.20g ticks-per-second=%.20g\n",(double)
2042 image->scene,(double) image->iterations,(double) image->delay,
2043 (double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002044 (void) WriteBlobString(image,buffer);
2045 }
2046 else
2047 {
2048 if (image->scene != 0)
2049 {
cristyb51dff52011-05-19 16:55:47 +00002050 (void) FormatLocaleString(buffer,MaxTextExtent,"scene=%.20g\n",
cristye8c25f92010-06-03 00:53:06 +00002051 (double) image->scene);
cristy3ed852e2009-09-05 21:47:34 +00002052 (void) WriteBlobString(image,buffer);
2053 }
2054 if (image->iterations != 0)
2055 {
cristyb51dff52011-05-19 16:55:47 +00002056 (void) FormatLocaleString(buffer,MaxTextExtent,"iterations=%.20g\n",
cristye8c25f92010-06-03 00:53:06 +00002057 (double) image->iterations);
cristy3ed852e2009-09-05 21:47:34 +00002058 (void) WriteBlobString(image,buffer);
2059 }
2060 if (image->delay != 0)
2061 {
cristyb51dff52011-05-19 16:55:47 +00002062 (void) FormatLocaleString(buffer,MaxTextExtent,"delay=%.20g\n",
cristye8c25f92010-06-03 00:53:06 +00002063 (double) image->delay);
cristy3ed852e2009-09-05 21:47:34 +00002064 (void) WriteBlobString(image,buffer);
2065 }
2066 if (image->ticks_per_second != UndefinedTicksPerSecond)
2067 {
cristyb51dff52011-05-19 16:55:47 +00002068 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00002069 "ticks-per-second=%.20g\n",(double) image->ticks_per_second);
cristy3ed852e2009-09-05 21:47:34 +00002070 (void) WriteBlobString(image,buffer);
2071 }
2072 }
2073 if (image->gravity != UndefinedGravity)
2074 {
cristyb51dff52011-05-19 16:55:47 +00002075 (void) FormatLocaleString(buffer,MaxTextExtent,"gravity=%s\n",
cristy042ee782011-04-22 18:48:30 +00002076 CommandOptionToMnemonic(MagickGravityOptions,image->gravity));
cristy3ed852e2009-09-05 21:47:34 +00002077 (void) WriteBlobString(image,buffer);
2078 }
2079 if (image->dispose != UndefinedDispose)
2080 {
cristyb51dff52011-05-19 16:55:47 +00002081 (void) FormatLocaleString(buffer,MaxTextExtent,"dispose=%s\n",
cristy042ee782011-04-22 18:48:30 +00002082 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
cristy3ed852e2009-09-05 21:47:34 +00002083 (void) WriteBlobString(image,buffer);
2084 }
2085 if (image->rendering_intent != UndefinedIntent)
2086 {
cristy0a30e182011-09-01 01:43:15 +00002087 (void) FormatLocaleString(buffer,MaxTextExtent,"rendering-intent=%s\n",
2088 CommandOptionToMnemonic(MagickIntentOptions,image->rendering_intent));
cristy3ed852e2009-09-05 21:47:34 +00002089 (void) WriteBlobString(image,buffer);
2090 }
2091 if (image->gamma != 0.0)
2092 {
cristyb51dff52011-05-19 16:55:47 +00002093 (void) FormatLocaleString(buffer,MaxTextExtent,"gamma=%g\n",
cristy3ed852e2009-09-05 21:47:34 +00002094 image->gamma);
2095 (void) WriteBlobString(image,buffer);
2096 }
2097 if (image->chromaticity.white_point.x != 0.0)
2098 {
2099 /*
2100 Note chomaticity points.
2101 */
cristyb51dff52011-05-19 16:55:47 +00002102 (void) FormatLocaleString(buffer,MaxTextExtent,"red-primary=%g,"
cristye7f51092010-01-17 00:39:37 +00002103 "%g green-primary=%g,%g blue-primary=%g,%g\n",
cristy3ed852e2009-09-05 21:47:34 +00002104 image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
2105 image->chromaticity.green_primary.x,
2106 image->chromaticity.green_primary.y,
2107 image->chromaticity.blue_primary.x,
2108 image->chromaticity.blue_primary.y);
2109 (void) WriteBlobString(image,buffer);
cristyb51dff52011-05-19 16:55:47 +00002110 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye7f51092010-01-17 00:39:37 +00002111 "white-point=%g,%g\n",image->chromaticity.white_point.x,
cristy8cd5b312010-01-07 01:10:24 +00002112 image->chromaticity.white_point.y);
cristy3ed852e2009-09-05 21:47:34 +00002113 (void) WriteBlobString(image,buffer);
2114 }
2115 if (image->orientation != UndefinedOrientation)
2116 {
cristyb51dff52011-05-19 16:55:47 +00002117 (void) FormatLocaleString(buffer,MaxTextExtent,"orientation=%s\n",
cristy042ee782011-04-22 18:48:30 +00002118 CommandOptionToMnemonic(MagickOrientationOptions,image->orientation));
cristy3ed852e2009-09-05 21:47:34 +00002119 (void) WriteBlobString(image,buffer);
2120 }
2121 if (image->profiles != (void *) NULL)
2122 {
2123 const char
2124 *name;
2125
2126 const StringInfo
2127 *profile;
2128
2129 /*
2130 Write image profiles.
2131 */
2132 ResetImageProfileIterator(image);
2133 name=GetNextImageProfile(image);
2134 while (name != (const char *) NULL)
2135 {
2136 profile=GetImageProfile(image,name);
2137 if (profile != (StringInfo *) NULL)
2138 {
cristyb51dff52011-05-19 16:55:47 +00002139 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00002140 "profile:%s=%.20g\n",name,(double)
2141 GetStringInfoLength(profile));
cristy3ed852e2009-09-05 21:47:34 +00002142 (void) WriteBlobString(image,buffer);
2143 }
2144 name=GetNextImageProfile(image);
2145 }
2146 }
2147 if (image->montage != (char *) NULL)
2148 {
cristyb51dff52011-05-19 16:55:47 +00002149 (void) FormatLocaleString(buffer,MaxTextExtent,"montage=%s\n",
cristy3ed852e2009-09-05 21:47:34 +00002150 image->montage);
2151 (void) WriteBlobString(image,buffer);
2152 }
2153 if (quantum_info->format == FloatingPointQuantumFormat)
cristyd15e6592011-10-15 00:13:06 +00002154 (void) SetImageProperty(image,"quantum:format","floating-point",
2155 exception);
cristy3ed852e2009-09-05 21:47:34 +00002156 ResetImagePropertyIterator(image);
2157 property=GetNextImageProperty(image);
2158 while (property != (const char *) NULL)
2159 {
cristyb51dff52011-05-19 16:55:47 +00002160 (void) FormatLocaleString(buffer,MaxTextExtent,"%s=",property);
cristy3ed852e2009-09-05 21:47:34 +00002161 (void) WriteBlobString(image,buffer);
cristyd15e6592011-10-15 00:13:06 +00002162 value=GetImageProperty(image,property,exception);
cristy3ed852e2009-09-05 21:47:34 +00002163 if (value != (const char *) NULL)
2164 {
cristybb503372010-05-27 20:51:26 +00002165 for (i=0; i < (ssize_t) strlen(value); i++)
cristy3ed852e2009-09-05 21:47:34 +00002166 if (isspace((int) ((unsigned char) value[i])) != 0)
2167 break;
cristybb503372010-05-27 20:51:26 +00002168 if (i <= (ssize_t) strlen(value))
cristy3ed852e2009-09-05 21:47:34 +00002169 (void) WriteBlobByte(image,'{');
2170 (void) WriteBlob(image,strlen(value),(const unsigned char *) value);
cristybb503372010-05-27 20:51:26 +00002171 if (i <= (ssize_t) strlen(value))
cristy3ed852e2009-09-05 21:47:34 +00002172 (void) WriteBlobByte(image,'}');
2173 }
2174 (void) WriteBlobByte(image,'\n');
2175 property=GetNextImageProperty(image);
2176 }
2177 (void) WriteBlobString(image,"\f\n:\032");
2178 if (image->montage != (char *) NULL)
2179 {
2180 /*
2181 Write montage tile directory.
2182 */
2183 if (image->directory != (char *) NULL)
2184 (void) WriteBlob(image,strlen(image->directory),(unsigned char *)
2185 image->directory);
2186 (void) WriteBlobByte(image,'\0');
2187 }
2188 if (image->profiles != (void *) NULL)
2189 {
2190 const char
2191 *name;
2192
2193 const StringInfo
2194 *profile;
2195
2196 /*
2197 Generic profile.
2198 */
2199 ResetImageProfileIterator(image);
2200 name=GetNextImageProfile(image);
2201 while (name != (const char *) NULL)
2202 {
2203 profile=GetImageProfile(image,name);
2204 (void) WriteBlob(image,GetStringInfoLength(profile),
2205 GetStringInfoDatum(profile));
2206 name=GetNextImageProfile(image);
2207 }
2208 }
2209 if (image->storage_class == PseudoClass)
2210 {
2211 size_t
2212 packet_size;
2213
2214 unsigned char
2215 *colormap,
2216 *q;
2217
2218 /*
2219 Allocate colormap.
2220 */
2221 packet_size=(size_t) (3*quantum_info->depth/8);
2222 colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
2223 packet_size*sizeof(*colormap));
2224 if (colormap == (unsigned char *) NULL)
2225 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2226 /*
2227 Write colormap to file.
2228 */
2229 q=colormap;
cristybb503372010-05-27 20:51:26 +00002230 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00002231 {
2232 switch (quantum_info->depth)
2233 {
2234 default:
2235 ThrowWriterException(CorruptImageError,"ImageDepthNotSupported");
2236 case 32:
2237 {
cristy4cb162a2010-05-30 03:04:47 +00002238 register unsigned int
cristy3ed852e2009-09-05 21:47:34 +00002239 pixel;
2240
2241 pixel=ScaleQuantumToLong(image->colormap[i].red);
2242 q=PopLongPixel(MSBEndian,pixel,q);
2243 pixel=ScaleQuantumToLong(image->colormap[i].green);
2244 q=PopLongPixel(MSBEndian,pixel,q);
2245 pixel=ScaleQuantumToLong(image->colormap[i].blue);
2246 q=PopLongPixel(MSBEndian,pixel,q);
2247 break;
2248 }
2249 case 16:
2250 {
2251 register unsigned short
2252 pixel;
2253
2254 pixel=ScaleQuantumToShort(image->colormap[i].red);
2255 q=PopShortPixel(MSBEndian,pixel,q);
2256 pixel=ScaleQuantumToShort(image->colormap[i].green);
2257 q=PopShortPixel(MSBEndian,pixel,q);
2258 pixel=ScaleQuantumToShort(image->colormap[i].blue);
2259 q=PopShortPixel(MSBEndian,pixel,q);
2260 break;
2261 }
2262 case 8:
2263 {
2264 register unsigned char
2265 pixel;
2266
2267 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].red);
2268 q=PopCharPixel(pixel,q);
2269 pixel=(unsigned char) ScaleQuantumToChar(
2270 image->colormap[i].green);
2271 q=PopCharPixel(pixel,q);
2272 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].blue);
2273 q=PopCharPixel(pixel,q);
2274 break;
2275 }
2276 }
2277 }
2278 (void) WriteBlob(image,packet_size*image->colors,colormap);
2279 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
2280 }
2281 /*
2282 Write image pixels to file.
2283 */
cristy330af6c2010-12-21 14:36:06 +00002284 status=MagickTrue;
2285 switch (compression)
2286 {
2287#if defined(MAGICKCORE_BZLIB_DELEGATE)
2288 case BZipCompression:
2289 {
cristy3a99dcf2011-12-17 01:29:40 +00002290 int
2291 code;
2292
cristy330af6c2010-12-21 14:36:06 +00002293 (void) ResetMagickMemory(&bzip_info,0,sizeof(bzip_info));
2294 bzip_info.bzalloc=AcquireBZIPMemory;
2295 bzip_info.bzfree=RelinquishBZIPMemory;
2296 code=BZ2_bzCompressInit(&bzip_info,(int) (image->quality ==
2297 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,
2298 9)),(int) image_info->verbose,0);
2299 if (code != BZ_OK)
2300 status=MagickFalse;
2301 break;
2302 }
2303#endif
2304#if defined(MAGICKCORE_LZMA_DELEGATE)
2305 case LZMACompression:
2306 {
cristy3a99dcf2011-12-17 01:29:40 +00002307 int
2308 code;
2309
cristy330af6c2010-12-21 14:36:06 +00002310 (void) ResetMagickMemory(&allocator,0,sizeof(allocator));
2311 allocator.alloc=AcquireLZMAMemory;
2312 allocator.free=RelinquishLZMAMemory;
cristy9d72f1a2010-12-21 20:46:59 +00002313 lzma_info=initialize_lzma;
cristy330af6c2010-12-21 14:36:06 +00002314 lzma_info.allocator=&allocator;
cristy9d72f1a2010-12-21 20:46:59 +00002315 code=lzma_easy_encoder(&lzma_info,image->quality/10,LZMA_CHECK_SHA256);
2316 if (code != LZMA_OK)
2317 status=MagickTrue;
cristy330af6c2010-12-21 14:36:06 +00002318 break;
2319 }
2320#endif
2321#if defined(MAGICKCORE_ZLIB_DELEGATE)
2322 case LZWCompression:
2323 case ZipCompression:
2324 {
cristy3a99dcf2011-12-17 01:29:40 +00002325 int
2326 code;
2327
cristy330af6c2010-12-21 14:36:06 +00002328 (void) ResetMagickMemory(&zip_info,0,sizeof(zip_info));
2329 zip_info.zalloc=AcquireZIPMemory;
2330 zip_info.zfree=RelinquishZIPMemory;
2331 code=deflateInit(&zip_info,(int) (image->quality ==
2332 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9)));
2333 if (code != Z_OK)
2334 status=MagickFalse;
2335 break;
2336 }
2337#endif
2338 default:
2339 break;
2340 }
cristy1e178e72011-08-28 19:44:34 +00002341 quantum_type=GetQuantumType(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002342 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002343 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002344 {
cristy4c08aed2011-07-01 19:47:50 +00002345 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00002346 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002347
cristybb503372010-05-27 20:51:26 +00002348 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002349 x;
2350
cristy330af6c2010-12-21 14:36:06 +00002351 if (status == MagickFalse)
2352 break;
cristy1e178e72011-08-28 19:44:34 +00002353 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002354 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002355 break;
cristy3ed852e2009-09-05 21:47:34 +00002356 q=pixels;
2357 switch (compression)
2358 {
cristy3ed852e2009-09-05 21:47:34 +00002359#if defined(MAGICKCORE_BZLIB_DELEGATE)
2360 case BZipCompression:
2361 {
cristy3ed852e2009-09-05 21:47:34 +00002362 bzip_info.next_in=(char *) pixels;
2363 bzip_info.avail_in=(unsigned int) (packet_size*image->columns);
cristy4c08aed2011-07-01 19:47:50 +00002364 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002365 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002366 do
2367 {
cristy3a99dcf2011-12-17 01:29:40 +00002368 int
2369 code;
2370
cristy3ed852e2009-09-05 21:47:34 +00002371 bzip_info.next_out=(char *) compress_pixels;
2372 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2373 image->columns);
2374 code=BZ2_bzCompress(&bzip_info,BZ_FLUSH);
cristy26377172010-12-20 19:01:58 +00002375 if (code != BZ_OK)
2376 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00002377 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2378 if (length != 0)
2379 {
2380 (void) WriteBlobMSBLong(image,(unsigned int) length);
2381 (void) WriteBlob(image,length,compress_pixels);
2382 }
2383 } while (bzip_info.avail_in != 0);
cristy26377172010-12-20 19:01:58 +00002384 break;
2385 }
2386#endif
2387#if defined(MAGICKCORE_LZMA_DELEGATE)
2388 case LZMACompression:
2389 {
cristy26377172010-12-20 19:01:58 +00002390 lzma_info.next_in=pixels;
cristy330af6c2010-12-21 14:36:06 +00002391 lzma_info.avail_in=packet_size*image->columns;
cristy4c08aed2011-07-01 19:47:50 +00002392 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002393 quantum_type,pixels,exception);
cristy26377172010-12-20 19:01:58 +00002394 do
2395 {
cristy3a99dcf2011-12-17 01:29:40 +00002396 int
2397 code;
2398
cristy26377172010-12-20 19:01:58 +00002399 lzma_info.next_out=compress_pixels;
2400 lzma_info.avail_out=packet_size*image->columns;
2401 code=lzma_code(&lzma_info,LZMA_RUN);
2402 if (code != LZMA_OK)
2403 status=MagickFalse;
2404 length=(size_t) (lzma_info.next_out-compress_pixels);
2405 if (length != 0)
2406 {
2407 (void) WriteBlobMSBLong(image,(unsigned int) length);
2408 (void) WriteBlob(image,length,compress_pixels);
2409 }
2410 } while (lzma_info.avail_in != 0);
cristy26377172010-12-20 19:01:58 +00002411 break;
2412 }
2413#endif
2414#if defined(MAGICKCORE_ZLIB_DELEGATE)
2415 case LZWCompression:
2416 case ZipCompression:
2417 {
cristy26377172010-12-20 19:01:58 +00002418 zip_info.next_in=pixels;
2419 zip_info.avail_in=(uInt) (packet_size*image->columns);
cristy4c08aed2011-07-01 19:47:50 +00002420 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002421 quantum_type,pixels,exception);
cristy26377172010-12-20 19:01:58 +00002422 do
2423 {
cristy3a99dcf2011-12-17 01:29:40 +00002424 int
2425 code;
2426
cristy26377172010-12-20 19:01:58 +00002427 zip_info.next_out=compress_pixels;
2428 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns);
2429 code=deflate(&zip_info,Z_SYNC_FLUSH);
2430 if (code != Z_OK)
2431 status=MagickFalse;
2432 length=(size_t) (zip_info.next_out-compress_pixels);
2433 if (length != 0)
2434 {
2435 (void) WriteBlobMSBLong(image,(unsigned int) length);
2436 (void) WriteBlob(image,length,compress_pixels);
2437 }
2438 } while (zip_info.avail_in != 0);
cristy3ed852e2009-09-05 21:47:34 +00002439 break;
2440 }
2441#endif
2442 case RLECompression:
2443 {
cristy4c08aed2011-07-01 19:47:50 +00002444 length=0;
cristy803640d2011-11-17 02:11:32 +00002445 GetPixelInfoPixel(image,p,&pixel);
cristyed231572011-07-14 02:18:59 +00002446 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00002447 for (x=1; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002448 {
cristy803640d2011-11-17 02:11:32 +00002449 GetPixelInfoPixel(image,p,&target);
cristy4c08aed2011-07-01 19:47:50 +00002450 if ((length < 255) &&
2451 (IsPixelInfoEquivalent(&pixel,&target) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00002452 length++;
2453 else
2454 {
cristyc82a27b2011-10-21 01:07:16 +00002455 q=PopRunlengthPacket(image,q,length,&pixel,exception);
cristy3ed852e2009-09-05 21:47:34 +00002456 length=0;
2457 }
cristy803640d2011-11-17 02:11:32 +00002458 GetPixelInfoPixel(image,p,&pixel);
cristyed231572011-07-14 02:18:59 +00002459 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002460 }
cristyc82a27b2011-10-21 01:07:16 +00002461 q=PopRunlengthPacket(image,q,length,&pixel,exception);
cristy3ed852e2009-09-05 21:47:34 +00002462 (void) WriteBlob(image,(size_t) (q-pixels),pixels);
2463 break;
2464 }
2465 default:
2466 {
cristy4c08aed2011-07-01 19:47:50 +00002467 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002468 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002469 (void) WriteBlob(image,packet_size*image->columns,pixels);
2470 break;
2471 }
2472 }
cristycee97112010-05-28 00:44:52 +00002473 if (image->previous == (Image *) NULL)
2474 {
2475 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2476 image->rows);
2477 if (status == MagickFalse)
2478 break;
2479 }
cristy3ed852e2009-09-05 21:47:34 +00002480 }
cristy330af6c2010-12-21 14:36:06 +00002481 switch (compression)
2482 {
2483#if defined(MAGICKCORE_BZLIB_DELEGATE)
2484 case BZipCompression:
2485 {
cristy3a99dcf2011-12-17 01:29:40 +00002486 int
2487 code;
2488
cristy330af6c2010-12-21 14:36:06 +00002489 for ( ; ; )
2490 {
2491 if (status == MagickFalse)
2492 break;
2493 bzip_info.next_out=(char *) compress_pixels;
2494 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size*
2495 image->columns);
2496 code=BZ2_bzCompress(&bzip_info,BZ_FINISH);
cristy330af6c2010-12-21 14:36:06 +00002497 length=(size_t) (bzip_info.next_out-(char *) compress_pixels);
2498 if (length != 0)
2499 {
2500 (void) WriteBlobMSBLong(image,(unsigned int) length);
2501 (void) WriteBlob(image,length,compress_pixels);
2502 }
2503 if (code == BZ_STREAM_END)
2504 break;
2505 }
2506 code=BZ2_bzCompressEnd(&bzip_info);
2507 if (code != BZ_OK)
2508 status=MagickFalse;
2509 break;
2510 }
2511#endif
2512#if defined(MAGICKCORE_LZMA_DELEGATE)
2513 case LZMACompression:
2514 {
cristy3a99dcf2011-12-17 01:29:40 +00002515 int
2516 code;
2517
cristy330af6c2010-12-21 14:36:06 +00002518 for ( ; ; )
2519 {
2520 if (status == MagickFalse)
2521 break;
2522 lzma_info.next_out=compress_pixels;
2523 lzma_info.avail_out=packet_size*image->columns;
2524 code=lzma_code(&lzma_info,LZMA_FINISH);
cristy330af6c2010-12-21 14:36:06 +00002525 length=(size_t) (lzma_info.next_out-compress_pixels);
2526 if (length > 6)
2527 {
2528 (void) WriteBlobMSBLong(image,(unsigned int) length);
2529 (void) WriteBlob(image,length,compress_pixels);
2530 }
2531 if (code == LZMA_STREAM_END)
2532 break;
2533 }
2534 lzma_end(&lzma_info);
2535 break;
2536 }
2537#endif
2538#if defined(MAGICKCORE_ZLIB_DELEGATE)
2539 case LZWCompression:
2540 case ZipCompression:
2541 {
cristy3a99dcf2011-12-17 01:29:40 +00002542 int
2543 code;
2544
cristy330af6c2010-12-21 14:36:06 +00002545 for ( ; ; )
2546 {
2547 if (status == MagickFalse)
2548 break;
2549 zip_info.next_out=compress_pixels;
cristyc3ca81b2011-10-17 18:05:54 +00002550 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns);
cristy330af6c2010-12-21 14:36:06 +00002551 code=deflate(&zip_info,Z_FINISH);
cristy330af6c2010-12-21 14:36:06 +00002552 length=(size_t) (zip_info.next_out-compress_pixels);
2553 if (length > 6)
2554 {
2555 (void) WriteBlobMSBLong(image,(unsigned int) length);
2556 (void) WriteBlob(image,length,compress_pixels);
2557 }
2558 if (code == Z_STREAM_END)
2559 break;
2560 }
2561 code=deflateEnd(&zip_info);
2562 if (code != Z_OK)
2563 status=MagickFalse;
2564 break;
2565 }
2566#endif
2567 default:
2568 break;
2569 }
cristy3ed852e2009-09-05 21:47:34 +00002570 quantum_info=DestroyQuantumInfo(quantum_info);
2571 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
2572 if (GetNextImageInList(image) == (Image *) NULL)
2573 break;
2574 image=SyncNextImageInList(image);
2575 status=SetImageProgress(image,SaveImagesTag,scene++,
2576 GetImageListLength(image));
2577 if (status == MagickFalse)
2578 break;
2579 } while (image_info->adjoin != MagickFalse);
2580 (void) CloseBlob(image);
2581 return(status);
2582}