blob: fc6966678571b28ee21a1f37da6eb7d29b5678ee [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% PPPP N N M M %
7% P P NN N MM MM %
8% PPPP N N N M M M %
9% P N NN M M %
10% P N N M M %
11% %
12% %
13% Read/Write PBMPlus Portable Anymap Image Format %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy7e41fe82010-12-04 23:12:08 +000020% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
42#include "magick/studio.h"
43#include "magick/blob.h"
44#include "magick/blob-private.h"
45#include "magick/cache.h"
46#include "magick/color.h"
47#include "magick/color-private.h"
48#include "magick/colorspace.h"
49#include "magick/exception.h"
50#include "magick/exception-private.h"
51#include "magick/image.h"
52#include "magick/image-private.h"
53#include "magick/list.h"
54#include "magick/magick.h"
55#include "magick/memory_.h"
cristyf2f27272009-12-17 14:48:46 +000056#include "magick/module.h"
cristy3ed852e2009-09-05 21:47:34 +000057#include "magick/monitor.h"
58#include "magick/monitor-private.h"
59#include "magick/pixel-private.h"
60#include "magick/property.h"
61#include "magick/quantum-private.h"
62#include "magick/static.h"
63#include "magick/statistic.h"
64#include "magick/string_.h"
cristyf2f27272009-12-17 14:48:46 +000065#include "magick/string-private.h"
cristy3ed852e2009-09-05 21:47:34 +000066
67/*
68 Forward declarations.
69*/
70static MagickBooleanType
71 WritePNMImage(const ImageInfo *,Image *);
72
73/*
74%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75% %
76% %
77% %
78% I s P N M %
79% %
80% %
81% %
82%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83%
84% IsPNM() returns MagickTrue if the image format type, identified by the
85% magick string, is PNM.
86%
87% The format of the IsPNM method is:
88%
89% MagickBooleanType IsPNM(const unsigned char *magick,const size_t extent)
90%
91% A description of each parameter follows:
92%
93% o magick: compare image format pattern against these bytes.
94%
95% o extent: Specifies the extent of the magick string.
96%
97*/
98static MagickBooleanType IsPNM(const unsigned char *magick,const size_t extent)
99{
100 if (extent < 2)
101 return(MagickFalse);
102 if ((*magick == (unsigned char) 'P') &&
103 ((magick[1] == '1') || (magick[1] == '2') || (magick[1] == '3') ||
104 (magick[1] == '4') || (magick[1] == '5') || (magick[1] == '6') ||
105 (magick[1] == '7') || (magick[1] == 'F') || (magick[1] == 'f')))
106 return(MagickTrue);
107 return(MagickFalse);
108}
109
110/*
111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
112% %
113% %
114% %
115% R e a d P N M I m a g e %
116% %
117% %
118% %
119%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120%
121% ReadPNMImage() reads a Portable Anymap image file and returns it.
122% It allocates the memory necessary for the new Image structure and returns
123% a pointer to the new image.
124%
125% The format of the ReadPNMImage method is:
126%
127% Image *ReadPNMImage(const ImageInfo *image_info,ExceptionInfo *exception)
128%
129% A description of each parameter follows:
130%
131% o image_info: the image info.
132%
133% o exception: return any errors or warnings in this structure.
134%
135*/
136
cristybb503372010-05-27 20:51:26 +0000137static inline ssize_t ConstrainPixel(Image *image,const ssize_t offset,
138 const size_t extent)
cristy3ed852e2009-09-05 21:47:34 +0000139{
cristybb503372010-05-27 20:51:26 +0000140 if ((offset < 0) || (offset > (ssize_t) extent))
cristy3ed852e2009-09-05 21:47:34 +0000141 {
142 (void) ThrowMagickException(&image->exception,GetMagickModule(),
143 CorruptImageError,"InvalidPixel","`%s'",image->filename);
144 return(0);
145 }
146 return(offset);
147}
148
cristybb503372010-05-27 20:51:26 +0000149static size_t PNMInteger(Image *image,const unsigned int base)
cristy3ed852e2009-09-05 21:47:34 +0000150{
151 char
152 *comment;
153
154 int
155 c;
156
157 register char
158 *p;
159
160 size_t
161 extent;
162
cristybb503372010-05-27 20:51:26 +0000163 size_t
cristy3ed852e2009-09-05 21:47:34 +0000164 value;
165
166 /*
167 Skip any leading whitespace.
168 */
169 extent=MaxTextExtent;
170 comment=(char *) NULL;
171 p=comment;
172 do
173 {
174 c=ReadBlobByte(image);
175 if (c == EOF)
176 return(0);
177 if (c == (int) '#')
178 {
179 /*
180 Read comment.
181 */
182 if (comment == (char *) NULL)
183 comment=AcquireString((char *) NULL);
184 p=comment+strlen(comment);
185 for ( ; (c != EOF) && (c != (int) '\n'); p++)
186 {
187 if ((size_t) (p-comment+1) >= extent)
188 {
189 extent<<=1;
190 comment=(char *) ResizeQuantumMemory(comment,extent+MaxTextExtent,
191 sizeof(*comment));
192 if (comment == (char *) NULL)
193 break;
194 p=comment+strlen(comment);
195 }
196 c=ReadBlobByte(image);
197 *p=(char) c;
198 *(p+1)='\0';
199 }
200 if (comment == (char *) NULL)
201 return(0);
202 continue;
203 }
204 } while (isdigit(c) == MagickFalse);
205 if (comment != (char *) NULL)
206 {
207 (void) SetImageProperty(image,"comment",comment);
208 comment=DestroyString(comment);
209 }
210 if (base == 2)
cristybb503372010-05-27 20:51:26 +0000211 return((size_t) (c-(int) '0'));
cristy3ed852e2009-09-05 21:47:34 +0000212 /*
213 Evaluate number.
214 */
215 value=0;
216 do
217 {
218 value*=10;
219 value+=c-(int) '0';
220 c=ReadBlobByte(image);
221 if (c == EOF)
222 return(value);
223 } while (isdigit(c) != MagickFalse);
224 return(value);
225}
226
227static Image *ReadPNMImage(const ImageInfo *image_info,ExceptionInfo *exception)
228{
229 char
230 format;
231
232 double
233 quantum_scale;
234
235 Image
236 *image;
237
cristybb503372010-05-27 20:51:26 +0000238 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000239 row,
240 y;
241
242 MagickBooleanType
243 status;
244
245 Quantum
246 *scale;
247
248 QuantumInfo
249 *quantum_info;
250
251 QuantumType
252 quantum_type;
253
cristybb503372010-05-27 20:51:26 +0000254 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000255 i;
256
257 size_t
258 extent,
259 packet_size;
260
261 ssize_t
262 count;
263
cristybb503372010-05-27 20:51:26 +0000264 size_t
cristy3ed852e2009-09-05 21:47:34 +0000265 depth,
266 max_value;
267
cristy3ed852e2009-09-05 21:47:34 +0000268 /*
269 Open image file.
270 */
271 assert(image_info != (const ImageInfo *) NULL);
272 assert(image_info->signature == MagickSignature);
273 if (image_info->debug != MagickFalse)
274 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
275 image_info->filename);
276 assert(exception != (ExceptionInfo *) NULL);
277 assert(exception->signature == MagickSignature);
278 image=AcquireImage(image_info);
279 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
280 if (status == MagickFalse)
281 {
282 image=DestroyImageList(image);
283 return((Image *) NULL);
284 }
285 /*
286 Read PNM image.
287 */
288 count=ReadBlob(image,1,(unsigned char *) &format);
289 do
290 {
291 /*
292 Initialize image structure.
293 */
294 if ((count != 1) || (format != 'P'))
295 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
296 max_value=1;
297 quantum_type=RGBQuantum;
298 quantum_scale=1.0;
299 format=(char) ReadBlobByte(image);
300 if (format != '7')
301 {
302 /*
303 PBM, PGM, PPM, and PNM.
304 */
305 image->columns=PNMInteger(image,10);
306 image->rows=PNMInteger(image,10);
307 if ((format == 'f') || (format == 'F'))
308 {
309 char
310 scale[MaxTextExtent];
311
312 (void) ReadBlobString(image,scale);
cristyf2f27272009-12-17 14:48:46 +0000313 quantum_scale=StringToDouble(scale);
cristy3ed852e2009-09-05 21:47:34 +0000314 }
315 else
316 {
317 if ((format == '1') || (format == '4'))
318 max_value=1; /* bitmap */
319 else
320 max_value=PNMInteger(image,10);
321 }
322 }
323 else
324 {
325 char
326 keyword[MaxTextExtent],
327 value[MaxTextExtent];
328
329 int
330 c;
331
332 register char
333 *p;
334
335 /*
336 PAM.
337 */
338 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
339 {
340 while (isspace((int) ((unsigned char) c)) != 0)
341 c=ReadBlobByte(image);
342 p=keyword;
343 do
344 {
345 if ((size_t) (p-keyword) < (MaxTextExtent-1))
346 *p++=c;
347 c=ReadBlobByte(image);
348 } while (isalnum(c));
349 *p='\0';
350 if (LocaleCompare(keyword,"endhdr") == 0)
351 break;
352 while (isspace((int) ((unsigned char) c)) != 0)
353 c=ReadBlobByte(image);
354 p=value;
355 while (isalnum(c) || (c == '_'))
356 {
357 if ((size_t) (p-value) < (MaxTextExtent-1))
358 *p++=c;
359 c=ReadBlobByte(image);
360 }
361 *p='\0';
362 /*
363 Assign a value to the specified keyword.
364 */
365 if (LocaleCompare(keyword,"depth") == 0)
cristye27293e2009-12-18 02:53:20 +0000366 packet_size=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000367 if (LocaleCompare(keyword,"height") == 0)
cristye27293e2009-12-18 02:53:20 +0000368 image->rows=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000369 if (LocaleCompare(keyword,"maxval") == 0)
cristye27293e2009-12-18 02:53:20 +0000370 max_value=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000371 if (LocaleCompare(keyword,"TUPLTYPE") == 0)
372 {
373 if (LocaleCompare(value,"BLACKANDWHITE") == 0)
374 quantum_type=GrayQuantum;
375 if (LocaleCompare(value,"BLACKANDWHITE_ALPHA") == 0)
376 {
377 quantum_type=GrayAlphaQuantum;
378 image->matte=MagickTrue;
379 }
380 if (LocaleCompare(value,"GRAYSCALE") == 0)
381 quantum_type=GrayQuantum;
382 if (LocaleCompare(value,"GRAYSCALE_ALPHA") == 0)
383 {
384 quantum_type=GrayAlphaQuantum;
385 image->matte=MagickTrue;
386 }
387 if (LocaleCompare(value,"RGB_ALPHA") == 0)
388 {
389 quantum_type=RGBAQuantum;
390 image->matte=MagickTrue;
391 }
392 if (LocaleCompare(value,"CMYK") == 0)
393 {
394 quantum_type=CMYKQuantum;
395 image->colorspace=CMYKColorspace;
396 }
397 if (LocaleCompare(value,"CMYK_ALPHA") == 0)
398 {
399 quantum_type=CMYKAQuantum;
400 image->colorspace=CMYKColorspace;
401 image->matte=MagickTrue;
402 }
403 }
404 if (LocaleCompare(keyword,"width") == 0)
cristye27293e2009-12-18 02:53:20 +0000405 image->columns=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000406 }
407 }
408 if ((image->columns == 0) || (image->rows == 0))
409 ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
410 if (max_value >= 65536)
411 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
412 for (depth=1; GetQuantumRange(depth) < max_value; depth++) ;
413 image->depth=depth;
414 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
415 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
416 break;
417 /*
418 Convert PNM pixels to runextent-encoded MIFF packets.
419 */
420 status=MagickTrue;
421 row=0;
422 switch (format)
423 {
424 case '1':
425 {
426 /*
427 Convert PBM image to pixel packets.
428 */
cristybb503372010-05-27 20:51:26 +0000429 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000430 {
cristybb503372010-05-27 20:51:26 +0000431 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000432 x;
433
434 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000435 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000436
437 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
438 if (q == (PixelPacket *) NULL)
439 break;
cristybb503372010-05-27 20:51:26 +0000440 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000441 {
442 q->red=(Quantum) (PNMInteger(image,2) == 0 ? QuantumRange : 0);
443 q->green=q->red;
444 q->blue=q->red;
445 q++;
446 }
447 if (SyncAuthenticPixels(image,exception) == MagickFalse)
448 break;
449 if (image->previous == (Image *) NULL)
450 {
cristycee97112010-05-28 00:44:52 +0000451 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
452 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000453 if (status == MagickFalse)
454 break;
455 }
456 }
457 image->type=BilevelType;
458 break;
459 }
460 case '2':
461 {
cristybb503372010-05-27 20:51:26 +0000462 size_t
cristy3ed852e2009-09-05 21:47:34 +0000463 intensity;
464
465 /*
466 Convert PGM image to pixel packets.
467 */
468 scale=(Quantum *) NULL;
469 if (max_value != (1U*QuantumRange))
470 {
471 /*
472 Compute pixel scaling table.
473 */
474 scale=(Quantum *) AcquireQuantumMemory((size_t) max_value+1UL,
475 sizeof(*scale));
476 if (scale == (Quantum *) NULL)
477 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000478 for (i=0; i <= (ssize_t) max_value; i++)
cristy3ed852e2009-09-05 21:47:34 +0000479 scale[i]=(Quantum) (((double) QuantumRange*i)/max_value+0.5);
480 }
cristybb503372010-05-27 20:51:26 +0000481 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000482 {
cristybb503372010-05-27 20:51:26 +0000483 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000484 x;
485
486 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000487 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000488
489 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
490 if (q == (PixelPacket *) NULL)
491 break;
cristybb503372010-05-27 20:51:26 +0000492 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000493 {
494 intensity=PNMInteger(image,10);
cristy3ed852e2009-09-05 21:47:34 +0000495 q->red=(Quantum) intensity;
cristyac23fd22010-05-11 14:48:58 +0000496 if (scale != (Quantum *) NULL)
cristybb503372010-05-27 20:51:26 +0000497 q->red=scale[ConstrainPixel(image,(ssize_t) intensity,max_value)];
cristy3ed852e2009-09-05 21:47:34 +0000498 q->green=q->red;
499 q->blue=q->red;
500 q++;
501 }
502 if (SyncAuthenticPixels(image,exception) == MagickFalse)
503 break;
504 if (image->previous == (Image *) NULL)
505 {
cristycee97112010-05-28 00:44:52 +0000506 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
507 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000508 if (status == MagickFalse)
509 break;
510 }
511 }
512 image->type=GrayscaleType;
513 if (scale != (Quantum *) NULL)
514 scale=(Quantum *) RelinquishMagickMemory(scale);
515 break;
516 }
517 case '3':
518 {
519 MagickPixelPacket
520 pixel;
521
522 /*
523 Convert PNM image to pixel packets.
524 */
525 scale=(Quantum *) NULL;
526 if (max_value != (1U*QuantumRange))
527 {
528 /*
529 Compute pixel scaling table.
530 */
531 scale=(Quantum *) AcquireQuantumMemory((size_t) max_value+1UL,
532 sizeof(*scale));
533 if (scale == (Quantum *) NULL)
534 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000535 for (i=0; i <= (ssize_t) max_value; i++)
cristy3ed852e2009-09-05 21:47:34 +0000536 scale[i]=(Quantum) (((double) QuantumRange*i)/max_value+0.5);
537 }
cristybb503372010-05-27 20:51:26 +0000538 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000539 {
cristybb503372010-05-27 20:51:26 +0000540 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000541 x;
542
543 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000544 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000545
546 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
547 if (q == (PixelPacket *) NULL)
548 break;
cristybb503372010-05-27 20:51:26 +0000549 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000550 {
551 pixel.red=(MagickRealType) PNMInteger(image,10);
552 pixel.green=(MagickRealType) PNMInteger(image,10);
553 pixel.blue=(MagickRealType) PNMInteger(image,10);
554 if (scale != (Quantum *) NULL)
555 {
cristybb503372010-05-27 20:51:26 +0000556 pixel.red=(MagickRealType) scale[ConstrainPixel(image,(ssize_t)
cristy3ed852e2009-09-05 21:47:34 +0000557 pixel.red,max_value)];
cristy34575212010-11-06 12:39:23 +0000558 pixel.green=(MagickRealType) scale[ConstrainPixel(image,
559 (ssize_t) pixel.green,max_value)];
cristybb503372010-05-27 20:51:26 +0000560 pixel.blue=(MagickRealType) scale[ConstrainPixel(image,(ssize_t)
cristy3ed852e2009-09-05 21:47:34 +0000561 pixel.blue,max_value)];
562 }
563 q->red=(Quantum) pixel.red;
564 q->green=(Quantum) pixel.green;
565 q->blue=(Quantum) pixel.blue;
566 q++;
567 }
568 if (SyncAuthenticPixels(image,exception) == MagickFalse)
569 break;
570 if (image->previous == (Image *) NULL)
571 {
cristycee97112010-05-28 00:44:52 +0000572 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
573 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000574 if (status == MagickFalse)
575 break;
576 }
577 }
578 if (scale != (Quantum *) NULL)
579 scale=(Quantum *) RelinquishMagickMemory(scale);
580 break;
581 }
582 case '4':
583 {
584 /*
585 Convert PBM raw image to pixel packets.
586 */
587 quantum_type=GrayQuantum;
588 if (image->storage_class == PseudoClass)
589 quantum_type=IndexQuantum;
590 quantum_info=AcquireQuantumInfo(image_info,image);
591 if (quantum_info == (QuantumInfo *) NULL)
592 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
593 SetQuantumMinIsWhite(quantum_info,MagickTrue);
594 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +0000595 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000596 {
cristybb503372010-05-27 20:51:26 +0000597 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000598 offset;
599
600 MagickBooleanType
601 sync;
602
603 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000604 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000605
606 ssize_t
607 count;
608
609 size_t
610 length;
611
612 unsigned char
613 *pixels;
614
615 if (status == MagickFalse)
616 continue;
617 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000618 {
619 count=ReadBlob(image,extent,pixels);
620 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
621 (image->previous == (Image *) NULL))
622 {
623 MagickBooleanType
624 proceed;
625
cristycee97112010-05-28 00:44:52 +0000626 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
627 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000628 if (proceed == MagickFalse)
629 status=MagickFalse;
630 }
631 offset=row++;
632 }
633 if (count != (ssize_t) extent)
634 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000635 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +0000636 if (q == (PixelPacket *) NULL)
637 {
638 status=MagickFalse;
639 continue;
640 }
cristyaa740112010-03-30 17:58:44 +0000641 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
642 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +0000643 if (length != extent)
644 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000645 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000646 if (sync == MagickFalse)
647 status=MagickFalse;
648 }
cristy3ed852e2009-09-05 21:47:34 +0000649 quantum_info=DestroyQuantumInfo(quantum_info);
650 if (status == MagickFalse)
651 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
652 SetQuantumImageType(image,quantum_type);
653 break;
654 }
655 case '5':
656 {
657 QuantumAny
658 range;
659
660 /*
661 Convert PGM raw image to pixel packets.
662 */
663 range=GetQuantumRange(image->depth);
664 quantum_type=GrayQuantum;
665 extent=(image->depth <= 8 ? 1 : 2)*image->columns;
666 quantum_info=AcquireQuantumInfo(image_info,image);
667 if (quantum_info == (QuantumInfo *) NULL)
668 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000669 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000670 {
cristybb503372010-05-27 20:51:26 +0000671 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000672 offset;
673
674 MagickBooleanType
675 sync;
676
677 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000678 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000679
cristybb503372010-05-27 20:51:26 +0000680 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000681 x;
682
683 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000684 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000685
686 ssize_t
687 count;
688
689 unsigned char
690 *pixels;
691
692 if (status == MagickFalse)
693 continue;
694 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000695 {
696 count=ReadBlob(image,extent,pixels);
697 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
698 (image->previous == (Image *) NULL))
699 {
700 MagickBooleanType
701 proceed;
702
cristy34575212010-11-06 12:39:23 +0000703 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
704 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000705 if (proceed == MagickFalse)
706 status=MagickFalse;
707 }
708 offset=row++;
709 }
710 if (count != (ssize_t) extent)
711 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000712 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +0000713 if (q == (PixelPacket *) NULL)
714 {
715 status=MagickFalse;
716 continue;
717 }
718 p=pixels;
719 if ((image->depth == 8) || (image->depth == 16))
cristyaa740112010-03-30 17:58:44 +0000720 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3ed852e2009-09-05 21:47:34 +0000721 quantum_type,pixels,exception);
722 else
723 if (image->depth <= 8)
724 {
725 unsigned char
726 pixel;
727
cristybb503372010-05-27 20:51:26 +0000728 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000729 {
730 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +0000731 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +0000732 q->green=q->red;
733 q->blue=q->red;
734 q++;
735 }
736 }
737 else
738 {
739 unsigned short
740 pixel;
741
cristybb503372010-05-27 20:51:26 +0000742 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000743 {
744 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +0000745 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +0000746 q->green=q->red;
747 q->blue=q->red;
748 q++;
749 }
750 }
cristyaa740112010-03-30 17:58:44 +0000751 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000752 if (sync == MagickFalse)
753 status=MagickFalse;
754 }
cristy3ed852e2009-09-05 21:47:34 +0000755 quantum_info=DestroyQuantumInfo(quantum_info);
756 if (status == MagickFalse)
757 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
758 SetQuantumImageType(image,quantum_type);
759 break;
760 }
761 case '6':
762 {
763 ImageType
764 type;
765
766 QuantumAny
767 range;
768
769 /*
770 Convert PNM raster image to pixel packets.
771 */
772 type=BilevelType;
773 quantum_type=RGBQuantum;
774 extent=3*(image->depth <= 8 ? 1 : 2)*image->columns;
775 range=GetQuantumRange(image->depth);
776 quantum_info=AcquireQuantumInfo(image_info,image);
777 if (quantum_info == (QuantumInfo *) NULL)
778 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000779 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000780 {
cristybb503372010-05-27 20:51:26 +0000781 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000782 offset;
783
784 MagickBooleanType
785 sync;
786
787 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000788 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000789
cristybb503372010-05-27 20:51:26 +0000790 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000791 x;
792
793 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000794 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000795
796 ssize_t
797 count;
798
cristy3ed852e2009-09-05 21:47:34 +0000799 unsigned char
800 *pixels;
801
802 if (status == MagickFalse)
803 continue;
804 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000805 {
806 count=ReadBlob(image,extent,pixels);
807 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
808 (image->previous == (Image *) NULL))
809 {
810 MagickBooleanType
811 proceed;
812
cristy34575212010-11-06 12:39:23 +0000813 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
814 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000815 if (proceed == MagickFalse)
816 status=MagickFalse;
817 }
818 offset=row++;
819 }
820 if (count != (ssize_t) extent)
821 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000822 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +0000823 if (q == (PixelPacket *) NULL)
824 {
825 status=MagickFalse;
826 continue;
827 }
828 p=pixels;
cristye90d7402010-03-14 18:21:29 +0000829 if (image->depth == 8)
cristybb503372010-05-27 20:51:26 +0000830 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000831 {
cristye90d7402010-03-14 18:21:29 +0000832 q->red=ScaleCharToQuantum(*p++);
833 q->green=ScaleCharToQuantum(*p++);
834 q->blue=ScaleCharToQuantum(*p++);
835 q->opacity=OpaqueOpacity;
836 q++;
cristy3ed852e2009-09-05 21:47:34 +0000837 }
838 else
cristye90d7402010-03-14 18:21:29 +0000839 if (image->depth == 16)
cristy3ed852e2009-09-05 21:47:34 +0000840 {
841 unsigned short
842 pixel;
843
cristybb503372010-05-27 20:51:26 +0000844 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000845 {
846 p=PushShortPixel(MSBEndian,p,&pixel);
cristye90d7402010-03-14 18:21:29 +0000847 q->red=ScaleShortToQuantum(pixel);
cristy3ed852e2009-09-05 21:47:34 +0000848 p=PushShortPixel(MSBEndian,p,&pixel);
cristye90d7402010-03-14 18:21:29 +0000849 q->green=ScaleShortToQuantum(pixel);
cristy3ed852e2009-09-05 21:47:34 +0000850 p=PushShortPixel(MSBEndian,p,&pixel);
cristye90d7402010-03-14 18:21:29 +0000851 q->blue=ScaleShortToQuantum(pixel);
852 q->opacity=OpaqueOpacity;
853 q++;
cristy3ed852e2009-09-05 21:47:34 +0000854 }
855 }
cristye90d7402010-03-14 18:21:29 +0000856 else
857 if (image->depth <= 8)
858 {
859 unsigned char
860 pixel;
861
cristybb503372010-05-27 20:51:26 +0000862 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000863 {
864 p=PushCharPixel(p,&pixel);
865 q->red=ScaleAnyToQuantum(pixel,range);
866 p=PushCharPixel(p,&pixel);
867 q->green=ScaleAnyToQuantum(pixel,range);
868 p=PushCharPixel(p,&pixel);
869 q->blue=ScaleAnyToQuantum(pixel,range);
870 q->opacity=OpaqueOpacity;
871 q++;
872 }
873 }
874 else
875 {
876 unsigned short
877 pixel;
878
cristybb503372010-05-27 20:51:26 +0000879 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000880 {
881 p=PushShortPixel(MSBEndian,p,&pixel);
882 q->red=ScaleAnyToQuantum(pixel,range);
883 p=PushShortPixel(MSBEndian,p,&pixel);
884 q->green=ScaleAnyToQuantum(pixel,range);
885 p=PushShortPixel(MSBEndian,p,&pixel);
886 q->blue=ScaleAnyToQuantum(pixel,range);
887 q->opacity=OpaqueOpacity;
888 q++;
889 }
890 }
cristy3ed852e2009-09-05 21:47:34 +0000891 if ((type == BilevelType) || (type == GrayscaleType))
cristy3ed852e2009-09-05 21:47:34 +0000892 {
cristyaa740112010-03-30 17:58:44 +0000893 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristybb503372010-05-27 20:51:26 +0000894 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000895 {
896 if ((type == BilevelType) &&
897 (IsMonochromePixel(q) == MagickFalse))
cristyc8e4cd42010-12-23 21:36:08 +0000898 type=IsGrayPixel(q) == MagickFalse ? UndefinedColorType :
cristye90d7402010-03-14 18:21:29 +0000899 GrayscaleType;
900 if ((type == GrayscaleType) && (IsGrayPixel(q) == MagickFalse))
cristyc8e4cd42010-12-23 21:36:08 +0000901 type=UndefinedColorType;
cristye90d7402010-03-14 18:21:29 +0000902 if ((type != BilevelType) && (type != GrayscaleType))
903 break;
904 q++;
905 }
cristy3ed852e2009-09-05 21:47:34 +0000906 }
cristyaa740112010-03-30 17:58:44 +0000907 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000908 if (sync == MagickFalse)
909 status=MagickFalse;
910 }
cristy3ed852e2009-09-05 21:47:34 +0000911 quantum_info=DestroyQuantumInfo(quantum_info);
912 if (status == MagickFalse)
913 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
cristyc8e4cd42010-12-23 21:36:08 +0000914 if (type != UndefinedColorType)
cristy3ed852e2009-09-05 21:47:34 +0000915 image->type=type;
916 break;
917 }
918 case '7':
919 {
920 register IndexPacket
921 *indexes;
922
923 QuantumAny
924 range;
925
cristybb503372010-05-27 20:51:26 +0000926 size_t
cristy3ed852e2009-09-05 21:47:34 +0000927 channels;
928
929 /*
930 Convert PAM raster image to pixel packets.
931 */
932 range=GetQuantumRange(image->depth);
933 switch (quantum_type)
934 {
935 case GrayQuantum:
936 case GrayAlphaQuantum:
937 {
938 channels=1;
939 break;
940 }
941 case CMYKQuantum:
942 case CMYKAQuantum:
943 {
944 channels=4;
945 break;
946 }
947 default:
948 {
949 channels=3;
950 break;
951 }
952 }
953 if (image->matte != MagickFalse)
954 channels++;
955 extent=channels*(image->depth <= 8 ? 1 : 2)*image->columns;
956 quantum_info=AcquireQuantumInfo(image_info,image);
957 if (quantum_info == (QuantumInfo *) NULL)
958 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000959 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000960 {
cristybb503372010-05-27 20:51:26 +0000961 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000962 offset;
963
964 MagickBooleanType
965 sync;
966
967 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000968 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000969
cristybb503372010-05-27 20:51:26 +0000970 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000971 x;
972
973 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000974 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000975
976 ssize_t
977 count;
978
979 unsigned char
980 *pixels;
981
982 if (status == MagickFalse)
983 continue;
984 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000985 {
986 count=ReadBlob(image,extent,pixels);
987 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
988 (image->previous == (Image *) NULL))
989 {
990 MagickBooleanType
991 proceed;
992
cristy34575212010-11-06 12:39:23 +0000993 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
994 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000995 if (proceed == MagickFalse)
996 status=MagickFalse;
997 }
998 offset=row++;
999 }
1000 if (count != (ssize_t) extent)
1001 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +00001002 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001003 if (q == (PixelPacket *) NULL)
1004 {
1005 status=MagickFalse;
1006 continue;
1007 }
cristyaa740112010-03-30 17:58:44 +00001008 indexes=GetAuthenticIndexQueue(image);
cristy3ed852e2009-09-05 21:47:34 +00001009 p=pixels;
1010 if ((image->depth == 8) || (image->depth == 16))
cristyaa740112010-03-30 17:58:44 +00001011 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3ed852e2009-09-05 21:47:34 +00001012 quantum_type,pixels,exception);
1013 else
1014 switch (quantum_type)
1015 {
1016 case GrayQuantum:
1017 case GrayAlphaQuantum:
1018 {
1019 if (image->depth <= 8)
1020 {
1021 unsigned char
1022 pixel;
1023
cristybb503372010-05-27 20:51:26 +00001024 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001025 {
1026 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001027 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001028 q->green=q->red;
1029 q->blue=q->red;
cristyce70c172010-01-07 17:15:30 +00001030 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001031 if (image->matte != MagickFalse)
1032 {
1033 p=PushCharPixel(p,&pixel);
cristy34575212010-11-06 12:39:23 +00001034 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,
1035 range));
cristy3ed852e2009-09-05 21:47:34 +00001036 }
1037 q++;
1038 }
1039 }
1040 else
1041 {
1042 unsigned short
1043 pixel;
1044
cristybb503372010-05-27 20:51:26 +00001045 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001046 {
1047 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001048 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001049 q->green=q->red;
1050 q->blue=q->red;
cristyce70c172010-01-07 17:15:30 +00001051 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001052 if (image->matte != MagickFalse)
1053 {
1054 p=PushShortPixel(MSBEndian,p,&pixel);
cristy34575212010-11-06 12:39:23 +00001055 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,
1056 range));
cristy3ed852e2009-09-05 21:47:34 +00001057 }
1058 q++;
1059 }
1060 }
1061 break;
1062 }
1063 case CMYKQuantum:
1064 case CMYKAQuantum:
1065 {
1066 if (image->depth <= 8)
1067 {
1068 unsigned char
1069 pixel;
1070
cristybb503372010-05-27 20:51:26 +00001071 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001072 {
1073 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001074 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001075 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001076 SetGreenPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001077 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001078 SetBluePixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001079 p=PushCharPixel(p,&pixel);
1080 indexes[x]=ScaleAnyToQuantum(pixel,range);
cristyce70c172010-01-07 17:15:30 +00001081 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001082 if (image->matte != MagickFalse)
1083 {
1084 p=PushCharPixel(p,&pixel);
cristy34575212010-11-06 12:39:23 +00001085 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,
1086 range));
cristy3ed852e2009-09-05 21:47:34 +00001087 }
1088 q++;
1089 }
1090 }
1091 else
1092 {
1093 unsigned short
1094 pixel;
1095
cristybb503372010-05-27 20:51:26 +00001096 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001097 {
1098 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001099 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001100 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001101 SetGreenPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001102 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001103 SetBluePixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001104 p=PushShortPixel(MSBEndian,p,&pixel);
1105 indexes[x]=ScaleAnyToQuantum(pixel,range);
cristyce70c172010-01-07 17:15:30 +00001106 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001107 if (image->matte != MagickFalse)
1108 {
1109 p=PushShortPixel(MSBEndian,p,&pixel);
cristy34575212010-11-06 12:39:23 +00001110 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,
1111 range));
cristy3ed852e2009-09-05 21:47:34 +00001112 }
1113 q++;
1114 }
1115 }
1116 break;
1117 }
1118 default:
1119 {
1120 if (image->depth <= 8)
1121 {
1122 unsigned char
1123 pixel;
1124
cristybb503372010-05-27 20:51:26 +00001125 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001126 {
1127 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001128 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001129 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001130 SetGreenPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001131 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001132 SetBluePixelComponent(q,ScaleAnyToQuantum(pixel,range));
1133 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001134 if (image->matte != MagickFalse)
1135 {
1136 p=PushCharPixel(p,&pixel);
cristy34575212010-11-06 12:39:23 +00001137 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,
1138 range));
cristy3ed852e2009-09-05 21:47:34 +00001139 }
1140 q++;
1141 }
1142 }
1143 else
1144 {
1145 unsigned short
1146 pixel;
1147
cristybb503372010-05-27 20:51:26 +00001148 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001149 {
1150 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001151 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001152 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001153 SetGreenPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001154 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001155 SetBluePixelComponent(q,ScaleAnyToQuantum(pixel,range));
1156 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001157 if (image->matte != MagickFalse)
1158 {
1159 p=PushShortPixel(MSBEndian,p,&pixel);
cristy34575212010-11-06 12:39:23 +00001160 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,
1161 range));
cristy3ed852e2009-09-05 21:47:34 +00001162 }
1163 q++;
1164 }
1165 }
1166 break;
1167 }
1168 }
cristyaa740112010-03-30 17:58:44 +00001169 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001170 if (sync == MagickFalse)
1171 status=MagickFalse;
1172 }
cristy3ed852e2009-09-05 21:47:34 +00001173 quantum_info=DestroyQuantumInfo(quantum_info);
1174 if (status == MagickFalse)
1175 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1176 SetQuantumImageType(image,quantum_type);
1177 break;
1178 }
1179 case 'F':
1180 case 'f':
1181 {
1182 /*
1183 Convert PFM raster image to pixel packets.
1184 */
1185 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
1186 image->endian=quantum_scale < 0.0 ? LSBEndian : MSBEndian;
1187 image->depth=32;
1188 quantum_info=AcquireQuantumInfo(image_info,image);
1189 if (quantum_info == (QuantumInfo *) NULL)
1190 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1191 status=SetQuantumDepth(image,quantum_info,32);
1192 if (status == MagickFalse)
1193 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1194 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1195 if (status == MagickFalse)
1196 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1197 SetQuantumScale(quantum_info,(MagickRealType) QuantumRange*
1198 fabs(quantum_scale));
1199 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +00001200 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001201 {
cristybb503372010-05-27 20:51:26 +00001202 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001203 offset;
1204
1205 MagickBooleanType
1206 sync;
1207
1208 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001209 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001210
1211 ssize_t
1212 count;
1213
1214 size_t
1215 length;
1216
1217 unsigned char
1218 *pixels;
1219
1220 if (status == MagickFalse)
1221 continue;
1222 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001223 {
1224 count=ReadBlob(image,extent,pixels);
1225 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1226 (image->previous == (Image *) NULL))
1227 {
1228 MagickBooleanType
1229 proceed;
1230
cristy34575212010-11-06 12:39:23 +00001231 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1232 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001233 if (proceed == MagickFalse)
1234 status=MagickFalse;
1235 }
1236 offset=row++;
1237 }
1238 if ((size_t) count != extent)
1239 status=MagickFalse;
cristybb503372010-05-27 20:51:26 +00001240 q=QueueAuthenticPixels(image,0,(ssize_t) (image->rows-offset-1),
cristyaa740112010-03-30 17:58:44 +00001241 image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001242 if (q == (PixelPacket *) NULL)
1243 {
1244 status=MagickFalse;
1245 continue;
1246 }
cristyaa740112010-03-30 17:58:44 +00001247 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1248 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001249 if (length != extent)
1250 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +00001251 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001252 if (sync == MagickFalse)
1253 status=MagickFalse;
1254 }
cristy3ed852e2009-09-05 21:47:34 +00001255 quantum_info=DestroyQuantumInfo(quantum_info);
1256 if (status == MagickFalse)
1257 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1258 SetQuantumImageType(image,quantum_type);
1259 break;
1260 }
1261 default:
1262 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1263 }
1264 if (EOFBlob(image) != MagickFalse)
1265 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
1266 "UnexpectedEndOfFile","`%s'",image->filename);
1267 /*
1268 Proceed to next image.
1269 */
1270 if (image_info->number_scenes != 0)
1271 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1272 break;
1273 if ((format == '1') || (format == '2') || (format == '3'))
1274 do
1275 {
1276 /*
1277 Skip to end of line.
1278 */
1279 count=ReadBlob(image,1,(unsigned char *) &format);
1280 if (count == 0)
1281 break;
1282 if ((count != 0) && (format == 'P'))
1283 break;
1284 } while (format != '\n');
1285 count=ReadBlob(image,1,(unsigned char *) &format);
1286 if ((count == 1) && (format == 'P'))
1287 {
1288 /*
1289 Allocate next image structure.
1290 */
1291 AcquireNextImage(image_info,image);
1292 if (GetNextImageInList(image) == (Image *) NULL)
1293 {
1294 image=DestroyImageList(image);
1295 return((Image *) NULL);
1296 }
1297 image=SyncNextImageInList(image);
1298 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1299 GetBlobSize(image));
1300 if (status == MagickFalse)
1301 break;
1302 }
1303 } while ((count == 1) && (format == 'P'));
1304 (void) CloseBlob(image);
1305 return(GetFirstImageInList(image));
1306}
1307
1308/*
1309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1310% %
1311% %
1312% %
1313% R e g i s t e r P N M I m a g e %
1314% %
1315% %
1316% %
1317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1318%
1319% RegisterPNMImage() adds properties for the PNM image format to
1320% the list of supported formats. The properties include the image format
1321% tag, a method to read and/or write the format, whether the format
1322% supports the saving of more than one frame to the same file or blob,
1323% whether the format supports native in-memory I/O, and a brief
1324% description of the format.
1325%
1326% The format of the RegisterPNMImage method is:
1327%
cristybb503372010-05-27 20:51:26 +00001328% size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001329%
1330*/
cristybb503372010-05-27 20:51:26 +00001331ModuleExport size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001332{
1333 MagickInfo
1334 *entry;
1335
1336 entry=SetMagickInfo("PAM");
1337 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1338 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1339 entry->description=ConstantString("Common 2-dimensional bitmap format");
1340 entry->module=ConstantString("PNM");
1341 (void) RegisterMagickInfo(entry);
1342 entry=SetMagickInfo("PBM");
1343 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1344 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1345 entry->description=ConstantString("Portable bitmap format (black and white)");
1346 entry->module=ConstantString("PNM");
1347 (void) RegisterMagickInfo(entry);
1348 entry=SetMagickInfo("PFM");
1349 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1350 entry->encoder=(EncodeImageHandler *) WritePNMImage;
cristye96405a2010-05-19 02:24:31 +00001351 entry->endian_support=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00001352 entry->description=ConstantString("Portable float format");
1353 entry->module=ConstantString("PFM");
1354 (void) RegisterMagickInfo(entry);
1355 entry=SetMagickInfo("PGM");
1356 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1357 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1358 entry->description=ConstantString("Portable graymap format (gray scale)");
1359 entry->module=ConstantString("PNM");
1360 (void) RegisterMagickInfo(entry);
1361 entry=SetMagickInfo("PNM");
1362 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1363 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1364 entry->magick=(IsImageFormatHandler *) IsPNM;
1365 entry->description=ConstantString("Portable anymap");
1366 entry->module=ConstantString("PNM");
1367 (void) RegisterMagickInfo(entry);
1368 entry=SetMagickInfo("PPM");
1369 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1370 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1371 entry->description=ConstantString("Portable pixmap format (color)");
1372 entry->module=ConstantString("PNM");
1373 (void) RegisterMagickInfo(entry);
1374 return(MagickImageCoderSignature);
1375}
1376
1377/*
1378%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1379% %
1380% %
1381% %
1382% U n r e g i s t e r P N M I m a g e %
1383% %
1384% %
1385% %
1386%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1387%
1388% UnregisterPNMImage() removes format registrations made by the
1389% PNM module from the list of supported formats.
1390%
1391% The format of the UnregisterPNMImage method is:
1392%
1393% UnregisterPNMImage(void)
1394%
1395*/
1396ModuleExport void UnregisterPNMImage(void)
1397{
1398 (void) UnregisterMagickInfo("PAM");
1399 (void) UnregisterMagickInfo("PBM");
1400 (void) UnregisterMagickInfo("PGM");
1401 (void) UnregisterMagickInfo("PNM");
1402 (void) UnregisterMagickInfo("PPM");
1403}
1404
1405/*
1406%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1407% %
1408% %
1409% %
1410% W r i t e P N M I m a g e %
1411% %
1412% %
1413% %
1414%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1415%
cristy661b5ad2010-01-13 00:54:42 +00001416% WritePNMImage() writes an image to a file in the PNM rasterfile format.
cristy3ed852e2009-09-05 21:47:34 +00001417%
1418% The format of the WritePNMImage method is:
1419%
1420% MagickBooleanType WritePNMImage(const ImageInfo *image_info,Image *image)
1421%
1422% A description of each parameter follows.
1423%
1424% o image_info: the image info.
1425%
1426% o image: The image.
1427%
1428*/
1429static MagickBooleanType WritePNMImage(const ImageInfo *image_info,Image *image)
1430{
1431 char
1432 buffer[MaxTextExtent],
1433 format,
1434 magick[MaxTextExtent];
1435
1436 const char
1437 *value;
1438
1439 IndexPacket
1440 index;
1441
cristybb503372010-05-27 20:51:26 +00001442 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001443 y;
1444
1445 MagickBooleanType
1446 status;
1447
1448 MagickOffsetType
1449 scene;
1450
1451 QuantumAny
1452 pixel;
1453
1454 QuantumInfo
1455 *quantum_info;
1456
1457 QuantumType
1458 quantum_type;
1459
cristybb503372010-05-27 20:51:26 +00001460 register ssize_t
cristy661b5ad2010-01-13 00:54:42 +00001461 i;
1462
cristy3ed852e2009-09-05 21:47:34 +00001463 register unsigned char
1464 *pixels,
1465 *q;
1466
cristy3ed852e2009-09-05 21:47:34 +00001467 size_t
1468 extent,
1469 packet_size;
1470
cristy95802a72010-09-05 19:07:17 +00001471 ssize_t
1472 count;
1473
cristy3ed852e2009-09-05 21:47:34 +00001474 /*
1475 Open output image file.
1476 */
1477 assert(image_info != (const ImageInfo *) NULL);
1478 assert(image_info->signature == MagickSignature);
1479 assert(image != (Image *) NULL);
1480 assert(image->signature == MagickSignature);
1481 if (image->debug != MagickFalse)
1482 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1483 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1484 if (status == MagickFalse)
1485 return(status);
1486 scene=0;
1487 do
1488 {
1489 /*
1490 Write PNM file header.
1491 */
1492 packet_size=3;
1493 quantum_type=RGBQuantum;
1494 (void) CopyMagickString(magick,image_info->magick,MaxTextExtent);
1495 switch (magick[1])
1496 {
1497 case 'A':
1498 case 'a':
1499 {
1500 format='7';
1501 break;
1502 }
1503 case 'B':
1504 case 'b':
1505 {
1506 format='4';
1507 if (image_info->compression == NoCompression)
1508 format='1';
1509 break;
1510 }
1511 case 'F':
1512 case 'f':
1513 {
1514 format='F';
1515 if (IsGrayImage(image,&image->exception) != MagickFalse)
1516 format='f';
1517 break;
1518 }
1519 case 'G':
1520 case 'g':
1521 {
1522 format='5';
1523 if (image_info->compression == NoCompression)
1524 format='2';
1525 break;
1526 }
1527 case 'N':
1528 case 'n':
1529 {
1530 if ((image_info->type != TrueColorType) &&
1531 (IsGrayImage(image,&image->exception) != MagickFalse))
1532 {
1533 format='5';
1534 if (image_info->compression == NoCompression)
1535 format='2';
1536 if (IsMonochromeImage(image,&image->exception) != MagickFalse)
1537 {
1538 format='4';
1539 if (image_info->compression == NoCompression)
1540 format='1';
1541 }
1542 break;
1543 }
1544 }
1545 default:
1546 {
1547 format='6';
1548 if (image_info->compression == NoCompression)
1549 format='3';
1550 break;
1551 }
1552 }
1553 (void) FormatMagickString(buffer,MaxTextExtent,"P%c\n",format);
1554 (void) WriteBlobString(image,buffer);
1555 value=GetImageProperty(image,"comment");
1556 if (value != (const char *) NULL)
1557 {
1558 register const char
1559 *p;
1560
1561 /*
1562 Write comments to file.
1563 */
1564 (void) WriteBlobByte(image,'#');
1565 for (p=value; *p != '\0'; p++)
1566 {
1567 (void) WriteBlobByte(image,(unsigned char) *p);
1568 if ((*p == '\r') && (*(p+1) != '\0'))
1569 (void) WriteBlobByte(image,'#');
1570 if ((*p == '\n') && (*(p+1) != '\0'))
1571 (void) WriteBlobByte(image,'#');
1572 }
1573 (void) WriteBlobByte(image,'\n');
1574 }
1575 if (format != '7')
1576 {
1577 if (image->colorspace != RGBColorspace)
1578 (void) TransformImageColorspace(image,RGBColorspace);
cristye8c25f92010-06-03 00:53:06 +00001579 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g %.20g\n",
1580 (double) image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001581 (void) WriteBlobString(image,buffer);
1582 }
1583 else
1584 {
1585 char
1586 type[MaxTextExtent];
1587
1588 /*
1589 PAM header.
1590 */
1591 (void) FormatMagickString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00001592 "WIDTH %.20g\nHEIGHT %.20g\n",(double) image->columns,(double)
1593 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001594 (void) WriteBlobString(image,buffer);
1595 quantum_type=GetQuantumType(image,&image->exception);
1596 switch (quantum_type)
1597 {
1598 case CMYKQuantum:
1599 case CMYKAQuantum:
1600 {
1601 packet_size=4;
1602 (void) CopyMagickString(type,"CMYK",MaxTextExtent);
1603 break;
1604 }
1605 case GrayQuantum:
1606 case GrayAlphaQuantum:
1607 {
1608 packet_size=1;
1609 (void) CopyMagickString(type,"GRAYSCALE",MaxTextExtent);
1610 break;
1611 }
1612 default:
1613 {
1614 quantum_type=RGBQuantum;
1615 if (image->matte != MagickFalse)
1616 quantum_type=RGBAQuantum;
1617 packet_size=3;
1618 (void) CopyMagickString(type,"RGB",MaxTextExtent);
1619 break;
1620 }
1621 }
1622 if (image->matte != MagickFalse)
1623 {
1624 packet_size++;
1625 (void) ConcatenateMagickString(type,"_ALPHA",MaxTextExtent);
1626 }
1627 if (image->depth > 16)
1628 image->depth=16;
1629 (void) FormatMagickString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00001630 "DEPTH %.20g\nMAXVAL %.20g\n",(double) packet_size,(double)
cristy3ed852e2009-09-05 21:47:34 +00001631 GetQuantumRange(image->depth));
1632 (void) WriteBlobString(image,buffer);
1633 (void) FormatMagickString(buffer,MaxTextExtent,"TUPLTYPE %s\nENDHDR\n",
1634 type);
1635 (void) WriteBlobString(image,buffer);
1636 }
1637 /*
1638 Convert runextent encoded to PNM raster pixels.
1639 */
1640 switch (format)
1641 {
1642 case '1':
1643 {
cristy661b5ad2010-01-13 00:54:42 +00001644 unsigned char
1645 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001646
1647 /*
1648 Convert image to a PBM image.
1649 */
cristy661b5ad2010-01-13 00:54:42 +00001650 q=pixels;
cristybb503372010-05-27 20:51:26 +00001651 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001652 {
1653 register const IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00001654 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00001655
1656 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001657 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001658
cristybb503372010-05-27 20:51:26 +00001659 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001660 x;
1661
1662 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1663 if (p == (const PixelPacket *) NULL)
1664 break;
1665 indexes=GetVirtualIndexQueue(image);
cristybb503372010-05-27 20:51:26 +00001666 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001667 {
1668 pixel=PixelIntensityToQuantum(p);
cristy661b5ad2010-01-13 00:54:42 +00001669 *q++=(unsigned char) (pixel >= (Quantum) (QuantumRange/2) ?
1670 '0' : '1');
1671 *q++=' ';
1672 if ((q-pixels+2) >= 80)
1673 {
1674 *q++='\n';
1675 (void) WriteBlob(image,q-pixels,pixels);
1676 q=pixels;
1677 i=0;
1678 }
cristy3ed852e2009-09-05 21:47:34 +00001679 p++;
1680 }
1681 if (image->previous == (Image *) NULL)
1682 {
cristycee97112010-05-28 00:44:52 +00001683 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1684 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001685 if (status == MagickFalse)
1686 break;
1687 }
1688 }
cristy661b5ad2010-01-13 00:54:42 +00001689 if (q != pixels)
1690 {
1691 *q++='\n';
1692 (void) WriteBlob(image,q-pixels,pixels);
1693 }
cristy3ed852e2009-09-05 21:47:34 +00001694 break;
1695 }
1696 case '2':
1697 {
cristy661b5ad2010-01-13 00:54:42 +00001698 unsigned char
1699 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001700
1701 /*
1702 Convert image to a PGM image.
1703 */
1704 if (image->depth <= 8)
1705 (void) WriteBlobString(image,"255\n");
1706 else
1707 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001708 q=pixels;
cristybb503372010-05-27 20:51:26 +00001709 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001710 {
1711 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001712 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001713
cristybb503372010-05-27 20:51:26 +00001714 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001715 x;
1716
1717 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1718 if (p == (const PixelPacket *) NULL)
1719 break;
cristybb503372010-05-27 20:51:26 +00001720 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001721 {
1722 index=PixelIntensityToQuantum(p);
1723 if (image->depth <= 8)
1724 count=(ssize_t) FormatMagickString(buffer,MaxTextExtent,"%u ",
1725 ScaleQuantumToChar(index));
1726 else
1727 count=(ssize_t) FormatMagickString(buffer,MaxTextExtent,"%u ",
1728 ScaleQuantumToShort(index));
cristy661b5ad2010-01-13 00:54:42 +00001729 extent=(size_t) count;
1730 (void) strncpy((char *) q,buffer,extent);
1731 q+=extent;
1732 if ((q-pixels+extent) >= 80)
1733 {
1734 *q++='\n';
1735 (void) WriteBlob(image,q-pixels,pixels);
1736 q=pixels;
1737 }
cristy3ed852e2009-09-05 21:47:34 +00001738 p++;
1739 }
1740 if (image->previous == (Image *) NULL)
1741 {
cristycee97112010-05-28 00:44:52 +00001742 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1743 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001744 if (status == MagickFalse)
1745 break;
1746 }
1747 }
cristy661b5ad2010-01-13 00:54:42 +00001748 if (q != pixels)
1749 {
1750 *q++='\n';
1751 (void) WriteBlob(image,q-pixels,pixels);
1752 }
cristy3ed852e2009-09-05 21:47:34 +00001753 break;
1754 }
1755 case '3':
1756 {
cristy661b5ad2010-01-13 00:54:42 +00001757 unsigned char
1758 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001759
1760 /*
1761 Convert image to a PNM image.
1762 */
1763 if (image->depth <= 8)
1764 (void) WriteBlobString(image,"255\n");
1765 else
1766 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001767 q=pixels;
cristybb503372010-05-27 20:51:26 +00001768 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001769 {
1770 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001771 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001772
cristybb503372010-05-27 20:51:26 +00001773 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001774 x;
1775
1776 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1777 if (p == (const PixelPacket *) NULL)
1778 break;
cristybb503372010-05-27 20:51:26 +00001779 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001780 {
1781 if (image->depth <= 8)
1782 count=(ssize_t) FormatMagickString(buffer,MaxTextExtent,
cristyce70c172010-01-07 17:15:30 +00001783 "%u %u %u ",ScaleQuantumToChar(GetRedPixelComponent(p)),
cristy375dc4b2010-01-12 20:24:58 +00001784 ScaleQuantumToChar(GetGreenPixelComponent(p)),
1785 ScaleQuantumToChar(GetBluePixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00001786 else
1787 count=(ssize_t) FormatMagickString(buffer,MaxTextExtent,
cristyce70c172010-01-07 17:15:30 +00001788 "%u %u %u ",ScaleQuantumToShort(GetRedPixelComponent(p)),
cristy375dc4b2010-01-12 20:24:58 +00001789 ScaleQuantumToShort(GetGreenPixelComponent(p)),
1790 ScaleQuantumToShort(GetBluePixelComponent(p)));
cristy661b5ad2010-01-13 00:54:42 +00001791 extent=(size_t) count;
1792 (void) strncpy((char *) q,buffer,extent);
1793 q+=extent;
1794 if ((q-pixels+extent) >= 80)
1795 {
1796 *q++='\n';
1797 (void) WriteBlob(image,q-pixels,pixels);
1798 q=pixels;
1799 }
cristy3ed852e2009-09-05 21:47:34 +00001800 p++;
1801 }
1802 if (image->previous == (Image *) NULL)
1803 {
cristycee97112010-05-28 00:44:52 +00001804 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1805 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001806 if (status == MagickFalse)
1807 break;
1808 }
1809 }
cristy661b5ad2010-01-13 00:54:42 +00001810 if (q != pixels)
1811 {
1812 *q++='\n';
1813 (void) WriteBlob(image,q-pixels,pixels);
1814 }
cristy3ed852e2009-09-05 21:47:34 +00001815 break;
1816 }
1817 case '4':
1818 {
1819 /*
1820 Convert image to a PBM image.
1821 */
1822 image->depth=1;
1823 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1824 if (quantum_info == (QuantumInfo *) NULL)
1825 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1826 quantum_info->min_is_white=MagickTrue;
1827 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00001828 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001829 {
1830 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001831 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001832
1833 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1834 if (p == (const PixelPacket *) NULL)
1835 break;
1836 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
1837 quantum_info,GrayQuantum,pixels,&image->exception);
1838 count=WriteBlob(image,extent,pixels);
1839 if (count != (ssize_t) extent)
1840 break;
1841 if (image->previous == (Image *) NULL)
1842 {
cristycee97112010-05-28 00:44:52 +00001843 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1844 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001845 if (status == MagickFalse)
1846 break;
1847 }
1848 }
1849 quantum_info=DestroyQuantumInfo(quantum_info);
1850 break;
1851 }
1852 case '5':
1853 {
1854 QuantumAny
1855 range;
1856
1857 /*
1858 Convert image to a PGM image.
1859 */
1860 if (image->depth > 8)
1861 image->depth=16;
cristye8c25f92010-06-03 00:53:06 +00001862 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g\n",(double)
cristy3ed852e2009-09-05 21:47:34 +00001863 GetQuantumRange(image->depth));
1864 (void) WriteBlobString(image,buffer);
1865 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1866 if (quantum_info == (QuantumInfo *) NULL)
1867 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1868 quantum_info->min_is_white=MagickTrue;
1869 pixels=GetQuantumPixels(quantum_info);
1870 extent=GetQuantumExtent(image,quantum_info,GrayQuantum);
1871 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001872 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001873 {
1874 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001875 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001876
cristybb503372010-05-27 20:51:26 +00001877 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001878 x;
1879
1880 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1881 if (p == (const PixelPacket *) NULL)
1882 break;
1883 q=pixels;
1884 if ((image->depth == 8) || (image->depth == 16))
1885 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
1886 quantum_info,GrayQuantum,pixels,&image->exception);
1887 else
1888 {
1889 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00001890 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001891 {
1892 if (IsGrayPixel(p) == MagickFalse)
1893 pixel=ScaleQuantumToAny(PixelIntensityToQuantum(p),range);
1894 else
1895 {
1896 if (image->depth == 8)
cristyce70c172010-01-07 17:15:30 +00001897 pixel=ScaleQuantumToChar(GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00001898 else
1899 pixel=ScaleQuantumToAny(p->red,range);
1900 }
1901 q=PopCharPixel((unsigned char) pixel,q);
1902 p++;
1903 }
1904 else
cristybb503372010-05-27 20:51:26 +00001905 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001906 {
1907 if (IsGrayPixel(p) == MagickFalse)
1908 pixel=ScaleQuantumToAny(PixelIntensityToQuantum(p),range);
1909 else
1910 {
1911 if (image->depth == 16)
cristyce70c172010-01-07 17:15:30 +00001912 pixel=ScaleQuantumToShort(GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00001913 else
1914 pixel=ScaleQuantumToAny(p->red,range);
1915 }
1916 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
1917 p++;
1918 }
1919 extent=(size_t) (q-pixels);
1920 }
1921 count=WriteBlob(image,extent,pixels);
1922 if (count != (ssize_t) extent)
1923 break;
1924 if (image->previous == (Image *) NULL)
1925 {
cristycee97112010-05-28 00:44:52 +00001926 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1927 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001928 if (status == MagickFalse)
1929 break;
1930 }
1931 }
1932 quantum_info=DestroyQuantumInfo(quantum_info);
1933 break;
1934 }
1935 case '6':
1936 {
1937 QuantumAny
1938 range;
1939
1940 /*
1941 Convert image to a PNM image.
1942 */
1943 if (image->depth > 8)
1944 image->depth=16;
cristye8c25f92010-06-03 00:53:06 +00001945 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g\n",(double)
cristy3ed852e2009-09-05 21:47:34 +00001946 GetQuantumRange(image->depth));
1947 (void) WriteBlobString(image,buffer);
1948 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1949 if (quantum_info == (QuantumInfo *) NULL)
1950 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1951 pixels=GetQuantumPixels(quantum_info);
1952 extent=GetQuantumExtent(image,quantum_info,quantum_type);
1953 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001954 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001955 {
1956 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001957 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001958
cristybb503372010-05-27 20:51:26 +00001959 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001960 x;
1961
1962 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1963 if (p == (const PixelPacket *) NULL)
1964 break;
1965 q=pixels;
1966 if ((image->depth == 8) || (image->depth == 16))
1967 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
1968 quantum_info,quantum_type,pixels,&image->exception);
1969 else
1970 {
1971 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00001972 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001973 {
1974 pixel=ScaleQuantumToAny(p->red,range);
1975 q=PopCharPixel((unsigned char) pixel,q);
1976 pixel=ScaleQuantumToAny(p->green,range);
1977 q=PopCharPixel((unsigned char) pixel,q);
1978 pixel=ScaleQuantumToAny(p->blue,range);
1979 q=PopCharPixel((unsigned char) pixel,q);
cristy3ed852e2009-09-05 21:47:34 +00001980 p++;
1981 }
1982 else
cristybb503372010-05-27 20:51:26 +00001983 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001984 {
1985 pixel=ScaleQuantumToAny(p->red,range);
1986 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
1987 pixel=ScaleQuantumToAny(p->green,range);
1988 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
1989 pixel=ScaleQuantumToAny(p->blue,range);
1990 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy3ed852e2009-09-05 21:47:34 +00001991 p++;
1992 }
1993 extent=(size_t) (q-pixels);
1994 }
1995 count=WriteBlob(image,extent,pixels);
1996 if (count != (ssize_t) extent)
1997 break;
1998 if (image->previous == (Image *) NULL)
1999 {
cristycee97112010-05-28 00:44:52 +00002000 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2001 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002002 if (status == MagickFalse)
2003 break;
2004 }
2005 }
2006 quantum_info=DestroyQuantumInfo(quantum_info);
2007 break;
2008 }
2009 case '7':
2010 {
2011 QuantumAny
2012 range;
2013
2014 /*
2015 Convert image to a PAM.
2016 */
2017 if (image->depth > 16)
2018 image->depth=16;
2019 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
2020 pixels=GetQuantumPixels(quantum_info);
2021 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00002022 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002023 {
2024 register const IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002025 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002026
2027 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002028 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002029
cristybb503372010-05-27 20:51:26 +00002030 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002031 x;
2032
2033 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2034 if (p == (const PixelPacket *) NULL)
2035 break;
2036 indexes=GetVirtualIndexQueue(image);
2037 q=pixels;
2038 if ((image->depth == 8) || (image->depth == 16))
2039 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
2040 quantum_info,quantum_type,pixels,&image->exception);
2041 else
2042 {
2043 switch (quantum_type)
2044 {
2045 case GrayQuantum:
2046 case GrayAlphaQuantum:
2047 {
2048 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002049 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002050 {
2051 pixel=ScaleQuantumToAny(PixelIntensityToQuantum(p),range);
2052 q=PopCharPixel((unsigned char) pixel,q);
2053 if (image->matte != MagickFalse)
2054 {
2055 pixel=(unsigned char) ScaleQuantumToAny(p->opacity,
2056 range);
2057 q=PopCharPixel((unsigned char) pixel,q);
2058 }
2059 p++;
2060 }
2061 else
cristybb503372010-05-27 20:51:26 +00002062 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002063 {
2064 pixel=ScaleQuantumToAny(PixelIntensityToQuantum(p),range);
2065 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2066 if (image->matte != MagickFalse)
2067 {
2068 pixel=(unsigned char) ScaleQuantumToAny(p->opacity,
2069 range);
2070 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2071 }
2072 p++;
2073 }
2074 break;
2075 }
2076 case CMYKQuantum:
2077 case CMYKAQuantum:
2078 {
2079 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002080 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002081 {
2082 pixel=ScaleQuantumToAny(p->red,range);
2083 q=PopCharPixel((unsigned char) pixel,q);
2084 pixel=ScaleQuantumToAny(p->green,range);
2085 q=PopCharPixel((unsigned char) pixel,q);
2086 pixel=ScaleQuantumToAny(p->blue,range);
2087 q=PopCharPixel((unsigned char) pixel,q);
2088 pixel=ScaleQuantumToAny(indexes[x],range);
2089 q=PopCharPixel((unsigned char) pixel,q);
2090 if (image->matte != MagickFalse)
2091 {
2092 pixel=ScaleQuantumToAny((Quantum) (QuantumRange-
cristyce70c172010-01-07 17:15:30 +00002093 GetOpacityPixelComponent(p)),range);
cristy3ed852e2009-09-05 21:47:34 +00002094 q=PopCharPixel((unsigned char) pixel,q);
2095 }
2096 p++;
2097 }
2098 else
cristybb503372010-05-27 20:51:26 +00002099 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002100 {
2101 pixel=ScaleQuantumToAny(p->red,range);
2102 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2103 pixel=ScaleQuantumToAny(p->green,range);
2104 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2105 pixel=ScaleQuantumToAny(p->blue,range);
2106 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2107 pixel=ScaleQuantumToAny(indexes[x],range);
2108 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2109 if (image->matte != MagickFalse)
2110 {
2111 pixel=ScaleQuantumToAny((Quantum) (QuantumRange-
cristyce70c172010-01-07 17:15:30 +00002112 GetOpacityPixelComponent(p)),range);
cristy3ed852e2009-09-05 21:47:34 +00002113 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2114 }
2115 p++;
2116 }
2117 break;
2118 }
2119 default:
2120 {
2121 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002122 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002123 {
2124 pixel=ScaleQuantumToAny(p->red,range);
2125 q=PopCharPixel((unsigned char) pixel,q);
2126 pixel=ScaleQuantumToAny(p->green,range);
2127 q=PopCharPixel((unsigned char) pixel,q);
2128 pixel=ScaleQuantumToAny(p->blue,range);
2129 q=PopCharPixel((unsigned char) pixel,q);
2130 if (image->matte != MagickFalse)
2131 {
2132 pixel=ScaleQuantumToAny((Quantum) (QuantumRange-
cristyce70c172010-01-07 17:15:30 +00002133 GetOpacityPixelComponent(p)),range);
cristy3ed852e2009-09-05 21:47:34 +00002134 q=PopCharPixel((unsigned char) pixel,q);
2135 }
2136 p++;
2137 }
2138 else
cristybb503372010-05-27 20:51:26 +00002139 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002140 {
2141 pixel=ScaleQuantumToAny(p->red,range);
2142 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2143 pixel=ScaleQuantumToAny(p->green,range);
2144 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2145 pixel=ScaleQuantumToAny(p->blue,range);
2146 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2147 if (image->matte != MagickFalse)
2148 {
2149 pixel=ScaleQuantumToAny((Quantum) (QuantumRange-
cristyce70c172010-01-07 17:15:30 +00002150 GetOpacityPixelComponent(p)),range);
cristy3ed852e2009-09-05 21:47:34 +00002151 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2152 }
2153 p++;
2154 }
2155 break;
2156 }
2157 }
2158 extent=(size_t) (q-pixels);
2159 }
2160 count=WriteBlob(image,extent,pixels);
2161 if (count != (ssize_t) extent)
2162 break;
2163 if (image->previous == (Image *) NULL)
2164 {
cristycee97112010-05-28 00:44:52 +00002165 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2166 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002167 if (status == MagickFalse)
2168 break;
2169 }
2170 }
2171 quantum_info=DestroyQuantumInfo(quantum_info);
2172 break;
2173 }
2174 case 'F':
2175 case 'f':
2176 {
2177 (void) WriteBlobString(image,image->endian != LSBEndian ? "1.0\n" :
2178 "-1.0\n");
2179 image->depth=32;
2180 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
2181 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
2182 if (quantum_info == (QuantumInfo *) NULL)
2183 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2184 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2185 if (status == MagickFalse)
2186 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2187 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002188 for (y=(ssize_t) image->rows-1; y >= 0; y--)
cristy3ed852e2009-09-05 21:47:34 +00002189 {
2190 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002191 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002192
2193 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2194 if (p == (const PixelPacket *) NULL)
2195 break;
2196 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
2197 quantum_info,quantum_type,pixels,&image->exception);
2198 (void) WriteBlob(image,extent,pixels);
2199 if (image->previous == (Image *) NULL)
2200 {
cristycee97112010-05-28 00:44:52 +00002201 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2202 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002203 if (status == MagickFalse)
2204 break;
2205 }
2206 }
2207 quantum_info=DestroyQuantumInfo(quantum_info);
2208 break;
2209 }
2210 }
2211 if (GetNextImageInList(image) == (Image *) NULL)
2212 break;
2213 image=SyncNextImageInList(image);
2214 status=SetImageProgress(image,SaveImagesTag,scene++,
2215 GetImageListLength(image));
2216 if (status == MagickFalse)
2217 break;
2218 } while (image_info->adjoin != MagickFalse);
2219 (void) CloseBlob(image);
2220 return(MagickTrue);
2221}