blob: 5fa89189fbbc32aa93eff6370cb007e1dd4ba9b4 [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% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/attribute.h"
44#include "MagickCore/blob.h"
45#include "MagickCore/blob-private.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/color.h"
48#include "MagickCore/color-private.h"
49#include "MagickCore/colorspace.h"
cristy510d06a2011-07-06 23:43:54 +000050#include "MagickCore/colorspace-private.h"
cristy4c08aed2011-07-01 19:47:50 +000051#include "MagickCore/exception.h"
52#include "MagickCore/exception-private.h"
53#include "MagickCore/image.h"
54#include "MagickCore/image-private.h"
55#include "MagickCore/list.h"
56#include "MagickCore/magick.h"
57#include "MagickCore/memory_.h"
58#include "MagickCore/module.h"
59#include "MagickCore/monitor.h"
60#include "MagickCore/monitor-private.h"
61#include "MagickCore/pixel-accessor.h"
62#include "MagickCore/property.h"
63#include "MagickCore/quantum-private.h"
64#include "MagickCore/static.h"
65#include "MagickCore/statistic.h"
66#include "MagickCore/string_.h"
67#include "MagickCore/string-private.h"
cristy3ed852e2009-09-05 21:47:34 +000068
69/*
70 Forward declarations.
71*/
72static MagickBooleanType
cristy1e178e72011-08-28 19:44:34 +000073 WritePNMImage(const ImageInfo *,Image *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +000074
75/*
76%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77% %
78% %
79% %
80% I s P N M %
81% %
82% %
83% %
84%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85%
86% IsPNM() returns MagickTrue if the image format type, identified by the
87% magick string, is PNM.
88%
89% The format of the IsPNM method is:
90%
91% MagickBooleanType IsPNM(const unsigned char *magick,const size_t extent)
92%
93% A description of each parameter follows:
94%
95% o magick: compare image format pattern against these bytes.
96%
97% o extent: Specifies the extent of the magick string.
98%
99*/
100static MagickBooleanType IsPNM(const unsigned char *magick,const size_t extent)
101{
102 if (extent < 2)
103 return(MagickFalse);
104 if ((*magick == (unsigned char) 'P') &&
105 ((magick[1] == '1') || (magick[1] == '2') || (magick[1] == '3') ||
106 (magick[1] == '4') || (magick[1] == '5') || (magick[1] == '6') ||
107 (magick[1] == '7') || (magick[1] == 'F') || (magick[1] == 'f')))
108 return(MagickTrue);
109 return(MagickFalse);
110}
111
112/*
113%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114% %
115% %
116% %
117% R e a d P N M I m a g e %
118% %
119% %
120% %
121%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122%
123% ReadPNMImage() reads a Portable Anymap image file and returns it.
124% It allocates the memory necessary for the new Image structure and returns
125% a pointer to the new image.
126%
127% The format of the ReadPNMImage method is:
128%
129% Image *ReadPNMImage(const ImageInfo *image_info,ExceptionInfo *exception)
130%
131% A description of each parameter follows:
132%
133% o image_info: the image info.
134%
135% o exception: return any errors or warnings in this structure.
136%
137*/
138
cristybb503372010-05-27 20:51:26 +0000139static inline ssize_t ConstrainPixel(Image *image,const ssize_t offset,
cristyc82a27b2011-10-21 01:07:16 +0000140 const size_t extent,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000141{
cristybb503372010-05-27 20:51:26 +0000142 if ((offset < 0) || (offset > (ssize_t) extent))
cristy3ed852e2009-09-05 21:47:34 +0000143 {
cristyc82a27b2011-10-21 01:07:16 +0000144 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
145 "InvalidPixel","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +0000146 return(0);
147 }
148 return(offset);
149}
150
cristyd15e6592011-10-15 00:13:06 +0000151static size_t PNMInteger(Image *image,const unsigned int base,
152 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000153{
154 char
155 *comment;
156
157 int
158 c;
159
160 register char
161 *p;
162
163 size_t
cristyaff6d802011-04-26 01:46:31 +0000164 extent,
cristy3ed852e2009-09-05 21:47:34 +0000165 value;
166
167 /*
168 Skip any leading whitespace.
169 */
170 extent=MaxTextExtent;
171 comment=(char *) NULL;
172 p=comment;
173 do
174 {
175 c=ReadBlobByte(image);
176 if (c == EOF)
177 return(0);
178 if (c == (int) '#')
179 {
180 /*
181 Read comment.
182 */
183 if (comment == (char *) NULL)
184 comment=AcquireString((char *) NULL);
185 p=comment+strlen(comment);
186 for ( ; (c != EOF) && (c != (int) '\n'); p++)
187 {
188 if ((size_t) (p-comment+1) >= extent)
189 {
190 extent<<=1;
191 comment=(char *) ResizeQuantumMemory(comment,extent+MaxTextExtent,
192 sizeof(*comment));
193 if (comment == (char *) NULL)
194 break;
195 p=comment+strlen(comment);
196 }
197 c=ReadBlobByte(image);
cristyc3dee302012-01-11 21:58:50 +0000198 if (c != (int) '\n')
199 {
200 *p=(char) c;
201 *(p+1)='\0';
202 }
cristy3ed852e2009-09-05 21:47:34 +0000203 }
204 if (comment == (char *) NULL)
205 return(0);
206 continue;
207 }
208 } while (isdigit(c) == MagickFalse);
209 if (comment != (char *) NULL)
210 {
cristyd15e6592011-10-15 00:13:06 +0000211 (void) SetImageProperty(image,"comment",comment,exception);
cristy3ed852e2009-09-05 21:47:34 +0000212 comment=DestroyString(comment);
213 }
214 if (base == 2)
cristybb503372010-05-27 20:51:26 +0000215 return((size_t) (c-(int) '0'));
cristy3ed852e2009-09-05 21:47:34 +0000216 /*
217 Evaluate number.
218 */
219 value=0;
220 do
221 {
222 value*=10;
223 value+=c-(int) '0';
224 c=ReadBlobByte(image);
225 if (c == EOF)
226 return(value);
227 } while (isdigit(c) != MagickFalse);
228 return(value);
229}
230
231static Image *ReadPNMImage(const ImageInfo *image_info,ExceptionInfo *exception)
232{
233 char
234 format;
235
236 double
237 quantum_scale;
238
239 Image
240 *image;
241
cristy3ed852e2009-09-05 21:47:34 +0000242 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
cristyaff6d802011-04-26 01:46:31 +0000258 depth,
cristy3ed852e2009-09-05 21:47:34 +0000259 extent,
cristyaff6d802011-04-26 01:46:31 +0000260 max_value,
cristy3ed852e2009-09-05 21:47:34 +0000261 packet_size;
262
263 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000264 count,
265 row,
266 y;
cristy3ed852e2009-09-05 21:47:34 +0000267
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);
cristy9950d572011-10-01 18:22:35 +0000278 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000279 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 */
cristyd15e6592011-10-15 00:13:06 +0000305 image->columns=PNMInteger(image,10,exception);
306 image->rows=PNMInteger(image,10,exception);
cristy3ed852e2009-09-05 21:47:34 +0000307 if ((format == 'f') || (format == 'F'))
308 {
309 char
310 scale[MaxTextExtent];
311
312 (void) ReadBlobString(image,scale);
cristydbdd0e32011-11-04 23:29:40 +0000313 quantum_scale=StringToDouble(scale,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000314 }
315 else
316 {
317 if ((format == '1') || (format == '4'))
318 max_value=1; /* bitmap */
319 else
cristyd15e6592011-10-15 00:13:06 +0000320 max_value=PNMInteger(image,10,exception);
cristy3ed852e2009-09-05 21:47:34 +0000321 }
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);
cristyda16f162011-02-19 23:52:17 +0000367 (void) packet_size;
cristy3ed852e2009-09-05 21:47:34 +0000368 if (LocaleCompare(keyword,"height") == 0)
cristye27293e2009-12-18 02:53:20 +0000369 image->rows=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000370 if (LocaleCompare(keyword,"maxval") == 0)
cristye27293e2009-12-18 02:53:20 +0000371 max_value=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000372 if (LocaleCompare(keyword,"TUPLTYPE") == 0)
373 {
374 if (LocaleCompare(value,"BLACKANDWHITE") == 0)
cristyb3a73b52011-07-26 01:34:43 +0000375 {
cristye2c4f182012-05-12 14:11:53 +0000376 SetImageColorspace(image,GRAYColorspace,exception);
cristyb3a73b52011-07-26 01:34:43 +0000377 quantum_type=GrayQuantum;
378 }
cristy7a201992012-05-12 23:30:43 +0000379 if (LocaleCompare(value,"BLACKANDWHITE_ALPHA") == 0)
380 {
381 SetImageColorspace(image,GRAYColorspace,exception);
382 image->matte=MagickTrue;
383 quantum_type=GrayAlphaQuantum;
384 }
385 if (LocaleCompare(value,"GRAYSCALE") == 0)
386 {
387 quantum_type=GrayQuantum;
388 SetImageColorspace(image,GRAYColorspace,exception);
389 }
cristy3ed852e2009-09-05 21:47:34 +0000390 if (LocaleCompare(value,"GRAYSCALE_ALPHA") == 0)
391 {
cristye2c4f182012-05-12 14:11:53 +0000392 SetImageColorspace(image,GRAYColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +0000393 image->matte=MagickTrue;
cristyb3a73b52011-07-26 01:34:43 +0000394 quantum_type=GrayAlphaQuantum;
cristy3ed852e2009-09-05 21:47:34 +0000395 }
396 if (LocaleCompare(value,"RGB_ALPHA") == 0)
397 {
cristy3ed852e2009-09-05 21:47:34 +0000398 image->matte=MagickTrue;
cristy7a201992012-05-12 23:30:43 +0000399 quantum_type=RGBAQuantum;
cristy3ed852e2009-09-05 21:47:34 +0000400 }
401 if (LocaleCompare(value,"CMYK") == 0)
402 {
cristye2c4f182012-05-12 14:11:53 +0000403 SetImageColorspace(image,CMYKColorspace,exception);
cristy7a201992012-05-12 23:30:43 +0000404 quantum_type=CMYKQuantum;
cristy3ed852e2009-09-05 21:47:34 +0000405 }
406 if (LocaleCompare(value,"CMYK_ALPHA") == 0)
407 {
cristye2c4f182012-05-12 14:11:53 +0000408 SetImageColorspace(image,CMYKColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +0000409 image->matte=MagickTrue;
cristy7a201992012-05-12 23:30:43 +0000410 quantum_type=CMYKAQuantum;
cristy3ed852e2009-09-05 21:47:34 +0000411 }
412 }
413 if (LocaleCompare(keyword,"width") == 0)
cristye27293e2009-12-18 02:53:20 +0000414 image->columns=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000415 }
416 }
417 if ((image->columns == 0) || (image->rows == 0))
418 ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
419 if (max_value >= 65536)
420 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
cristy3f1ee592011-06-15 23:03:58 +0000421 for (depth=1; GetQuantumRange(depth) < max_value; depth++) ;
cristy3ed852e2009-09-05 21:47:34 +0000422 image->depth=depth;
423 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
424 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
425 break;
426 /*
427 Convert PNM pixels to runextent-encoded MIFF packets.
428 */
429 status=MagickTrue;
430 row=0;
431 switch (format)
432 {
433 case '1':
434 {
435 /*
436 Convert PBM image to pixel packets.
437 */
cristye2c4f182012-05-12 14:11:53 +0000438 SetImageColorspace(image,GRAYColorspace,exception);
cristybb503372010-05-27 20:51:26 +0000439 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000440 {
cristybb503372010-05-27 20:51:26 +0000441 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000442 x;
443
cristy4c08aed2011-07-01 19:47:50 +0000444 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000445 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000446
447 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000448 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000449 break;
cristybb503372010-05-27 20:51:26 +0000450 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000451 {
cristy08528502012-01-01 00:52:17 +0000452 SetPixelGray(image,PNMInteger(image,2,exception) == 0 ?
cristyd15e6592011-10-15 00:13:06 +0000453 QuantumRange : 0,q);
cristyed231572011-07-14 02:18:59 +0000454 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000455 }
456 if (SyncAuthenticPixels(image,exception) == MagickFalse)
457 break;
458 if (image->previous == (Image *) NULL)
459 {
cristycee97112010-05-28 00:44:52 +0000460 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
461 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000462 if (status == MagickFalse)
463 break;
464 }
465 }
466 image->type=BilevelType;
467 break;
468 }
469 case '2':
470 {
cristybb503372010-05-27 20:51:26 +0000471 size_t
cristy3ed852e2009-09-05 21:47:34 +0000472 intensity;
473
474 /*
475 Convert PGM image to pixel packets.
476 */
cristye2c4f182012-05-12 14:11:53 +0000477 SetImageColorspace(image,GRAYColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +0000478 scale=(Quantum *) NULL;
479 if (max_value != (1U*QuantumRange))
480 {
481 /*
482 Compute pixel scaling table.
483 */
484 scale=(Quantum *) AcquireQuantumMemory((size_t) max_value+1UL,
485 sizeof(*scale));
486 if (scale == (Quantum *) NULL)
487 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000488 for (i=0; i <= (ssize_t) max_value; i++)
cristy3ed852e2009-09-05 21:47:34 +0000489 scale[i]=(Quantum) (((double) QuantumRange*i)/max_value+0.5);
490 }
cristybb503372010-05-27 20:51:26 +0000491 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000492 {
cristybb503372010-05-27 20:51:26 +0000493 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000494 x;
495
cristy4c08aed2011-07-01 19:47:50 +0000496 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000497 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000498
499 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyb3a73b52011-07-26 01:34:43 +0000500 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000501 break;
cristybb503372010-05-27 20:51:26 +0000502 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000503 {
cristyd15e6592011-10-15 00:13:06 +0000504 intensity=PNMInteger(image,10,exception);
cristy08528502012-01-01 00:52:17 +0000505 SetPixelGray(image,intensity,q);
cristyac23fd22010-05-11 14:48:58 +0000506 if (scale != (Quantum *) NULL)
cristy08528502012-01-01 00:52:17 +0000507 SetPixelGray(image,scale[ConstrainPixel(image,(ssize_t) intensity,
cristyc82a27b2011-10-21 01:07:16 +0000508 max_value,exception)],q);
cristyed231572011-07-14 02:18:59 +0000509 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000510 }
511 if (SyncAuthenticPixels(image,exception) == MagickFalse)
512 break;
513 if (image->previous == (Image *) NULL)
514 {
cristycee97112010-05-28 00:44:52 +0000515 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
516 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000517 if (status == MagickFalse)
518 break;
519 }
520 }
521 image->type=GrayscaleType;
522 if (scale != (Quantum *) NULL)
523 scale=(Quantum *) RelinquishMagickMemory(scale);
524 break;
525 }
526 case '3':
527 {
cristy4c08aed2011-07-01 19:47:50 +0000528 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +0000529 pixel;
530
531 /*
532 Convert PNM image to pixel packets.
533 */
534 scale=(Quantum *) NULL;
535 if (max_value != (1U*QuantumRange))
536 {
537 /*
538 Compute pixel scaling table.
539 */
540 scale=(Quantum *) AcquireQuantumMemory((size_t) max_value+1UL,
541 sizeof(*scale));
542 if (scale == (Quantum *) NULL)
543 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000544 for (i=0; i <= (ssize_t) max_value; i++)
cristy3ed852e2009-09-05 21:47:34 +0000545 scale[i]=(Quantum) (((double) QuantumRange*i)/max_value+0.5);
546 }
cristybb503372010-05-27 20:51:26 +0000547 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000548 {
cristybb503372010-05-27 20:51:26 +0000549 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000550 x;
551
cristy4c08aed2011-07-01 19:47:50 +0000552 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000553 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000554
555 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000556 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000557 break;
cristybb503372010-05-27 20:51:26 +0000558 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000559 {
cristyd15e6592011-10-15 00:13:06 +0000560 pixel.red=(MagickRealType) PNMInteger(image,10,exception);
561 pixel.green=(MagickRealType) PNMInteger(image,10,exception);
562 pixel.blue=(MagickRealType) PNMInteger(image,10,exception);
cristy3ed852e2009-09-05 21:47:34 +0000563 if (scale != (Quantum *) NULL)
564 {
cristybb503372010-05-27 20:51:26 +0000565 pixel.red=(MagickRealType) scale[ConstrainPixel(image,(ssize_t)
cristyc82a27b2011-10-21 01:07:16 +0000566 pixel.red,max_value,exception)];
cristy34575212010-11-06 12:39:23 +0000567 pixel.green=(MagickRealType) scale[ConstrainPixel(image,
cristyc82a27b2011-10-21 01:07:16 +0000568 (ssize_t) pixel.green,max_value,exception)];
cristybb503372010-05-27 20:51:26 +0000569 pixel.blue=(MagickRealType) scale[ConstrainPixel(image,(ssize_t)
cristyc82a27b2011-10-21 01:07:16 +0000570 pixel.blue,max_value,exception)];
cristy3ed852e2009-09-05 21:47:34 +0000571 }
cristy94b11832011-09-08 19:46:03 +0000572 SetPixelRed(image,ClampToQuantum(pixel.red),q);
573 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
574 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
cristyed231572011-07-14 02:18:59 +0000575 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000576 }
577 if (SyncAuthenticPixels(image,exception) == MagickFalse)
578 break;
579 if (image->previous == (Image *) NULL)
580 {
cristycee97112010-05-28 00:44:52 +0000581 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
582 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000583 if (status == MagickFalse)
584 break;
585 }
586 }
587 if (scale != (Quantum *) NULL)
588 scale=(Quantum *) RelinquishMagickMemory(scale);
589 break;
590 }
591 case '4':
592 {
593 /*
594 Convert PBM raw image to pixel packets.
595 */
cristye2c4f182012-05-12 14:11:53 +0000596 SetImageColorspace(image,GRAYColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +0000597 quantum_type=GrayQuantum;
598 if (image->storage_class == PseudoClass)
599 quantum_type=IndexQuantum;
600 quantum_info=AcquireQuantumInfo(image_info,image);
601 if (quantum_info == (QuantumInfo *) NULL)
602 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
603 SetQuantumMinIsWhite(quantum_info,MagickTrue);
604 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +0000605 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000606 {
cristy3ed852e2009-09-05 21:47:34 +0000607 MagickBooleanType
608 sync;
609
cristy4c08aed2011-07-01 19:47:50 +0000610 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000611 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000612
613 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000614 count,
615 offset;
cristy3ed852e2009-09-05 21:47:34 +0000616
617 size_t
618 length;
619
620 unsigned char
621 *pixels;
622
623 if (status == MagickFalse)
624 continue;
625 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000626 {
627 count=ReadBlob(image,extent,pixels);
628 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
629 (image->previous == (Image *) NULL))
630 {
631 MagickBooleanType
632 proceed;
633
cristycee97112010-05-28 00:44:52 +0000634 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
635 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000636 if (proceed == MagickFalse)
637 status=MagickFalse;
638 }
639 offset=row++;
640 }
641 if (count != (ssize_t) extent)
642 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000643 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000644 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000645 {
646 status=MagickFalse;
647 continue;
648 }
cristyaa740112010-03-30 17:58:44 +0000649 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
650 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +0000651 if (length != extent)
652 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000653 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000654 if (sync == MagickFalse)
655 status=MagickFalse;
656 }
cristy3ed852e2009-09-05 21:47:34 +0000657 quantum_info=DestroyQuantumInfo(quantum_info);
658 if (status == MagickFalse)
659 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
660 SetQuantumImageType(image,quantum_type);
661 break;
662 }
663 case '5':
664 {
665 QuantumAny
666 range;
667
668 /*
669 Convert PGM raw image to pixel packets.
670 */
cristye2c4f182012-05-12 14:11:53 +0000671 SetImageColorspace(image,GRAYColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +0000672 range=GetQuantumRange(image->depth);
673 quantum_type=GrayQuantum;
674 extent=(image->depth <= 8 ? 1 : 2)*image->columns;
675 quantum_info=AcquireQuantumInfo(image_info,image);
676 if (quantum_info == (QuantumInfo *) NULL)
677 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000678 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000679 {
cristy3ed852e2009-09-05 21:47:34 +0000680 MagickBooleanType
681 sync;
682
683 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000684 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000685
cristybb503372010-05-27 20:51:26 +0000686 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000687 x;
688
cristy4c08aed2011-07-01 19:47:50 +0000689 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000690 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000691
692 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000693 count,
694 offset;
cristy3ed852e2009-09-05 21:47:34 +0000695
696 unsigned char
697 *pixels;
698
699 if (status == MagickFalse)
700 continue;
701 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000702 {
703 count=ReadBlob(image,extent,pixels);
704 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
705 (image->previous == (Image *) NULL))
706 {
707 MagickBooleanType
708 proceed;
709
cristy34575212010-11-06 12:39:23 +0000710 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
711 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000712 if (proceed == MagickFalse)
713 status=MagickFalse;
714 }
715 offset=row++;
716 }
717 if (count != (ssize_t) extent)
718 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000719 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000720 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000721 {
722 status=MagickFalse;
723 continue;
724 }
725 p=pixels;
726 if ((image->depth == 8) || (image->depth == 16))
cristyaa740112010-03-30 17:58:44 +0000727 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3ed852e2009-09-05 21:47:34 +0000728 quantum_type,pixels,exception);
729 else
730 if (image->depth <= 8)
731 {
732 unsigned char
733 pixel;
734
cristybb503372010-05-27 20:51:26 +0000735 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000736 {
737 p=PushCharPixel(p,&pixel);
cristy08528502012-01-01 00:52:17 +0000738 SetPixelGray(image,ScaleAnyToQuantum(pixel,range),q);
cristyed231572011-07-14 02:18:59 +0000739 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000740 }
741 }
742 else
743 {
744 unsigned short
745 pixel;
746
cristybb503372010-05-27 20:51:26 +0000747 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000748 {
749 p=PushShortPixel(MSBEndian,p,&pixel);
cristy08528502012-01-01 00:52:17 +0000750 SetPixelGray(image,ScaleAnyToQuantum(pixel,range),q);
cristyed231572011-07-14 02:18:59 +0000751 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000752 }
753 }
cristyaa740112010-03-30 17:58:44 +0000754 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000755 if (sync == MagickFalse)
756 status=MagickFalse;
757 }
cristy3ed852e2009-09-05 21:47:34 +0000758 quantum_info=DestroyQuantumInfo(quantum_info);
759 if (status == MagickFalse)
760 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
761 SetQuantumImageType(image,quantum_type);
762 break;
763 }
764 case '6':
765 {
766 ImageType
767 type;
768
769 QuantumAny
770 range;
771
772 /*
773 Convert PNM raster image to pixel packets.
774 */
775 type=BilevelType;
776 quantum_type=RGBQuantum;
777 extent=3*(image->depth <= 8 ? 1 : 2)*image->columns;
778 range=GetQuantumRange(image->depth);
779 quantum_info=AcquireQuantumInfo(image_info,image);
780 if (quantum_info == (QuantumInfo *) NULL)
781 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000782 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000783 {
cristy3ed852e2009-09-05 21:47:34 +0000784 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
cristy4c08aed2011-07-01 19:47:50 +0000793 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000794 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000795
796 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000797 count,
798 offset;
cristy3ed852e2009-09-05 21:47:34 +0000799
cristy3ed852e2009-09-05 21:47:34 +0000800 unsigned char
801 *pixels;
802
803 if (status == MagickFalse)
804 continue;
805 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000806 {
807 count=ReadBlob(image,extent,pixels);
808 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
809 (image->previous == (Image *) NULL))
810 {
811 MagickBooleanType
812 proceed;
813
cristy34575212010-11-06 12:39:23 +0000814 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
815 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000816 if (proceed == MagickFalse)
817 status=MagickFalse;
818 }
819 offset=row++;
820 }
821 if (count != (ssize_t) extent)
822 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000823 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000824 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000825 {
826 status=MagickFalse;
827 continue;
828 }
829 p=pixels;
cristye90d7402010-03-14 18:21:29 +0000830 if (image->depth == 8)
cristybb503372010-05-27 20:51:26 +0000831 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000832 {
cristy4c08aed2011-07-01 19:47:50 +0000833 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
834 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
835 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
836 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000837 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000838 }
839 else
cristye90d7402010-03-14 18:21:29 +0000840 if (image->depth == 16)
cristy3ed852e2009-09-05 21:47:34 +0000841 {
842 unsigned short
843 pixel;
844
cristybb503372010-05-27 20:51:26 +0000845 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000846 {
847 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000848 SetPixelRed(image,ScaleShortToQuantum(pixel),q);
cristy3ed852e2009-09-05 21:47:34 +0000849 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000850 SetPixelGreen(image,ScaleShortToQuantum(pixel),q);
cristy3ed852e2009-09-05 21:47:34 +0000851 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000852 SetPixelBlue(image,ScaleShortToQuantum(pixel),q);
853 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000854 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000855 }
856 }
cristye90d7402010-03-14 18:21:29 +0000857 else
858 if (image->depth <= 8)
859 {
860 unsigned char
861 pixel;
862
cristybb503372010-05-27 20:51:26 +0000863 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000864 {
865 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000866 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000867 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000868 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000869 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000870 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
871 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000872 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000873 }
874 }
875 else
876 {
877 unsigned short
878 pixel;
879
cristybb503372010-05-27 20:51:26 +0000880 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000881 {
882 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000883 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000884 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000885 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000886 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000887 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
888 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000889 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000890 }
891 }
cristy3ed852e2009-09-05 21:47:34 +0000892 if ((type == BilevelType) || (type == GrayscaleType))
cristy3ed852e2009-09-05 21:47:34 +0000893 {
cristyaa740112010-03-30 17:58:44 +0000894 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristybb503372010-05-27 20:51:26 +0000895 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000896 {
897 if ((type == BilevelType) &&
cristy4c08aed2011-07-01 19:47:50 +0000898 (IsPixelMonochrome(image,q) == MagickFalse))
899 type=IsPixelGray(image,q) == MagickFalse ? UndefinedType :
cristye90d7402010-03-14 18:21:29 +0000900 GrayscaleType;
cristy4c08aed2011-07-01 19:47:50 +0000901 if ((type == GrayscaleType) &&
902 (IsPixelGray(image,q) == MagickFalse))
cristy5f1c1ff2010-12-23 21:38:06 +0000903 type=UndefinedType;
cristye90d7402010-03-14 18:21:29 +0000904 if ((type != BilevelType) && (type != GrayscaleType))
905 break;
cristyed231572011-07-14 02:18:59 +0000906 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000907 }
cristy3ed852e2009-09-05 21:47:34 +0000908 }
cristyaa740112010-03-30 17:58:44 +0000909 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000910 if (sync == MagickFalse)
911 status=MagickFalse;
912 }
cristy3ed852e2009-09-05 21:47:34 +0000913 quantum_info=DestroyQuantumInfo(quantum_info);
914 if (status == MagickFalse)
915 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
cristy5f1c1ff2010-12-23 21:38:06 +0000916 if (type != UndefinedType)
cristy3ed852e2009-09-05 21:47:34 +0000917 image->type=type;
918 break;
919 }
920 case '7':
921 {
cristy3ed852e2009-09-05 21:47:34 +0000922 QuantumAny
923 range;
924
cristybb503372010-05-27 20:51:26 +0000925 size_t
cristy3ed852e2009-09-05 21:47:34 +0000926 channels;
927
928 /*
929 Convert PAM raster image to pixel packets.
930 */
931 range=GetQuantumRange(image->depth);
932 switch (quantum_type)
933 {
934 case GrayQuantum:
935 case GrayAlphaQuantum:
936 {
937 channels=1;
938 break;
939 }
940 case CMYKQuantum:
941 case CMYKAQuantum:
942 {
943 channels=4;
944 break;
945 }
946 default:
947 {
948 channels=3;
949 break;
950 }
951 }
952 if (image->matte != MagickFalse)
953 channels++;
954 extent=channels*(image->depth <= 8 ? 1 : 2)*image->columns;
955 quantum_info=AcquireQuantumInfo(image_info,image);
956 if (quantum_info == (QuantumInfo *) NULL)
957 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000958 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000959 {
cristy3ed852e2009-09-05 21:47:34 +0000960 MagickBooleanType
961 sync;
962
963 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000964 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000965
cristybb503372010-05-27 20:51:26 +0000966 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000967 x;
968
cristy4c08aed2011-07-01 19:47:50 +0000969 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000970 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000971
972 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000973 count,
974 offset;
cristy3ed852e2009-09-05 21:47:34 +0000975
976 unsigned char
977 *pixels;
978
979 if (status == MagickFalse)
980 continue;
981 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000982 {
983 count=ReadBlob(image,extent,pixels);
984 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
985 (image->previous == (Image *) NULL))
986 {
987 MagickBooleanType
988 proceed;
989
cristy34575212010-11-06 12:39:23 +0000990 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
991 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000992 if (proceed == MagickFalse)
993 status=MagickFalse;
994 }
995 offset=row++;
996 }
997 if (count != (ssize_t) extent)
998 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000999 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00001000 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001001 {
1002 status=MagickFalse;
1003 continue;
1004 }
cristy3ed852e2009-09-05 21:47:34 +00001005 p=pixels;
1006 if ((image->depth == 8) || (image->depth == 16))
cristyaa740112010-03-30 17:58:44 +00001007 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3ed852e2009-09-05 21:47:34 +00001008 quantum_type,pixels,exception);
1009 else
1010 switch (quantum_type)
1011 {
1012 case GrayQuantum:
1013 case GrayAlphaQuantum:
1014 {
1015 if (image->depth <= 8)
1016 {
1017 unsigned char
1018 pixel;
1019
cristybb503372010-05-27 20:51:26 +00001020 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001021 {
1022 p=PushCharPixel(p,&pixel);
cristy08528502012-01-01 00:52:17 +00001023 SetPixelGray(image,ScaleAnyToQuantum(pixel,range),q);
cristy4c08aed2011-07-01 19:47:50 +00001024 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001025 if (image->matte != MagickFalse)
1026 {
1027 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001028 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001029 }
cristyed231572011-07-14 02:18:59 +00001030 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001031 }
1032 }
1033 else
1034 {
1035 unsigned short
1036 pixel;
1037
cristybb503372010-05-27 20:51:26 +00001038 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001039 {
1040 p=PushShortPixel(MSBEndian,p,&pixel);
cristy08528502012-01-01 00:52:17 +00001041 SetPixelGray(image,ScaleAnyToQuantum(pixel,range),q);
cristy4c08aed2011-07-01 19:47:50 +00001042 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001043 if (image->matte != MagickFalse)
1044 {
1045 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001046 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001047 }
cristyed231572011-07-14 02:18:59 +00001048 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001049 }
1050 }
1051 break;
1052 }
1053 case CMYKQuantum:
1054 case CMYKAQuantum:
1055 {
1056 if (image->depth <= 8)
1057 {
1058 unsigned char
1059 pixel;
1060
cristybb503372010-05-27 20:51:26 +00001061 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001062 {
1063 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001064 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001065 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001066 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001067 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001068 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001069 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001070 SetPixelBlack(image,ScaleAnyToQuantum(pixel,range),q);
1071 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001072 if (image->matte != MagickFalse)
1073 {
1074 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001075 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001076 }
cristyed231572011-07-14 02:18:59 +00001077 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001078 }
1079 }
1080 else
1081 {
1082 unsigned short
1083 pixel;
1084
cristybb503372010-05-27 20:51:26 +00001085 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001086 {
1087 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001088 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001089 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001090 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001091 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001092 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001093 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001094 SetPixelBlack(image,ScaleAnyToQuantum(pixel,range),q);
1095 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001096 if (image->matte != MagickFalse)
1097 {
1098 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001099 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001100 }
cristyed231572011-07-14 02:18:59 +00001101 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001102 }
1103 }
1104 break;
1105 }
1106 default:
1107 {
1108 if (image->depth <= 8)
1109 {
1110 unsigned char
1111 pixel;
1112
cristybb503372010-05-27 20:51:26 +00001113 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001114 {
1115 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001116 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001117 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001118 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001119 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001120 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
1121 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001122 if (image->matte != MagickFalse)
1123 {
1124 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001125 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001126 }
cristyed231572011-07-14 02:18:59 +00001127 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001128 }
1129 }
1130 else
1131 {
1132 unsigned short
1133 pixel;
1134
cristybb503372010-05-27 20:51:26 +00001135 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001136 {
1137 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001138 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001139 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001140 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001141 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001142 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
1143 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001144 if (image->matte != MagickFalse)
1145 {
1146 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001147 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001148 }
cristyed231572011-07-14 02:18:59 +00001149 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001150 }
1151 }
1152 break;
1153 }
1154 }
cristyaa740112010-03-30 17:58:44 +00001155 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001156 if (sync == MagickFalse)
1157 status=MagickFalse;
1158 }
cristy3ed852e2009-09-05 21:47:34 +00001159 quantum_info=DestroyQuantumInfo(quantum_info);
1160 if (status == MagickFalse)
1161 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1162 SetQuantumImageType(image,quantum_type);
1163 break;
1164 }
1165 case 'F':
1166 case 'f':
1167 {
1168 /*
1169 Convert PFM raster image to pixel packets.
1170 */
cristyaf6eb932012-01-01 01:22:59 +00001171 if (format == 'f')
cristye2c4f182012-05-12 14:11:53 +00001172 SetImageColorspace(image,GRAYColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +00001173 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
1174 image->endian=quantum_scale < 0.0 ? LSBEndian : MSBEndian;
1175 image->depth=32;
1176 quantum_info=AcquireQuantumInfo(image_info,image);
1177 if (quantum_info == (QuantumInfo *) NULL)
1178 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1179 status=SetQuantumDepth(image,quantum_info,32);
1180 if (status == MagickFalse)
1181 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1182 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1183 if (status == MagickFalse)
1184 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1185 SetQuantumScale(quantum_info,(MagickRealType) QuantumRange*
1186 fabs(quantum_scale));
1187 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +00001188 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001189 {
cristy3ed852e2009-09-05 21:47:34 +00001190 MagickBooleanType
1191 sync;
1192
cristy4c08aed2011-07-01 19:47:50 +00001193 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00001194 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001195
1196 ssize_t
cristyaff6d802011-04-26 01:46:31 +00001197 count,
1198 offset;
cristy3ed852e2009-09-05 21:47:34 +00001199
1200 size_t
1201 length;
1202
1203 unsigned char
1204 *pixels;
1205
1206 if (status == MagickFalse)
1207 continue;
1208 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001209 {
1210 count=ReadBlob(image,extent,pixels);
1211 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1212 (image->previous == (Image *) NULL))
1213 {
1214 MagickBooleanType
1215 proceed;
1216
cristy34575212010-11-06 12:39:23 +00001217 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1218 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001219 if (proceed == MagickFalse)
1220 status=MagickFalse;
1221 }
1222 offset=row++;
1223 }
1224 if ((size_t) count != extent)
1225 status=MagickFalse;
cristybb503372010-05-27 20:51:26 +00001226 q=QueueAuthenticPixels(image,0,(ssize_t) (image->rows-offset-1),
cristyaa740112010-03-30 17:58:44 +00001227 image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00001228 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001229 {
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)
cristy5d792232012-01-31 17:02:45 +00001251 {
1252 (void) ThrowMagickException(exception,GetMagickModule(),
1253 CorruptImageError,"UnexpectedEndOfFile","`%s'",image->filename);
1254 break;
1255 }
cristy3ed852e2009-09-05 21:47:34 +00001256 /*
1257 Proceed to next image.
1258 */
1259 if (image_info->number_scenes != 0)
1260 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1261 break;
1262 if ((format == '1') || (format == '2') || (format == '3'))
1263 do
1264 {
1265 /*
1266 Skip to end of line.
1267 */
1268 count=ReadBlob(image,1,(unsigned char *) &format);
1269 if (count == 0)
1270 break;
1271 if ((count != 0) && (format == 'P'))
1272 break;
1273 } while (format != '\n');
1274 count=ReadBlob(image,1,(unsigned char *) &format);
1275 if ((count == 1) && (format == 'P'))
1276 {
1277 /*
1278 Allocate next image structure.
1279 */
cristy9950d572011-10-01 18:22:35 +00001280 AcquireNextImage(image_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001281 if (GetNextImageInList(image) == (Image *) NULL)
1282 {
1283 image=DestroyImageList(image);
1284 return((Image *) NULL);
1285 }
1286 image=SyncNextImageInList(image);
1287 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1288 GetBlobSize(image));
1289 if (status == MagickFalse)
1290 break;
1291 }
1292 } while ((count == 1) && (format == 'P'));
1293 (void) CloseBlob(image);
1294 return(GetFirstImageInList(image));
1295}
1296
1297/*
1298%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1299% %
1300% %
1301% %
1302% R e g i s t e r P N M I m a g e %
1303% %
1304% %
1305% %
1306%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1307%
1308% RegisterPNMImage() adds properties for the PNM image format to
1309% the list of supported formats. The properties include the image format
1310% tag, a method to read and/or write the format, whether the format
1311% supports the saving of more than one frame to the same file or blob,
1312% whether the format supports native in-memory I/O, and a brief
1313% description of the format.
1314%
1315% The format of the RegisterPNMImage method is:
1316%
cristybb503372010-05-27 20:51:26 +00001317% size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001318%
1319*/
cristybb503372010-05-27 20:51:26 +00001320ModuleExport size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001321{
1322 MagickInfo
1323 *entry;
1324
1325 entry=SetMagickInfo("PAM");
1326 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1327 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1328 entry->description=ConstantString("Common 2-dimensional bitmap format");
1329 entry->module=ConstantString("PNM");
1330 (void) RegisterMagickInfo(entry);
1331 entry=SetMagickInfo("PBM");
1332 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1333 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1334 entry->description=ConstantString("Portable bitmap format (black and white)");
1335 entry->module=ConstantString("PNM");
1336 (void) RegisterMagickInfo(entry);
1337 entry=SetMagickInfo("PFM");
1338 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1339 entry->encoder=(EncodeImageHandler *) WritePNMImage;
cristye96405a2010-05-19 02:24:31 +00001340 entry->endian_support=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00001341 entry->description=ConstantString("Portable float format");
1342 entry->module=ConstantString("PFM");
1343 (void) RegisterMagickInfo(entry);
1344 entry=SetMagickInfo("PGM");
1345 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1346 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1347 entry->description=ConstantString("Portable graymap format (gray scale)");
1348 entry->module=ConstantString("PNM");
1349 (void) RegisterMagickInfo(entry);
1350 entry=SetMagickInfo("PNM");
1351 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1352 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1353 entry->magick=(IsImageFormatHandler *) IsPNM;
1354 entry->description=ConstantString("Portable anymap");
1355 entry->module=ConstantString("PNM");
1356 (void) RegisterMagickInfo(entry);
1357 entry=SetMagickInfo("PPM");
1358 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1359 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1360 entry->description=ConstantString("Portable pixmap format (color)");
1361 entry->module=ConstantString("PNM");
1362 (void) RegisterMagickInfo(entry);
1363 return(MagickImageCoderSignature);
1364}
1365
1366/*
1367%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1368% %
1369% %
1370% %
1371% U n r e g i s t e r P N M I m a g e %
1372% %
1373% %
1374% %
1375%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1376%
1377% UnregisterPNMImage() removes format registrations made by the
1378% PNM module from the list of supported formats.
1379%
1380% The format of the UnregisterPNMImage method is:
1381%
1382% UnregisterPNMImage(void)
1383%
1384*/
1385ModuleExport void UnregisterPNMImage(void)
1386{
1387 (void) UnregisterMagickInfo("PAM");
1388 (void) UnregisterMagickInfo("PBM");
1389 (void) UnregisterMagickInfo("PGM");
1390 (void) UnregisterMagickInfo("PNM");
1391 (void) UnregisterMagickInfo("PPM");
1392}
1393
1394/*
1395%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1396% %
1397% %
1398% %
1399% W r i t e P N M I m a g e %
1400% %
1401% %
1402% %
1403%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1404%
cristy661b5ad2010-01-13 00:54:42 +00001405% WritePNMImage() writes an image to a file in the PNM rasterfile format.
cristy3ed852e2009-09-05 21:47:34 +00001406%
1407% The format of the WritePNMImage method is:
1408%
cristy1e178e72011-08-28 19:44:34 +00001409% MagickBooleanType WritePNMImage(const ImageInfo *image_info,
1410% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001411%
1412% A description of each parameter follows.
1413%
1414% o image_info: the image info.
1415%
1416% o image: The image.
1417%
cristy1e178e72011-08-28 19:44:34 +00001418% o exception: return any errors or warnings in this structure.
1419%
cristy3ed852e2009-09-05 21:47:34 +00001420*/
cristy1e178e72011-08-28 19:44:34 +00001421static MagickBooleanType WritePNMImage(const ImageInfo *image_info,Image *image,
1422 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001423{
1424 char
1425 buffer[MaxTextExtent],
1426 format,
1427 magick[MaxTextExtent];
1428
1429 const char
1430 *value;
1431
cristy3ed852e2009-09-05 21:47:34 +00001432 MagickBooleanType
1433 status;
1434
1435 MagickOffsetType
1436 scene;
1437
cristy4c08aed2011-07-01 19:47:50 +00001438 Quantum
1439 index;
1440
cristy3ed852e2009-09-05 21:47:34 +00001441 QuantumAny
1442 pixel;
1443
1444 QuantumInfo
1445 *quantum_info;
1446
1447 QuantumType
1448 quantum_type;
1449
cristy3ed852e2009-09-05 21:47:34 +00001450 register unsigned char
1451 *pixels,
1452 *q;
1453
cristy3ed852e2009-09-05 21:47:34 +00001454 size_t
1455 extent,
1456 packet_size;
1457
cristy95802a72010-09-05 19:07:17 +00001458 ssize_t
cristyaff6d802011-04-26 01:46:31 +00001459 count,
1460 y;
cristy95802a72010-09-05 19:07:17 +00001461
cristy3ed852e2009-09-05 21:47:34 +00001462 /*
1463 Open output image file.
1464 */
1465 assert(image_info != (const ImageInfo *) NULL);
1466 assert(image_info->signature == MagickSignature);
1467 assert(image != (Image *) NULL);
1468 assert(image->signature == MagickSignature);
1469 if (image->debug != MagickFalse)
1470 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy3a37efd2011-08-28 20:31:03 +00001471 assert(exception != (ExceptionInfo *) NULL);
1472 assert(exception->signature == MagickSignature);
cristy1e178e72011-08-28 19:44:34 +00001473 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy3ed852e2009-09-05 21:47:34 +00001474 if (status == MagickFalse)
1475 return(status);
1476 scene=0;
1477 do
1478 {
1479 /*
1480 Write PNM file header.
1481 */
1482 packet_size=3;
1483 quantum_type=RGBQuantum;
1484 (void) CopyMagickString(magick,image_info->magick,MaxTextExtent);
1485 switch (magick[1])
1486 {
1487 case 'A':
1488 case 'a':
1489 {
1490 format='7';
1491 break;
1492 }
1493 case 'B':
1494 case 'b':
1495 {
1496 format='4';
1497 if (image_info->compression == NoCompression)
1498 format='1';
1499 break;
1500 }
1501 case 'F':
1502 case 'f':
1503 {
1504 format='F';
cristy1e178e72011-08-28 19:44:34 +00001505 if (IsImageGray(image,exception) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001506 format='f';
1507 break;
1508 }
1509 case 'G':
1510 case 'g':
1511 {
1512 format='5';
1513 if (image_info->compression == NoCompression)
1514 format='2';
1515 break;
1516 }
1517 case 'N':
1518 case 'n':
1519 {
1520 if ((image_info->type != TrueColorType) &&
cristy1e178e72011-08-28 19:44:34 +00001521 (IsImageGray(image,exception) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001522 {
1523 format='5';
1524 if (image_info->compression == NoCompression)
1525 format='2';
cristy1e178e72011-08-28 19:44:34 +00001526 if (IsImageMonochrome(image,exception) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001527 {
1528 format='4';
1529 if (image_info->compression == NoCompression)
1530 format='1';
1531 }
1532 break;
1533 }
1534 }
1535 default:
1536 {
1537 format='6';
1538 if (image_info->compression == NoCompression)
1539 format='3';
1540 break;
1541 }
1542 }
cristyb51dff52011-05-19 16:55:47 +00001543 (void) FormatLocaleString(buffer,MaxTextExtent,"P%c\n",format);
cristy3ed852e2009-09-05 21:47:34 +00001544 (void) WriteBlobString(image,buffer);
cristyd15e6592011-10-15 00:13:06 +00001545 value=GetImageProperty(image,"comment",exception);
cristy3ed852e2009-09-05 21:47:34 +00001546 if (value != (const char *) NULL)
1547 {
1548 register const char
1549 *p;
1550
1551 /*
1552 Write comments to file.
1553 */
1554 (void) WriteBlobByte(image,'#');
1555 for (p=value; *p != '\0'; p++)
1556 {
1557 (void) WriteBlobByte(image,(unsigned char) *p);
1558 if ((*p == '\r') && (*(p+1) != '\0'))
1559 (void) WriteBlobByte(image,'#');
1560 if ((*p == '\n') && (*(p+1) != '\0'))
1561 (void) WriteBlobByte(image,'#');
1562 }
1563 (void) WriteBlobByte(image,'\n');
1564 }
1565 if (format != '7')
1566 {
cristyd9ecd042012-06-17 18:26:12 +00001567 if ((IssRGBColorspace(image->colorspace) == MagickFalse) &&
1568 (IsImageGray(image,exception) == MagickFalse))
cristy8d951092012-02-08 18:54:56 +00001569 (void) TransformImageColorspace(image,sRGBColorspace,exception);
cristyb51dff52011-05-19 16:55:47 +00001570 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n",
cristye8c25f92010-06-03 00:53:06 +00001571 (double) image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001572 (void) WriteBlobString(image,buffer);
1573 }
1574 else
1575 {
1576 char
1577 type[MaxTextExtent];
1578
1579 /*
1580 PAM header.
1581 */
cristyb51dff52011-05-19 16:55:47 +00001582 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00001583 "WIDTH %.20g\nHEIGHT %.20g\n",(double) image->columns,(double)
1584 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001585 (void) WriteBlobString(image,buffer);
cristy1e178e72011-08-28 19:44:34 +00001586 quantum_type=GetQuantumType(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001587 switch (quantum_type)
1588 {
1589 case CMYKQuantum:
1590 case CMYKAQuantum:
1591 {
1592 packet_size=4;
1593 (void) CopyMagickString(type,"CMYK",MaxTextExtent);
1594 break;
1595 }
1596 case GrayQuantum:
1597 case GrayAlphaQuantum:
1598 {
1599 packet_size=1;
1600 (void) CopyMagickString(type,"GRAYSCALE",MaxTextExtent);
1601 break;
1602 }
1603 default:
1604 {
1605 quantum_type=RGBQuantum;
1606 if (image->matte != MagickFalse)
1607 quantum_type=RGBAQuantum;
1608 packet_size=3;
1609 (void) CopyMagickString(type,"RGB",MaxTextExtent);
1610 break;
1611 }
1612 }
1613 if (image->matte != MagickFalse)
1614 {
1615 packet_size++;
1616 (void) ConcatenateMagickString(type,"_ALPHA",MaxTextExtent);
1617 }
1618 if (image->depth > 16)
1619 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001620 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00001621 "DEPTH %.20g\nMAXVAL %.20g\n",(double) packet_size,(double)
cristy2b9582a2011-07-04 17:38:56 +00001622 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001623 (void) WriteBlobString(image,buffer);
cristyb51dff52011-05-19 16:55:47 +00001624 (void) FormatLocaleString(buffer,MaxTextExtent,"TUPLTYPE %s\nENDHDR\n",
cristy3ed852e2009-09-05 21:47:34 +00001625 type);
1626 (void) WriteBlobString(image,buffer);
1627 }
1628 /*
1629 Convert runextent encoded to PNM raster pixels.
1630 */
1631 switch (format)
1632 {
1633 case '1':
1634 {
cristy661b5ad2010-01-13 00:54:42 +00001635 unsigned char
1636 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001637
1638 /*
1639 Convert image to a PBM image.
1640 */
cristy661b5ad2010-01-13 00:54:42 +00001641 q=pixels;
cristybb503372010-05-27 20:51:26 +00001642 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001643 {
cristy4c08aed2011-07-01 19:47:50 +00001644 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001645 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001646
cristybb503372010-05-27 20:51:26 +00001647 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001648 x;
1649
cristy1e178e72011-08-28 19:44:34 +00001650 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001651 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001652 break;
cristybb503372010-05-27 20:51:26 +00001653 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001654 {
cristy4c08aed2011-07-01 19:47:50 +00001655 pixel=GetPixelIntensity(image,p);
cristy661b5ad2010-01-13 00:54:42 +00001656 *q++=(unsigned char) (pixel >= (Quantum) (QuantumRange/2) ?
1657 '0' : '1');
1658 *q++=' ';
1659 if ((q-pixels+2) >= 80)
1660 {
1661 *q++='\n';
1662 (void) WriteBlob(image,q-pixels,pixels);
1663 q=pixels;
cristy661b5ad2010-01-13 00:54:42 +00001664 }
cristyed231572011-07-14 02:18:59 +00001665 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001666 }
1667 if (image->previous == (Image *) NULL)
1668 {
cristycee97112010-05-28 00:44:52 +00001669 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1670 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001671 if (status == MagickFalse)
1672 break;
1673 }
1674 }
cristy661b5ad2010-01-13 00:54:42 +00001675 if (q != pixels)
1676 {
1677 *q++='\n';
1678 (void) WriteBlob(image,q-pixels,pixels);
1679 }
cristy3ed852e2009-09-05 21:47:34 +00001680 break;
1681 }
1682 case '2':
1683 {
cristy661b5ad2010-01-13 00:54:42 +00001684 unsigned char
1685 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001686
1687 /*
1688 Convert image to a PGM image.
1689 */
1690 if (image->depth <= 8)
1691 (void) WriteBlobString(image,"255\n");
1692 else
1693 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001694 q=pixels;
cristybb503372010-05-27 20:51:26 +00001695 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001696 {
cristy4c08aed2011-07-01 19:47:50 +00001697 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001698 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001699
cristybb503372010-05-27 20:51:26 +00001700 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001701 x;
1702
cristy1e178e72011-08-28 19:44:34 +00001703 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001704 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001705 break;
cristybb503372010-05-27 20:51:26 +00001706 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001707 {
cristy4c08aed2011-07-01 19:47:50 +00001708 index=GetPixelIntensity(image,p);
cristy3ed852e2009-09-05 21:47:34 +00001709 if (image->depth <= 8)
cristyb51dff52011-05-19 16:55:47 +00001710 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,"%u ",
cristy3ed852e2009-09-05 21:47:34 +00001711 ScaleQuantumToChar(index));
1712 else
cristyb51dff52011-05-19 16:55:47 +00001713 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,"%u ",
cristy3ed852e2009-09-05 21:47:34 +00001714 ScaleQuantumToShort(index));
cristy661b5ad2010-01-13 00:54:42 +00001715 extent=(size_t) count;
1716 (void) strncpy((char *) q,buffer,extent);
1717 q+=extent;
1718 if ((q-pixels+extent) >= 80)
1719 {
1720 *q++='\n';
1721 (void) WriteBlob(image,q-pixels,pixels);
1722 q=pixels;
1723 }
cristyed231572011-07-14 02:18:59 +00001724 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001725 }
1726 if (image->previous == (Image *) NULL)
1727 {
cristycee97112010-05-28 00:44:52 +00001728 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1729 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001730 if (status == MagickFalse)
1731 break;
1732 }
1733 }
cristy661b5ad2010-01-13 00:54:42 +00001734 if (q != pixels)
1735 {
1736 *q++='\n';
1737 (void) WriteBlob(image,q-pixels,pixels);
1738 }
cristy3ed852e2009-09-05 21:47:34 +00001739 break;
1740 }
1741 case '3':
1742 {
cristy661b5ad2010-01-13 00:54:42 +00001743 unsigned char
1744 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001745
1746 /*
1747 Convert image to a PNM image.
1748 */
1749 if (image->depth <= 8)
1750 (void) WriteBlobString(image,"255\n");
1751 else
1752 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001753 q=pixels;
cristybb503372010-05-27 20:51:26 +00001754 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001755 {
cristy4c08aed2011-07-01 19:47:50 +00001756 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001757 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001758
cristybb503372010-05-27 20:51:26 +00001759 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001760 x;
1761
cristy1e178e72011-08-28 19:44:34 +00001762 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001763 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001764 break;
cristybb503372010-05-27 20:51:26 +00001765 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001766 {
1767 if (image->depth <= 8)
cristyb51dff52011-05-19 16:55:47 +00001768 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,
cristy4c08aed2011-07-01 19:47:50 +00001769 "%u %u %u ",ScaleQuantumToChar(GetPixelRed(image,p)),
1770 ScaleQuantumToChar(GetPixelGreen(image,p)),
1771 ScaleQuantumToChar(GetPixelBlue(image,p)));
cristy3ed852e2009-09-05 21:47:34 +00001772 else
cristyb51dff52011-05-19 16:55:47 +00001773 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,
cristy4c08aed2011-07-01 19:47:50 +00001774 "%u %u %u ",ScaleQuantumToShort(GetPixelRed(image,p)),
1775 ScaleQuantumToShort(GetPixelGreen(image,p)),
1776 ScaleQuantumToShort(GetPixelBlue(image,p)));
cristy661b5ad2010-01-13 00:54:42 +00001777 extent=(size_t) count;
1778 (void) strncpy((char *) q,buffer,extent);
1779 q+=extent;
1780 if ((q-pixels+extent) >= 80)
1781 {
1782 *q++='\n';
1783 (void) WriteBlob(image,q-pixels,pixels);
1784 q=pixels;
1785 }
cristyed231572011-07-14 02:18:59 +00001786 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001787 }
1788 if (image->previous == (Image *) NULL)
1789 {
cristycee97112010-05-28 00:44:52 +00001790 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1791 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001792 if (status == MagickFalse)
1793 break;
1794 }
1795 }
cristy661b5ad2010-01-13 00:54:42 +00001796 if (q != pixels)
1797 {
1798 *q++='\n';
1799 (void) WriteBlob(image,q-pixels,pixels);
1800 }
cristy3ed852e2009-09-05 21:47:34 +00001801 break;
1802 }
1803 case '4':
1804 {
1805 /*
1806 Convert image to a PBM image.
1807 */
1808 image->depth=1;
1809 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1810 if (quantum_info == (QuantumInfo *) NULL)
1811 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1812 quantum_info->min_is_white=MagickTrue;
1813 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00001814 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001815 {
cristy4c08aed2011-07-01 19:47:50 +00001816 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001817 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001818
cristy1e178e72011-08-28 19:44:34 +00001819 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001820 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001821 break;
cristy4c08aed2011-07-01 19:47:50 +00001822 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001823 GrayQuantum,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001824 count=WriteBlob(image,extent,pixels);
1825 if (count != (ssize_t) extent)
1826 break;
1827 if (image->previous == (Image *) NULL)
1828 {
cristycee97112010-05-28 00:44:52 +00001829 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1830 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001831 if (status == MagickFalse)
1832 break;
1833 }
1834 }
1835 quantum_info=DestroyQuantumInfo(quantum_info);
1836 break;
1837 }
1838 case '5':
1839 {
1840 QuantumAny
1841 range;
1842
1843 /*
1844 Convert image to a PGM image.
1845 */
1846 if (image->depth > 8)
1847 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001848 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g\n",(double)
cristy2b9582a2011-07-04 17:38:56 +00001849 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001850 (void) WriteBlobString(image,buffer);
1851 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1852 if (quantum_info == (QuantumInfo *) NULL)
1853 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1854 quantum_info->min_is_white=MagickTrue;
1855 pixels=GetQuantumPixels(quantum_info);
1856 extent=GetQuantumExtent(image,quantum_info,GrayQuantum);
1857 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001858 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001859 {
cristy4c08aed2011-07-01 19:47:50 +00001860 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001861 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001862
cristybb503372010-05-27 20:51:26 +00001863 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001864 x;
1865
cristy1e178e72011-08-28 19:44:34 +00001866 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001867 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001868 break;
1869 q=pixels;
1870 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00001871 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001872 GrayQuantum,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001873 else
1874 {
1875 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00001876 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001877 {
cristy4c08aed2011-07-01 19:47:50 +00001878 if (IsPixelGray(image,p) == MagickFalse)
1879 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001880 else
1881 {
1882 if (image->depth == 8)
cristy4c08aed2011-07-01 19:47:50 +00001883 pixel=ScaleQuantumToChar(GetPixelRed(image,p));
cristy3ed852e2009-09-05 21:47:34 +00001884 else
cristy4c08aed2011-07-01 19:47:50 +00001885 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001886 }
1887 q=PopCharPixel((unsigned char) pixel,q);
cristyed231572011-07-14 02:18:59 +00001888 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001889 }
1890 else
cristybb503372010-05-27 20:51:26 +00001891 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001892 {
cristy4c08aed2011-07-01 19:47:50 +00001893 if (IsPixelGray(image,p) == MagickFalse)
1894 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001895 else
1896 {
1897 if (image->depth == 16)
cristy4c08aed2011-07-01 19:47:50 +00001898 pixel=ScaleQuantumToShort(GetPixelRed(image,p));
cristy3ed852e2009-09-05 21:47:34 +00001899 else
cristy4c08aed2011-07-01 19:47:50 +00001900 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001901 }
1902 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyed231572011-07-14 02:18:59 +00001903 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001904 }
1905 extent=(size_t) (q-pixels);
1906 }
1907 count=WriteBlob(image,extent,pixels);
1908 if (count != (ssize_t) extent)
1909 break;
1910 if (image->previous == (Image *) NULL)
1911 {
cristycee97112010-05-28 00:44:52 +00001912 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1913 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001914 if (status == MagickFalse)
1915 break;
1916 }
1917 }
1918 quantum_info=DestroyQuantumInfo(quantum_info);
1919 break;
1920 }
1921 case '6':
1922 {
1923 QuantumAny
1924 range;
1925
1926 /*
1927 Convert image to a PNM image.
1928 */
1929 if (image->depth > 8)
1930 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001931 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g\n",(double)
cristy2b9582a2011-07-04 17:38:56 +00001932 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001933 (void) WriteBlobString(image,buffer);
1934 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1935 if (quantum_info == (QuantumInfo *) NULL)
1936 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1937 pixels=GetQuantumPixels(quantum_info);
1938 extent=GetQuantumExtent(image,quantum_info,quantum_type);
1939 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001940 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001941 {
cristy4c08aed2011-07-01 19:47:50 +00001942 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001943 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001944
cristybb503372010-05-27 20:51:26 +00001945 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001946 x;
1947
cristy1e178e72011-08-28 19:44:34 +00001948 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001949 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001950 break;
1951 q=pixels;
1952 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00001953 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001954 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001955 else
1956 {
1957 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00001958 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001959 {
cristy4c08aed2011-07-01 19:47:50 +00001960 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001961 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001962 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001963 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001964 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001965 q=PopCharPixel((unsigned char) pixel,q);
cristyed231572011-07-14 02:18:59 +00001966 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001967 }
1968 else
cristybb503372010-05-27 20:51:26 +00001969 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001970 {
cristy4c08aed2011-07-01 19:47:50 +00001971 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001972 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001973 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001974 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001975 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001976 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyed231572011-07-14 02:18:59 +00001977 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001978 }
1979 extent=(size_t) (q-pixels);
1980 }
1981 count=WriteBlob(image,extent,pixels);
1982 if (count != (ssize_t) extent)
1983 break;
1984 if (image->previous == (Image *) NULL)
1985 {
cristycee97112010-05-28 00:44:52 +00001986 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1987 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001988 if (status == MagickFalse)
1989 break;
1990 }
1991 }
1992 quantum_info=DestroyQuantumInfo(quantum_info);
1993 break;
1994 }
1995 case '7':
1996 {
1997 QuantumAny
1998 range;
1999
2000 /*
2001 Convert image to a PAM.
2002 */
2003 if (image->depth > 16)
2004 image->depth=16;
2005 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
2006 pixels=GetQuantumPixels(quantum_info);
2007 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00002008 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002009 {
cristy4c08aed2011-07-01 19:47:50 +00002010 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00002011 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002012
cristybb503372010-05-27 20:51:26 +00002013 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002014 x;
2015
cristy1e178e72011-08-28 19:44:34 +00002016 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002017 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002018 break;
cristy3ed852e2009-09-05 21:47:34 +00002019 q=pixels;
2020 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00002021 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002022 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002023 else
2024 {
2025 switch (quantum_type)
2026 {
2027 case GrayQuantum:
2028 case GrayAlphaQuantum:
2029 {
2030 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002031 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002032 {
cristy4c08aed2011-07-01 19:47:50 +00002033 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002034 q=PopCharPixel((unsigned char) pixel,q);
2035 if (image->matte != MagickFalse)
2036 {
cristyaff6d802011-04-26 01:46:31 +00002037 pixel=(unsigned char) ScaleQuantumToAny(
cristy4c08aed2011-07-01 19:47:50 +00002038 GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002039 q=PopCharPixel((unsigned char) pixel,q);
2040 }
cristyed231572011-07-14 02:18:59 +00002041 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002042 }
2043 else
cristybb503372010-05-27 20:51:26 +00002044 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002045 {
cristy4c08aed2011-07-01 19:47:50 +00002046 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002047 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2048 if (image->matte != MagickFalse)
2049 {
cristyaff6d802011-04-26 01:46:31 +00002050 pixel=(unsigned char) ScaleQuantumToAny(
cristy4c08aed2011-07-01 19:47:50 +00002051 GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002052 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2053 }
cristyed231572011-07-14 02:18:59 +00002054 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002055 }
2056 break;
2057 }
2058 case CMYKQuantum:
2059 case CMYKAQuantum:
2060 {
2061 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002062 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002063 {
cristy4c08aed2011-07-01 19:47:50 +00002064 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002065 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002066 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002067 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002068 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002069 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002070 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002071 q=PopCharPixel((unsigned char) pixel,q);
2072 if (image->matte != MagickFalse)
2073 {
cristy4c08aed2011-07-01 19:47:50 +00002074 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002075 q=PopCharPixel((unsigned char) pixel,q);
2076 }
cristyed231572011-07-14 02:18:59 +00002077 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002078 }
2079 else
cristybb503372010-05-27 20:51:26 +00002080 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002081 {
cristy4c08aed2011-07-01 19:47:50 +00002082 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002083 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002084 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002085 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002086 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002087 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002088 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002089 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2090 if (image->matte != MagickFalse)
2091 {
cristy4c08aed2011-07-01 19:47:50 +00002092 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002093 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2094 }
cristyed231572011-07-14 02:18:59 +00002095 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002096 }
2097 break;
2098 }
2099 default:
2100 {
2101 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002102 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002103 {
cristy4c08aed2011-07-01 19:47:50 +00002104 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002105 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002106 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002107 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002108 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002109 q=PopCharPixel((unsigned char) pixel,q);
2110 if (image->matte != MagickFalse)
2111 {
cristy4c08aed2011-07-01 19:47:50 +00002112 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002113 q=PopCharPixel((unsigned char) pixel,q);
2114 }
cristyed231572011-07-14 02:18:59 +00002115 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002116 }
2117 else
cristybb503372010-05-27 20:51:26 +00002118 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002119 {
cristy4c08aed2011-07-01 19:47:50 +00002120 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002121 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002122 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002123 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002124 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002125 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2126 if (image->matte != MagickFalse)
2127 {
cristy4c08aed2011-07-01 19:47:50 +00002128 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002129 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2130 }
cristyed231572011-07-14 02:18:59 +00002131 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002132 }
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 {
cristycee97112010-05-28 00:44:52 +00002143 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2144 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002145 if (status == MagickFalse)
2146 break;
2147 }
2148 }
2149 quantum_info=DestroyQuantumInfo(quantum_info);
2150 break;
2151 }
2152 case 'F':
2153 case 'f':
2154 {
2155 (void) WriteBlobString(image,image->endian != LSBEndian ? "1.0\n" :
2156 "-1.0\n");
2157 image->depth=32;
2158 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
2159 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
2160 if (quantum_info == (QuantumInfo *) NULL)
2161 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2162 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2163 if (status == MagickFalse)
2164 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2165 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002166 for (y=(ssize_t) image->rows-1; y >= 0; y--)
cristy3ed852e2009-09-05 21:47:34 +00002167 {
cristy4c08aed2011-07-01 19:47:50 +00002168 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00002169 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002170
cristy1e178e72011-08-28 19:44:34 +00002171 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002172 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002173 break;
cristy4c08aed2011-07-01 19:47:50 +00002174 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002175 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002176 (void) WriteBlob(image,extent,pixels);
2177 if (image->previous == (Image *) NULL)
2178 {
cristycee97112010-05-28 00:44:52 +00002179 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2180 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002181 if (status == MagickFalse)
2182 break;
2183 }
2184 }
2185 quantum_info=DestroyQuantumInfo(quantum_info);
2186 break;
2187 }
2188 }
2189 if (GetNextImageInList(image) == (Image *) NULL)
2190 break;
2191 image=SyncNextImageInList(image);
2192 status=SetImageProgress(image,SaveImagesTag,scene++,
2193 GetImageListLength(image));
2194 if (status == MagickFalse)
2195 break;
2196 } while (image_info->adjoin != MagickFalse);
2197 (void) CloseBlob(image);
2198 return(MagickTrue);
2199}