blob: 9313b720ce47bc38e64a7d5bab509751e0001fcc [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
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)];
cristybb503372010-05-27 20:51:26 +0000558 pixel.green=(MagickRealType) scale[ConstrainPixel(image,(ssize_t)
cristy3ed852e2009-09-05 21:47:34 +0000559 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
cristycee97112010-05-28 00:44:52 +0000703 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType) row,
704 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
cristycee97112010-05-28 00:44:52 +0000813 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType) row,
814 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))
898 type=IsGrayPixel(q) == MagickFalse ? UndefinedType :
899 GrayscaleType;
900 if ((type == GrayscaleType) && (IsGrayPixel(q) == MagickFalse))
901 type=UndefinedType;
902 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");
914 if (type != UndefinedType)
915 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
cristycee97112010-05-28 00:44:52 +0000993 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType) row,
994 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);
cristyce70c172010-01-07 17:15:30 +00001034 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001035 }
1036 q++;
1037 }
1038 }
1039 else
1040 {
1041 unsigned short
1042 pixel;
1043
cristybb503372010-05-27 20:51:26 +00001044 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001045 {
1046 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001047 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001048 q->green=q->red;
1049 q->blue=q->red;
cristyce70c172010-01-07 17:15:30 +00001050 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001051 if (image->matte != MagickFalse)
1052 {
1053 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001054 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001055 }
1056 q++;
1057 }
1058 }
1059 break;
1060 }
1061 case CMYKQuantum:
1062 case CMYKAQuantum:
1063 {
1064 if (image->depth <= 8)
1065 {
1066 unsigned char
1067 pixel;
1068
cristybb503372010-05-27 20:51:26 +00001069 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001070 {
1071 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001072 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001073 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001074 SetGreenPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001075 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001076 SetBluePixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001077 p=PushCharPixel(p,&pixel);
1078 indexes[x]=ScaleAnyToQuantum(pixel,range);
cristyce70c172010-01-07 17:15:30 +00001079 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001080 if (image->matte != MagickFalse)
1081 {
1082 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001083 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001084 }
1085 q++;
1086 }
1087 }
1088 else
1089 {
1090 unsigned short
1091 pixel;
1092
cristybb503372010-05-27 20:51:26 +00001093 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001094 {
1095 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001096 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001097 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001098 SetGreenPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001099 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001100 SetBluePixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001101 p=PushShortPixel(MSBEndian,p,&pixel);
1102 indexes[x]=ScaleAnyToQuantum(pixel,range);
cristyce70c172010-01-07 17:15:30 +00001103 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001104 if (image->matte != MagickFalse)
1105 {
1106 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001107 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001108 }
1109 q++;
1110 }
1111 }
1112 break;
1113 }
1114 default:
1115 {
1116 if (image->depth <= 8)
1117 {
1118 unsigned char
1119 pixel;
1120
cristybb503372010-05-27 20:51:26 +00001121 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001122 {
1123 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001124 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001125 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001126 SetGreenPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001127 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001128 SetBluePixelComponent(q,ScaleAnyToQuantum(pixel,range));
1129 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001130 if (image->matte != MagickFalse)
1131 {
1132 p=PushCharPixel(p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001133 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001134 }
1135 q++;
1136 }
1137 }
1138 else
1139 {
1140 unsigned short
1141 pixel;
1142
cristybb503372010-05-27 20:51:26 +00001143 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001144 {
1145 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001146 SetRedPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001147 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001148 SetGreenPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001149 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001150 SetBluePixelComponent(q,ScaleAnyToQuantum(pixel,range));
1151 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00001152 if (image->matte != MagickFalse)
1153 {
1154 p=PushShortPixel(MSBEndian,p,&pixel);
cristyce70c172010-01-07 17:15:30 +00001155 SetOpacityPixelComponent(q,ScaleAnyToQuantum(pixel,range));
cristy3ed852e2009-09-05 21:47:34 +00001156 }
1157 q++;
1158 }
1159 }
1160 break;
1161 }
1162 }
cristyaa740112010-03-30 17:58:44 +00001163 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001164 if (sync == MagickFalse)
1165 status=MagickFalse;
1166 }
cristy3ed852e2009-09-05 21:47:34 +00001167 quantum_info=DestroyQuantumInfo(quantum_info);
1168 if (status == MagickFalse)
1169 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1170 SetQuantumImageType(image,quantum_type);
1171 break;
1172 }
1173 case 'F':
1174 case 'f':
1175 {
1176 /*
1177 Convert PFM raster image to pixel packets.
1178 */
1179 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
1180 image->endian=quantum_scale < 0.0 ? LSBEndian : MSBEndian;
1181 image->depth=32;
1182 quantum_info=AcquireQuantumInfo(image_info,image);
1183 if (quantum_info == (QuantumInfo *) NULL)
1184 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1185 status=SetQuantumDepth(image,quantum_info,32);
1186 if (status == MagickFalse)
1187 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1188 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1189 if (status == MagickFalse)
1190 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1191 SetQuantumScale(quantum_info,(MagickRealType) QuantumRange*
1192 fabs(quantum_scale));
1193 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +00001194 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001195 {
cristybb503372010-05-27 20:51:26 +00001196 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001197 offset;
1198
1199 MagickBooleanType
1200 sync;
1201
1202 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001203 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001204
1205 ssize_t
1206 count;
1207
1208 size_t
1209 length;
1210
1211 unsigned char
1212 *pixels;
1213
1214 if (status == MagickFalse)
1215 continue;
1216 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001217 {
1218 count=ReadBlob(image,extent,pixels);
1219 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1220 (image->previous == (Image *) NULL))
1221 {
1222 MagickBooleanType
1223 proceed;
1224
cristycee97112010-05-28 00:44:52 +00001225 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType) row,
1226 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001227 if (proceed == MagickFalse)
1228 status=MagickFalse;
1229 }
1230 offset=row++;
1231 }
1232 if ((size_t) count != extent)
1233 status=MagickFalse;
cristybb503372010-05-27 20:51:26 +00001234 q=QueueAuthenticPixels(image,0,(ssize_t) (image->rows-offset-1),
cristyaa740112010-03-30 17:58:44 +00001235 image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001236 if (q == (PixelPacket *) NULL)
1237 {
1238 status=MagickFalse;
1239 continue;
1240 }
cristyaa740112010-03-30 17:58:44 +00001241 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1242 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001243 if (length != extent)
1244 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +00001245 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001246 if (sync == MagickFalse)
1247 status=MagickFalse;
1248 }
cristy3ed852e2009-09-05 21:47:34 +00001249 quantum_info=DestroyQuantumInfo(quantum_info);
1250 if (status == MagickFalse)
1251 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1252 SetQuantumImageType(image,quantum_type);
1253 break;
1254 }
1255 default:
1256 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1257 }
1258 if (EOFBlob(image) != MagickFalse)
1259 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
1260 "UnexpectedEndOfFile","`%s'",image->filename);
1261 /*
1262 Proceed to next image.
1263 */
1264 if (image_info->number_scenes != 0)
1265 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1266 break;
1267 if ((format == '1') || (format == '2') || (format == '3'))
1268 do
1269 {
1270 /*
1271 Skip to end of line.
1272 */
1273 count=ReadBlob(image,1,(unsigned char *) &format);
1274 if (count == 0)
1275 break;
1276 if ((count != 0) && (format == 'P'))
1277 break;
1278 } while (format != '\n');
1279 count=ReadBlob(image,1,(unsigned char *) &format);
1280 if ((count == 1) && (format == 'P'))
1281 {
1282 /*
1283 Allocate next image structure.
1284 */
1285 AcquireNextImage(image_info,image);
1286 if (GetNextImageInList(image) == (Image *) NULL)
1287 {
1288 image=DestroyImageList(image);
1289 return((Image *) NULL);
1290 }
1291 image=SyncNextImageInList(image);
1292 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1293 GetBlobSize(image));
1294 if (status == MagickFalse)
1295 break;
1296 }
1297 } while ((count == 1) && (format == 'P'));
1298 (void) CloseBlob(image);
1299 return(GetFirstImageInList(image));
1300}
1301
1302/*
1303%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1304% %
1305% %
1306% %
1307% R e g i s t e r P N M I m a g e %
1308% %
1309% %
1310% %
1311%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1312%
1313% RegisterPNMImage() adds properties for the PNM image format to
1314% the list of supported formats. The properties include the image format
1315% tag, a method to read and/or write the format, whether the format
1316% supports the saving of more than one frame to the same file or blob,
1317% whether the format supports native in-memory I/O, and a brief
1318% description of the format.
1319%
1320% The format of the RegisterPNMImage method is:
1321%
cristybb503372010-05-27 20:51:26 +00001322% size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001323%
1324*/
cristybb503372010-05-27 20:51:26 +00001325ModuleExport size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001326{
1327 MagickInfo
1328 *entry;
1329
1330 entry=SetMagickInfo("PAM");
1331 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1332 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1333 entry->description=ConstantString("Common 2-dimensional bitmap format");
1334 entry->module=ConstantString("PNM");
1335 (void) RegisterMagickInfo(entry);
1336 entry=SetMagickInfo("PBM");
1337 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1338 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1339 entry->description=ConstantString("Portable bitmap format (black and white)");
1340 entry->module=ConstantString("PNM");
1341 (void) RegisterMagickInfo(entry);
1342 entry=SetMagickInfo("PFM");
1343 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1344 entry->encoder=(EncodeImageHandler *) WritePNMImage;
cristye96405a2010-05-19 02:24:31 +00001345 entry->endian_support=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00001346 entry->description=ConstantString("Portable float format");
1347 entry->module=ConstantString("PFM");
1348 (void) RegisterMagickInfo(entry);
1349 entry=SetMagickInfo("PGM");
1350 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1351 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1352 entry->description=ConstantString("Portable graymap format (gray scale)");
1353 entry->module=ConstantString("PNM");
1354 (void) RegisterMagickInfo(entry);
1355 entry=SetMagickInfo("PNM");
1356 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1357 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1358 entry->magick=(IsImageFormatHandler *) IsPNM;
1359 entry->description=ConstantString("Portable anymap");
1360 entry->module=ConstantString("PNM");
1361 (void) RegisterMagickInfo(entry);
1362 entry=SetMagickInfo("PPM");
1363 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1364 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1365 entry->description=ConstantString("Portable pixmap format (color)");
1366 entry->module=ConstantString("PNM");
1367 (void) RegisterMagickInfo(entry);
1368 return(MagickImageCoderSignature);
1369}
1370
1371/*
1372%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1373% %
1374% %
1375% %
1376% U n r e g i s t e r P N M I m a g e %
1377% %
1378% %
1379% %
1380%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1381%
1382% UnregisterPNMImage() removes format registrations made by the
1383% PNM module from the list of supported formats.
1384%
1385% The format of the UnregisterPNMImage method is:
1386%
1387% UnregisterPNMImage(void)
1388%
1389*/
1390ModuleExport void UnregisterPNMImage(void)
1391{
1392 (void) UnregisterMagickInfo("PAM");
1393 (void) UnregisterMagickInfo("PBM");
1394 (void) UnregisterMagickInfo("PGM");
1395 (void) UnregisterMagickInfo("PNM");
1396 (void) UnregisterMagickInfo("PPM");
1397}
1398
1399/*
1400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1401% %
1402% %
1403% %
1404% W r i t e P N M I m a g e %
1405% %
1406% %
1407% %
1408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1409%
cristy661b5ad2010-01-13 00:54:42 +00001410% WritePNMImage() writes an image to a file in the PNM rasterfile format.
cristy3ed852e2009-09-05 21:47:34 +00001411%
1412% The format of the WritePNMImage method is:
1413%
1414% MagickBooleanType WritePNMImage(const ImageInfo *image_info,Image *image)
1415%
1416% A description of each parameter follows.
1417%
1418% o image_info: the image info.
1419%
1420% o image: The image.
1421%
1422*/
1423static MagickBooleanType WritePNMImage(const ImageInfo *image_info,Image *image)
1424{
1425 char
1426 buffer[MaxTextExtent],
1427 format,
1428 magick[MaxTextExtent];
1429
1430 const char
1431 *value;
1432
1433 IndexPacket
1434 index;
1435
cristybb503372010-05-27 20:51:26 +00001436 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001437 y;
1438
1439 MagickBooleanType
1440 status;
1441
1442 MagickOffsetType
1443 scene;
1444
1445 QuantumAny
1446 pixel;
1447
1448 QuantumInfo
1449 *quantum_info;
1450
1451 QuantumType
1452 quantum_type;
1453
cristybb503372010-05-27 20:51:26 +00001454 register ssize_t
cristy661b5ad2010-01-13 00:54:42 +00001455 i;
1456
cristy3ed852e2009-09-05 21:47:34 +00001457 register unsigned char
1458 *pixels,
1459 *q;
1460
1461 ssize_t
1462 count;
1463
1464 size_t
1465 extent,
1466 packet_size;
1467
1468 /*
1469 Open output image file.
1470 */
1471 assert(image_info != (const ImageInfo *) NULL);
1472 assert(image_info->signature == MagickSignature);
1473 assert(image != (Image *) NULL);
1474 assert(image->signature == MagickSignature);
1475 if (image->debug != MagickFalse)
1476 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1477 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1478 if (status == MagickFalse)
1479 return(status);
1480 scene=0;
1481 do
1482 {
1483 /*
1484 Write PNM file header.
1485 */
1486 packet_size=3;
1487 quantum_type=RGBQuantum;
1488 (void) CopyMagickString(magick,image_info->magick,MaxTextExtent);
1489 switch (magick[1])
1490 {
1491 case 'A':
1492 case 'a':
1493 {
1494 format='7';
1495 break;
1496 }
1497 case 'B':
1498 case 'b':
1499 {
1500 format='4';
1501 if (image_info->compression == NoCompression)
1502 format='1';
1503 break;
1504 }
1505 case 'F':
1506 case 'f':
1507 {
1508 format='F';
1509 if (IsGrayImage(image,&image->exception) != MagickFalse)
1510 format='f';
1511 break;
1512 }
1513 case 'G':
1514 case 'g':
1515 {
1516 format='5';
1517 if (image_info->compression == NoCompression)
1518 format='2';
1519 break;
1520 }
1521 case 'N':
1522 case 'n':
1523 {
1524 if ((image_info->type != TrueColorType) &&
1525 (IsGrayImage(image,&image->exception) != MagickFalse))
1526 {
1527 format='5';
1528 if (image_info->compression == NoCompression)
1529 format='2';
1530 if (IsMonochromeImage(image,&image->exception) != MagickFalse)
1531 {
1532 format='4';
1533 if (image_info->compression == NoCompression)
1534 format='1';
1535 }
1536 break;
1537 }
1538 }
1539 default:
1540 {
1541 format='6';
1542 if (image_info->compression == NoCompression)
1543 format='3';
1544 break;
1545 }
1546 }
1547 (void) FormatMagickString(buffer,MaxTextExtent,"P%c\n",format);
1548 (void) WriteBlobString(image,buffer);
1549 value=GetImageProperty(image,"comment");
1550 if (value != (const char *) NULL)
1551 {
1552 register const char
1553 *p;
1554
1555 /*
1556 Write comments to file.
1557 */
1558 (void) WriteBlobByte(image,'#');
1559 for (p=value; *p != '\0'; p++)
1560 {
1561 (void) WriteBlobByte(image,(unsigned char) *p);
1562 if ((*p == '\r') && (*(p+1) != '\0'))
1563 (void) WriteBlobByte(image,'#');
1564 if ((*p == '\n') && (*(p+1) != '\0'))
1565 (void) WriteBlobByte(image,'#');
1566 }
1567 (void) WriteBlobByte(image,'\n');
1568 }
1569 if (format != '7')
1570 {
1571 if (image->colorspace != RGBColorspace)
1572 (void) TransformImageColorspace(image,RGBColorspace);
1573 (void) FormatMagickString(buffer,MaxTextExtent,"%lu %lu\n",
cristyf2faecf2010-05-28 19:19:36 +00001574 (unsigned long) image->columns,(unsigned long) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001575 (void) WriteBlobString(image,buffer);
1576 }
1577 else
1578 {
1579 char
1580 type[MaxTextExtent];
1581
1582 /*
1583 PAM header.
1584 */
1585 (void) FormatMagickString(buffer,MaxTextExtent,
cristyf2faecf2010-05-28 19:19:36 +00001586 "WIDTH %lu\nHEIGHT %lu\n",(unsigned long) image->columns,
1587 (unsigned long) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001588 (void) WriteBlobString(image,buffer);
1589 quantum_type=GetQuantumType(image,&image->exception);
1590 switch (quantum_type)
1591 {
1592 case CMYKQuantum:
1593 case CMYKAQuantum:
1594 {
1595 packet_size=4;
1596 (void) CopyMagickString(type,"CMYK",MaxTextExtent);
1597 break;
1598 }
1599 case GrayQuantum:
1600 case GrayAlphaQuantum:
1601 {
1602 packet_size=1;
1603 (void) CopyMagickString(type,"GRAYSCALE",MaxTextExtent);
1604 break;
1605 }
1606 default:
1607 {
1608 quantum_type=RGBQuantum;
1609 if (image->matte != MagickFalse)
1610 quantum_type=RGBAQuantum;
1611 packet_size=3;
1612 (void) CopyMagickString(type,"RGB",MaxTextExtent);
1613 break;
1614 }
1615 }
1616 if (image->matte != MagickFalse)
1617 {
1618 packet_size++;
1619 (void) ConcatenateMagickString(type,"_ALPHA",MaxTextExtent);
1620 }
1621 if (image->depth > 16)
1622 image->depth=16;
1623 (void) FormatMagickString(buffer,MaxTextExtent,
cristyf2faecf2010-05-28 19:19:36 +00001624 "DEPTH %lu\nMAXVAL %lu\n",(unsigned long) packet_size,(unsigned long)
cristy3ed852e2009-09-05 21:47:34 +00001625 GetQuantumRange(image->depth));
1626 (void) WriteBlobString(image,buffer);
1627 (void) FormatMagickString(buffer,MaxTextExtent,"TUPLTYPE %s\nENDHDR\n",
1628 type);
1629 (void) WriteBlobString(image,buffer);
1630 }
1631 /*
1632 Convert runextent encoded to PNM raster pixels.
1633 */
1634 switch (format)
1635 {
1636 case '1':
1637 {
cristy661b5ad2010-01-13 00:54:42 +00001638 unsigned char
1639 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001640
1641 /*
1642 Convert image to a PBM image.
1643 */
cristy661b5ad2010-01-13 00:54:42 +00001644 q=pixels;
cristybb503372010-05-27 20:51:26 +00001645 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001646 {
1647 register const IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00001648 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00001649
1650 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001651 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001652
cristybb503372010-05-27 20:51:26 +00001653 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001654 x;
1655
1656 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1657 if (p == (const PixelPacket *) NULL)
1658 break;
1659 indexes=GetVirtualIndexQueue(image);
cristybb503372010-05-27 20:51:26 +00001660 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001661 {
1662 pixel=PixelIntensityToQuantum(p);
cristy661b5ad2010-01-13 00:54:42 +00001663 *q++=(unsigned char) (pixel >= (Quantum) (QuantumRange/2) ?
1664 '0' : '1');
1665 *q++=' ';
1666 if ((q-pixels+2) >= 80)
1667 {
1668 *q++='\n';
1669 (void) WriteBlob(image,q-pixels,pixels);
1670 q=pixels;
1671 i=0;
1672 }
cristy3ed852e2009-09-05 21:47:34 +00001673 p++;
1674 }
1675 if (image->previous == (Image *) NULL)
1676 {
cristycee97112010-05-28 00:44:52 +00001677 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1678 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001679 if (status == MagickFalse)
1680 break;
1681 }
1682 }
cristy661b5ad2010-01-13 00:54:42 +00001683 if (q != pixels)
1684 {
1685 *q++='\n';
1686 (void) WriteBlob(image,q-pixels,pixels);
1687 }
cristy3ed852e2009-09-05 21:47:34 +00001688 break;
1689 }
1690 case '2':
1691 {
cristy661b5ad2010-01-13 00:54:42 +00001692 unsigned char
1693 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001694
1695 /*
1696 Convert image to a PGM image.
1697 */
1698 if (image->depth <= 8)
1699 (void) WriteBlobString(image,"255\n");
1700 else
1701 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001702 q=pixels;
cristybb503372010-05-27 20:51:26 +00001703 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001704 {
1705 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001706 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001707
cristybb503372010-05-27 20:51:26 +00001708 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001709 x;
1710
1711 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1712 if (p == (const PixelPacket *) NULL)
1713 break;
cristybb503372010-05-27 20:51:26 +00001714 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001715 {
1716 index=PixelIntensityToQuantum(p);
1717 if (image->depth <= 8)
1718 count=(ssize_t) FormatMagickString(buffer,MaxTextExtent,"%u ",
1719 ScaleQuantumToChar(index));
1720 else
1721 count=(ssize_t) FormatMagickString(buffer,MaxTextExtent,"%u ",
1722 ScaleQuantumToShort(index));
cristy661b5ad2010-01-13 00:54:42 +00001723 extent=(size_t) count;
1724 (void) strncpy((char *) q,buffer,extent);
1725 q+=extent;
1726 if ((q-pixels+extent) >= 80)
1727 {
1728 *q++='\n';
1729 (void) WriteBlob(image,q-pixels,pixels);
1730 q=pixels;
1731 }
cristy3ed852e2009-09-05 21:47:34 +00001732 p++;
1733 }
1734 if (image->previous == (Image *) NULL)
1735 {
cristycee97112010-05-28 00:44:52 +00001736 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1737 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001738 if (status == MagickFalse)
1739 break;
1740 }
1741 }
cristy661b5ad2010-01-13 00:54:42 +00001742 if (q != pixels)
1743 {
1744 *q++='\n';
1745 (void) WriteBlob(image,q-pixels,pixels);
1746 }
cristy3ed852e2009-09-05 21:47:34 +00001747 break;
1748 }
1749 case '3':
1750 {
cristy661b5ad2010-01-13 00:54:42 +00001751 unsigned char
1752 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001753
1754 /*
1755 Convert image to a PNM image.
1756 */
1757 if (image->depth <= 8)
1758 (void) WriteBlobString(image,"255\n");
1759 else
1760 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001761 q=pixels;
cristybb503372010-05-27 20:51:26 +00001762 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001763 {
1764 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001765 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001766
cristybb503372010-05-27 20:51:26 +00001767 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001768 x;
1769
1770 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1771 if (p == (const PixelPacket *) NULL)
1772 break;
cristybb503372010-05-27 20:51:26 +00001773 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001774 {
1775 if (image->depth <= 8)
1776 count=(ssize_t) FormatMagickString(buffer,MaxTextExtent,
cristyce70c172010-01-07 17:15:30 +00001777 "%u %u %u ",ScaleQuantumToChar(GetRedPixelComponent(p)),
cristy375dc4b2010-01-12 20:24:58 +00001778 ScaleQuantumToChar(GetGreenPixelComponent(p)),
1779 ScaleQuantumToChar(GetBluePixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00001780 else
1781 count=(ssize_t) FormatMagickString(buffer,MaxTextExtent,
cristyce70c172010-01-07 17:15:30 +00001782 "%u %u %u ",ScaleQuantumToShort(GetRedPixelComponent(p)),
cristy375dc4b2010-01-12 20:24:58 +00001783 ScaleQuantumToShort(GetGreenPixelComponent(p)),
1784 ScaleQuantumToShort(GetBluePixelComponent(p)));
cristy661b5ad2010-01-13 00:54:42 +00001785 extent=(size_t) count;
1786 (void) strncpy((char *) q,buffer,extent);
1787 q+=extent;
1788 if ((q-pixels+extent) >= 80)
1789 {
1790 *q++='\n';
1791 (void) WriteBlob(image,q-pixels,pixels);
1792 q=pixels;
1793 }
cristy3ed852e2009-09-05 21:47:34 +00001794 p++;
1795 }
1796 if (image->previous == (Image *) NULL)
1797 {
cristycee97112010-05-28 00:44:52 +00001798 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1799 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001800 if (status == MagickFalse)
1801 break;
1802 }
1803 }
cristy661b5ad2010-01-13 00:54:42 +00001804 if (q != pixels)
1805 {
1806 *q++='\n';
1807 (void) WriteBlob(image,q-pixels,pixels);
1808 }
cristy3ed852e2009-09-05 21:47:34 +00001809 break;
1810 }
1811 case '4':
1812 {
1813 /*
1814 Convert image to a PBM image.
1815 */
1816 image->depth=1;
1817 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1818 if (quantum_info == (QuantumInfo *) NULL)
1819 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1820 quantum_info->min_is_white=MagickTrue;
1821 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00001822 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001823 {
1824 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001825 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001826
1827 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1828 if (p == (const PixelPacket *) NULL)
1829 break;
1830 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
1831 quantum_info,GrayQuantum,pixels,&image->exception);
1832 count=WriteBlob(image,extent,pixels);
1833 if (count != (ssize_t) extent)
1834 break;
1835 if (image->previous == (Image *) NULL)
1836 {
cristycee97112010-05-28 00:44:52 +00001837 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1838 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001839 if (status == MagickFalse)
1840 break;
1841 }
1842 }
1843 quantum_info=DestroyQuantumInfo(quantum_info);
1844 break;
1845 }
1846 case '5':
1847 {
1848 QuantumAny
1849 range;
1850
1851 /*
1852 Convert image to a PGM image.
1853 */
1854 if (image->depth > 8)
1855 image->depth=16;
cristyf2faecf2010-05-28 19:19:36 +00001856 (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",(unsigned long)
cristy3ed852e2009-09-05 21:47:34 +00001857 GetQuantumRange(image->depth));
1858 (void) WriteBlobString(image,buffer);
1859 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1860 if (quantum_info == (QuantumInfo *) NULL)
1861 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1862 quantum_info->min_is_white=MagickTrue;
1863 pixels=GetQuantumPixels(quantum_info);
1864 extent=GetQuantumExtent(image,quantum_info,GrayQuantum);
1865 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001866 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001867 {
1868 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001869 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001870
cristybb503372010-05-27 20:51:26 +00001871 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001872 x;
1873
1874 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1875 if (p == (const PixelPacket *) NULL)
1876 break;
1877 q=pixels;
1878 if ((image->depth == 8) || (image->depth == 16))
1879 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
1880 quantum_info,GrayQuantum,pixels,&image->exception);
1881 else
1882 {
1883 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00001884 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001885 {
1886 if (IsGrayPixel(p) == MagickFalse)
1887 pixel=ScaleQuantumToAny(PixelIntensityToQuantum(p),range);
1888 else
1889 {
1890 if (image->depth == 8)
cristyce70c172010-01-07 17:15:30 +00001891 pixel=ScaleQuantumToChar(GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00001892 else
1893 pixel=ScaleQuantumToAny(p->red,range);
1894 }
1895 q=PopCharPixel((unsigned char) pixel,q);
1896 p++;
1897 }
1898 else
cristybb503372010-05-27 20:51:26 +00001899 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001900 {
1901 if (IsGrayPixel(p) == MagickFalse)
1902 pixel=ScaleQuantumToAny(PixelIntensityToQuantum(p),range);
1903 else
1904 {
1905 if (image->depth == 16)
cristyce70c172010-01-07 17:15:30 +00001906 pixel=ScaleQuantumToShort(GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00001907 else
1908 pixel=ScaleQuantumToAny(p->red,range);
1909 }
1910 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
1911 p++;
1912 }
1913 extent=(size_t) (q-pixels);
1914 }
1915 count=WriteBlob(image,extent,pixels);
1916 if (count != (ssize_t) extent)
1917 break;
1918 if (image->previous == (Image *) NULL)
1919 {
cristycee97112010-05-28 00:44:52 +00001920 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1921 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001922 if (status == MagickFalse)
1923 break;
1924 }
1925 }
1926 quantum_info=DestroyQuantumInfo(quantum_info);
1927 break;
1928 }
1929 case '6':
1930 {
1931 QuantumAny
1932 range;
1933
1934 /*
1935 Convert image to a PNM image.
1936 */
1937 if (image->depth > 8)
1938 image->depth=16;
cristyf2faecf2010-05-28 19:19:36 +00001939 (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",(unsigned long)
cristy3ed852e2009-09-05 21:47:34 +00001940 GetQuantumRange(image->depth));
1941 (void) WriteBlobString(image,buffer);
1942 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1943 if (quantum_info == (QuantumInfo *) NULL)
1944 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1945 pixels=GetQuantumPixels(quantum_info);
1946 extent=GetQuantumExtent(image,quantum_info,quantum_type);
1947 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001948 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001949 {
1950 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001951 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001952
cristybb503372010-05-27 20:51:26 +00001953 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001954 x;
1955
1956 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1957 if (p == (const PixelPacket *) NULL)
1958 break;
1959 q=pixels;
1960 if ((image->depth == 8) || (image->depth == 16))
1961 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
1962 quantum_info,quantum_type,pixels,&image->exception);
1963 else
1964 {
1965 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00001966 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001967 {
1968 pixel=ScaleQuantumToAny(p->red,range);
1969 q=PopCharPixel((unsigned char) pixel,q);
1970 pixel=ScaleQuantumToAny(p->green,range);
1971 q=PopCharPixel((unsigned char) pixel,q);
1972 pixel=ScaleQuantumToAny(p->blue,range);
1973 q=PopCharPixel((unsigned char) pixel,q);
cristy3ed852e2009-09-05 21:47:34 +00001974 p++;
1975 }
1976 else
cristybb503372010-05-27 20:51:26 +00001977 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001978 {
1979 pixel=ScaleQuantumToAny(p->red,range);
1980 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
1981 pixel=ScaleQuantumToAny(p->green,range);
1982 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
1983 pixel=ScaleQuantumToAny(p->blue,range);
1984 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy3ed852e2009-09-05 21:47:34 +00001985 p++;
1986 }
1987 extent=(size_t) (q-pixels);
1988 }
1989 count=WriteBlob(image,extent,pixels);
1990 if (count != (ssize_t) extent)
1991 break;
1992 if (image->previous == (Image *) NULL)
1993 {
cristycee97112010-05-28 00:44:52 +00001994 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1995 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001996 if (status == MagickFalse)
1997 break;
1998 }
1999 }
2000 quantum_info=DestroyQuantumInfo(quantum_info);
2001 break;
2002 }
2003 case '7':
2004 {
2005 QuantumAny
2006 range;
2007
2008 /*
2009 Convert image to a PAM.
2010 */
2011 if (image->depth > 16)
2012 image->depth=16;
2013 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
2014 pixels=GetQuantumPixels(quantum_info);
2015 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00002016 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002017 {
2018 register const IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002019 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002020
2021 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002022 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002023
cristybb503372010-05-27 20:51:26 +00002024 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002025 x;
2026
2027 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2028 if (p == (const PixelPacket *) NULL)
2029 break;
2030 indexes=GetVirtualIndexQueue(image);
2031 q=pixels;
2032 if ((image->depth == 8) || (image->depth == 16))
2033 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
2034 quantum_info,quantum_type,pixels,&image->exception);
2035 else
2036 {
2037 switch (quantum_type)
2038 {
2039 case GrayQuantum:
2040 case GrayAlphaQuantum:
2041 {
2042 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002043 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002044 {
2045 pixel=ScaleQuantumToAny(PixelIntensityToQuantum(p),range);
2046 q=PopCharPixel((unsigned char) pixel,q);
2047 if (image->matte != MagickFalse)
2048 {
2049 pixel=(unsigned char) ScaleQuantumToAny(p->opacity,
2050 range);
2051 q=PopCharPixel((unsigned char) pixel,q);
2052 }
2053 p++;
2054 }
2055 else
cristybb503372010-05-27 20:51:26 +00002056 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002057 {
2058 pixel=ScaleQuantumToAny(PixelIntensityToQuantum(p),range);
2059 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2060 if (image->matte != MagickFalse)
2061 {
2062 pixel=(unsigned char) ScaleQuantumToAny(p->opacity,
2063 range);
2064 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2065 }
2066 p++;
2067 }
2068 break;
2069 }
2070 case CMYKQuantum:
2071 case CMYKAQuantum:
2072 {
2073 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002074 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002075 {
2076 pixel=ScaleQuantumToAny(p->red,range);
2077 q=PopCharPixel((unsigned char) pixel,q);
2078 pixel=ScaleQuantumToAny(p->green,range);
2079 q=PopCharPixel((unsigned char) pixel,q);
2080 pixel=ScaleQuantumToAny(p->blue,range);
2081 q=PopCharPixel((unsigned char) pixel,q);
2082 pixel=ScaleQuantumToAny(indexes[x],range);
2083 q=PopCharPixel((unsigned char) pixel,q);
2084 if (image->matte != MagickFalse)
2085 {
2086 pixel=ScaleQuantumToAny((Quantum) (QuantumRange-
cristyce70c172010-01-07 17:15:30 +00002087 GetOpacityPixelComponent(p)),range);
cristy3ed852e2009-09-05 21:47:34 +00002088 q=PopCharPixel((unsigned char) pixel,q);
2089 }
2090 p++;
2091 }
2092 else
cristybb503372010-05-27 20:51:26 +00002093 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002094 {
2095 pixel=ScaleQuantumToAny(p->red,range);
2096 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2097 pixel=ScaleQuantumToAny(p->green,range);
2098 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2099 pixel=ScaleQuantumToAny(p->blue,range);
2100 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2101 pixel=ScaleQuantumToAny(indexes[x],range);
2102 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2103 if (image->matte != MagickFalse)
2104 {
2105 pixel=ScaleQuantumToAny((Quantum) (QuantumRange-
cristyce70c172010-01-07 17:15:30 +00002106 GetOpacityPixelComponent(p)),range);
cristy3ed852e2009-09-05 21:47:34 +00002107 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2108 }
2109 p++;
2110 }
2111 break;
2112 }
2113 default:
2114 {
2115 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002116 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002117 {
2118 pixel=ScaleQuantumToAny(p->red,range);
2119 q=PopCharPixel((unsigned char) pixel,q);
2120 pixel=ScaleQuantumToAny(p->green,range);
2121 q=PopCharPixel((unsigned char) pixel,q);
2122 pixel=ScaleQuantumToAny(p->blue,range);
2123 q=PopCharPixel((unsigned char) pixel,q);
2124 if (image->matte != MagickFalse)
2125 {
2126 pixel=ScaleQuantumToAny((Quantum) (QuantumRange-
cristyce70c172010-01-07 17:15:30 +00002127 GetOpacityPixelComponent(p)),range);
cristy3ed852e2009-09-05 21:47:34 +00002128 q=PopCharPixel((unsigned char) pixel,q);
2129 }
2130 p++;
2131 }
2132 else
cristybb503372010-05-27 20:51:26 +00002133 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002134 {
2135 pixel=ScaleQuantumToAny(p->red,range);
2136 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2137 pixel=ScaleQuantumToAny(p->green,range);
2138 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2139 pixel=ScaleQuantumToAny(p->blue,range);
2140 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2141 if (image->matte != MagickFalse)
2142 {
2143 pixel=ScaleQuantumToAny((Quantum) (QuantumRange-
cristyce70c172010-01-07 17:15:30 +00002144 GetOpacityPixelComponent(p)),range);
cristy3ed852e2009-09-05 21:47:34 +00002145 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2146 }
2147 p++;
2148 }
2149 break;
2150 }
2151 }
2152 extent=(size_t) (q-pixels);
2153 }
2154 count=WriteBlob(image,extent,pixels);
2155 if (count != (ssize_t) extent)
2156 break;
2157 if (image->previous == (Image *) NULL)
2158 {
cristycee97112010-05-28 00:44:52 +00002159 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2160 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002161 if (status == MagickFalse)
2162 break;
2163 }
2164 }
2165 quantum_info=DestroyQuantumInfo(quantum_info);
2166 break;
2167 }
2168 case 'F':
2169 case 'f':
2170 {
2171 (void) WriteBlobString(image,image->endian != LSBEndian ? "1.0\n" :
2172 "-1.0\n");
2173 image->depth=32;
2174 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
2175 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
2176 if (quantum_info == (QuantumInfo *) NULL)
2177 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2178 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2179 if (status == MagickFalse)
2180 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2181 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002182 for (y=(ssize_t) image->rows-1; y >= 0; y--)
cristy3ed852e2009-09-05 21:47:34 +00002183 {
2184 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002185 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002186
2187 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2188 if (p == (const PixelPacket *) NULL)
2189 break;
2190 extent=ExportQuantumPixels(image,(const CacheView *) NULL,
2191 quantum_info,quantum_type,pixels,&image->exception);
2192 (void) WriteBlob(image,extent,pixels);
2193 if (image->previous == (Image *) NULL)
2194 {
cristycee97112010-05-28 00:44:52 +00002195 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2196 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002197 if (status == MagickFalse)
2198 break;
2199 }
2200 }
2201 quantum_info=DestroyQuantumInfo(quantum_info);
2202 break;
2203 }
2204 }
2205 if (GetNextImageInList(image) == (Image *) NULL)
2206 break;
2207 image=SyncNextImageInList(image);
2208 status=SetImageProgress(image,SaveImagesTag,scene++,
2209 GetImageListLength(image));
2210 if (status == MagickFalse)
2211 break;
2212 } while (image_info->adjoin != MagickFalse);
2213 (void) CloseBlob(image);
2214 return(MagickTrue);
2215}