blob: 906b21d437dad68c7cb4b6ab07625f9315dbb8a0 [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);
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);
cristydbdd0e32011-11-04 23:29:40 +0000310 quantum_scale=StringToDouble(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 {
cristy08528502012-01-01 00:52:17 +0000445 SetPixelGray(image,PNMInteger(image,2,exception) == 0 ?
cristyd15e6592011-10-15 00:13:06 +0000446 QuantumRange : 0,q);
cristyed231572011-07-14 02:18:59 +0000447 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000448 }
449 if (SyncAuthenticPixels(image,exception) == MagickFalse)
450 break;
451 if (image->previous == (Image *) NULL)
452 {
cristycee97112010-05-28 00:44:52 +0000453 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
454 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000455 if (status == MagickFalse)
456 break;
457 }
458 }
459 image->type=BilevelType;
460 break;
461 }
462 case '2':
463 {
cristybb503372010-05-27 20:51:26 +0000464 size_t
cristy3ed852e2009-09-05 21:47:34 +0000465 intensity;
466
467 /*
468 Convert PGM image to pixel packets.
469 */
cristyb3a73b52011-07-26 01:34:43 +0000470 image->colorspace=GRAYColorspace;
cristy3ed852e2009-09-05 21:47:34 +0000471 scale=(Quantum *) NULL;
472 if (max_value != (1U*QuantumRange))
473 {
474 /*
475 Compute pixel scaling table.
476 */
477 scale=(Quantum *) AcquireQuantumMemory((size_t) max_value+1UL,
478 sizeof(*scale));
479 if (scale == (Quantum *) NULL)
480 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000481 for (i=0; i <= (ssize_t) max_value; i++)
cristy3ed852e2009-09-05 21:47:34 +0000482 scale[i]=(Quantum) (((double) QuantumRange*i)/max_value+0.5);
483 }
cristybb503372010-05-27 20:51:26 +0000484 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000485 {
cristybb503372010-05-27 20:51:26 +0000486 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000487 x;
488
cristy4c08aed2011-07-01 19:47:50 +0000489 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000490 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000491
492 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyb3a73b52011-07-26 01:34:43 +0000493 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000494 break;
cristybb503372010-05-27 20:51:26 +0000495 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000496 {
cristyd15e6592011-10-15 00:13:06 +0000497 intensity=PNMInteger(image,10,exception);
cristy08528502012-01-01 00:52:17 +0000498 SetPixelGray(image,intensity,q);
cristyac23fd22010-05-11 14:48:58 +0000499 if (scale != (Quantum *) NULL)
cristy08528502012-01-01 00:52:17 +0000500 SetPixelGray(image,scale[ConstrainPixel(image,(ssize_t) intensity,
cristyc82a27b2011-10-21 01:07:16 +0000501 max_value,exception)],q);
cristyed231572011-07-14 02:18:59 +0000502 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000503 }
504 if (SyncAuthenticPixels(image,exception) == MagickFalse)
505 break;
506 if (image->previous == (Image *) NULL)
507 {
cristycee97112010-05-28 00:44:52 +0000508 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
509 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000510 if (status == MagickFalse)
511 break;
512 }
513 }
514 image->type=GrayscaleType;
515 if (scale != (Quantum *) NULL)
516 scale=(Quantum *) RelinquishMagickMemory(scale);
517 break;
518 }
519 case '3':
520 {
cristy4c08aed2011-07-01 19:47:50 +0000521 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +0000522 pixel;
523
524 /*
525 Convert PNM image to pixel packets.
526 */
527 scale=(Quantum *) NULL;
528 if (max_value != (1U*QuantumRange))
529 {
530 /*
531 Compute pixel scaling table.
532 */
533 scale=(Quantum *) AcquireQuantumMemory((size_t) max_value+1UL,
534 sizeof(*scale));
535 if (scale == (Quantum *) NULL)
536 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000537 for (i=0; i <= (ssize_t) max_value; i++)
cristy3ed852e2009-09-05 21:47:34 +0000538 scale[i]=(Quantum) (((double) QuantumRange*i)/max_value+0.5);
539 }
cristybb503372010-05-27 20:51:26 +0000540 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000541 {
cristybb503372010-05-27 20:51:26 +0000542 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000543 x;
544
cristy4c08aed2011-07-01 19:47:50 +0000545 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000546 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000547
548 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000549 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000550 break;
cristybb503372010-05-27 20:51:26 +0000551 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000552 {
cristyd15e6592011-10-15 00:13:06 +0000553 pixel.red=(MagickRealType) PNMInteger(image,10,exception);
554 pixel.green=(MagickRealType) PNMInteger(image,10,exception);
555 pixel.blue=(MagickRealType) PNMInteger(image,10,exception);
cristy3ed852e2009-09-05 21:47:34 +0000556 if (scale != (Quantum *) NULL)
557 {
cristybb503372010-05-27 20:51:26 +0000558 pixel.red=(MagickRealType) scale[ConstrainPixel(image,(ssize_t)
cristyc82a27b2011-10-21 01:07:16 +0000559 pixel.red,max_value,exception)];
cristy34575212010-11-06 12:39:23 +0000560 pixel.green=(MagickRealType) scale[ConstrainPixel(image,
cristyc82a27b2011-10-21 01:07:16 +0000561 (ssize_t) pixel.green,max_value,exception)];
cristybb503372010-05-27 20:51:26 +0000562 pixel.blue=(MagickRealType) scale[ConstrainPixel(image,(ssize_t)
cristyc82a27b2011-10-21 01:07:16 +0000563 pixel.blue,max_value,exception)];
cristy3ed852e2009-09-05 21:47:34 +0000564 }
cristy94b11832011-09-08 19:46:03 +0000565 SetPixelRed(image,ClampToQuantum(pixel.red),q);
566 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
567 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
cristyed231572011-07-14 02:18:59 +0000568 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000569 }
570 if (SyncAuthenticPixels(image,exception) == MagickFalse)
571 break;
572 if (image->previous == (Image *) NULL)
573 {
cristycee97112010-05-28 00:44:52 +0000574 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
575 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000576 if (status == MagickFalse)
577 break;
578 }
579 }
580 if (scale != (Quantum *) NULL)
581 scale=(Quantum *) RelinquishMagickMemory(scale);
582 break;
583 }
584 case '4':
585 {
586 /*
587 Convert PBM raw image to pixel packets.
588 */
cristyb3a73b52011-07-26 01:34:43 +0000589 image->colorspace=GRAYColorspace;
cristy3ed852e2009-09-05 21:47:34 +0000590 quantum_type=GrayQuantum;
591 if (image->storage_class == PseudoClass)
592 quantum_type=IndexQuantum;
593 quantum_info=AcquireQuantumInfo(image_info,image);
594 if (quantum_info == (QuantumInfo *) NULL)
595 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
596 SetQuantumMinIsWhite(quantum_info,MagickTrue);
597 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +0000598 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000599 {
cristy3ed852e2009-09-05 21:47:34 +0000600 MagickBooleanType
601 sync;
602
cristy4c08aed2011-07-01 19:47:50 +0000603 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000604 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000605
606 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000607 count,
608 offset;
cristy3ed852e2009-09-05 21:47:34 +0000609
610 size_t
611 length;
612
613 unsigned char
614 *pixels;
615
616 if (status == MagickFalse)
617 continue;
618 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000619 {
620 count=ReadBlob(image,extent,pixels);
621 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
622 (image->previous == (Image *) NULL))
623 {
624 MagickBooleanType
625 proceed;
626
cristycee97112010-05-28 00:44:52 +0000627 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
628 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000629 if (proceed == MagickFalse)
630 status=MagickFalse;
631 }
632 offset=row++;
633 }
634 if (count != (ssize_t) extent)
635 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000636 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000637 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000638 {
639 status=MagickFalse;
640 continue;
641 }
cristyaa740112010-03-30 17:58:44 +0000642 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
643 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +0000644 if (length != extent)
645 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000646 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000647 if (sync == MagickFalse)
648 status=MagickFalse;
649 }
cristy3ed852e2009-09-05 21:47:34 +0000650 quantum_info=DestroyQuantumInfo(quantum_info);
651 if (status == MagickFalse)
652 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
653 SetQuantumImageType(image,quantum_type);
654 break;
655 }
656 case '5':
657 {
658 QuantumAny
659 range;
660
661 /*
662 Convert PGM raw image to pixel packets.
663 */
cristyb3a73b52011-07-26 01:34:43 +0000664 image->colorspace=GRAYColorspace;
cristy3ed852e2009-09-05 21:47:34 +0000665 range=GetQuantumRange(image->depth);
666 quantum_type=GrayQuantum;
667 extent=(image->depth <= 8 ? 1 : 2)*image->columns;
668 quantum_info=AcquireQuantumInfo(image_info,image);
669 if (quantum_info == (QuantumInfo *) NULL)
670 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000671 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000672 {
cristy3ed852e2009-09-05 21:47:34 +0000673 MagickBooleanType
674 sync;
675
676 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000677 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000678
cristybb503372010-05-27 20:51:26 +0000679 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000680 x;
681
cristy4c08aed2011-07-01 19:47:50 +0000682 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000683 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000684
685 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000686 count,
687 offset;
cristy3ed852e2009-09-05 21:47:34 +0000688
689 unsigned char
690 *pixels;
691
692 if (status == MagickFalse)
693 continue;
694 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000695 {
696 count=ReadBlob(image,extent,pixels);
697 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
698 (image->previous == (Image *) NULL))
699 {
700 MagickBooleanType
701 proceed;
702
cristy34575212010-11-06 12:39:23 +0000703 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
704 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000705 if (proceed == MagickFalse)
706 status=MagickFalse;
707 }
708 offset=row++;
709 }
710 if (count != (ssize_t) extent)
711 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000712 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000713 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000714 {
715 status=MagickFalse;
716 continue;
717 }
718 p=pixels;
719 if ((image->depth == 8) || (image->depth == 16))
cristyaa740112010-03-30 17:58:44 +0000720 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3ed852e2009-09-05 21:47:34 +0000721 quantum_type,pixels,exception);
722 else
723 if (image->depth <= 8)
724 {
725 unsigned char
726 pixel;
727
cristybb503372010-05-27 20:51:26 +0000728 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000729 {
730 p=PushCharPixel(p,&pixel);
cristy08528502012-01-01 00:52:17 +0000731 SetPixelGray(image,ScaleAnyToQuantum(pixel,range),q);
cristyed231572011-07-14 02:18:59 +0000732 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000733 }
734 }
735 else
736 {
737 unsigned short
738 pixel;
739
cristybb503372010-05-27 20:51:26 +0000740 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000741 {
742 p=PushShortPixel(MSBEndian,p,&pixel);
cristy08528502012-01-01 00:52:17 +0000743 SetPixelGray(image,ScaleAnyToQuantum(pixel,range),q);
cristyed231572011-07-14 02:18:59 +0000744 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000745 }
746 }
cristyaa740112010-03-30 17:58:44 +0000747 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000748 if (sync == MagickFalse)
749 status=MagickFalse;
750 }
cristy3ed852e2009-09-05 21:47:34 +0000751 quantum_info=DestroyQuantumInfo(quantum_info);
752 if (status == MagickFalse)
753 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
754 SetQuantumImageType(image,quantum_type);
755 break;
756 }
757 case '6':
758 {
759 ImageType
760 type;
761
762 QuantumAny
763 range;
764
765 /*
766 Convert PNM raster image to pixel packets.
767 */
768 type=BilevelType;
769 quantum_type=RGBQuantum;
770 extent=3*(image->depth <= 8 ? 1 : 2)*image->columns;
771 range=GetQuantumRange(image->depth);
772 quantum_info=AcquireQuantumInfo(image_info,image);
773 if (quantum_info == (QuantumInfo *) NULL)
774 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000775 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000776 {
cristy3ed852e2009-09-05 21:47:34 +0000777 MagickBooleanType
778 sync;
779
780 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000781 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000782
cristybb503372010-05-27 20:51:26 +0000783 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000784 x;
785
cristy4c08aed2011-07-01 19:47:50 +0000786 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000787 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000788
789 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000790 count,
791 offset;
cristy3ed852e2009-09-05 21:47:34 +0000792
cristy3ed852e2009-09-05 21:47:34 +0000793 unsigned char
794 *pixels;
795
796 if (status == MagickFalse)
797 continue;
798 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000799 {
800 count=ReadBlob(image,extent,pixels);
801 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
802 (image->previous == (Image *) NULL))
803 {
804 MagickBooleanType
805 proceed;
806
cristy34575212010-11-06 12:39:23 +0000807 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
808 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000809 if (proceed == MagickFalse)
810 status=MagickFalse;
811 }
812 offset=row++;
813 }
814 if (count != (ssize_t) extent)
815 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000816 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000817 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000818 {
819 status=MagickFalse;
820 continue;
821 }
822 p=pixels;
cristye90d7402010-03-14 18:21:29 +0000823 if (image->depth == 8)
cristybb503372010-05-27 20:51:26 +0000824 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000825 {
cristy4c08aed2011-07-01 19:47:50 +0000826 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
827 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
828 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
829 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000830 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000831 }
832 else
cristye90d7402010-03-14 18:21:29 +0000833 if (image->depth == 16)
cristy3ed852e2009-09-05 21:47:34 +0000834 {
835 unsigned short
836 pixel;
837
cristybb503372010-05-27 20:51:26 +0000838 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000839 {
840 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000841 SetPixelRed(image,ScaleShortToQuantum(pixel),q);
cristy3ed852e2009-09-05 21:47:34 +0000842 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000843 SetPixelGreen(image,ScaleShortToQuantum(pixel),q);
cristy3ed852e2009-09-05 21:47:34 +0000844 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000845 SetPixelBlue(image,ScaleShortToQuantum(pixel),q);
846 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000847 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000848 }
849 }
cristye90d7402010-03-14 18:21:29 +0000850 else
851 if (image->depth <= 8)
852 {
853 unsigned char
854 pixel;
855
cristybb503372010-05-27 20:51:26 +0000856 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000857 {
858 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000859 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000860 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000861 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000862 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000863 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
864 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000865 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000866 }
867 }
868 else
869 {
870 unsigned short
871 pixel;
872
cristybb503372010-05-27 20:51:26 +0000873 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000874 {
875 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000876 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000877 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000878 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000879 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000880 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
881 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000882 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000883 }
884 }
cristy3ed852e2009-09-05 21:47:34 +0000885 if ((type == BilevelType) || (type == GrayscaleType))
cristy3ed852e2009-09-05 21:47:34 +0000886 {
cristyaa740112010-03-30 17:58:44 +0000887 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristybb503372010-05-27 20:51:26 +0000888 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000889 {
890 if ((type == BilevelType) &&
cristy4c08aed2011-07-01 19:47:50 +0000891 (IsPixelMonochrome(image,q) == MagickFalse))
892 type=IsPixelGray(image,q) == MagickFalse ? UndefinedType :
cristye90d7402010-03-14 18:21:29 +0000893 GrayscaleType;
cristy4c08aed2011-07-01 19:47:50 +0000894 if ((type == GrayscaleType) &&
895 (IsPixelGray(image,q) == MagickFalse))
cristy5f1c1ff2010-12-23 21:38:06 +0000896 type=UndefinedType;
cristye90d7402010-03-14 18:21:29 +0000897 if ((type != BilevelType) && (type != GrayscaleType))
898 break;
cristyed231572011-07-14 02:18:59 +0000899 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000900 }
cristy3ed852e2009-09-05 21:47:34 +0000901 }
cristyaa740112010-03-30 17:58:44 +0000902 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000903 if (sync == MagickFalse)
904 status=MagickFalse;
905 }
cristy3ed852e2009-09-05 21:47:34 +0000906 quantum_info=DestroyQuantumInfo(quantum_info);
907 if (status == MagickFalse)
908 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
cristy5f1c1ff2010-12-23 21:38:06 +0000909 if (type != UndefinedType)
cristy3ed852e2009-09-05 21:47:34 +0000910 image->type=type;
911 break;
912 }
913 case '7':
914 {
cristy3ed852e2009-09-05 21:47:34 +0000915 QuantumAny
916 range;
917
cristybb503372010-05-27 20:51:26 +0000918 size_t
cristy3ed852e2009-09-05 21:47:34 +0000919 channels;
920
921 /*
922 Convert PAM raster image to pixel packets.
923 */
924 range=GetQuantumRange(image->depth);
925 switch (quantum_type)
926 {
927 case GrayQuantum:
928 case GrayAlphaQuantum:
929 {
930 channels=1;
931 break;
932 }
933 case CMYKQuantum:
934 case CMYKAQuantum:
935 {
936 channels=4;
937 break;
938 }
939 default:
940 {
941 channels=3;
942 break;
943 }
944 }
945 if (image->matte != MagickFalse)
946 channels++;
947 extent=channels*(image->depth <= 8 ? 1 : 2)*image->columns;
948 quantum_info=AcquireQuantumInfo(image_info,image);
949 if (quantum_info == (QuantumInfo *) NULL)
950 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000951 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000952 {
cristy3ed852e2009-09-05 21:47:34 +0000953 MagickBooleanType
954 sync;
955
956 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000957 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000958
cristybb503372010-05-27 20:51:26 +0000959 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000960 x;
961
cristy4c08aed2011-07-01 19:47:50 +0000962 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000963 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000964
965 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000966 count,
967 offset;
cristy3ed852e2009-09-05 21:47:34 +0000968
969 unsigned char
970 *pixels;
971
972 if (status == MagickFalse)
973 continue;
974 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000975 {
976 count=ReadBlob(image,extent,pixels);
977 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
978 (image->previous == (Image *) NULL))
979 {
980 MagickBooleanType
981 proceed;
982
cristy34575212010-11-06 12:39:23 +0000983 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
984 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000985 if (proceed == MagickFalse)
986 status=MagickFalse;
987 }
988 offset=row++;
989 }
990 if (count != (ssize_t) extent)
991 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000992 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000993 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000994 {
995 status=MagickFalse;
996 continue;
997 }
cristy3ed852e2009-09-05 21:47:34 +0000998 p=pixels;
999 if ((image->depth == 8) || (image->depth == 16))
cristyaa740112010-03-30 17:58:44 +00001000 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3ed852e2009-09-05 21:47:34 +00001001 quantum_type,pixels,exception);
1002 else
1003 switch (quantum_type)
1004 {
1005 case GrayQuantum:
1006 case GrayAlphaQuantum:
1007 {
1008 if (image->depth <= 8)
1009 {
1010 unsigned char
1011 pixel;
1012
cristybb503372010-05-27 20:51:26 +00001013 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001014 {
1015 p=PushCharPixel(p,&pixel);
cristy08528502012-01-01 00:52:17 +00001016 SetPixelGray(image,ScaleAnyToQuantum(pixel,range),q);
cristy4c08aed2011-07-01 19:47:50 +00001017 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001018 if (image->matte != MagickFalse)
1019 {
1020 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001021 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001022 }
cristyed231572011-07-14 02:18:59 +00001023 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001024 }
1025 }
1026 else
1027 {
1028 unsigned short
1029 pixel;
1030
cristybb503372010-05-27 20:51:26 +00001031 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001032 {
1033 p=PushShortPixel(MSBEndian,p,&pixel);
cristy08528502012-01-01 00:52:17 +00001034 SetPixelGray(image,ScaleAnyToQuantum(pixel,range),q);
cristy4c08aed2011-07-01 19:47:50 +00001035 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001036 if (image->matte != MagickFalse)
1037 {
1038 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001039 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001040 }
cristyed231572011-07-14 02:18:59 +00001041 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001042 }
1043 }
1044 break;
1045 }
1046 case CMYKQuantum:
1047 case CMYKAQuantum:
1048 {
1049 if (image->depth <= 8)
1050 {
1051 unsigned char
1052 pixel;
1053
cristybb503372010-05-27 20:51:26 +00001054 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001055 {
1056 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001057 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001058 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001059 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001060 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001061 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001062 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001063 SetPixelBlack(image,ScaleAnyToQuantum(pixel,range),q);
1064 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001065 if (image->matte != MagickFalse)
1066 {
1067 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001068 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001069 }
cristyed231572011-07-14 02:18:59 +00001070 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001071 }
1072 }
1073 else
1074 {
1075 unsigned short
1076 pixel;
1077
cristybb503372010-05-27 20:51:26 +00001078 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001079 {
1080 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001081 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001082 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001083 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001084 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001085 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001086 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001087 SetPixelBlack(image,ScaleAnyToQuantum(pixel,range),q);
1088 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001089 if (image->matte != MagickFalse)
1090 {
1091 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001092 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001093 }
cristyed231572011-07-14 02:18:59 +00001094 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001095 }
1096 }
1097 break;
1098 }
1099 default:
1100 {
1101 if (image->depth <= 8)
1102 {
1103 unsigned char
1104 pixel;
1105
cristybb503372010-05-27 20:51:26 +00001106 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001107 {
1108 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001109 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001110 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001111 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001112 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001113 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
1114 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001115 if (image->matte != MagickFalse)
1116 {
1117 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001118 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001119 }
cristyed231572011-07-14 02:18:59 +00001120 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001121 }
1122 }
1123 else
1124 {
1125 unsigned short
1126 pixel;
1127
cristybb503372010-05-27 20:51:26 +00001128 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001129 {
1130 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001131 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001132 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001133 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001134 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001135 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
1136 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001137 if (image->matte != MagickFalse)
1138 {
1139 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001140 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001141 }
cristyed231572011-07-14 02:18:59 +00001142 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001143 }
1144 }
1145 break;
1146 }
1147 }
cristyaa740112010-03-30 17:58:44 +00001148 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001149 if (sync == MagickFalse)
1150 status=MagickFalse;
1151 }
cristy3ed852e2009-09-05 21:47:34 +00001152 quantum_info=DestroyQuantumInfo(quantum_info);
1153 if (status == MagickFalse)
1154 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1155 SetQuantumImageType(image,quantum_type);
1156 break;
1157 }
1158 case 'F':
1159 case 'f':
1160 {
1161 /*
1162 Convert PFM raster image to pixel packets.
1163 */
cristyaf6eb932012-01-01 01:22:59 +00001164 if (format == 'f')
1165 image->colorspace=GRAYColorspace;
cristy3ed852e2009-09-05 21:47:34 +00001166 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
1167 image->endian=quantum_scale < 0.0 ? LSBEndian : MSBEndian;
1168 image->depth=32;
1169 quantum_info=AcquireQuantumInfo(image_info,image);
1170 if (quantum_info == (QuantumInfo *) NULL)
1171 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1172 status=SetQuantumDepth(image,quantum_info,32);
1173 if (status == MagickFalse)
1174 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1175 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1176 if (status == MagickFalse)
1177 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1178 SetQuantumScale(quantum_info,(MagickRealType) QuantumRange*
1179 fabs(quantum_scale));
1180 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +00001181 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001182 {
cristy3ed852e2009-09-05 21:47:34 +00001183 MagickBooleanType
1184 sync;
1185
cristy4c08aed2011-07-01 19:47:50 +00001186 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00001187 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001188
1189 ssize_t
cristyaff6d802011-04-26 01:46:31 +00001190 count,
1191 offset;
cristy3ed852e2009-09-05 21:47:34 +00001192
1193 size_t
1194 length;
1195
1196 unsigned char
1197 *pixels;
1198
1199 if (status == MagickFalse)
1200 continue;
1201 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001202 {
1203 count=ReadBlob(image,extent,pixels);
1204 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1205 (image->previous == (Image *) NULL))
1206 {
1207 MagickBooleanType
1208 proceed;
1209
cristy34575212010-11-06 12:39:23 +00001210 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1211 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001212 if (proceed == MagickFalse)
1213 status=MagickFalse;
1214 }
1215 offset=row++;
1216 }
1217 if ((size_t) count != extent)
1218 status=MagickFalse;
cristybb503372010-05-27 20:51:26 +00001219 q=QueueAuthenticPixels(image,0,(ssize_t) (image->rows-offset-1),
cristyaa740112010-03-30 17:58:44 +00001220 image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00001221 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001222 {
1223 status=MagickFalse;
1224 continue;
1225 }
cristyaa740112010-03-30 17:58:44 +00001226 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1227 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001228 if (length != extent)
1229 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +00001230 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001231 if (sync == MagickFalse)
1232 status=MagickFalse;
1233 }
cristy3ed852e2009-09-05 21:47:34 +00001234 quantum_info=DestroyQuantumInfo(quantum_info);
1235 if (status == MagickFalse)
1236 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1237 SetQuantumImageType(image,quantum_type);
1238 break;
1239 }
1240 default:
1241 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1242 }
1243 if (EOFBlob(image) != MagickFalse)
1244 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
1245 "UnexpectedEndOfFile","`%s'",image->filename);
1246 /*
1247 Proceed to next image.
1248 */
1249 if (image_info->number_scenes != 0)
1250 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1251 break;
1252 if ((format == '1') || (format == '2') || (format == '3'))
1253 do
1254 {
1255 /*
1256 Skip to end of line.
1257 */
1258 count=ReadBlob(image,1,(unsigned char *) &format);
1259 if (count == 0)
1260 break;
1261 if ((count != 0) && (format == 'P'))
1262 break;
1263 } while (format != '\n');
1264 count=ReadBlob(image,1,(unsigned char *) &format);
1265 if ((count == 1) && (format == 'P'))
1266 {
1267 /*
1268 Allocate next image structure.
1269 */
cristy9950d572011-10-01 18:22:35 +00001270 AcquireNextImage(image_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001271 if (GetNextImageInList(image) == (Image *) NULL)
1272 {
1273 image=DestroyImageList(image);
1274 return((Image *) NULL);
1275 }
1276 image=SyncNextImageInList(image);
1277 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1278 GetBlobSize(image));
1279 if (status == MagickFalse)
1280 break;
1281 }
1282 } while ((count == 1) && (format == 'P'));
1283 (void) CloseBlob(image);
1284 return(GetFirstImageInList(image));
1285}
1286
1287/*
1288%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1289% %
1290% %
1291% %
1292% R e g i s t e r P N M I m a g e %
1293% %
1294% %
1295% %
1296%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1297%
1298% RegisterPNMImage() adds properties for the PNM image format to
1299% the list of supported formats. The properties include the image format
1300% tag, a method to read and/or write the format, whether the format
1301% supports the saving of more than one frame to the same file or blob,
1302% whether the format supports native in-memory I/O, and a brief
1303% description of the format.
1304%
1305% The format of the RegisterPNMImage method is:
1306%
cristybb503372010-05-27 20:51:26 +00001307% size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001308%
1309*/
cristybb503372010-05-27 20:51:26 +00001310ModuleExport size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001311{
1312 MagickInfo
1313 *entry;
1314
1315 entry=SetMagickInfo("PAM");
1316 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1317 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1318 entry->description=ConstantString("Common 2-dimensional bitmap format");
1319 entry->module=ConstantString("PNM");
1320 (void) RegisterMagickInfo(entry);
1321 entry=SetMagickInfo("PBM");
1322 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1323 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1324 entry->description=ConstantString("Portable bitmap format (black and white)");
1325 entry->module=ConstantString("PNM");
1326 (void) RegisterMagickInfo(entry);
1327 entry=SetMagickInfo("PFM");
1328 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1329 entry->encoder=(EncodeImageHandler *) WritePNMImage;
cristye96405a2010-05-19 02:24:31 +00001330 entry->endian_support=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00001331 entry->description=ConstantString("Portable float format");
1332 entry->module=ConstantString("PFM");
1333 (void) RegisterMagickInfo(entry);
1334 entry=SetMagickInfo("PGM");
1335 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1336 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1337 entry->description=ConstantString("Portable graymap format (gray scale)");
1338 entry->module=ConstantString("PNM");
1339 (void) RegisterMagickInfo(entry);
1340 entry=SetMagickInfo("PNM");
1341 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1342 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1343 entry->magick=(IsImageFormatHandler *) IsPNM;
1344 entry->description=ConstantString("Portable anymap");
1345 entry->module=ConstantString("PNM");
1346 (void) RegisterMagickInfo(entry);
1347 entry=SetMagickInfo("PPM");
1348 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1349 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1350 entry->description=ConstantString("Portable pixmap format (color)");
1351 entry->module=ConstantString("PNM");
1352 (void) RegisterMagickInfo(entry);
1353 return(MagickImageCoderSignature);
1354}
1355
1356/*
1357%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1358% %
1359% %
1360% %
1361% U n r e g i s t e r P N M I m a g e %
1362% %
1363% %
1364% %
1365%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1366%
1367% UnregisterPNMImage() removes format registrations made by the
1368% PNM module from the list of supported formats.
1369%
1370% The format of the UnregisterPNMImage method is:
1371%
1372% UnregisterPNMImage(void)
1373%
1374*/
1375ModuleExport void UnregisterPNMImage(void)
1376{
1377 (void) UnregisterMagickInfo("PAM");
1378 (void) UnregisterMagickInfo("PBM");
1379 (void) UnregisterMagickInfo("PGM");
1380 (void) UnregisterMagickInfo("PNM");
1381 (void) UnregisterMagickInfo("PPM");
1382}
1383
1384/*
1385%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1386% %
1387% %
1388% %
1389% W r i t e P N M I m a g e %
1390% %
1391% %
1392% %
1393%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1394%
cristy661b5ad2010-01-13 00:54:42 +00001395% WritePNMImage() writes an image to a file in the PNM rasterfile format.
cristy3ed852e2009-09-05 21:47:34 +00001396%
1397% The format of the WritePNMImage method is:
1398%
cristy1e178e72011-08-28 19:44:34 +00001399% MagickBooleanType WritePNMImage(const ImageInfo *image_info,
1400% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001401%
1402% A description of each parameter follows.
1403%
1404% o image_info: the image info.
1405%
1406% o image: The image.
1407%
cristy1e178e72011-08-28 19:44:34 +00001408% o exception: return any errors or warnings in this structure.
1409%
cristy3ed852e2009-09-05 21:47:34 +00001410*/
cristy1e178e72011-08-28 19:44:34 +00001411static MagickBooleanType WritePNMImage(const ImageInfo *image_info,Image *image,
1412 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001413{
1414 char
1415 buffer[MaxTextExtent],
1416 format,
1417 magick[MaxTextExtent];
1418
1419 const char
1420 *value;
1421
cristy3ed852e2009-09-05 21:47:34 +00001422 MagickBooleanType
1423 status;
1424
1425 MagickOffsetType
1426 scene;
1427
cristy4c08aed2011-07-01 19:47:50 +00001428 Quantum
1429 index;
1430
cristy3ed852e2009-09-05 21:47:34 +00001431 QuantumAny
1432 pixel;
1433
1434 QuantumInfo
1435 *quantum_info;
1436
1437 QuantumType
1438 quantum_type;
1439
cristy3ed852e2009-09-05 21:47:34 +00001440 register unsigned char
1441 *pixels,
1442 *q;
1443
cristy3ed852e2009-09-05 21:47:34 +00001444 size_t
1445 extent,
1446 packet_size;
1447
cristy95802a72010-09-05 19:07:17 +00001448 ssize_t
cristyaff6d802011-04-26 01:46:31 +00001449 count,
1450 y;
cristy95802a72010-09-05 19:07:17 +00001451
cristy3ed852e2009-09-05 21:47:34 +00001452 /*
1453 Open output image file.
1454 */
1455 assert(image_info != (const ImageInfo *) NULL);
1456 assert(image_info->signature == MagickSignature);
1457 assert(image != (Image *) NULL);
1458 assert(image->signature == MagickSignature);
1459 if (image->debug != MagickFalse)
1460 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy3a37efd2011-08-28 20:31:03 +00001461 assert(exception != (ExceptionInfo *) NULL);
1462 assert(exception->signature == MagickSignature);
cristy1e178e72011-08-28 19:44:34 +00001463 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy3ed852e2009-09-05 21:47:34 +00001464 if (status == MagickFalse)
1465 return(status);
1466 scene=0;
1467 do
1468 {
1469 /*
1470 Write PNM file header.
1471 */
1472 packet_size=3;
1473 quantum_type=RGBQuantum;
1474 (void) CopyMagickString(magick,image_info->magick,MaxTextExtent);
1475 switch (magick[1])
1476 {
1477 case 'A':
1478 case 'a':
1479 {
1480 format='7';
1481 break;
1482 }
1483 case 'B':
1484 case 'b':
1485 {
1486 format='4';
1487 if (image_info->compression == NoCompression)
1488 format='1';
1489 break;
1490 }
1491 case 'F':
1492 case 'f':
1493 {
1494 format='F';
cristy1e178e72011-08-28 19:44:34 +00001495 if (IsImageGray(image,exception) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001496 format='f';
1497 break;
1498 }
1499 case 'G':
1500 case 'g':
1501 {
1502 format='5';
1503 if (image_info->compression == NoCompression)
1504 format='2';
1505 break;
1506 }
1507 case 'N':
1508 case 'n':
1509 {
1510 if ((image_info->type != TrueColorType) &&
cristy1e178e72011-08-28 19:44:34 +00001511 (IsImageGray(image,exception) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001512 {
1513 format='5';
1514 if (image_info->compression == NoCompression)
1515 format='2';
cristy1e178e72011-08-28 19:44:34 +00001516 if (IsImageMonochrome(image,exception) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001517 {
1518 format='4';
1519 if (image_info->compression == NoCompression)
1520 format='1';
1521 }
1522 break;
1523 }
1524 }
1525 default:
1526 {
1527 format='6';
1528 if (image_info->compression == NoCompression)
1529 format='3';
1530 break;
1531 }
1532 }
cristyb51dff52011-05-19 16:55:47 +00001533 (void) FormatLocaleString(buffer,MaxTextExtent,"P%c\n",format);
cristy3ed852e2009-09-05 21:47:34 +00001534 (void) WriteBlobString(image,buffer);
cristyd15e6592011-10-15 00:13:06 +00001535 value=GetImageProperty(image,"comment",exception);
cristy3ed852e2009-09-05 21:47:34 +00001536 if (value != (const char *) NULL)
1537 {
1538 register const char
1539 *p;
1540
1541 /*
1542 Write comments to file.
1543 */
1544 (void) WriteBlobByte(image,'#');
1545 for (p=value; *p != '\0'; p++)
1546 {
1547 (void) WriteBlobByte(image,(unsigned char) *p);
1548 if ((*p == '\r') && (*(p+1) != '\0'))
1549 (void) WriteBlobByte(image,'#');
1550 if ((*p == '\n') && (*(p+1) != '\0'))
1551 (void) WriteBlobByte(image,'#');
1552 }
1553 (void) WriteBlobByte(image,'\n');
1554 }
1555 if (format != '7')
1556 {
cristy510d06a2011-07-06 23:43:54 +00001557 if (IsRGBColorspace(image->colorspace) == MagickFalse)
cristye941a752011-10-15 01:52:48 +00001558 (void) TransformImageColorspace(image,RGBColorspace,exception);
cristyb51dff52011-05-19 16:55:47 +00001559 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n",
cristye8c25f92010-06-03 00:53:06 +00001560 (double) image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001561 (void) WriteBlobString(image,buffer);
1562 }
1563 else
1564 {
1565 char
1566 type[MaxTextExtent];
1567
1568 /*
1569 PAM header.
1570 */
cristyb51dff52011-05-19 16:55:47 +00001571 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00001572 "WIDTH %.20g\nHEIGHT %.20g\n",(double) image->columns,(double)
1573 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001574 (void) WriteBlobString(image,buffer);
cristy1e178e72011-08-28 19:44:34 +00001575 quantum_type=GetQuantumType(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001576 switch (quantum_type)
1577 {
1578 case CMYKQuantum:
1579 case CMYKAQuantum:
1580 {
1581 packet_size=4;
1582 (void) CopyMagickString(type,"CMYK",MaxTextExtent);
1583 break;
1584 }
1585 case GrayQuantum:
1586 case GrayAlphaQuantum:
1587 {
1588 packet_size=1;
1589 (void) CopyMagickString(type,"GRAYSCALE",MaxTextExtent);
1590 break;
1591 }
1592 default:
1593 {
1594 quantum_type=RGBQuantum;
1595 if (image->matte != MagickFalse)
1596 quantum_type=RGBAQuantum;
1597 packet_size=3;
1598 (void) CopyMagickString(type,"RGB",MaxTextExtent);
1599 break;
1600 }
1601 }
1602 if (image->matte != MagickFalse)
1603 {
1604 packet_size++;
1605 (void) ConcatenateMagickString(type,"_ALPHA",MaxTextExtent);
1606 }
1607 if (image->depth > 16)
1608 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001609 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00001610 "DEPTH %.20g\nMAXVAL %.20g\n",(double) packet_size,(double)
cristy2b9582a2011-07-04 17:38:56 +00001611 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001612 (void) WriteBlobString(image,buffer);
cristyb51dff52011-05-19 16:55:47 +00001613 (void) FormatLocaleString(buffer,MaxTextExtent,"TUPLTYPE %s\nENDHDR\n",
cristy3ed852e2009-09-05 21:47:34 +00001614 type);
1615 (void) WriteBlobString(image,buffer);
1616 }
1617 /*
1618 Convert runextent encoded to PNM raster pixels.
1619 */
1620 switch (format)
1621 {
1622 case '1':
1623 {
cristy661b5ad2010-01-13 00:54:42 +00001624 unsigned char
1625 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001626
1627 /*
1628 Convert image to a PBM image.
1629 */
cristy661b5ad2010-01-13 00:54:42 +00001630 q=pixels;
cristybb503372010-05-27 20:51:26 +00001631 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001632 {
cristy4c08aed2011-07-01 19:47:50 +00001633 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001634 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001635
cristybb503372010-05-27 20:51:26 +00001636 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001637 x;
1638
cristy1e178e72011-08-28 19:44:34 +00001639 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001640 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001641 break;
cristybb503372010-05-27 20:51:26 +00001642 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001643 {
cristy4c08aed2011-07-01 19:47:50 +00001644 pixel=GetPixelIntensity(image,p);
cristy661b5ad2010-01-13 00:54:42 +00001645 *q++=(unsigned char) (pixel >= (Quantum) (QuantumRange/2) ?
1646 '0' : '1');
1647 *q++=' ';
1648 if ((q-pixels+2) >= 80)
1649 {
1650 *q++='\n';
1651 (void) WriteBlob(image,q-pixels,pixels);
1652 q=pixels;
cristy661b5ad2010-01-13 00:54:42 +00001653 }
cristyed231572011-07-14 02:18:59 +00001654 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001655 }
1656 if (image->previous == (Image *) NULL)
1657 {
cristycee97112010-05-28 00:44:52 +00001658 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1659 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001660 if (status == MagickFalse)
1661 break;
1662 }
1663 }
cristy661b5ad2010-01-13 00:54:42 +00001664 if (q != pixels)
1665 {
1666 *q++='\n';
1667 (void) WriteBlob(image,q-pixels,pixels);
1668 }
cristy3ed852e2009-09-05 21:47:34 +00001669 break;
1670 }
1671 case '2':
1672 {
cristy661b5ad2010-01-13 00:54:42 +00001673 unsigned char
1674 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001675
1676 /*
1677 Convert image to a PGM image.
1678 */
1679 if (image->depth <= 8)
1680 (void) WriteBlobString(image,"255\n");
1681 else
1682 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001683 q=pixels;
cristybb503372010-05-27 20:51:26 +00001684 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001685 {
cristy4c08aed2011-07-01 19:47:50 +00001686 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001687 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001688
cristybb503372010-05-27 20:51:26 +00001689 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001690 x;
1691
cristy1e178e72011-08-28 19:44:34 +00001692 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001693 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001694 break;
cristybb503372010-05-27 20:51:26 +00001695 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001696 {
cristy4c08aed2011-07-01 19:47:50 +00001697 index=GetPixelIntensity(image,p);
cristy3ed852e2009-09-05 21:47:34 +00001698 if (image->depth <= 8)
cristyb51dff52011-05-19 16:55:47 +00001699 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,"%u ",
cristy3ed852e2009-09-05 21:47:34 +00001700 ScaleQuantumToChar(index));
1701 else
cristyb51dff52011-05-19 16:55:47 +00001702 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,"%u ",
cristy3ed852e2009-09-05 21:47:34 +00001703 ScaleQuantumToShort(index));
cristy661b5ad2010-01-13 00:54:42 +00001704 extent=(size_t) count;
1705 (void) strncpy((char *) q,buffer,extent);
1706 q+=extent;
1707 if ((q-pixels+extent) >= 80)
1708 {
1709 *q++='\n';
1710 (void) WriteBlob(image,q-pixels,pixels);
1711 q=pixels;
1712 }
cristyed231572011-07-14 02:18:59 +00001713 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001714 }
1715 if (image->previous == (Image *) NULL)
1716 {
cristycee97112010-05-28 00:44:52 +00001717 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1718 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001719 if (status == MagickFalse)
1720 break;
1721 }
1722 }
cristy661b5ad2010-01-13 00:54:42 +00001723 if (q != pixels)
1724 {
1725 *q++='\n';
1726 (void) WriteBlob(image,q-pixels,pixels);
1727 }
cristy3ed852e2009-09-05 21:47:34 +00001728 break;
1729 }
1730 case '3':
1731 {
cristy661b5ad2010-01-13 00:54:42 +00001732 unsigned char
1733 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001734
1735 /*
1736 Convert image to a PNM image.
1737 */
1738 if (image->depth <= 8)
1739 (void) WriteBlobString(image,"255\n");
1740 else
1741 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001742 q=pixels;
cristybb503372010-05-27 20:51:26 +00001743 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001744 {
cristy4c08aed2011-07-01 19:47:50 +00001745 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001746 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001747
cristybb503372010-05-27 20:51:26 +00001748 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001749 x;
1750
cristy1e178e72011-08-28 19:44:34 +00001751 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001752 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001753 break;
cristybb503372010-05-27 20:51:26 +00001754 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001755 {
1756 if (image->depth <= 8)
cristyb51dff52011-05-19 16:55:47 +00001757 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,
cristy4c08aed2011-07-01 19:47:50 +00001758 "%u %u %u ",ScaleQuantumToChar(GetPixelRed(image,p)),
1759 ScaleQuantumToChar(GetPixelGreen(image,p)),
1760 ScaleQuantumToChar(GetPixelBlue(image,p)));
cristy3ed852e2009-09-05 21:47:34 +00001761 else
cristyb51dff52011-05-19 16:55:47 +00001762 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,
cristy4c08aed2011-07-01 19:47:50 +00001763 "%u %u %u ",ScaleQuantumToShort(GetPixelRed(image,p)),
1764 ScaleQuantumToShort(GetPixelGreen(image,p)),
1765 ScaleQuantumToShort(GetPixelBlue(image,p)));
cristy661b5ad2010-01-13 00:54:42 +00001766 extent=(size_t) count;
1767 (void) strncpy((char *) q,buffer,extent);
1768 q+=extent;
1769 if ((q-pixels+extent) >= 80)
1770 {
1771 *q++='\n';
1772 (void) WriteBlob(image,q-pixels,pixels);
1773 q=pixels;
1774 }
cristyed231572011-07-14 02:18:59 +00001775 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001776 }
1777 if (image->previous == (Image *) NULL)
1778 {
cristycee97112010-05-28 00:44:52 +00001779 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1780 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001781 if (status == MagickFalse)
1782 break;
1783 }
1784 }
cristy661b5ad2010-01-13 00:54:42 +00001785 if (q != pixels)
1786 {
1787 *q++='\n';
1788 (void) WriteBlob(image,q-pixels,pixels);
1789 }
cristy3ed852e2009-09-05 21:47:34 +00001790 break;
1791 }
1792 case '4':
1793 {
1794 /*
1795 Convert image to a PBM image.
1796 */
1797 image->depth=1;
1798 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1799 if (quantum_info == (QuantumInfo *) NULL)
1800 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1801 quantum_info->min_is_white=MagickTrue;
1802 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00001803 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001804 {
cristy4c08aed2011-07-01 19:47:50 +00001805 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001806 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001807
cristy1e178e72011-08-28 19:44:34 +00001808 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001809 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001810 break;
cristy4c08aed2011-07-01 19:47:50 +00001811 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001812 GrayQuantum,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001813 count=WriteBlob(image,extent,pixels);
1814 if (count != (ssize_t) extent)
1815 break;
1816 if (image->previous == (Image *) NULL)
1817 {
cristycee97112010-05-28 00:44:52 +00001818 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1819 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001820 if (status == MagickFalse)
1821 break;
1822 }
1823 }
1824 quantum_info=DestroyQuantumInfo(quantum_info);
1825 break;
1826 }
1827 case '5':
1828 {
1829 QuantumAny
1830 range;
1831
1832 /*
1833 Convert image to a PGM image.
1834 */
1835 if (image->depth > 8)
1836 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001837 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g\n",(double)
cristy2b9582a2011-07-04 17:38:56 +00001838 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001839 (void) WriteBlobString(image,buffer);
1840 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1841 if (quantum_info == (QuantumInfo *) NULL)
1842 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1843 quantum_info->min_is_white=MagickTrue;
1844 pixels=GetQuantumPixels(quantum_info);
1845 extent=GetQuantumExtent(image,quantum_info,GrayQuantum);
1846 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001847 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001848 {
cristy4c08aed2011-07-01 19:47:50 +00001849 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001850 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001851
cristybb503372010-05-27 20:51:26 +00001852 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001853 x;
1854
cristy1e178e72011-08-28 19:44:34 +00001855 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001856 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001857 break;
1858 q=pixels;
1859 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00001860 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001861 GrayQuantum,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001862 else
1863 {
1864 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00001865 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001866 {
cristy4c08aed2011-07-01 19:47:50 +00001867 if (IsPixelGray(image,p) == MagickFalse)
1868 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001869 else
1870 {
1871 if (image->depth == 8)
cristy4c08aed2011-07-01 19:47:50 +00001872 pixel=ScaleQuantumToChar(GetPixelRed(image,p));
cristy3ed852e2009-09-05 21:47:34 +00001873 else
cristy4c08aed2011-07-01 19:47:50 +00001874 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001875 }
1876 q=PopCharPixel((unsigned char) pixel,q);
cristyed231572011-07-14 02:18:59 +00001877 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001878 }
1879 else
cristybb503372010-05-27 20:51:26 +00001880 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001881 {
cristy4c08aed2011-07-01 19:47:50 +00001882 if (IsPixelGray(image,p) == MagickFalse)
1883 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001884 else
1885 {
1886 if (image->depth == 16)
cristy4c08aed2011-07-01 19:47:50 +00001887 pixel=ScaleQuantumToShort(GetPixelRed(image,p));
cristy3ed852e2009-09-05 21:47:34 +00001888 else
cristy4c08aed2011-07-01 19:47:50 +00001889 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001890 }
1891 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyed231572011-07-14 02:18:59 +00001892 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001893 }
1894 extent=(size_t) (q-pixels);
1895 }
1896 count=WriteBlob(image,extent,pixels);
1897 if (count != (ssize_t) extent)
1898 break;
1899 if (image->previous == (Image *) NULL)
1900 {
cristycee97112010-05-28 00:44:52 +00001901 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1902 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001903 if (status == MagickFalse)
1904 break;
1905 }
1906 }
1907 quantum_info=DestroyQuantumInfo(quantum_info);
1908 break;
1909 }
1910 case '6':
1911 {
1912 QuantumAny
1913 range;
1914
1915 /*
1916 Convert image to a PNM image.
1917 */
1918 if (image->depth > 8)
1919 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001920 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g\n",(double)
cristy2b9582a2011-07-04 17:38:56 +00001921 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001922 (void) WriteBlobString(image,buffer);
1923 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1924 if (quantum_info == (QuantumInfo *) NULL)
1925 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1926 pixels=GetQuantumPixels(quantum_info);
1927 extent=GetQuantumExtent(image,quantum_info,quantum_type);
1928 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001929 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001930 {
cristy4c08aed2011-07-01 19:47:50 +00001931 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001932 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001933
cristybb503372010-05-27 20:51:26 +00001934 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001935 x;
1936
cristy1e178e72011-08-28 19:44:34 +00001937 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001938 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001939 break;
1940 q=pixels;
1941 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00001942 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001943 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001944 else
1945 {
1946 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00001947 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001948 {
cristy4c08aed2011-07-01 19:47:50 +00001949 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001950 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001951 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001952 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001953 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001954 q=PopCharPixel((unsigned char) pixel,q);
cristyed231572011-07-14 02:18:59 +00001955 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001956 }
1957 else
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=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001962 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001963 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001964 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001965 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyed231572011-07-14 02:18:59 +00001966 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001967 }
1968 extent=(size_t) (q-pixels);
1969 }
1970 count=WriteBlob(image,extent,pixels);
1971 if (count != (ssize_t) extent)
1972 break;
1973 if (image->previous == (Image *) NULL)
1974 {
cristycee97112010-05-28 00:44:52 +00001975 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1976 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001977 if (status == MagickFalse)
1978 break;
1979 }
1980 }
1981 quantum_info=DestroyQuantumInfo(quantum_info);
1982 break;
1983 }
1984 case '7':
1985 {
1986 QuantumAny
1987 range;
1988
1989 /*
1990 Convert image to a PAM.
1991 */
1992 if (image->depth > 16)
1993 image->depth=16;
1994 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1995 pixels=GetQuantumPixels(quantum_info);
1996 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001997 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001998 {
cristy4c08aed2011-07-01 19:47:50 +00001999 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00002000 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002001
cristybb503372010-05-27 20:51:26 +00002002 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002003 x;
2004
cristy1e178e72011-08-28 19:44:34 +00002005 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002006 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002007 break;
cristy3ed852e2009-09-05 21:47:34 +00002008 q=pixels;
2009 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00002010 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002011 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002012 else
2013 {
2014 switch (quantum_type)
2015 {
2016 case GrayQuantum:
2017 case GrayAlphaQuantum:
2018 {
2019 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002020 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002021 {
cristy4c08aed2011-07-01 19:47:50 +00002022 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002023 q=PopCharPixel((unsigned char) pixel,q);
2024 if (image->matte != MagickFalse)
2025 {
cristyaff6d802011-04-26 01:46:31 +00002026 pixel=(unsigned char) ScaleQuantumToAny(
cristy4c08aed2011-07-01 19:47:50 +00002027 GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002028 q=PopCharPixel((unsigned char) pixel,q);
2029 }
cristyed231572011-07-14 02:18:59 +00002030 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002031 }
2032 else
cristybb503372010-05-27 20:51:26 +00002033 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002034 {
cristy4c08aed2011-07-01 19:47:50 +00002035 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002036 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2037 if (image->matte != MagickFalse)
2038 {
cristyaff6d802011-04-26 01:46:31 +00002039 pixel=(unsigned char) ScaleQuantumToAny(
cristy4c08aed2011-07-01 19:47:50 +00002040 GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002041 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2042 }
cristyed231572011-07-14 02:18:59 +00002043 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002044 }
2045 break;
2046 }
2047 case CMYKQuantum:
2048 case CMYKAQuantum:
2049 {
2050 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002051 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002052 {
cristy4c08aed2011-07-01 19:47:50 +00002053 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002054 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002055 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002056 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002057 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002058 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002059 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002060 q=PopCharPixel((unsigned char) pixel,q);
2061 if (image->matte != MagickFalse)
2062 {
cristy4c08aed2011-07-01 19:47:50 +00002063 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002064 q=PopCharPixel((unsigned char) pixel,q);
2065 }
cristyed231572011-07-14 02:18:59 +00002066 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002067 }
2068 else
cristybb503372010-05-27 20:51:26 +00002069 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002070 {
cristy4c08aed2011-07-01 19:47:50 +00002071 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002072 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002073 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002074 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002075 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002076 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002077 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002078 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2079 if (image->matte != MagickFalse)
2080 {
cristy4c08aed2011-07-01 19:47:50 +00002081 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002082 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2083 }
cristyed231572011-07-14 02:18:59 +00002084 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002085 }
2086 break;
2087 }
2088 default:
2089 {
2090 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002091 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002092 {
cristy4c08aed2011-07-01 19:47:50 +00002093 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002094 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002095 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002096 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002097 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002098 q=PopCharPixel((unsigned char) pixel,q);
2099 if (image->matte != MagickFalse)
2100 {
cristy4c08aed2011-07-01 19:47:50 +00002101 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002102 q=PopCharPixel((unsigned char) pixel,q);
2103 }
cristyed231572011-07-14 02:18:59 +00002104 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002105 }
2106 else
cristybb503372010-05-27 20:51:26 +00002107 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002108 {
cristy4c08aed2011-07-01 19:47:50 +00002109 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002110 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002111 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002112 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002113 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002114 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2115 if (image->matte != MagickFalse)
2116 {
cristy4c08aed2011-07-01 19:47:50 +00002117 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002118 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2119 }
cristyed231572011-07-14 02:18:59 +00002120 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002121 }
2122 break;
2123 }
2124 }
2125 extent=(size_t) (q-pixels);
2126 }
2127 count=WriteBlob(image,extent,pixels);
2128 if (count != (ssize_t) extent)
2129 break;
2130 if (image->previous == (Image *) NULL)
2131 {
cristycee97112010-05-28 00:44:52 +00002132 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2133 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002134 if (status == MagickFalse)
2135 break;
2136 }
2137 }
2138 quantum_info=DestroyQuantumInfo(quantum_info);
2139 break;
2140 }
2141 case 'F':
2142 case 'f':
2143 {
2144 (void) WriteBlobString(image,image->endian != LSBEndian ? "1.0\n" :
2145 "-1.0\n");
2146 image->depth=32;
2147 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
2148 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
2149 if (quantum_info == (QuantumInfo *) NULL)
2150 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2151 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2152 if (status == MagickFalse)
2153 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2154 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002155 for (y=(ssize_t) image->rows-1; y >= 0; y--)
cristy3ed852e2009-09-05 21:47:34 +00002156 {
cristy4c08aed2011-07-01 19:47:50 +00002157 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00002158 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002159
cristy1e178e72011-08-28 19:44:34 +00002160 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002161 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002162 break;
cristy4c08aed2011-07-01 19:47:50 +00002163 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002164 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002165 (void) WriteBlob(image,extent,pixels);
2166 if (image->previous == (Image *) NULL)
2167 {
cristycee97112010-05-28 00:44:52 +00002168 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2169 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002170 if (status == MagickFalse)
2171 break;
2172 }
2173 }
2174 quantum_info=DestroyQuantumInfo(quantum_info);
2175 break;
2176 }
2177 }
2178 if (GetNextImageInList(image) == (Image *) NULL)
2179 break;
2180 image=SyncNextImageInList(image);
2181 status=SetImageProgress(image,SaveImagesTag,scene++,
2182 GetImageListLength(image));
2183 if (status == MagickFalse)
2184 break;
2185 } while (image_info->adjoin != MagickFalse);
2186 (void) CloseBlob(image);
2187 return(MagickTrue);
2188}