blob: e743a19ddacef318ce6d1bd8e9f55b119cd67bca [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% %
cristy16af1cb2009-12-11 21:38:29 +000020% Copyright 1999-2010 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
137static inline long ConstrainPixel(Image *image,const long offset,
138 const unsigned long extent)
139{
140 if ((offset < 0) || (offset > (long) extent))
141 {
142 (void) ThrowMagickException(&image->exception,GetMagickModule(),
143 CorruptImageError,"InvalidPixel","`%s'",image->filename);
144 return(0);
145 }
146 return(offset);
147}
148
149static unsigned long PNMInteger(Image *image,const unsigned int base)
150{
151 char
152 *comment;
153
154 int
155 c;
156
157 register char
158 *p;
159
160 size_t
161 extent;
162
163 unsigned long
164 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)
211 return((unsigned long) (c-(int) '0'));
212 /*
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
238 long
239 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
254 register long
255 i;
256
257 size_t
258 extent,
259 packet_size;
260
261 ssize_t
262 count;
263
264 unsigned long
265 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 */
429 for (y=0; y < (long) image->rows; y++)
430 {
431 register long
432 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;
440 for (x=0; x < (long) image->columns; x++)
441 {
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 {
451 status=SetImageProgress(image,LoadImageTag,y,image->rows);
452 if (status == MagickFalse)
453 break;
454 }
455 }
456 image->type=BilevelType;
457 break;
458 }
459 case '2':
460 {
461 unsigned long
462 intensity;
463
464 /*
465 Convert PGM image to pixel packets.
466 */
467 scale=(Quantum *) NULL;
468 if (max_value != (1U*QuantumRange))
469 {
470 /*
471 Compute pixel scaling table.
472 */
473 scale=(Quantum *) AcquireQuantumMemory((size_t) max_value+1UL,
474 sizeof(*scale));
475 if (scale == (Quantum *) NULL)
476 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
477 for (i=0; i <= (long) max_value; i++)
478 scale[i]=(Quantum) (((double) QuantumRange*i)/max_value+0.5);
479 }
480 for (y=0; y < (long) image->rows; y++)
481 {
482 register long
483 x;
484
485 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000486 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000487
488 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
489 if (q == (PixelPacket *) NULL)
490 break;
491 for (x=0; x < (long) image->columns; x++)
492 {
493 intensity=PNMInteger(image,10);
cristy3ed852e2009-09-05 21:47:34 +0000494 q->red=(Quantum) intensity;
cristyac23fd22010-05-11 14:48:58 +0000495 if (scale != (Quantum *) NULL)
496 q->red=scale[ConstrainPixel(image,(long) intensity,max_value)];
cristy3ed852e2009-09-05 21:47:34 +0000497 q->green=q->red;
498 q->blue=q->red;
499 q++;
500 }
501 if (SyncAuthenticPixels(image,exception) == MagickFalse)
502 break;
503 if (image->previous == (Image *) NULL)
504 {
505 status=SetImageProgress(image,LoadImageTag,y,image->rows);
506 if (status == MagickFalse)
507 break;
508 }
509 }
510 image->type=GrayscaleType;
511 if (scale != (Quantum *) NULL)
512 scale=(Quantum *) RelinquishMagickMemory(scale);
513 break;
514 }
515 case '3':
516 {
517 MagickPixelPacket
518 pixel;
519
520 /*
521 Convert PNM image to pixel packets.
522 */
523 scale=(Quantum *) NULL;
524 if (max_value != (1U*QuantumRange))
525 {
526 /*
527 Compute pixel scaling table.
528 */
529 scale=(Quantum *) AcquireQuantumMemory((size_t) max_value+1UL,
530 sizeof(*scale));
531 if (scale == (Quantum *) NULL)
532 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
533 for (i=0; i <= (long) max_value; i++)
534 scale[i]=(Quantum) (((double) QuantumRange*i)/max_value+0.5);
535 }
536 for (y=0; y < (long) image->rows; y++)
537 {
538 register long
539 x;
540
541 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000542 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000543
544 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
545 if (q == (PixelPacket *) NULL)
546 break;
547 for (x=0; x < (long) image->columns; x++)
548 {
549 pixel.red=(MagickRealType) PNMInteger(image,10);
550 pixel.green=(MagickRealType) PNMInteger(image,10);
551 pixel.blue=(MagickRealType) PNMInteger(image,10);
552 if (scale != (Quantum *) NULL)
553 {
554 pixel.red=(MagickRealType) scale[ConstrainPixel(image,(long)
555 pixel.red,max_value)];
556 pixel.green=(MagickRealType) scale[ConstrainPixel(image,(long)
557 pixel.green,max_value)];
558 pixel.blue=(MagickRealType) scale[ConstrainPixel(image,(long)
559 pixel.blue,max_value)];
560 }
561 q->red=(Quantum) pixel.red;
562 q->green=(Quantum) pixel.green;
563 q->blue=(Quantum) pixel.blue;
564 q++;
565 }
566 if (SyncAuthenticPixels(image,exception) == MagickFalse)
567 break;
568 if (image->previous == (Image *) NULL)
569 {
570 status=SetImageProgress(image,LoadImageTag,y,image->rows);
571 if (status == MagickFalse)
572 break;
573 }
574 }
575 if (scale != (Quantum *) NULL)
576 scale=(Quantum *) RelinquishMagickMemory(scale);
577 break;
578 }
579 case '4':
580 {
581 /*
582 Convert PBM raw image to pixel packets.
583 */
584 quantum_type=GrayQuantum;
585 if (image->storage_class == PseudoClass)
586 quantum_type=IndexQuantum;
587 quantum_info=AcquireQuantumInfo(image_info,image);
588 if (quantum_info == (QuantumInfo *) NULL)
589 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
590 SetQuantumMinIsWhite(quantum_info,MagickTrue);
591 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristy3ed852e2009-09-05 21:47:34 +0000592 for (y=0; y < (long) image->rows; y++)
593 {
594 long
595 offset;
596
597 MagickBooleanType
598 sync;
599
600 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000601 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000602
603 ssize_t
604 count;
605
606 size_t
607 length;
608
609 unsigned char
610 *pixels;
611
612 if (status == MagickFalse)
613 continue;
614 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000615 {
616 count=ReadBlob(image,extent,pixels);
617 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
618 (image->previous == (Image *) NULL))
619 {
620 MagickBooleanType
621 proceed;
622
623 proceed=SetImageProgress(image,LoadImageTag,row,image->rows);
624 if (proceed == MagickFalse)
625 status=MagickFalse;
626 }
627 offset=row++;
628 }
629 if (count != (ssize_t) extent)
630 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000631 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +0000632 if (q == (PixelPacket *) NULL)
633 {
634 status=MagickFalse;
635 continue;
636 }
cristyaa740112010-03-30 17:58:44 +0000637 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
638 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +0000639 if (length != extent)
640 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000641 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000642 if (sync == MagickFalse)
643 status=MagickFalse;
644 }
cristy3ed852e2009-09-05 21:47:34 +0000645 quantum_info=DestroyQuantumInfo(quantum_info);
646 if (status == MagickFalse)
647 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
648 SetQuantumImageType(image,quantum_type);
649 break;
650 }
651 case '5':
652 {
653 QuantumAny
654 range;
655
656 /*
657 Convert PGM raw image to pixel packets.
658 */
659 range=GetQuantumRange(image->depth);
660 quantum_type=GrayQuantum;
661 extent=(image->depth <= 8 ? 1 : 2)*image->columns;
662 quantum_info=AcquireQuantumInfo(image_info,image);
663 if (quantum_info == (QuantumInfo *) NULL)
664 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristy3ed852e2009-09-05 21:47:34 +0000665 for (y=0; y < (long) image->rows; y++)
666 {
667 long
668 offset;
669
670 MagickBooleanType
671 sync;
672
673 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000674 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000675
676 register long
677 x;
678
679 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000680 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000681
682 ssize_t
683 count;
684
685 unsigned char
686 *pixels;
687
688 if (status == MagickFalse)
689 continue;
690 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000691 {
692 count=ReadBlob(image,extent,pixels);
693 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
694 (image->previous == (Image *) NULL))
695 {
696 MagickBooleanType
697 proceed;
698
699 proceed=SetImageProgress(image,LoadImageTag,row,image->rows);
700 if (proceed == MagickFalse)
701 status=MagickFalse;
702 }
703 offset=row++;
704 }
705 if (count != (ssize_t) extent)
706 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000707 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +0000708 if (q == (PixelPacket *) NULL)
709 {
710 status=MagickFalse;
711 continue;
712 }
713 p=pixels;
714 if ((image->depth == 8) || (image->depth == 16))
cristyaa740112010-03-30 17:58:44 +0000715 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3ed852e2009-09-05 21:47:34 +0000716 quantum_type,pixels,exception);
717 else
718 if (image->depth <= 8)
719 {
720 unsigned char
721 pixel;
722
723 for (x=0; x < (long) image->columns; x++)
724 {
725 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +0000726 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +0000727 q->green=q->red;
728 q->blue=q->red;
729 q++;
730 }
731 }
732 else
733 {
734 unsigned short
735 pixel;
736
737 for (x=0; x < (long) image->columns; x++)
738 {
739 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +0000740 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +0000741 q->green=q->red;
742 q->blue=q->red;
743 q++;
744 }
745 }
cristyaa740112010-03-30 17:58:44 +0000746 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000747 if (sync == MagickFalse)
748 status=MagickFalse;
749 }
cristy3ed852e2009-09-05 21:47:34 +0000750 quantum_info=DestroyQuantumInfo(quantum_info);
751 if (status == MagickFalse)
752 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
753 SetQuantumImageType(image,quantum_type);
754 break;
755 }
756 case '6':
757 {
758 ImageType
759 type;
760
761 QuantumAny
762 range;
763
764 /*
765 Convert PNM raster image to pixel packets.
766 */
767 type=BilevelType;
768 quantum_type=RGBQuantum;
769 extent=3*(image->depth <= 8 ? 1 : 2)*image->columns;
770 range=GetQuantumRange(image->depth);
771 quantum_info=AcquireQuantumInfo(image_info,image);
772 if (quantum_info == (QuantumInfo *) NULL)
773 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristy3ed852e2009-09-05 21:47:34 +0000774 for (y=0; y < (long) image->rows; y++)
775 {
776 long
777 offset;
778
779 MagickBooleanType
780 sync;
781
782 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000783 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000784
785 register long
786 x;
787
788 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000789 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000790
791 ssize_t
792 count;
793
cristy3ed852e2009-09-05 21:47:34 +0000794 unsigned char
795 *pixels;
796
797 if (status == MagickFalse)
798 continue;
799 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000800 {
801 count=ReadBlob(image,extent,pixels);
802 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
803 (image->previous == (Image *) NULL))
804 {
805 MagickBooleanType
806 proceed;
807
808 proceed=SetImageProgress(image,LoadImageTag,row,image->rows);
809 if (proceed == MagickFalse)
810 status=MagickFalse;
811 }
812 offset=row++;
813 }
814 if (count != (ssize_t) extent)
815 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000816 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +0000817 if (q == (PixelPacket *) NULL)
818 {
819 status=MagickFalse;
820 continue;
821 }
822 p=pixels;
cristye90d7402010-03-14 18:21:29 +0000823 if (image->depth == 8)
824 for (x=0; x < (long) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000825 {
cristye90d7402010-03-14 18:21:29 +0000826 q->red=ScaleCharToQuantum(*p++);
827 q->green=ScaleCharToQuantum(*p++);
828 q->blue=ScaleCharToQuantum(*p++);
829 q->opacity=OpaqueOpacity;
830 q++;
cristy3ed852e2009-09-05 21:47:34 +0000831 }
832 else
cristye90d7402010-03-14 18:21:29 +0000833 if (image->depth == 16)
cristy3ed852e2009-09-05 21:47:34 +0000834 {
835 unsigned short
836 pixel;
837
cristy3ed852e2009-09-05 21:47:34 +0000838 for (x=0; x < (long) image->columns; x++)
839 {
840 p=PushShortPixel(MSBEndian,p,&pixel);
cristye90d7402010-03-14 18:21:29 +0000841 q->red=ScaleShortToQuantum(pixel);
cristy3ed852e2009-09-05 21:47:34 +0000842 p=PushShortPixel(MSBEndian,p,&pixel);
cristye90d7402010-03-14 18:21:29 +0000843 q->green=ScaleShortToQuantum(pixel);
cristy3ed852e2009-09-05 21:47:34 +0000844 p=PushShortPixel(MSBEndian,p,&pixel);
cristye90d7402010-03-14 18:21:29 +0000845 q->blue=ScaleShortToQuantum(pixel);
846 q->opacity=OpaqueOpacity;
847 q++;
cristy3ed852e2009-09-05 21:47:34 +0000848 }
849 }
cristye90d7402010-03-14 18:21:29 +0000850 else
851 if (image->depth <= 8)
852 {
853 unsigned char
854 pixel;
855
856 for (x=0; x < (long) image->columns; x++)
857 {
858 p=PushCharPixel(p,&pixel);
859 q->red=ScaleAnyToQuantum(pixel,range);
860 p=PushCharPixel(p,&pixel);
861 q->green=ScaleAnyToQuantum(pixel,range);
862 p=PushCharPixel(p,&pixel);
863 q->blue=ScaleAnyToQuantum(pixel,range);
864 q->opacity=OpaqueOpacity;
865 q++;
866 }
867 }
868 else
869 {
870 unsigned short
871 pixel;
872
873 for (x=0; x < (long) image->columns; x++)
874 {
875 p=PushShortPixel(MSBEndian,p,&pixel);
876 q->red=ScaleAnyToQuantum(pixel,range);
877 p=PushShortPixel(MSBEndian,p,&pixel);
878 q->green=ScaleAnyToQuantum(pixel,range);
879 p=PushShortPixel(MSBEndian,p,&pixel);
880 q->blue=ScaleAnyToQuantum(pixel,range);
881 q->opacity=OpaqueOpacity;
882 q++;
883 }
884 }
cristy3ed852e2009-09-05 21:47:34 +0000885 if ((type == BilevelType) || (type == GrayscaleType))
cristy3ed852e2009-09-05 21:47:34 +0000886 {
cristyaa740112010-03-30 17:58:44 +0000887 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristye90d7402010-03-14 18:21:29 +0000888 for (x=0; x < (long) image->columns; x++)
889 {
890 if ((type == BilevelType) &&
891 (IsMonochromePixel(q) == MagickFalse))
892 type=IsGrayPixel(q) == MagickFalse ? UndefinedType :
893 GrayscaleType;
894 if ((type == GrayscaleType) && (IsGrayPixel(q) == MagickFalse))
895 type=UndefinedType;
896 if ((type != BilevelType) && (type != GrayscaleType))
897 break;
898 q++;
899 }
cristy3ed852e2009-09-05 21:47:34 +0000900 }
cristyaa740112010-03-30 17:58:44 +0000901 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000902 if (sync == MagickFalse)
903 status=MagickFalse;
904 }
cristy3ed852e2009-09-05 21:47:34 +0000905 quantum_info=DestroyQuantumInfo(quantum_info);
906 if (status == MagickFalse)
907 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
908 if (type != UndefinedType)
909 image->type=type;
910 break;
911 }
912 case '7':
913 {
914 register IndexPacket
915 *indexes;
916
917 QuantumAny
918 range;
919
920 unsigned long
921 channels;
922
923 /*
924 Convert PAM raster image to pixel packets.
925 */
926 range=GetQuantumRange(image->depth);
927 switch (quantum_type)
928 {
929 case GrayQuantum:
930 case GrayAlphaQuantum:
931 {
932 channels=1;
933 break;
934 }
935 case CMYKQuantum:
936 case CMYKAQuantum:
937 {
938 channels=4;
939 break;
940 }
941 default:
942 {
943 channels=3;
944 break;
945 }
946 }
947 if (image->matte != MagickFalse)
948 channels++;
949 extent=channels*(image->depth <= 8 ? 1 : 2)*image->columns;
950 quantum_info=AcquireQuantumInfo(image_info,image);
951 if (quantum_info == (QuantumInfo *) NULL)
952 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristy3ed852e2009-09-05 21:47:34 +0000953 for (y=0; y < (long) image->rows; y++)
954 {
955 long
956 offset;
957
958 MagickBooleanType
959 sync;
960
961 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000962 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000963
964 register long
965 x;
966
967 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000968 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000969
970 ssize_t
971 count;
972
973 unsigned char
974 *pixels;
975
976 if (status == MagickFalse)
977 continue;
978 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000979 {
980 count=ReadBlob(image,extent,pixels);
981 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
982 (image->previous == (Image *) NULL))
983 {
984 MagickBooleanType
985 proceed;
986
987 proceed=SetImageProgress(image,LoadImageTag,row,image->rows);
988 if (proceed == MagickFalse)
989 status=MagickFalse;
990 }
991 offset=row++;
992 }
993 if (count != (ssize_t) extent)
994 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000995 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +0000996 if (q == (PixelPacket *) NULL)
997 {
998 status=MagickFalse;
999 continue;
1000 }
cristyaa740112010-03-30 17:58:44 +00001001 indexes=GetAuthenticIndexQueue(image);
cristy3ed852e2009-09-05 21:47:34 +00001002 p=pixels;
1003 if ((image->depth == 8) || (image->depth == 16))
cristyaa740112010-03-30 17:58:44 +00001004 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3ed852e2009-09-05 21:47:34 +00001005 quantum_type,pixels,exception);
1006 else
1007 switch (quantum_type)
1008 {
1009 case GrayQuantum:
1010 case GrayAlphaQuantum:
1011 {
1012 if (image->depth <= 8)
1013 {
1014 unsigned char
1015 pixel;
1016
1017 for (x=0; x < (long) image->columns; x++)
1018 {
1019 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001020 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001021 q->green=q->red;
1022 q->blue=q->red;
cristyce70c172010-01-07 17:15:30 +00001023 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001024 if (image->matte != MagickFalse)
1025 {
1026 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001027 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001028 }
1029 q++;
1030 }
1031 }
1032 else
1033 {
1034 unsigned short
1035 pixel;
1036
1037 for (x=0; x < (long) image->columns; x++)
1038 {
1039 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001040 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001041 q->green=q->red;
1042 q->blue=q->red;
cristyce70c172010-01-07 17:15:30 +00001043 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001044 if (image->matte != MagickFalse)
1045 {
1046 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001047 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001048 }
1049 q++;
1050 }
1051 }
1052 break;
1053 }
1054 case CMYKQuantum:
1055 case CMYKAQuantum:
1056 {
1057 if (image->depth <= 8)
1058 {
1059 unsigned char
1060 pixel;
1061
1062 for (x=0; x < (long) image->columns; x++)
1063 {
1064 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001065 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001066 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001067 SetGreenPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001068 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001069 SetBluePixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001070 p=PushCharPixel(p,&pixel);
1071 indexes[x]=ScaleAnyToQuantum(pixel,range);
cristyce70c172010-01-07 17:15:30 +00001072 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001073 if (image->matte != MagickFalse)
1074 {
1075 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001076 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001077 }
1078 q++;
1079 }
1080 }
1081 else
1082 {
1083 unsigned short
1084 pixel;
1085
1086 for (x=0; x < (long) image->columns; x++)
1087 {
1088 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001089 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001090 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001091 SetGreenPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001092 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001093 SetBluePixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001094 p=PushShortPixel(MSBEndian,p,&pixel);
1095 indexes[x]=ScaleAnyToQuantum(pixel,range);
cristyce70c172010-01-07 17:15:30 +00001096 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001097 if (image->matte != MagickFalse)
1098 {
1099 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001100 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001101 }
1102 q++;
1103 }
1104 }
1105 break;
1106 }
1107 default:
1108 {
1109 if (image->depth <= 8)
1110 {
1111 unsigned char
1112 pixel;
1113
1114 for (x=0; x < (long) image->columns; x++)
1115 {
1116 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001117 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001118 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001119 SetGreenPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001120 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001121 SetBluePixelComponent(q,ScaleAnyToQuantum(pixel,range));
1122 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001123 if (image->matte != MagickFalse)
1124 {
1125 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001126 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001127 }
1128 q++;
1129 }
1130 }
1131 else
1132 {
1133 unsigned short
1134 pixel;
1135
1136 for (x=0; x < (long) image->columns; x++)
1137 {
1138 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001139 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001140 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001141 SetGreenPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001142 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001143 SetBluePixelComponent(q,ScaleAnyToQuantum(pixel,range));
1144 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001145 if (image->matte != MagickFalse)
1146 {
1147 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001148 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001149 }
1150 q++;
1151 }
1152 }
1153 break;
1154 }
1155 }
cristyaa740112010-03-30 17:58:44 +00001156 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001157 if (sync == MagickFalse)
1158 status=MagickFalse;
1159 }
cristy3ed852e2009-09-05 21:47:34 +00001160 quantum_info=DestroyQuantumInfo(quantum_info);
1161 if (status == MagickFalse)
1162 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1163 SetQuantumImageType(image,quantum_type);
1164 break;
1165 }
1166 case 'F':
1167 case 'f':
1168 {
1169 /*
1170 Convert PFM raster image to pixel packets.
1171 */
1172 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
1173 image->endian=quantum_scale < 0.0 ? LSBEndian : MSBEndian;
1174 image->depth=32;
1175 quantum_info=AcquireQuantumInfo(image_info,image);
1176 if (quantum_info == (QuantumInfo *) NULL)
1177 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1178 status=SetQuantumDepth(image,quantum_info,32);
1179 if (status == MagickFalse)
1180 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1181 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1182 if (status == MagickFalse)
1183 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1184 SetQuantumScale(quantum_info,(MagickRealType) QuantumRange*
1185 fabs(quantum_scale));
1186 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristy3ed852e2009-09-05 21:47:34 +00001187 for (y=0; y < (long) image->rows; y++)
1188 {
1189 long
1190 offset;
1191
1192 MagickBooleanType
1193 sync;
1194
1195 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001196 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001197
1198 ssize_t
1199 count;
1200
1201 size_t
1202 length;
1203
1204 unsigned char
1205 *pixels;
1206
1207 if (status == MagickFalse)
1208 continue;
1209 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001210 {
1211 count=ReadBlob(image,extent,pixels);
1212 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1213 (image->previous == (Image *) NULL))
1214 {
1215 MagickBooleanType
1216 proceed;
1217
1218 proceed=SetImageProgress(image,LoadImageTag,row,image->rows);
1219 if (proceed == MagickFalse)
1220 status=MagickFalse;
1221 }
1222 offset=row++;
1223 }
1224 if ((size_t) count != extent)
1225 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +00001226 q=QueueAuthenticPixels(image,0,(long) (image->rows-offset-1),
1227 image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001228 if (q == (PixelPacket *) NULL)
1229 {
1230 status=MagickFalse;
1231 continue;
1232 }
cristyaa740112010-03-30 17:58:44 +00001233 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1234 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001235 if (length != extent)
1236 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +00001237 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001238 if (sync == MagickFalse)
1239 status=MagickFalse;
1240 }
cristy3ed852e2009-09-05 21:47:34 +00001241 quantum_info=DestroyQuantumInfo(quantum_info);
1242 if (status == MagickFalse)
1243 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1244 SetQuantumImageType(image,quantum_type);
1245 break;
1246 }
1247 default:
1248 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1249 }
1250 if (EOFBlob(image) != MagickFalse)
1251 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
1252 "UnexpectedEndOfFile","`%s'",image->filename);
1253 /*
1254 Proceed to next image.
1255 */
1256 if (image_info->number_scenes != 0)
1257 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1258 break;
1259 if ((format == '1') || (format == '2') || (format == '3'))
1260 do
1261 {
1262 /*
1263 Skip to end of line.
1264 */
1265 count=ReadBlob(image,1,(unsigned char *) &format);
1266 if (count == 0)
1267 break;
1268 if ((count != 0) && (format == 'P'))
1269 break;
1270 } while (format != '\n');
1271 count=ReadBlob(image,1,(unsigned char *) &format);
1272 if ((count == 1) && (format == 'P'))
1273 {
1274 /*
1275 Allocate next image structure.
1276 */
1277 AcquireNextImage(image_info,image);
1278 if (GetNextImageInList(image) == (Image *) NULL)
1279 {
1280 image=DestroyImageList(image);
1281 return((Image *) NULL);
1282 }
1283 image=SyncNextImageInList(image);
1284 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1285 GetBlobSize(image));
1286 if (status == MagickFalse)
1287 break;
1288 }
1289 } while ((count == 1) && (format == 'P'));
1290 (void) CloseBlob(image);
1291 return(GetFirstImageInList(image));
1292}
1293
1294/*
1295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1296% %
1297% %
1298% %
1299% R e g i s t e r P N M I m a g e %
1300% %
1301% %
1302% %
1303%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1304%
1305% RegisterPNMImage() adds properties for the PNM image format to
1306% the list of supported formats. The properties include the image format
1307% tag, a method to read and/or write the format, whether the format
1308% supports the saving of more than one frame to the same file or blob,
1309% whether the format supports native in-memory I/O, and a brief
1310% description of the format.
1311%
1312% The format of the RegisterPNMImage method is:
1313%
1314% unsigned long RegisterPNMImage(void)
1315%
1316*/
1317ModuleExport unsigned long RegisterPNMImage(void)
1318{
1319 MagickInfo
1320 *entry;
1321
1322 entry=SetMagickInfo("PAM");
1323 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1324 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1325 entry->description=ConstantString("Common 2-dimensional bitmap format");
1326 entry->module=ConstantString("PNM");
1327 (void) RegisterMagickInfo(entry);
1328 entry=SetMagickInfo("PBM");
1329 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1330 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1331 entry->description=ConstantString("Portable bitmap format (black and white)");
1332 entry->module=ConstantString("PNM");
1333 (void) RegisterMagickInfo(entry);
1334 entry=SetMagickInfo("PFM");
1335 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1336 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1337 entry->description=ConstantString("Portable float format");
1338 entry->module=ConstantString("PFM");
1339 (void) RegisterMagickInfo(entry);
1340 entry=SetMagickInfo("PGM");
1341 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1342 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1343 entry->description=ConstantString("Portable graymap format (gray scale)");
1344 entry->module=ConstantString("PNM");
1345 (void) RegisterMagickInfo(entry);
1346 entry=SetMagickInfo("PNM");
1347 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1348 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1349 entry->magick=(IsImageFormatHandler *) IsPNM;
1350 entry->description=ConstantString("Portable anymap");
1351 entry->module=ConstantString("PNM");
1352 (void) RegisterMagickInfo(entry);
1353 entry=SetMagickInfo("PPM");
1354 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1355 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1356 entry->description=ConstantString("Portable pixmap format (color)");
1357 entry->module=ConstantString("PNM");
1358 (void) RegisterMagickInfo(entry);
1359 return(MagickImageCoderSignature);
1360}
1361
1362/*
1363%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1364% %
1365% %
1366% %
1367% U n r e g i s t e r P N M I m a g e %
1368% %
1369% %
1370% %
1371%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1372%
1373% UnregisterPNMImage() removes format registrations made by the
1374% PNM module from the list of supported formats.
1375%
1376% The format of the UnregisterPNMImage method is:
1377%
1378% UnregisterPNMImage(void)
1379%
1380*/
1381ModuleExport void UnregisterPNMImage(void)
1382{
1383 (void) UnregisterMagickInfo("PAM");
1384 (void) UnregisterMagickInfo("PBM");
1385 (void) UnregisterMagickInfo("PGM");
1386 (void) UnregisterMagickInfo("PNM");
1387 (void) UnregisterMagickInfo("PPM");
1388}
1389
1390/*
1391%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1392% %
1393% %
1394% %
1395% W r i t e P N M I m a g e %
1396% %
1397% %
1398% %
1399%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1400%
cristy661b5ad2010-01-13 00:54:42 +00001401% WritePNMImage() writes an image to a file in the PNM rasterfile format.
cristy3ed852e2009-09-05 21:47:34 +00001402%
1403% The format of the WritePNMImage method is:
1404%
1405% MagickBooleanType WritePNMImage(const ImageInfo *image_info,Image *image)
1406%
1407% A description of each parameter follows.
1408%
1409% o image_info: the image info.
1410%
1411% o image: The image.
1412%
1413*/
1414static MagickBooleanType WritePNMImage(const ImageInfo *image_info,Image *image)
1415{
1416 char
1417 buffer[MaxTextExtent],
1418 format,
1419 magick[MaxTextExtent];
1420
1421 const char
1422 *value;
1423
1424 IndexPacket
1425 index;
1426
1427 long
1428 y;
1429
1430 MagickBooleanType
1431 status;
1432
1433 MagickOffsetType
1434 scene;
1435
1436 QuantumAny
1437 pixel;
1438
1439 QuantumInfo
1440 *quantum_info;
1441
1442 QuantumType
1443 quantum_type;
1444
cristy661b5ad2010-01-13 00:54:42 +00001445 register long
1446 i;
1447
cristy3ed852e2009-09-05 21:47:34 +00001448 register unsigned char
1449 *pixels,
1450 *q;
1451
1452 ssize_t
1453 count;
1454
1455 size_t
1456 extent,
1457 packet_size;
1458
1459 /*
1460 Open output image file.
1461 */
1462 assert(image_info != (const ImageInfo *) NULL);
1463 assert(image_info->signature == MagickSignature);
1464 assert(image != (Image *) NULL);
1465 assert(image->signature == MagickSignature);
1466 if (image->debug != MagickFalse)
1467 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1468 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1469 if (status == MagickFalse)
1470 return(status);
1471 scene=0;
1472 do
1473 {
1474 /*
1475 Write PNM file header.
1476 */
1477 packet_size=3;
1478 quantum_type=RGBQuantum;
1479 (void) CopyMagickString(magick,image_info->magick,MaxTextExtent);
1480 switch (magick[1])
1481 {
1482 case 'A':
1483 case 'a':
1484 {
1485 format='7';
1486 break;
1487 }
1488 case 'B':
1489 case 'b':
1490 {
1491 format='4';
1492 if (image_info->compression == NoCompression)
1493 format='1';
1494 break;
1495 }
1496 case 'F':
1497 case 'f':
1498 {
1499 format='F';
1500 if (IsGrayImage(image,&image->exception) != MagickFalse)
1501 format='f';
1502 break;
1503 }
1504 case 'G':
1505 case 'g':
1506 {
1507 format='5';
1508 if (image_info->compression == NoCompression)
1509 format='2';
1510 break;
1511 }
1512 case 'N':
1513 case 'n':
1514 {
1515 if ((image_info->type != TrueColorType) &&
1516 (IsGrayImage(image,&image->exception) != MagickFalse))
1517 {
1518 format='5';
1519 if (image_info->compression == NoCompression)
1520 format='2';
1521 if (IsMonochromeImage(image,&image->exception) != MagickFalse)
1522 {
1523 format='4';
1524 if (image_info->compression == NoCompression)
1525 format='1';
1526 }
1527 break;
1528 }
1529 }
1530 default:
1531 {
1532 format='6';
1533 if (image_info->compression == NoCompression)
1534 format='3';
1535 break;
1536 }
1537 }
1538 (void) FormatMagickString(buffer,MaxTextExtent,"P%c\n",format);
1539 (void) WriteBlobString(image,buffer);
1540 value=GetImageProperty(image,"comment");
1541 if (value != (const char *) NULL)
1542 {
1543 register const char
1544 *p;
1545
1546 /*
1547 Write comments to file.
1548 */
1549 (void) WriteBlobByte(image,'#');
1550 for (p=value; *p != '\0'; p++)
1551 {
1552 (void) WriteBlobByte(image,(unsigned char) *p);
1553 if ((*p == '\r') && (*(p+1) != '\0'))
1554 (void) WriteBlobByte(image,'#');
1555 if ((*p == '\n') && (*(p+1) != '\0'))
1556 (void) WriteBlobByte(image,'#');
1557 }
1558 (void) WriteBlobByte(image,'\n');
1559 }
1560 if (format != '7')
1561 {
1562 if (image->colorspace != RGBColorspace)
1563 (void) TransformImageColorspace(image,RGBColorspace);
1564 (void) FormatMagickString(buffer,MaxTextExtent,"%lu %lu\n",
1565 image->columns,image->rows);
1566 (void) WriteBlobString(image,buffer);
1567 }
1568 else
1569 {
1570 char
1571 type[MaxTextExtent];
1572
1573 /*
1574 PAM header.
1575 */
1576 (void) FormatMagickString(buffer,MaxTextExtent,
1577 "WIDTH %lu\nHEIGHT %lu\n",image->columns,image->rows);
1578 (void) WriteBlobString(image,buffer);
1579 quantum_type=GetQuantumType(image,&image->exception);
1580 switch (quantum_type)
1581 {
1582 case CMYKQuantum:
1583 case CMYKAQuantum:
1584 {
1585 packet_size=4;
1586 (void) CopyMagickString(type,"CMYK",MaxTextExtent);
1587 break;
1588 }
1589 case GrayQuantum:
1590 case GrayAlphaQuantum:
1591 {
1592 packet_size=1;
1593 (void) CopyMagickString(type,"GRAYSCALE",MaxTextExtent);
1594 break;
1595 }
1596 default:
1597 {
1598 quantum_type=RGBQuantum;
1599 if (image->matte != MagickFalse)
1600 quantum_type=RGBAQuantum;
1601 packet_size=3;
1602 (void) CopyMagickString(type,"RGB",MaxTextExtent);
1603 break;
1604 }
1605 }
1606 if (image->matte != MagickFalse)
1607 {
1608 packet_size++;
1609 (void) ConcatenateMagickString(type,"_ALPHA",MaxTextExtent);
1610 }
1611 if (image->depth > 16)
1612 image->depth=16;
1613 (void) FormatMagickString(buffer,MaxTextExtent,
1614 "DEPTH %lu\nMAXVAL %lu\n",(unsigned long) packet_size,(unsigned long)
1615 GetQuantumRange(image->depth));
1616 (void) WriteBlobString(image,buffer);
1617 (void) FormatMagickString(buffer,MaxTextExtent,"TUPLTYPE %s\nENDHDR\n",
1618 type);
1619 (void) WriteBlobString(image,buffer);
1620 }
1621 /*
1622 Convert runextent encoded to PNM raster pixels.
1623 */
1624 switch (format)
1625 {
1626 case '1':
1627 {
cristy661b5ad2010-01-13 00:54:42 +00001628 unsigned char
1629 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001630
1631 /*
1632 Convert image to a PBM image.
1633 */
cristy661b5ad2010-01-13 00:54:42 +00001634 q=pixels;
cristy3ed852e2009-09-05 21:47:34 +00001635 for (y=0; y < (long) image->rows; y++)
1636 {
1637 register const IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00001638 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00001639
1640 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001641 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001642
1643 register long
1644 x;
1645
1646 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1647 if (p == (const PixelPacket *) NULL)
1648 break;
1649 indexes=GetVirtualIndexQueue(image);
1650 for (x=0; x < (long) image->columns; x++)
1651 {
1652 pixel=PixelIntensityToQuantum(p);
cristy661b5ad2010-01-13 00:54:42 +00001653 *q++=(unsigned char) (pixel >= (Quantum) (QuantumRange/2) ?
1654 '0' : '1');
1655 *q++=' ';
1656 if ((q-pixels+2) >= 80)
1657 {
1658 *q++='\n';
1659 (void) WriteBlob(image,q-pixels,pixels);
1660 q=pixels;
1661 i=0;
1662 }
cristy3ed852e2009-09-05 21:47:34 +00001663 p++;
1664 }
1665 if (image->previous == (Image *) NULL)
1666 {
1667 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1668 if (status == MagickFalse)
1669 break;
1670 }
1671 }
cristy661b5ad2010-01-13 00:54:42 +00001672 if (q != pixels)
1673 {
1674 *q++='\n';
1675 (void) WriteBlob(image,q-pixels,pixels);
1676 }
cristy3ed852e2009-09-05 21:47:34 +00001677 break;
1678 }
1679 case '2':
1680 {
cristy661b5ad2010-01-13 00:54:42 +00001681 unsigned char
1682 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001683
1684 /*
1685 Convert image to a PGM image.
1686 */
1687 if (image->depth <= 8)
1688 (void) WriteBlobString(image,"255\n");
1689 else
1690 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001691 q=pixels;
cristy3ed852e2009-09-05 21:47:34 +00001692 for (y=0; y < (long) image->rows; y++)
1693 {
1694 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001695 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001696
1697 register long
1698 x;
1699
1700 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1701 if (p == (const PixelPacket *) NULL)
1702 break;
1703 for (x=0; x < (long) image->columns; x++)
1704 {
1705 index=PixelIntensityToQuantum(p);
1706 if (image->depth <= 8)
1707 count=(ssize_t) FormatMagickString(buffer,MaxTextExtent,"%u ",
1708 ScaleQuantumToChar(index));
1709 else
1710 count=(ssize_t) FormatMagickString(buffer,MaxTextExtent,"%u ",
1711 ScaleQuantumToShort(index));
cristy661b5ad2010-01-13 00:54:42 +00001712 extent=(size_t) count;
1713 (void) strncpy((char *) q,buffer,extent);
1714 q+=extent;
1715 if ((q-pixels+extent) >= 80)
1716 {
1717 *q++='\n';
1718 (void) WriteBlob(image,q-pixels,pixels);
1719 q=pixels;
1720 }
cristy3ed852e2009-09-05 21:47:34 +00001721 p++;
1722 }
1723 if (image->previous == (Image *) NULL)
1724 {
1725 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1726 if (status == MagickFalse)
1727 break;
1728 }
1729 }
cristy661b5ad2010-01-13 00:54:42 +00001730 if (q != pixels)
1731 {
1732 *q++='\n';
1733 (void) WriteBlob(image,q-pixels,pixels);
1734 }
cristy3ed852e2009-09-05 21:47:34 +00001735 break;
1736 }
1737 case '3':
1738 {
cristy661b5ad2010-01-13 00:54:42 +00001739 unsigned char
1740 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001741
1742 /*
1743 Convert image to a PNM image.
1744 */
1745 if (image->depth <= 8)
1746 (void) WriteBlobString(image,"255\n");
1747 else
1748 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001749 q=pixels;
cristy3ed852e2009-09-05 21:47:34 +00001750 for (y=0; y < (long) image->rows; y++)
1751 {
1752 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001753 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001754
1755 register long
1756 x;
1757
1758 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1759 if (p == (const PixelPacket *) NULL)
1760 break;
1761 for (x=0; x < (long) image->columns; x++)
1762 {
1763 if (image->depth <= 8)
1764 count=(ssize_t) FormatMagickString(buffer,MaxTextExtent,
cristyce70c172010-01-07 17:15:30 +00001765 "%u %u %u ",ScaleQuantumToChar(GetRedPixelComponent(p)),
cristy375dc4b2010-01-12 20:24:58 +00001766 ScaleQuantumToChar(GetGreenPixelComponent(p)),
1767 ScaleQuantumToChar(GetBluePixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00001768 else
1769 count=(ssize_t) FormatMagickString(buffer,MaxTextExtent,
cristyce70c172010-01-07 17:15:30 +00001770 "%u %u %u ",ScaleQuantumToShort(GetRedPixelComponent(p)),
cristy375dc4b2010-01-12 20:24:58 +00001771 ScaleQuantumToShort(GetGreenPixelComponent(p)),
1772 ScaleQuantumToShort(GetBluePixelComponent(p)));
cristy661b5ad2010-01-13 00:54:42 +00001773 extent=(size_t) count;
1774 (void) strncpy((char *) q,buffer,extent);
1775 q+=extent;
1776 if ((q-pixels+extent) >= 80)
1777 {
1778 *q++='\n';
1779 (void) WriteBlob(image,q-pixels,pixels);
1780 q=pixels;
1781 }
cristy3ed852e2009-09-05 21:47:34 +00001782 p++;
1783 }
1784 if (image->previous == (Image *) NULL)
1785 {
1786 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1787 if (status == MagickFalse)
1788 break;
1789 }
1790 }
cristy661b5ad2010-01-13 00:54:42 +00001791 if (q != pixels)
1792 {
1793 *q++='\n';
1794 (void) WriteBlob(image,q-pixels,pixels);
1795 }
cristy3ed852e2009-09-05 21:47:34 +00001796 break;
1797 }
1798 case '4':
1799 {
1800 /*
1801 Convert image to a PBM image.
1802 */
1803 image->depth=1;
1804 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1805 if (quantum_info == (QuantumInfo *) NULL)
1806 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1807 quantum_info->min_is_white=MagickTrue;
1808 pixels=GetQuantumPixels(quantum_info);
1809 for (y=0; y < (long) image->rows; y++)
1810 {
1811 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001812 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001813
1814 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1815 if (p == (const PixelPacket *) NULL)
1816 break;
1817 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
1818 quantum_info,GrayQuantum,pixels,&image->exception);
1819 count=WriteBlob(image,extent,pixels);
1820 if (count != (ssize_t) extent)
1821 break;
1822 if (image->previous == (Image *) NULL)
1823 {
1824 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1825 if (status == MagickFalse)
1826 break;
1827 }
1828 }
1829 quantum_info=DestroyQuantumInfo(quantum_info);
1830 break;
1831 }
1832 case '5':
1833 {
1834 QuantumAny
1835 range;
1836
1837 /*
1838 Convert image to a PGM image.
1839 */
1840 if (image->depth > 8)
1841 image->depth=16;
1842 (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",(unsigned long)
1843 GetQuantumRange(image->depth));
1844 (void) WriteBlobString(image,buffer);
1845 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1846 if (quantum_info == (QuantumInfo *) NULL)
1847 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1848 quantum_info->min_is_white=MagickTrue;
1849 pixels=GetQuantumPixels(quantum_info);
1850 extent=GetQuantumExtent(image,quantum_info,GrayQuantum);
1851 range=GetQuantumRange(image->depth);
1852 for (y=0; y < (long) image->rows; y++)
1853 {
1854 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001855 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001856
1857 register long
1858 x;
1859
1860 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1861 if (p == (const PixelPacket *) NULL)
1862 break;
1863 q=pixels;
1864 if ((image->depth == 8) || (image->depth == 16))
1865 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
1866 quantum_info,GrayQuantum,pixels,&image->exception);
1867 else
1868 {
1869 if (image->depth <= 8)
1870 for (x=0; x < (long) image->columns; x++)
1871 {
1872 if (IsGrayPixel(p) == MagickFalse)
1873 pixel=ScaleQuantumToAny(PixelIntensityToQuantum(p),range);
1874 else
1875 {
1876 if (image->depth == 8)
cristyce70c172010-01-07 17:15:30 +00001877 pixel=ScaleQuantumToChar(GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00001878 else
1879 pixel=ScaleQuantumToAny(p->red,range);
1880 }
1881 q=PopCharPixel((unsigned char) pixel,q);
1882 p++;
1883 }
1884 else
1885 for (x=0; x < (long) image->columns; x++)
1886 {
1887 if (IsGrayPixel(p) == MagickFalse)
1888 pixel=ScaleQuantumToAny(PixelIntensityToQuantum(p),range);
1889 else
1890 {
1891 if (image->depth == 16)
cristyce70c172010-01-07 17:15:30 +00001892 pixel=ScaleQuantumToShort(GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00001893 else
1894 pixel=ScaleQuantumToAny(p->red,range);
1895 }
1896 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
1897 p++;
1898 }
1899 extent=(size_t) (q-pixels);
1900 }
1901 count=WriteBlob(image,extent,pixels);
1902 if (count != (ssize_t) extent)
1903 break;
1904 if (image->previous == (Image *) NULL)
1905 {
1906 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1907 if (status == MagickFalse)
1908 break;
1909 }
1910 }
1911 quantum_info=DestroyQuantumInfo(quantum_info);
1912 break;
1913 }
1914 case '6':
1915 {
1916 QuantumAny
1917 range;
1918
1919 /*
1920 Convert image to a PNM image.
1921 */
1922 if (image->depth > 8)
1923 image->depth=16;
1924 (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",(unsigned long)
1925 GetQuantumRange(image->depth));
1926 (void) WriteBlobString(image,buffer);
1927 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1928 if (quantum_info == (QuantumInfo *) NULL)
1929 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1930 pixels=GetQuantumPixels(quantum_info);
1931 extent=GetQuantumExtent(image,quantum_info,quantum_type);
1932 range=GetQuantumRange(image->depth);
1933 for (y=0; y < (long) image->rows; y++)
1934 {
1935 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001936 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001937
1938 register long
1939 x;
1940
1941 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1942 if (p == (const PixelPacket *) NULL)
1943 break;
1944 q=pixels;
1945 if ((image->depth == 8) || (image->depth == 16))
1946 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
1947 quantum_info,quantum_type,pixels,&image->exception);
1948 else
1949 {
1950 if (image->depth <= 8)
1951 for (x=0; x < (long) image->columns; x++)
1952 {
1953 pixel=ScaleQuantumToAny(p->red,range);
1954 q=PopCharPixel((unsigned char) pixel,q);
1955 pixel=ScaleQuantumToAny(p->green,range);
1956 q=PopCharPixel((unsigned char) pixel,q);
1957 pixel=ScaleQuantumToAny(p->blue,range);
1958 q=PopCharPixel((unsigned char) pixel,q);
cristy3ed852e2009-09-05 21:47:34 +00001959 p++;
1960 }
1961 else
1962 for (x=0; x < (long) image->columns; x++)
1963 {
1964 pixel=ScaleQuantumToAny(p->red,range);
1965 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
1966 pixel=ScaleQuantumToAny(p->green,range);
1967 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
1968 pixel=ScaleQuantumToAny(p->blue,range);
1969 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy3ed852e2009-09-05 21:47:34 +00001970 p++;
1971 }
1972 extent=(size_t) (q-pixels);
1973 }
1974 count=WriteBlob(image,extent,pixels);
1975 if (count != (ssize_t) extent)
1976 break;
1977 if (image->previous == (Image *) NULL)
1978 {
1979 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1980 if (status == MagickFalse)
1981 break;
1982 }
1983 }
1984 quantum_info=DestroyQuantumInfo(quantum_info);
1985 break;
1986 }
1987 case '7':
1988 {
1989 QuantumAny
1990 range;
1991
1992 /*
1993 Convert image to a PAM.
1994 */
1995 if (image->depth > 16)
1996 image->depth=16;
1997 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1998 pixels=GetQuantumPixels(quantum_info);
1999 range=GetQuantumRange(image->depth);
2000 for (y=0; y < (long) image->rows; y++)
2001 {
2002 register const IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002003 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002004
2005 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002006 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002007
2008 register long
2009 x;
2010
2011 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2012 if (p == (const PixelPacket *) NULL)
2013 break;
2014 indexes=GetVirtualIndexQueue(image);
2015 q=pixels;
2016 if ((image->depth == 8) || (image->depth == 16))
2017 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
2018 quantum_info,quantum_type,pixels,&image->exception);
2019 else
2020 {
2021 switch (quantum_type)
2022 {
2023 case GrayQuantum:
2024 case GrayAlphaQuantum:
2025 {
2026 if (image->depth <= 8)
2027 for (x=0; x < (long) image->columns; x++)
2028 {
2029 pixel=ScaleQuantumToAny(PixelIntensityToQuantum(p),range);
2030 q=PopCharPixel((unsigned char) pixel,q);
2031 if (image->matte != MagickFalse)
2032 {
2033 pixel=(unsigned char) ScaleQuantumToAny(p->opacity,
2034 range);
2035 q=PopCharPixel((unsigned char) pixel,q);
2036 }
2037 p++;
2038 }
2039 else
2040 for (x=0; x < (long) image->columns; x++)
2041 {
2042 pixel=ScaleQuantumToAny(PixelIntensityToQuantum(p),range);
2043 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2044 if (image->matte != MagickFalse)
2045 {
2046 pixel=(unsigned char) ScaleQuantumToAny(p->opacity,
2047 range);
2048 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2049 }
2050 p++;
2051 }
2052 break;
2053 }
2054 case CMYKQuantum:
2055 case CMYKAQuantum:
2056 {
2057 if (image->depth <= 8)
2058 for (x=0; x < (long) image->columns; x++)
2059 {
2060 pixel=ScaleQuantumToAny(p->red,range);
2061 q=PopCharPixel((unsigned char) pixel,q);
2062 pixel=ScaleQuantumToAny(p->green,range);
2063 q=PopCharPixel((unsigned char) pixel,q);
2064 pixel=ScaleQuantumToAny(p->blue,range);
2065 q=PopCharPixel((unsigned char) pixel,q);
2066 pixel=ScaleQuantumToAny(indexes[x],range);
2067 q=PopCharPixel((unsigned char) pixel,q);
2068 if (image->matte != MagickFalse)
2069 {
2070 pixel=ScaleQuantumToAny((Quantum) (QuantumRange-
cristyce70c172010-01-07 17:15:30 +00002071 GetOpacityPixelComponent(p)),range);
cristy3ed852e2009-09-05 21:47:34 +00002072 q=PopCharPixel((unsigned char) pixel,q);
2073 }
2074 p++;
2075 }
2076 else
2077 for (x=0; x < (long) image->columns; x++)
2078 {
2079 pixel=ScaleQuantumToAny(p->red,range);
2080 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2081 pixel=ScaleQuantumToAny(p->green,range);
2082 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2083 pixel=ScaleQuantumToAny(p->blue,range);
2084 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2085 pixel=ScaleQuantumToAny(indexes[x],range);
2086 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2087 if (image->matte != MagickFalse)
2088 {
2089 pixel=ScaleQuantumToAny((Quantum) (QuantumRange-
cristyce70c172010-01-07 17:15:30 +00002090 GetOpacityPixelComponent(p)),range);
cristy3ed852e2009-09-05 21:47:34 +00002091 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2092 }
2093 p++;
2094 }
2095 break;
2096 }
2097 default:
2098 {
2099 if (image->depth <= 8)
2100 for (x=0; x < (long) image->columns; x++)
2101 {
2102 pixel=ScaleQuantumToAny(p->red,range);
2103 q=PopCharPixel((unsigned char) pixel,q);
2104 pixel=ScaleQuantumToAny(p->green,range);
2105 q=PopCharPixel((unsigned char) pixel,q);
2106 pixel=ScaleQuantumToAny(p->blue,range);
2107 q=PopCharPixel((unsigned char) pixel,q);
2108 if (image->matte != MagickFalse)
2109 {
2110 pixel=ScaleQuantumToAny((Quantum) (QuantumRange-
cristyce70c172010-01-07 17:15:30 +00002111 GetOpacityPixelComponent(p)),range);
cristy3ed852e2009-09-05 21:47:34 +00002112 q=PopCharPixel((unsigned char) pixel,q);
2113 }
2114 p++;
2115 }
2116 else
2117 for (x=0; x < (long) image->columns; x++)
2118 {
2119 pixel=ScaleQuantumToAny(p->red,range);
2120 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2121 pixel=ScaleQuantumToAny(p->green,range);
2122 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2123 pixel=ScaleQuantumToAny(p->blue,range);
2124 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2125 if (image->matte != MagickFalse)
2126 {
2127 pixel=ScaleQuantumToAny((Quantum) (QuantumRange-
cristyce70c172010-01-07 17:15:30 +00002128 GetOpacityPixelComponent(p)),range);
cristy3ed852e2009-09-05 21:47:34 +00002129 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2130 }
2131 p++;
2132 }
2133 break;
2134 }
2135 }
2136 extent=(size_t) (q-pixels);
2137 }
2138 count=WriteBlob(image,extent,pixels);
2139 if (count != (ssize_t) extent)
2140 break;
2141 if (image->previous == (Image *) NULL)
2142 {
2143 status=SetImageProgress(image,SaveImageTag,y,image->rows);
2144 if (status == MagickFalse)
2145 break;
2146 }
2147 }
2148 quantum_info=DestroyQuantumInfo(quantum_info);
2149 break;
2150 }
2151 case 'F':
2152 case 'f':
2153 {
2154 (void) WriteBlobString(image,image->endian != LSBEndian ? "1.0\n" :
2155 "-1.0\n");
2156 image->depth=32;
2157 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
2158 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
2159 if (quantum_info == (QuantumInfo *) NULL)
2160 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2161 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2162 if (status == MagickFalse)
2163 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2164 pixels=GetQuantumPixels(quantum_info);
2165 for (y=(long) image->rows-1; y >= 0; y--)
2166 {
2167 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002168 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002169
2170 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2171 if (p == (const PixelPacket *) NULL)
2172 break;
2173 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
2174 quantum_info,quantum_type,pixels,&image->exception);
2175 (void) WriteBlob(image,extent,pixels);
2176 if (image->previous == (Image *) NULL)
2177 {
2178 status=SetImageProgress(image,SaveImageTag,y,image->rows);
2179 if (status == MagickFalse)
2180 break;
2181 }
2182 }
2183 quantum_info=DestroyQuantumInfo(quantum_info);
2184 break;
2185 }
2186 }
2187 if (GetNextImageInList(image) == (Image *) NULL)
2188 break;
2189 image=SyncNextImageInList(image);
2190 status=SetImageProgress(image,SaveImagesTag,scene++,
2191 GetImageListLength(image));
2192 if (status == MagickFalse)
2193 break;
2194 } while (image_info->adjoin != MagickFalse);
2195 (void) CloseBlob(image);
2196 return(MagickTrue);
2197}