blob: ba155cc46845a01fc3c95383aac13a9e1b5b554d [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% PPPP N N M M %
7% P P NN N MM MM %
8% PPPP N N N M M M %
9% P N NN M M %
10% P N N M M %
11% %
12% %
13% Read/Write PBMPlus Portable Anymap Image Format %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy7e41fe82010-12-04 23:12:08 +000020% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
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,
140 const size_t extent)
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 {
144 (void) ThrowMagickException(&image->exception,GetMagickModule(),
145 CorruptImageError,"InvalidPixel","`%s'",image->filename);
146 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);
198 *p=(char) c;
199 *(p+1)='\0';
200 }
201 if (comment == (char *) NULL)
202 return(0);
203 continue;
204 }
205 } while (isdigit(c) == MagickFalse);
206 if (comment != (char *) NULL)
207 {
cristyd15e6592011-10-15 00:13:06 +0000208 (void) SetImageProperty(image,"comment",comment,exception);
cristy3ed852e2009-09-05 21:47:34 +0000209 comment=DestroyString(comment);
210 }
211 if (base == 2)
cristybb503372010-05-27 20:51:26 +0000212 return((size_t) (c-(int) '0'));
cristy3ed852e2009-09-05 21:47:34 +0000213 /*
214 Evaluate number.
215 */
216 value=0;
217 do
218 {
219 value*=10;
220 value+=c-(int) '0';
221 c=ReadBlobByte(image);
222 if (c == EOF)
223 return(value);
224 } while (isdigit(c) != MagickFalse);
225 return(value);
226}
227
228static Image *ReadPNMImage(const ImageInfo *image_info,ExceptionInfo *exception)
229{
230 char
231 format;
232
233 double
234 quantum_scale;
235
236 Image
237 *image;
238
cristy3ed852e2009-09-05 21:47:34 +0000239 MagickBooleanType
240 status;
241
242 Quantum
243 *scale;
244
245 QuantumInfo
246 *quantum_info;
247
248 QuantumType
249 quantum_type;
250
cristybb503372010-05-27 20:51:26 +0000251 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000252 i;
253
254 size_t
cristyaff6d802011-04-26 01:46:31 +0000255 depth,
cristy3ed852e2009-09-05 21:47:34 +0000256 extent,
cristyaff6d802011-04-26 01:46:31 +0000257 max_value,
cristy3ed852e2009-09-05 21:47:34 +0000258 packet_size;
259
260 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000261 count,
262 row,
263 y;
cristy3ed852e2009-09-05 21:47:34 +0000264
cristy3ed852e2009-09-05 21:47:34 +0000265 /*
266 Open image file.
267 */
268 assert(image_info != (const ImageInfo *) NULL);
269 assert(image_info->signature == MagickSignature);
270 if (image_info->debug != MagickFalse)
271 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
272 image_info->filename);
273 assert(exception != (ExceptionInfo *) NULL);
274 assert(exception->signature == MagickSignature);
cristy9950d572011-10-01 18:22:35 +0000275 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000276 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
277 if (status == MagickFalse)
278 {
279 image=DestroyImageList(image);
280 return((Image *) NULL);
281 }
282 /*
283 Read PNM image.
284 */
285 count=ReadBlob(image,1,(unsigned char *) &format);
286 do
287 {
288 /*
289 Initialize image structure.
290 */
291 if ((count != 1) || (format != 'P'))
292 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
293 max_value=1;
294 quantum_type=RGBQuantum;
295 quantum_scale=1.0;
296 format=(char) ReadBlobByte(image);
297 if (format != '7')
298 {
299 /*
300 PBM, PGM, PPM, and PNM.
301 */
cristyd15e6592011-10-15 00:13:06 +0000302 image->columns=PNMInteger(image,10,exception);
303 image->rows=PNMInteger(image,10,exception);
cristy3ed852e2009-09-05 21:47:34 +0000304 if ((format == 'f') || (format == 'F'))
305 {
306 char
307 scale[MaxTextExtent];
308
309 (void) ReadBlobString(image,scale);
cristyc1acd842011-05-19 23:05:47 +0000310 quantum_scale=InterpretLocaleValue(scale,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000311 }
312 else
313 {
314 if ((format == '1') || (format == '4'))
315 max_value=1; /* bitmap */
316 else
cristyd15e6592011-10-15 00:13:06 +0000317 max_value=PNMInteger(image,10,exception);
cristy3ed852e2009-09-05 21:47:34 +0000318 }
319 }
320 else
321 {
322 char
323 keyword[MaxTextExtent],
324 value[MaxTextExtent];
325
326 int
327 c;
328
329 register char
330 *p;
331
332 /*
333 PAM.
334 */
335 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
336 {
337 while (isspace((int) ((unsigned char) c)) != 0)
338 c=ReadBlobByte(image);
339 p=keyword;
340 do
341 {
342 if ((size_t) (p-keyword) < (MaxTextExtent-1))
343 *p++=c;
344 c=ReadBlobByte(image);
345 } while (isalnum(c));
346 *p='\0';
347 if (LocaleCompare(keyword,"endhdr") == 0)
348 break;
349 while (isspace((int) ((unsigned char) c)) != 0)
350 c=ReadBlobByte(image);
351 p=value;
352 while (isalnum(c) || (c == '_'))
353 {
354 if ((size_t) (p-value) < (MaxTextExtent-1))
355 *p++=c;
356 c=ReadBlobByte(image);
357 }
358 *p='\0';
359 /*
360 Assign a value to the specified keyword.
361 */
362 if (LocaleCompare(keyword,"depth") == 0)
cristye27293e2009-12-18 02:53:20 +0000363 packet_size=StringToUnsignedLong(value);
cristyda16f162011-02-19 23:52:17 +0000364 (void) packet_size;
cristy3ed852e2009-09-05 21:47:34 +0000365 if (LocaleCompare(keyword,"height") == 0)
cristye27293e2009-12-18 02:53:20 +0000366 image->rows=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000367 if (LocaleCompare(keyword,"maxval") == 0)
cristye27293e2009-12-18 02:53:20 +0000368 max_value=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000369 if (LocaleCompare(keyword,"TUPLTYPE") == 0)
370 {
371 if (LocaleCompare(value,"BLACKANDWHITE") == 0)
372 quantum_type=GrayQuantum;
373 if (LocaleCompare(value,"BLACKANDWHITE_ALPHA") == 0)
374 {
375 quantum_type=GrayAlphaQuantum;
376 image->matte=MagickTrue;
377 }
378 if (LocaleCompare(value,"GRAYSCALE") == 0)
cristyb3a73b52011-07-26 01:34:43 +0000379 {
380 image->colorspace=GRAYColorspace;
381 quantum_type=GrayQuantum;
382 }
cristy3ed852e2009-09-05 21:47:34 +0000383 if (LocaleCompare(value,"GRAYSCALE_ALPHA") == 0)
384 {
cristyb3a73b52011-07-26 01:34:43 +0000385 image->colorspace=GRAYColorspace;
cristy3ed852e2009-09-05 21:47:34 +0000386 image->matte=MagickTrue;
cristyb3a73b52011-07-26 01:34:43 +0000387 quantum_type=GrayAlphaQuantum;
cristy3ed852e2009-09-05 21:47:34 +0000388 }
389 if (LocaleCompare(value,"RGB_ALPHA") == 0)
390 {
391 quantum_type=RGBAQuantum;
392 image->matte=MagickTrue;
393 }
394 if (LocaleCompare(value,"CMYK") == 0)
395 {
396 quantum_type=CMYKQuantum;
397 image->colorspace=CMYKColorspace;
398 }
399 if (LocaleCompare(value,"CMYK_ALPHA") == 0)
400 {
401 quantum_type=CMYKAQuantum;
402 image->colorspace=CMYKColorspace;
403 image->matte=MagickTrue;
404 }
405 }
406 if (LocaleCompare(keyword,"width") == 0)
cristye27293e2009-12-18 02:53:20 +0000407 image->columns=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000408 }
409 }
410 if ((image->columns == 0) || (image->rows == 0))
411 ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
412 if (max_value >= 65536)
413 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
cristy3f1ee592011-06-15 23:03:58 +0000414 for (depth=1; GetQuantumRange(depth) < max_value; depth++) ;
cristy3ed852e2009-09-05 21:47:34 +0000415 image->depth=depth;
416 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
417 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
418 break;
419 /*
420 Convert PNM pixels to runextent-encoded MIFF packets.
421 */
422 status=MagickTrue;
423 row=0;
424 switch (format)
425 {
426 case '1':
427 {
428 /*
429 Convert PBM image to pixel packets.
430 */
cristyb3a73b52011-07-26 01:34:43 +0000431 image->colorspace=GRAYColorspace;
cristybb503372010-05-27 20:51:26 +0000432 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000433 {
cristybb503372010-05-27 20:51:26 +0000434 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000435 x;
436
cristy4c08aed2011-07-01 19:47:50 +0000437 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000438 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000439
440 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000441 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000442 break;
cristybb503372010-05-27 20:51:26 +0000443 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000444 {
cristyd15e6592011-10-15 00:13:06 +0000445 SetPixelRed(image,PNMInteger(image,2,exception) == 0 ?
446 QuantumRange : 0,q);
cristy4c08aed2011-07-01 19:47:50 +0000447 SetPixelGreen(image,GetPixelRed(image,q),q);
448 SetPixelBlue(image,GetPixelRed(image,q),q);
cristyed231572011-07-14 02:18:59 +0000449 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000450 }
451 if (SyncAuthenticPixels(image,exception) == MagickFalse)
452 break;
453 if (image->previous == (Image *) NULL)
454 {
cristycee97112010-05-28 00:44:52 +0000455 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
456 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000457 if (status == MagickFalse)
458 break;
459 }
460 }
461 image->type=BilevelType;
462 break;
463 }
464 case '2':
465 {
cristybb503372010-05-27 20:51:26 +0000466 size_t
cristy3ed852e2009-09-05 21:47:34 +0000467 intensity;
468
469 /*
470 Convert PGM image to pixel packets.
471 */
cristyb3a73b52011-07-26 01:34:43 +0000472 image->colorspace=GRAYColorspace;
cristy3ed852e2009-09-05 21:47:34 +0000473 scale=(Quantum *) NULL;
474 if (max_value != (1U*QuantumRange))
475 {
476 /*
477 Compute pixel scaling table.
478 */
479 scale=(Quantum *) AcquireQuantumMemory((size_t) max_value+1UL,
480 sizeof(*scale));
481 if (scale == (Quantum *) NULL)
482 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000483 for (i=0; i <= (ssize_t) max_value; i++)
cristy3ed852e2009-09-05 21:47:34 +0000484 scale[i]=(Quantum) (((double) QuantumRange*i)/max_value+0.5);
485 }
cristybb503372010-05-27 20:51:26 +0000486 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000487 {
cristybb503372010-05-27 20:51:26 +0000488 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000489 x;
490
cristy4c08aed2011-07-01 19:47:50 +0000491 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000492 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000493
494 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyb3a73b52011-07-26 01:34:43 +0000495 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000496 break;
cristybb503372010-05-27 20:51:26 +0000497 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000498 {
cristyd15e6592011-10-15 00:13:06 +0000499 intensity=PNMInteger(image,10,exception);
cristy4c08aed2011-07-01 19:47:50 +0000500 SetPixelRed(image,intensity,q);
cristyac23fd22010-05-11 14:48:58 +0000501 if (scale != (Quantum *) NULL)
cristy4c08aed2011-07-01 19:47:50 +0000502 SetPixelRed(image,scale[ConstrainPixel(image,(ssize_t) intensity,
503 max_value)],q);
504 SetPixelGreen(image,GetPixelRed(image,q),q);
505 SetPixelBlue(image,GetPixelRed(image,q),q);
cristyed231572011-07-14 02:18:59 +0000506 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000507 }
508 if (SyncAuthenticPixels(image,exception) == MagickFalse)
509 break;
510 if (image->previous == (Image *) NULL)
511 {
cristycee97112010-05-28 00:44:52 +0000512 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
513 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000514 if (status == MagickFalse)
515 break;
516 }
517 }
518 image->type=GrayscaleType;
519 if (scale != (Quantum *) NULL)
520 scale=(Quantum *) RelinquishMagickMemory(scale);
521 break;
522 }
523 case '3':
524 {
cristy4c08aed2011-07-01 19:47:50 +0000525 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +0000526 pixel;
527
528 /*
529 Convert PNM image to pixel packets.
530 */
531 scale=(Quantum *) NULL;
532 if (max_value != (1U*QuantumRange))
533 {
534 /*
535 Compute pixel scaling table.
536 */
537 scale=(Quantum *) AcquireQuantumMemory((size_t) max_value+1UL,
538 sizeof(*scale));
539 if (scale == (Quantum *) NULL)
540 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000541 for (i=0; i <= (ssize_t) max_value; i++)
cristy3ed852e2009-09-05 21:47:34 +0000542 scale[i]=(Quantum) (((double) QuantumRange*i)/max_value+0.5);
543 }
cristybb503372010-05-27 20:51:26 +0000544 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000545 {
cristybb503372010-05-27 20:51:26 +0000546 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000547 x;
548
cristy4c08aed2011-07-01 19:47:50 +0000549 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000550 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000551
552 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000553 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000554 break;
cristybb503372010-05-27 20:51:26 +0000555 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000556 {
cristyd15e6592011-10-15 00:13:06 +0000557 pixel.red=(MagickRealType) PNMInteger(image,10,exception);
558 pixel.green=(MagickRealType) PNMInteger(image,10,exception);
559 pixel.blue=(MagickRealType) PNMInteger(image,10,exception);
cristy3ed852e2009-09-05 21:47:34 +0000560 if (scale != (Quantum *) NULL)
561 {
cristybb503372010-05-27 20:51:26 +0000562 pixel.red=(MagickRealType) scale[ConstrainPixel(image,(ssize_t)
cristy3ed852e2009-09-05 21:47:34 +0000563 pixel.red,max_value)];
cristy34575212010-11-06 12:39:23 +0000564 pixel.green=(MagickRealType) scale[ConstrainPixel(image,
565 (ssize_t) pixel.green,max_value)];
cristybb503372010-05-27 20:51:26 +0000566 pixel.blue=(MagickRealType) scale[ConstrainPixel(image,(ssize_t)
cristy3ed852e2009-09-05 21:47:34 +0000567 pixel.blue,max_value)];
568 }
cristy94b11832011-09-08 19:46:03 +0000569 SetPixelRed(image,ClampToQuantum(pixel.red),q);
570 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
571 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
cristyed231572011-07-14 02:18:59 +0000572 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000573 }
574 if (SyncAuthenticPixels(image,exception) == MagickFalse)
575 break;
576 if (image->previous == (Image *) NULL)
577 {
cristycee97112010-05-28 00:44:52 +0000578 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
579 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000580 if (status == MagickFalse)
581 break;
582 }
583 }
584 if (scale != (Quantum *) NULL)
585 scale=(Quantum *) RelinquishMagickMemory(scale);
586 break;
587 }
588 case '4':
589 {
590 /*
591 Convert PBM raw image to pixel packets.
592 */
cristyb3a73b52011-07-26 01:34:43 +0000593 image->colorspace=GRAYColorspace;
cristy3ed852e2009-09-05 21:47:34 +0000594 quantum_type=GrayQuantum;
595 if (image->storage_class == PseudoClass)
596 quantum_type=IndexQuantum;
597 quantum_info=AcquireQuantumInfo(image_info,image);
598 if (quantum_info == (QuantumInfo *) NULL)
599 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
600 SetQuantumMinIsWhite(quantum_info,MagickTrue);
601 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +0000602 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000603 {
cristy3ed852e2009-09-05 21:47:34 +0000604 MagickBooleanType
605 sync;
606
cristy4c08aed2011-07-01 19:47:50 +0000607 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000608 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000609
610 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000611 count,
612 offset;
cristy3ed852e2009-09-05 21:47:34 +0000613
614 size_t
615 length;
616
617 unsigned char
618 *pixels;
619
620 if (status == MagickFalse)
621 continue;
622 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000623 {
624 count=ReadBlob(image,extent,pixels);
625 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
626 (image->previous == (Image *) NULL))
627 {
628 MagickBooleanType
629 proceed;
630
cristycee97112010-05-28 00:44:52 +0000631 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
632 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000633 if (proceed == MagickFalse)
634 status=MagickFalse;
635 }
636 offset=row++;
637 }
638 if (count != (ssize_t) extent)
639 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000640 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000641 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000642 {
643 status=MagickFalse;
644 continue;
645 }
cristyaa740112010-03-30 17:58:44 +0000646 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
647 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +0000648 if (length != extent)
649 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000650 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000651 if (sync == MagickFalse)
652 status=MagickFalse;
653 }
cristy3ed852e2009-09-05 21:47:34 +0000654 quantum_info=DestroyQuantumInfo(quantum_info);
655 if (status == MagickFalse)
656 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
657 SetQuantumImageType(image,quantum_type);
658 break;
659 }
660 case '5':
661 {
662 QuantumAny
663 range;
664
665 /*
666 Convert PGM raw image to pixel packets.
667 */
cristyb3a73b52011-07-26 01:34:43 +0000668 image->colorspace=GRAYColorspace;
cristy3ed852e2009-09-05 21:47:34 +0000669 range=GetQuantumRange(image->depth);
670 quantum_type=GrayQuantum;
671 extent=(image->depth <= 8 ? 1 : 2)*image->columns;
672 quantum_info=AcquireQuantumInfo(image_info,image);
673 if (quantum_info == (QuantumInfo *) NULL)
674 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000675 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000676 {
cristy3ed852e2009-09-05 21:47:34 +0000677 MagickBooleanType
678 sync;
679
680 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000681 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000682
cristybb503372010-05-27 20:51:26 +0000683 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000684 x;
685
cristy4c08aed2011-07-01 19:47:50 +0000686 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000687 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000688
689 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000690 count,
691 offset;
cristy3ed852e2009-09-05 21:47:34 +0000692
693 unsigned char
694 *pixels;
695
696 if (status == MagickFalse)
697 continue;
698 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000699 {
700 count=ReadBlob(image,extent,pixels);
701 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
702 (image->previous == (Image *) NULL))
703 {
704 MagickBooleanType
705 proceed;
706
cristy34575212010-11-06 12:39:23 +0000707 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
708 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000709 if (proceed == MagickFalse)
710 status=MagickFalse;
711 }
712 offset=row++;
713 }
714 if (count != (ssize_t) extent)
715 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000716 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000717 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000718 {
719 status=MagickFalse;
720 continue;
721 }
722 p=pixels;
723 if ((image->depth == 8) || (image->depth == 16))
cristyaa740112010-03-30 17:58:44 +0000724 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3ed852e2009-09-05 21:47:34 +0000725 quantum_type,pixels,exception);
726 else
727 if (image->depth <= 8)
728 {
729 unsigned char
730 pixel;
731
cristybb503372010-05-27 20:51:26 +0000732 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000733 {
734 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000735 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
736 SetPixelGreen(image,GetPixelRed(image,q),q);
737 SetPixelBlue(image,GetPixelRed(image,q),q);
cristyed231572011-07-14 02:18:59 +0000738 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000739 }
740 }
741 else
742 {
743 unsigned short
744 pixel;
745
cristybb503372010-05-27 20:51:26 +0000746 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000747 {
748 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000749 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
750 SetPixelGreen(image,GetPixelRed(image,q),q);
751 SetPixelBlue(image,GetPixelRed(image,q),q);
cristyed231572011-07-14 02:18:59 +0000752 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000753 }
754 }
cristyaa740112010-03-30 17:58:44 +0000755 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000756 if (sync == MagickFalse)
757 status=MagickFalse;
758 }
cristy3ed852e2009-09-05 21:47:34 +0000759 quantum_info=DestroyQuantumInfo(quantum_info);
760 if (status == MagickFalse)
761 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
762 SetQuantumImageType(image,quantum_type);
763 break;
764 }
765 case '6':
766 {
767 ImageType
768 type;
769
770 QuantumAny
771 range;
772
773 /*
774 Convert PNM raster image to pixel packets.
775 */
776 type=BilevelType;
777 quantum_type=RGBQuantum;
778 extent=3*(image->depth <= 8 ? 1 : 2)*image->columns;
779 range=GetQuantumRange(image->depth);
780 quantum_info=AcquireQuantumInfo(image_info,image);
781 if (quantum_info == (QuantumInfo *) NULL)
782 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000783 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000784 {
cristy3ed852e2009-09-05 21:47:34 +0000785 MagickBooleanType
786 sync;
787
788 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000789 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000790
cristybb503372010-05-27 20:51:26 +0000791 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000792 x;
793
cristy4c08aed2011-07-01 19:47:50 +0000794 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000795 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000796
797 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000798 count,
799 offset;
cristy3ed852e2009-09-05 21:47:34 +0000800
cristy3ed852e2009-09-05 21:47:34 +0000801 unsigned char
802 *pixels;
803
804 if (status == MagickFalse)
805 continue;
806 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000807 {
808 count=ReadBlob(image,extent,pixels);
809 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
810 (image->previous == (Image *) NULL))
811 {
812 MagickBooleanType
813 proceed;
814
cristy34575212010-11-06 12:39:23 +0000815 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
816 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000817 if (proceed == MagickFalse)
818 status=MagickFalse;
819 }
820 offset=row++;
821 }
822 if (count != (ssize_t) extent)
823 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000824 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000825 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000826 {
827 status=MagickFalse;
828 continue;
829 }
830 p=pixels;
cristye90d7402010-03-14 18:21:29 +0000831 if (image->depth == 8)
cristybb503372010-05-27 20:51:26 +0000832 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000833 {
cristy4c08aed2011-07-01 19:47:50 +0000834 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
835 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
836 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
837 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000838 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000839 }
840 else
cristye90d7402010-03-14 18:21:29 +0000841 if (image->depth == 16)
cristy3ed852e2009-09-05 21:47:34 +0000842 {
843 unsigned short
844 pixel;
845
cristybb503372010-05-27 20:51:26 +0000846 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000847 {
848 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000849 SetPixelRed(image,ScaleShortToQuantum(pixel),q);
cristy3ed852e2009-09-05 21:47:34 +0000850 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000851 SetPixelGreen(image,ScaleShortToQuantum(pixel),q);
cristy3ed852e2009-09-05 21:47:34 +0000852 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000853 SetPixelBlue(image,ScaleShortToQuantum(pixel),q);
854 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000855 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000856 }
857 }
cristye90d7402010-03-14 18:21:29 +0000858 else
859 if (image->depth <= 8)
860 {
861 unsigned char
862 pixel;
863
cristybb503372010-05-27 20:51:26 +0000864 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000865 {
866 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000867 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000868 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000869 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000870 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000871 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
872 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000873 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000874 }
875 }
876 else
877 {
878 unsigned short
879 pixel;
880
cristybb503372010-05-27 20:51:26 +0000881 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000882 {
883 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000884 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000885 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000886 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000887 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000888 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
889 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000890 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000891 }
892 }
cristy3ed852e2009-09-05 21:47:34 +0000893 if ((type == BilevelType) || (type == GrayscaleType))
cristy3ed852e2009-09-05 21:47:34 +0000894 {
cristyaa740112010-03-30 17:58:44 +0000895 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristybb503372010-05-27 20:51:26 +0000896 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000897 {
898 if ((type == BilevelType) &&
cristy4c08aed2011-07-01 19:47:50 +0000899 (IsPixelMonochrome(image,q) == MagickFalse))
900 type=IsPixelGray(image,q) == MagickFalse ? UndefinedType :
cristye90d7402010-03-14 18:21:29 +0000901 GrayscaleType;
cristy4c08aed2011-07-01 19:47:50 +0000902 if ((type == GrayscaleType) &&
903 (IsPixelGray(image,q) == MagickFalse))
cristy5f1c1ff2010-12-23 21:38:06 +0000904 type=UndefinedType;
cristye90d7402010-03-14 18:21:29 +0000905 if ((type != BilevelType) && (type != GrayscaleType))
906 break;
cristyed231572011-07-14 02:18:59 +0000907 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000908 }
cristy3ed852e2009-09-05 21:47:34 +0000909 }
cristyaa740112010-03-30 17:58:44 +0000910 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000911 if (sync == MagickFalse)
912 status=MagickFalse;
913 }
cristy3ed852e2009-09-05 21:47:34 +0000914 quantum_info=DestroyQuantumInfo(quantum_info);
915 if (status == MagickFalse)
916 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
cristy5f1c1ff2010-12-23 21:38:06 +0000917 if (type != UndefinedType)
cristy3ed852e2009-09-05 21:47:34 +0000918 image->type=type;
919 break;
920 }
921 case '7':
922 {
cristy3ed852e2009-09-05 21:47:34 +0000923 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 {
cristy3ed852e2009-09-05 21:47:34 +0000961 MagickBooleanType
962 sync;
963
964 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000965 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000966
cristybb503372010-05-27 20:51:26 +0000967 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000968 x;
969
cristy4c08aed2011-07-01 19:47:50 +0000970 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000971 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000972
973 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000974 count,
975 offset;
cristy3ed852e2009-09-05 21:47:34 +0000976
977 unsigned char
978 *pixels;
979
980 if (status == MagickFalse)
981 continue;
982 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000983 {
984 count=ReadBlob(image,extent,pixels);
985 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
986 (image->previous == (Image *) NULL))
987 {
988 MagickBooleanType
989 proceed;
990
cristy34575212010-11-06 12:39:23 +0000991 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
992 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000993 if (proceed == MagickFalse)
994 status=MagickFalse;
995 }
996 offset=row++;
997 }
998 if (count != (ssize_t) extent)
999 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +00001000 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00001001 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001002 {
1003 status=MagickFalse;
1004 continue;
1005 }
cristy3ed852e2009-09-05 21:47:34 +00001006 p=pixels;
1007 if ((image->depth == 8) || (image->depth == 16))
cristyaa740112010-03-30 17:58:44 +00001008 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3ed852e2009-09-05 21:47:34 +00001009 quantum_type,pixels,exception);
1010 else
1011 switch (quantum_type)
1012 {
1013 case GrayQuantum:
1014 case GrayAlphaQuantum:
1015 {
1016 if (image->depth <= 8)
1017 {
1018 unsigned char
1019 pixel;
1020
cristybb503372010-05-27 20:51:26 +00001021 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001022 {
1023 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001024 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
1025 SetPixelGreen(image,GetPixelRed(image,q),q);
1026 SetPixelBlue(image,GetPixelRed(image,q),q);
1027 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001028 if (image->matte != MagickFalse)
1029 {
1030 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001031 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001032 }
cristyed231572011-07-14 02:18:59 +00001033 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001034 }
1035 }
1036 else
1037 {
1038 unsigned short
1039 pixel;
1040
cristybb503372010-05-27 20:51:26 +00001041 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001042 {
1043 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001044 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
1045 SetPixelGreen(image,GetPixelRed(image,q),q);
1046 SetPixelBlue(image,GetPixelRed(image,q),q);
1047 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001048 if (image->matte != MagickFalse)
1049 {
1050 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001051 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001052 }
cristyed231572011-07-14 02:18:59 +00001053 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001054 }
1055 }
1056 break;
1057 }
1058 case CMYKQuantum:
1059 case CMYKAQuantum:
1060 {
1061 if (image->depth <= 8)
1062 {
1063 unsigned char
1064 pixel;
1065
cristybb503372010-05-27 20:51:26 +00001066 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001067 {
1068 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001069 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001070 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001071 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001072 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001073 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001074 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001075 SetPixelBlack(image,ScaleAnyToQuantum(pixel,range),q);
1076 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001077 if (image->matte != MagickFalse)
1078 {
1079 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001080 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001081 }
cristyed231572011-07-14 02:18:59 +00001082 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001083 }
1084 }
1085 else
1086 {
1087 unsigned short
1088 pixel;
1089
cristybb503372010-05-27 20:51:26 +00001090 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001091 {
1092 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001093 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001094 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001095 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001096 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001097 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001098 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001099 SetPixelBlack(image,ScaleAnyToQuantum(pixel,range),q);
1100 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001101 if (image->matte != MagickFalse)
1102 {
1103 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001104 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001105 }
cristyed231572011-07-14 02:18:59 +00001106 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001107 }
1108 }
1109 break;
1110 }
1111 default:
1112 {
1113 if (image->depth <= 8)
1114 {
1115 unsigned char
1116 pixel;
1117
cristybb503372010-05-27 20:51:26 +00001118 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001119 {
1120 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001121 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001122 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001123 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001124 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001125 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
1126 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001127 if (image->matte != MagickFalse)
1128 {
1129 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001130 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001131 }
cristyed231572011-07-14 02:18:59 +00001132 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001133 }
1134 }
1135 else
1136 {
1137 unsigned short
1138 pixel;
1139
cristybb503372010-05-27 20:51:26 +00001140 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001141 {
1142 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001143 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001144 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001145 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001146 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001147 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
1148 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001149 if (image->matte != MagickFalse)
1150 {
1151 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001152 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001153 }
cristyed231572011-07-14 02:18:59 +00001154 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001155 }
1156 }
1157 break;
1158 }
1159 }
cristyaa740112010-03-30 17:58:44 +00001160 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001161 if (sync == MagickFalse)
1162 status=MagickFalse;
1163 }
cristy3ed852e2009-09-05 21:47:34 +00001164 quantum_info=DestroyQuantumInfo(quantum_info);
1165 if (status == MagickFalse)
1166 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1167 SetQuantumImageType(image,quantum_type);
1168 break;
1169 }
1170 case 'F':
1171 case 'f':
1172 {
1173 /*
1174 Convert PFM raster image to pixel packets.
1175 */
1176 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
1177 image->endian=quantum_scale < 0.0 ? LSBEndian : MSBEndian;
1178 image->depth=32;
1179 quantum_info=AcquireQuantumInfo(image_info,image);
1180 if (quantum_info == (QuantumInfo *) NULL)
1181 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1182 status=SetQuantumDepth(image,quantum_info,32);
1183 if (status == MagickFalse)
1184 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1185 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1186 if (status == MagickFalse)
1187 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1188 SetQuantumScale(quantum_info,(MagickRealType) QuantumRange*
1189 fabs(quantum_scale));
1190 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +00001191 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001192 {
cristy3ed852e2009-09-05 21:47:34 +00001193 MagickBooleanType
1194 sync;
1195
cristy4c08aed2011-07-01 19:47:50 +00001196 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00001197 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001198
1199 ssize_t
cristyaff6d802011-04-26 01:46:31 +00001200 count,
1201 offset;
cristy3ed852e2009-09-05 21:47:34 +00001202
1203 size_t
1204 length;
1205
1206 unsigned char
1207 *pixels;
1208
1209 if (status == MagickFalse)
1210 continue;
1211 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001212 {
1213 count=ReadBlob(image,extent,pixels);
1214 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1215 (image->previous == (Image *) NULL))
1216 {
1217 MagickBooleanType
1218 proceed;
1219
cristy34575212010-11-06 12:39:23 +00001220 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1221 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001222 if (proceed == MagickFalse)
1223 status=MagickFalse;
1224 }
1225 offset=row++;
1226 }
1227 if ((size_t) count != extent)
1228 status=MagickFalse;
cristybb503372010-05-27 20:51:26 +00001229 q=QueueAuthenticPixels(image,0,(ssize_t) (image->rows-offset-1),
cristyaa740112010-03-30 17:58:44 +00001230 image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00001231 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001232 {
1233 status=MagickFalse;
1234 continue;
1235 }
cristyaa740112010-03-30 17:58:44 +00001236 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1237 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001238 if (length != extent)
1239 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +00001240 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001241 if (sync == MagickFalse)
1242 status=MagickFalse;
1243 }
cristy3ed852e2009-09-05 21:47:34 +00001244 quantum_info=DestroyQuantumInfo(quantum_info);
1245 if (status == MagickFalse)
1246 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1247 SetQuantumImageType(image,quantum_type);
1248 break;
1249 }
1250 default:
1251 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1252 }
1253 if (EOFBlob(image) != MagickFalse)
1254 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
1255 "UnexpectedEndOfFile","`%s'",image->filename);
1256 /*
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 {
cristy510d06a2011-07-06 23:43:54 +00001567 if (IsRGBColorspace(image->colorspace) == MagickFalse)
cristye941a752011-10-15 01:52:48 +00001568 (void) TransformImageColorspace(image,RGBColorspace,exception);
cristyb51dff52011-05-19 16:55:47 +00001569 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n",
cristye8c25f92010-06-03 00:53:06 +00001570 (double) image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001571 (void) WriteBlobString(image,buffer);
1572 }
1573 else
1574 {
1575 char
1576 type[MaxTextExtent];
1577
1578 /*
1579 PAM header.
1580 */
cristyb51dff52011-05-19 16:55:47 +00001581 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00001582 "WIDTH %.20g\nHEIGHT %.20g\n",(double) image->columns,(double)
1583 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001584 (void) WriteBlobString(image,buffer);
cristy1e178e72011-08-28 19:44:34 +00001585 quantum_type=GetQuantumType(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001586 switch (quantum_type)
1587 {
1588 case CMYKQuantum:
1589 case CMYKAQuantum:
1590 {
1591 packet_size=4;
1592 (void) CopyMagickString(type,"CMYK",MaxTextExtent);
1593 break;
1594 }
1595 case GrayQuantum:
1596 case GrayAlphaQuantum:
1597 {
1598 packet_size=1;
1599 (void) CopyMagickString(type,"GRAYSCALE",MaxTextExtent);
1600 break;
1601 }
1602 default:
1603 {
1604 quantum_type=RGBQuantum;
1605 if (image->matte != MagickFalse)
1606 quantum_type=RGBAQuantum;
1607 packet_size=3;
1608 (void) CopyMagickString(type,"RGB",MaxTextExtent);
1609 break;
1610 }
1611 }
1612 if (image->matte != MagickFalse)
1613 {
1614 packet_size++;
1615 (void) ConcatenateMagickString(type,"_ALPHA",MaxTextExtent);
1616 }
1617 if (image->depth > 16)
1618 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001619 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00001620 "DEPTH %.20g\nMAXVAL %.20g\n",(double) packet_size,(double)
cristy2b9582a2011-07-04 17:38:56 +00001621 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001622 (void) WriteBlobString(image,buffer);
cristyb51dff52011-05-19 16:55:47 +00001623 (void) FormatLocaleString(buffer,MaxTextExtent,"TUPLTYPE %s\nENDHDR\n",
cristy3ed852e2009-09-05 21:47:34 +00001624 type);
1625 (void) WriteBlobString(image,buffer);
1626 }
1627 /*
1628 Convert runextent encoded to PNM raster pixels.
1629 */
1630 switch (format)
1631 {
1632 case '1':
1633 {
cristy661b5ad2010-01-13 00:54:42 +00001634 unsigned char
1635 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001636
1637 /*
1638 Convert image to a PBM image.
1639 */
cristy661b5ad2010-01-13 00:54:42 +00001640 q=pixels;
cristybb503372010-05-27 20:51:26 +00001641 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001642 {
cristy4c08aed2011-07-01 19:47:50 +00001643 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001644 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001645
cristybb503372010-05-27 20:51:26 +00001646 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001647 x;
1648
cristy1e178e72011-08-28 19:44:34 +00001649 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001650 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001651 break;
cristybb503372010-05-27 20:51:26 +00001652 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001653 {
cristy4c08aed2011-07-01 19:47:50 +00001654 pixel=GetPixelIntensity(image,p);
cristy661b5ad2010-01-13 00:54:42 +00001655 *q++=(unsigned char) (pixel >= (Quantum) (QuantumRange/2) ?
1656 '0' : '1');
1657 *q++=' ';
1658 if ((q-pixels+2) >= 80)
1659 {
1660 *q++='\n';
1661 (void) WriteBlob(image,q-pixels,pixels);
1662 q=pixels;
cristy661b5ad2010-01-13 00:54:42 +00001663 }
cristyed231572011-07-14 02:18:59 +00001664 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001665 }
1666 if (image->previous == (Image *) NULL)
1667 {
cristycee97112010-05-28 00:44:52 +00001668 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1669 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001670 if (status == MagickFalse)
1671 break;
1672 }
1673 }
cristy661b5ad2010-01-13 00:54:42 +00001674 if (q != pixels)
1675 {
1676 *q++='\n';
1677 (void) WriteBlob(image,q-pixels,pixels);
1678 }
cristy3ed852e2009-09-05 21:47:34 +00001679 break;
1680 }
1681 case '2':
1682 {
cristy661b5ad2010-01-13 00:54:42 +00001683 unsigned char
1684 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001685
1686 /*
1687 Convert image to a PGM image.
1688 */
1689 if (image->depth <= 8)
1690 (void) WriteBlobString(image,"255\n");
1691 else
1692 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001693 q=pixels;
cristybb503372010-05-27 20:51:26 +00001694 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001695 {
cristy4c08aed2011-07-01 19:47:50 +00001696 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001697 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001698
cristybb503372010-05-27 20:51:26 +00001699 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001700 x;
1701
cristy1e178e72011-08-28 19:44:34 +00001702 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001703 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001704 break;
cristybb503372010-05-27 20:51:26 +00001705 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001706 {
cristy4c08aed2011-07-01 19:47:50 +00001707 index=GetPixelIntensity(image,p);
cristy3ed852e2009-09-05 21:47:34 +00001708 if (image->depth <= 8)
cristyb51dff52011-05-19 16:55:47 +00001709 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,"%u ",
cristy3ed852e2009-09-05 21:47:34 +00001710 ScaleQuantumToChar(index));
1711 else
cristyb51dff52011-05-19 16:55:47 +00001712 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,"%u ",
cristy3ed852e2009-09-05 21:47:34 +00001713 ScaleQuantumToShort(index));
cristy661b5ad2010-01-13 00:54:42 +00001714 extent=(size_t) count;
1715 (void) strncpy((char *) q,buffer,extent);
1716 q+=extent;
1717 if ((q-pixels+extent) >= 80)
1718 {
1719 *q++='\n';
1720 (void) WriteBlob(image,q-pixels,pixels);
1721 q=pixels;
1722 }
cristyed231572011-07-14 02:18:59 +00001723 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001724 }
1725 if (image->previous == (Image *) NULL)
1726 {
cristycee97112010-05-28 00:44:52 +00001727 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1728 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001729 if (status == MagickFalse)
1730 break;
1731 }
1732 }
cristy661b5ad2010-01-13 00:54:42 +00001733 if (q != pixels)
1734 {
1735 *q++='\n';
1736 (void) WriteBlob(image,q-pixels,pixels);
1737 }
cristy3ed852e2009-09-05 21:47:34 +00001738 break;
1739 }
1740 case '3':
1741 {
cristy661b5ad2010-01-13 00:54:42 +00001742 unsigned char
1743 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001744
1745 /*
1746 Convert image to a PNM image.
1747 */
1748 if (image->depth <= 8)
1749 (void) WriteBlobString(image,"255\n");
1750 else
1751 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001752 q=pixels;
cristybb503372010-05-27 20:51:26 +00001753 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001754 {
cristy4c08aed2011-07-01 19:47:50 +00001755 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001756 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001757
cristybb503372010-05-27 20:51:26 +00001758 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001759 x;
1760
cristy1e178e72011-08-28 19:44:34 +00001761 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001762 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001763 break;
cristybb503372010-05-27 20:51:26 +00001764 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001765 {
1766 if (image->depth <= 8)
cristyb51dff52011-05-19 16:55:47 +00001767 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,
cristy4c08aed2011-07-01 19:47:50 +00001768 "%u %u %u ",ScaleQuantumToChar(GetPixelRed(image,p)),
1769 ScaleQuantumToChar(GetPixelGreen(image,p)),
1770 ScaleQuantumToChar(GetPixelBlue(image,p)));
cristy3ed852e2009-09-05 21:47:34 +00001771 else
cristyb51dff52011-05-19 16:55:47 +00001772 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,
cristy4c08aed2011-07-01 19:47:50 +00001773 "%u %u %u ",ScaleQuantumToShort(GetPixelRed(image,p)),
1774 ScaleQuantumToShort(GetPixelGreen(image,p)),
1775 ScaleQuantumToShort(GetPixelBlue(image,p)));
cristy661b5ad2010-01-13 00:54:42 +00001776 extent=(size_t) count;
1777 (void) strncpy((char *) q,buffer,extent);
1778 q+=extent;
1779 if ((q-pixels+extent) >= 80)
1780 {
1781 *q++='\n';
1782 (void) WriteBlob(image,q-pixels,pixels);
1783 q=pixels;
1784 }
cristyed231572011-07-14 02:18:59 +00001785 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001786 }
1787 if (image->previous == (Image *) NULL)
1788 {
cristycee97112010-05-28 00:44:52 +00001789 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1790 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001791 if (status == MagickFalse)
1792 break;
1793 }
1794 }
cristy661b5ad2010-01-13 00:54:42 +00001795 if (q != pixels)
1796 {
1797 *q++='\n';
1798 (void) WriteBlob(image,q-pixels,pixels);
1799 }
cristy3ed852e2009-09-05 21:47:34 +00001800 break;
1801 }
1802 case '4':
1803 {
1804 /*
1805 Convert image to a PBM image.
1806 */
1807 image->depth=1;
1808 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1809 if (quantum_info == (QuantumInfo *) NULL)
1810 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1811 quantum_info->min_is_white=MagickTrue;
1812 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00001813 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001814 {
cristy4c08aed2011-07-01 19:47:50 +00001815 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001816 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001817
cristy1e178e72011-08-28 19:44:34 +00001818 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001819 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001820 break;
cristy4c08aed2011-07-01 19:47:50 +00001821 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001822 GrayQuantum,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001823 count=WriteBlob(image,extent,pixels);
1824 if (count != (ssize_t) extent)
1825 break;
1826 if (image->previous == (Image *) NULL)
1827 {
cristycee97112010-05-28 00:44:52 +00001828 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1829 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001830 if (status == MagickFalse)
1831 break;
1832 }
1833 }
1834 quantum_info=DestroyQuantumInfo(quantum_info);
1835 break;
1836 }
1837 case '5':
1838 {
1839 QuantumAny
1840 range;
1841
1842 /*
1843 Convert image to a PGM image.
1844 */
1845 if (image->depth > 8)
1846 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001847 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g\n",(double)
cristy2b9582a2011-07-04 17:38:56 +00001848 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001849 (void) WriteBlobString(image,buffer);
1850 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1851 if (quantum_info == (QuantumInfo *) NULL)
1852 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1853 quantum_info->min_is_white=MagickTrue;
1854 pixels=GetQuantumPixels(quantum_info);
1855 extent=GetQuantumExtent(image,quantum_info,GrayQuantum);
1856 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001857 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001858 {
cristy4c08aed2011-07-01 19:47:50 +00001859 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001860 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001861
cristybb503372010-05-27 20:51:26 +00001862 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001863 x;
1864
cristy1e178e72011-08-28 19:44:34 +00001865 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001866 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001867 break;
1868 q=pixels;
1869 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00001870 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001871 GrayQuantum,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001872 else
1873 {
1874 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00001875 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001876 {
cristy4c08aed2011-07-01 19:47:50 +00001877 if (IsPixelGray(image,p) == MagickFalse)
1878 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001879 else
1880 {
1881 if (image->depth == 8)
cristy4c08aed2011-07-01 19:47:50 +00001882 pixel=ScaleQuantumToChar(GetPixelRed(image,p));
cristy3ed852e2009-09-05 21:47:34 +00001883 else
cristy4c08aed2011-07-01 19:47:50 +00001884 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001885 }
1886 q=PopCharPixel((unsigned char) pixel,q);
cristyed231572011-07-14 02:18:59 +00001887 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001888 }
1889 else
cristybb503372010-05-27 20:51:26 +00001890 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001891 {
cristy4c08aed2011-07-01 19:47:50 +00001892 if (IsPixelGray(image,p) == MagickFalse)
1893 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001894 else
1895 {
1896 if (image->depth == 16)
cristy4c08aed2011-07-01 19:47:50 +00001897 pixel=ScaleQuantumToShort(GetPixelRed(image,p));
cristy3ed852e2009-09-05 21:47:34 +00001898 else
cristy4c08aed2011-07-01 19:47:50 +00001899 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001900 }
1901 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyed231572011-07-14 02:18:59 +00001902 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001903 }
1904 extent=(size_t) (q-pixels);
1905 }
1906 count=WriteBlob(image,extent,pixels);
1907 if (count != (ssize_t) extent)
1908 break;
1909 if (image->previous == (Image *) NULL)
1910 {
cristycee97112010-05-28 00:44:52 +00001911 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1912 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001913 if (status == MagickFalse)
1914 break;
1915 }
1916 }
1917 quantum_info=DestroyQuantumInfo(quantum_info);
1918 break;
1919 }
1920 case '6':
1921 {
1922 QuantumAny
1923 range;
1924
1925 /*
1926 Convert image to a PNM image.
1927 */
1928 if (image->depth > 8)
1929 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001930 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g\n",(double)
cristy2b9582a2011-07-04 17:38:56 +00001931 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001932 (void) WriteBlobString(image,buffer);
1933 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1934 if (quantum_info == (QuantumInfo *) NULL)
1935 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1936 pixels=GetQuantumPixels(quantum_info);
1937 extent=GetQuantumExtent(image,quantum_info,quantum_type);
1938 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001939 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001940 {
cristy4c08aed2011-07-01 19:47:50 +00001941 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001942 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001943
cristybb503372010-05-27 20:51:26 +00001944 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001945 x;
1946
cristy1e178e72011-08-28 19:44:34 +00001947 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001948 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001949 break;
1950 q=pixels;
1951 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00001952 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001953 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001954 else
1955 {
1956 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00001957 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001958 {
cristy4c08aed2011-07-01 19:47:50 +00001959 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001960 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001961 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001962 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001963 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001964 q=PopCharPixel((unsigned char) pixel,q);
cristyed231572011-07-14 02:18:59 +00001965 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001966 }
1967 else
cristybb503372010-05-27 20:51:26 +00001968 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001969 {
cristy4c08aed2011-07-01 19:47:50 +00001970 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001971 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001972 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001973 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001974 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001975 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyed231572011-07-14 02:18:59 +00001976 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001977 }
1978 extent=(size_t) (q-pixels);
1979 }
1980 count=WriteBlob(image,extent,pixels);
1981 if (count != (ssize_t) extent)
1982 break;
1983 if (image->previous == (Image *) NULL)
1984 {
cristycee97112010-05-28 00:44:52 +00001985 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1986 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001987 if (status == MagickFalse)
1988 break;
1989 }
1990 }
1991 quantum_info=DestroyQuantumInfo(quantum_info);
1992 break;
1993 }
1994 case '7':
1995 {
1996 QuantumAny
1997 range;
1998
1999 /*
2000 Convert image to a PAM.
2001 */
2002 if (image->depth > 16)
2003 image->depth=16;
2004 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
2005 pixels=GetQuantumPixels(quantum_info);
2006 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00002007 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002008 {
cristy4c08aed2011-07-01 19:47:50 +00002009 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00002010 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002011
cristybb503372010-05-27 20:51:26 +00002012 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002013 x;
2014
cristy1e178e72011-08-28 19:44:34 +00002015 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002016 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002017 break;
cristy3ed852e2009-09-05 21:47:34 +00002018 q=pixels;
2019 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00002020 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002021 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002022 else
2023 {
2024 switch (quantum_type)
2025 {
2026 case GrayQuantum:
2027 case GrayAlphaQuantum:
2028 {
2029 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002030 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002031 {
cristy4c08aed2011-07-01 19:47:50 +00002032 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002033 q=PopCharPixel((unsigned char) pixel,q);
2034 if (image->matte != MagickFalse)
2035 {
cristyaff6d802011-04-26 01:46:31 +00002036 pixel=(unsigned char) ScaleQuantumToAny(
cristy4c08aed2011-07-01 19:47:50 +00002037 GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002038 q=PopCharPixel((unsigned char) pixel,q);
2039 }
cristyed231572011-07-14 02:18:59 +00002040 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002041 }
2042 else
cristybb503372010-05-27 20:51:26 +00002043 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002044 {
cristy4c08aed2011-07-01 19:47:50 +00002045 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002046 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2047 if (image->matte != MagickFalse)
2048 {
cristyaff6d802011-04-26 01:46:31 +00002049 pixel=(unsigned char) ScaleQuantumToAny(
cristy4c08aed2011-07-01 19:47:50 +00002050 GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002051 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2052 }
cristyed231572011-07-14 02:18:59 +00002053 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002054 }
2055 break;
2056 }
2057 case CMYKQuantum:
2058 case CMYKAQuantum:
2059 {
2060 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002061 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002062 {
cristy4c08aed2011-07-01 19:47:50 +00002063 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002064 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002065 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002066 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002067 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002068 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002069 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002070 q=PopCharPixel((unsigned char) pixel,q);
2071 if (image->matte != MagickFalse)
2072 {
cristy4c08aed2011-07-01 19:47:50 +00002073 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002074 q=PopCharPixel((unsigned char) pixel,q);
2075 }
cristyed231572011-07-14 02:18:59 +00002076 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002077 }
2078 else
cristybb503372010-05-27 20:51:26 +00002079 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002080 {
cristy4c08aed2011-07-01 19:47:50 +00002081 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002082 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002083 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002084 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002085 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002086 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002087 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002088 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2089 if (image->matte != MagickFalse)
2090 {
cristy4c08aed2011-07-01 19:47:50 +00002091 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002092 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2093 }
cristyed231572011-07-14 02:18:59 +00002094 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002095 }
2096 break;
2097 }
2098 default:
2099 {
2100 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002101 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002102 {
cristy4c08aed2011-07-01 19:47:50 +00002103 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002104 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002105 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002106 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002107 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002108 q=PopCharPixel((unsigned char) pixel,q);
2109 if (image->matte != MagickFalse)
2110 {
cristy4c08aed2011-07-01 19:47:50 +00002111 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002112 q=PopCharPixel((unsigned char) pixel,q);
2113 }
cristyed231572011-07-14 02:18:59 +00002114 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002115 }
2116 else
cristybb503372010-05-27 20:51:26 +00002117 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002118 {
cristy4c08aed2011-07-01 19:47:50 +00002119 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002120 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002121 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002122 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002123 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002124 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2125 if (image->matte != MagickFalse)
2126 {
cristy4c08aed2011-07-01 19:47:50 +00002127 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002128 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2129 }
cristyed231572011-07-14 02:18:59 +00002130 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002131 }
2132 break;
2133 }
2134 }
2135 extent=(size_t) (q-pixels);
2136 }
2137 count=WriteBlob(image,extent,pixels);
2138 if (count != (ssize_t) extent)
2139 break;
2140 if (image->previous == (Image *) NULL)
2141 {
cristycee97112010-05-28 00:44:52 +00002142 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2143 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002144 if (status == MagickFalse)
2145 break;
2146 }
2147 }
2148 quantum_info=DestroyQuantumInfo(quantum_info);
2149 break;
2150 }
2151 case 'F':
2152 case 'f':
2153 {
2154 (void) WriteBlobString(image,image->endian != LSBEndian ? "1.0\n" :
2155 "-1.0\n");
2156 image->depth=32;
2157 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
2158 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
2159 if (quantum_info == (QuantumInfo *) NULL)
2160 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2161 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2162 if (status == MagickFalse)
2163 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2164 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002165 for (y=(ssize_t) image->rows-1; y >= 0; y--)
cristy3ed852e2009-09-05 21:47:34 +00002166 {
cristy4c08aed2011-07-01 19:47:50 +00002167 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00002168 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002169
cristy1e178e72011-08-28 19:44:34 +00002170 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002171 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002172 break;
cristy4c08aed2011-07-01 19:47:50 +00002173 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002174 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002175 (void) WriteBlob(image,extent,pixels);
2176 if (image->previous == (Image *) NULL)
2177 {
cristycee97112010-05-28 00:44:52 +00002178 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2179 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002180 if (status == MagickFalse)
2181 break;
2182 }
2183 }
2184 quantum_info=DestroyQuantumInfo(quantum_info);
2185 break;
2186 }
2187 }
2188 if (GetNextImageInList(image) == (Image *) NULL)
2189 break;
2190 image=SyncNextImageInList(image);
2191 status=SetImageProgress(image,SaveImagesTag,scene++,
2192 GetImageListLength(image));
2193 if (status == MagickFalse)
2194 break;
2195 } while (image_info->adjoin != MagickFalse);
2196 (void) CloseBlob(image);
2197 return(MagickTrue);
2198}