blob: 4d21c310241531d6aab8a37a8b037cb5a1060304 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% PPPP N N M M %
7% P P NN N MM MM %
8% PPPP N N N M M M %
9% P N NN M M %
10% P N N M M %
11% %
12% %
13% Read/Write PBMPlus Portable Anymap Image Format %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/attribute.h"
44#include "MagickCore/blob.h"
45#include "MagickCore/blob-private.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/color.h"
48#include "MagickCore/color-private.h"
49#include "MagickCore/colorspace.h"
cristy510d06a2011-07-06 23:43:54 +000050#include "MagickCore/colorspace-private.h"
cristy4c08aed2011-07-01 19:47:50 +000051#include "MagickCore/exception.h"
52#include "MagickCore/exception-private.h"
53#include "MagickCore/image.h"
54#include "MagickCore/image-private.h"
55#include "MagickCore/list.h"
56#include "MagickCore/magick.h"
57#include "MagickCore/memory_.h"
58#include "MagickCore/module.h"
59#include "MagickCore/monitor.h"
60#include "MagickCore/monitor-private.h"
61#include "MagickCore/pixel-accessor.h"
62#include "MagickCore/property.h"
63#include "MagickCore/quantum-private.h"
64#include "MagickCore/static.h"
65#include "MagickCore/statistic.h"
66#include "MagickCore/string_.h"
67#include "MagickCore/string-private.h"
cristy3ed852e2009-09-05 21:47:34 +000068
69/*
70 Forward declarations.
71*/
72static MagickBooleanType
cristy1e178e72011-08-28 19:44:34 +000073 WritePNMImage(const ImageInfo *,Image *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +000074
75/*
76%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77% %
78% %
79% %
80% I s P N M %
81% %
82% %
83% %
84%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85%
86% IsPNM() returns MagickTrue if the image format type, identified by the
87% magick string, is PNM.
88%
89% The format of the IsPNM method is:
90%
91% MagickBooleanType IsPNM(const unsigned char *magick,const size_t extent)
92%
93% A description of each parameter follows:
94%
95% o magick: compare image format pattern against these bytes.
96%
97% o extent: Specifies the extent of the magick string.
98%
99*/
100static MagickBooleanType IsPNM(const unsigned char *magick,const size_t extent)
101{
102 if (extent < 2)
103 return(MagickFalse);
104 if ((*magick == (unsigned char) 'P') &&
105 ((magick[1] == '1') || (magick[1] == '2') || (magick[1] == '3') ||
106 (magick[1] == '4') || (magick[1] == '5') || (magick[1] == '6') ||
107 (magick[1] == '7') || (magick[1] == 'F') || (magick[1] == 'f')))
108 return(MagickTrue);
109 return(MagickFalse);
110}
111
112/*
113%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114% %
115% %
116% %
117% R e a d P N M I m a g e %
118% %
119% %
120% %
121%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122%
123% ReadPNMImage() reads a Portable Anymap image file and returns it.
124% It allocates the memory necessary for the new Image structure and returns
125% a pointer to the new image.
126%
127% The format of the ReadPNMImage method is:
128%
129% Image *ReadPNMImage(const ImageInfo *image_info,ExceptionInfo *exception)
130%
131% A description of each parameter follows:
132%
133% o image_info: the image info.
134%
135% o exception: return any errors or warnings in this structure.
136%
137*/
138
cristybb503372010-05-27 20:51:26 +0000139static inline ssize_t ConstrainPixel(Image *image,const ssize_t offset,
cristyc82a27b2011-10-21 01:07:16 +0000140 const size_t extent,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000141{
cristybb503372010-05-27 20:51:26 +0000142 if ((offset < 0) || (offset > (ssize_t) extent))
cristy3ed852e2009-09-05 21:47:34 +0000143 {
cristyc82a27b2011-10-21 01:07:16 +0000144 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
145 "InvalidPixel","`%s'",image->filename);
cristy3ed852e2009-09-05 21:47:34 +0000146 return(0);
147 }
148 return(offset);
149}
150
cristyd15e6592011-10-15 00:13:06 +0000151static size_t PNMInteger(Image *image,const unsigned int base,
152 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000153{
154 char
155 *comment;
156
157 int
158 c;
159
160 register char
161 *p;
162
163 size_t
cristyaff6d802011-04-26 01:46:31 +0000164 extent,
cristy3ed852e2009-09-05 21:47:34 +0000165 value;
166
167 /*
168 Skip any leading whitespace.
169 */
170 extent=MaxTextExtent;
171 comment=(char *) NULL;
172 p=comment;
173 do
174 {
175 c=ReadBlobByte(image);
176 if (c == EOF)
177 return(0);
178 if (c == (int) '#')
179 {
180 /*
181 Read comment.
182 */
183 if (comment == (char *) NULL)
184 comment=AcquireString((char *) NULL);
185 p=comment+strlen(comment);
186 for ( ; (c != EOF) && (c != (int) '\n'); p++)
187 {
188 if ((size_t) (p-comment+1) >= extent)
189 {
190 extent<<=1;
191 comment=(char *) ResizeQuantumMemory(comment,extent+MaxTextExtent,
192 sizeof(*comment));
193 if (comment == (char *) NULL)
194 break;
195 p=comment+strlen(comment);
196 }
197 c=ReadBlobByte(image);
cristyc3dee302012-01-11 21:58:50 +0000198 if (c != (int) '\n')
199 {
200 *p=(char) c;
201 *(p+1)='\0';
202 }
cristy3ed852e2009-09-05 21:47:34 +0000203 }
204 if (comment == (char *) NULL)
205 return(0);
206 continue;
207 }
208 } while (isdigit(c) == MagickFalse);
209 if (comment != (char *) NULL)
210 {
cristyd15e6592011-10-15 00:13:06 +0000211 (void) SetImageProperty(image,"comment",comment,exception);
cristy3ed852e2009-09-05 21:47:34 +0000212 comment=DestroyString(comment);
213 }
214 if (base == 2)
cristybb503372010-05-27 20:51:26 +0000215 return((size_t) (c-(int) '0'));
cristy3ed852e2009-09-05 21:47:34 +0000216 /*
217 Evaluate number.
218 */
219 value=0;
220 do
221 {
222 value*=10;
223 value+=c-(int) '0';
224 c=ReadBlobByte(image);
225 if (c == EOF)
226 return(value);
227 } while (isdigit(c) != MagickFalse);
228 return(value);
229}
230
231static Image *ReadPNMImage(const ImageInfo *image_info,ExceptionInfo *exception)
232{
233 char
234 format;
235
236 double
237 quantum_scale;
238
239 Image
240 *image;
241
cristy3ed852e2009-09-05 21:47:34 +0000242 MagickBooleanType
243 status;
244
245 Quantum
246 *scale;
247
248 QuantumInfo
249 *quantum_info;
250
251 QuantumType
252 quantum_type;
253
cristybb503372010-05-27 20:51:26 +0000254 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000255 i;
256
257 size_t
cristyaff6d802011-04-26 01:46:31 +0000258 depth,
cristy3ed852e2009-09-05 21:47:34 +0000259 extent,
cristyaff6d802011-04-26 01:46:31 +0000260 max_value,
cristy3ed852e2009-09-05 21:47:34 +0000261 packet_size;
262
263 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000264 count,
265 row,
266 y;
cristy3ed852e2009-09-05 21:47:34 +0000267
cristy3ed852e2009-09-05 21:47:34 +0000268 /*
269 Open image file.
270 */
271 assert(image_info != (const ImageInfo *) NULL);
272 assert(image_info->signature == MagickSignature);
273 if (image_info->debug != MagickFalse)
274 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
275 image_info->filename);
276 assert(exception != (ExceptionInfo *) NULL);
277 assert(exception->signature == MagickSignature);
cristy9950d572011-10-01 18:22:35 +0000278 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000279 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
280 if (status == MagickFalse)
281 {
282 image=DestroyImageList(image);
283 return((Image *) NULL);
284 }
285 /*
286 Read PNM image.
287 */
288 count=ReadBlob(image,1,(unsigned char *) &format);
289 do
290 {
291 /*
292 Initialize image structure.
293 */
294 if ((count != 1) || (format != 'P'))
295 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
296 max_value=1;
297 quantum_type=RGBQuantum;
298 quantum_scale=1.0;
299 format=(char) ReadBlobByte(image);
300 if (format != '7')
301 {
302 /*
303 PBM, PGM, PPM, and PNM.
304 */
cristyd15e6592011-10-15 00:13:06 +0000305 image->columns=PNMInteger(image,10,exception);
306 image->rows=PNMInteger(image,10,exception);
cristy3ed852e2009-09-05 21:47:34 +0000307 if ((format == 'f') || (format == 'F'))
308 {
309 char
310 scale[MaxTextExtent];
311
312 (void) ReadBlobString(image,scale);
cristydbdd0e32011-11-04 23:29:40 +0000313 quantum_scale=StringToDouble(scale,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000314 }
315 else
316 {
317 if ((format == '1') || (format == '4'))
318 max_value=1; /* bitmap */
319 else
cristyd15e6592011-10-15 00:13:06 +0000320 max_value=PNMInteger(image,10,exception);
cristy3ed852e2009-09-05 21:47:34 +0000321 }
322 }
323 else
324 {
325 char
326 keyword[MaxTextExtent],
327 value[MaxTextExtent];
328
329 int
330 c;
331
332 register char
333 *p;
334
335 /*
336 PAM.
337 */
338 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
339 {
340 while (isspace((int) ((unsigned char) c)) != 0)
341 c=ReadBlobByte(image);
342 p=keyword;
343 do
344 {
345 if ((size_t) (p-keyword) < (MaxTextExtent-1))
346 *p++=c;
347 c=ReadBlobByte(image);
348 } while (isalnum(c));
349 *p='\0';
350 if (LocaleCompare(keyword,"endhdr") == 0)
351 break;
352 while (isspace((int) ((unsigned char) c)) != 0)
353 c=ReadBlobByte(image);
354 p=value;
355 while (isalnum(c) || (c == '_'))
356 {
357 if ((size_t) (p-value) < (MaxTextExtent-1))
358 *p++=c;
359 c=ReadBlobByte(image);
360 }
361 *p='\0';
362 /*
363 Assign a value to the specified keyword.
364 */
365 if (LocaleCompare(keyword,"depth") == 0)
cristye27293e2009-12-18 02:53:20 +0000366 packet_size=StringToUnsignedLong(value);
cristyda16f162011-02-19 23:52:17 +0000367 (void) packet_size;
cristy3ed852e2009-09-05 21:47:34 +0000368 if (LocaleCompare(keyword,"height") == 0)
cristye27293e2009-12-18 02:53:20 +0000369 image->rows=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000370 if (LocaleCompare(keyword,"maxval") == 0)
cristye27293e2009-12-18 02:53:20 +0000371 max_value=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000372 if (LocaleCompare(keyword,"TUPLTYPE") == 0)
373 {
374 if (LocaleCompare(value,"BLACKANDWHITE") == 0)
375 quantum_type=GrayQuantum;
376 if (LocaleCompare(value,"BLACKANDWHITE_ALPHA") == 0)
377 {
378 quantum_type=GrayAlphaQuantum;
379 image->matte=MagickTrue;
380 }
381 if (LocaleCompare(value,"GRAYSCALE") == 0)
cristyb3a73b52011-07-26 01:34:43 +0000382 {
383 image->colorspace=GRAYColorspace;
384 quantum_type=GrayQuantum;
385 }
cristy3ed852e2009-09-05 21:47:34 +0000386 if (LocaleCompare(value,"GRAYSCALE_ALPHA") == 0)
387 {
cristyb3a73b52011-07-26 01:34:43 +0000388 image->colorspace=GRAYColorspace;
cristy3ed852e2009-09-05 21:47:34 +0000389 image->matte=MagickTrue;
cristyb3a73b52011-07-26 01:34:43 +0000390 quantum_type=GrayAlphaQuantum;
cristy3ed852e2009-09-05 21:47:34 +0000391 }
392 if (LocaleCompare(value,"RGB_ALPHA") == 0)
393 {
394 quantum_type=RGBAQuantum;
395 image->matte=MagickTrue;
396 }
397 if (LocaleCompare(value,"CMYK") == 0)
398 {
399 quantum_type=CMYKQuantum;
400 image->colorspace=CMYKColorspace;
401 }
402 if (LocaleCompare(value,"CMYK_ALPHA") == 0)
403 {
404 quantum_type=CMYKAQuantum;
405 image->colorspace=CMYKColorspace;
406 image->matte=MagickTrue;
407 }
408 }
409 if (LocaleCompare(keyword,"width") == 0)
cristye27293e2009-12-18 02:53:20 +0000410 image->columns=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000411 }
412 }
413 if ((image->columns == 0) || (image->rows == 0))
414 ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
415 if (max_value >= 65536)
416 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
cristy3f1ee592011-06-15 23:03:58 +0000417 for (depth=1; GetQuantumRange(depth) < max_value; depth++) ;
cristy3ed852e2009-09-05 21:47:34 +0000418 image->depth=depth;
419 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
420 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
421 break;
422 /*
423 Convert PNM pixels to runextent-encoded MIFF packets.
424 */
425 status=MagickTrue;
426 row=0;
427 switch (format)
428 {
429 case '1':
430 {
431 /*
432 Convert PBM image to pixel packets.
433 */
cristyb3a73b52011-07-26 01:34:43 +0000434 image->colorspace=GRAYColorspace;
cristybb503372010-05-27 20:51:26 +0000435 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000436 {
cristybb503372010-05-27 20:51:26 +0000437 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000438 x;
439
cristy4c08aed2011-07-01 19:47:50 +0000440 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000441 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000442
443 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000444 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000445 break;
cristybb503372010-05-27 20:51:26 +0000446 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000447 {
cristy08528502012-01-01 00:52:17 +0000448 SetPixelGray(image,PNMInteger(image,2,exception) == 0 ?
cristyd15e6592011-10-15 00:13:06 +0000449 QuantumRange : 0,q);
cristyed231572011-07-14 02:18:59 +0000450 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000451 }
452 if (SyncAuthenticPixels(image,exception) == MagickFalse)
453 break;
454 if (image->previous == (Image *) NULL)
455 {
cristycee97112010-05-28 00:44:52 +0000456 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
457 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000458 if (status == MagickFalse)
459 break;
460 }
461 }
462 image->type=BilevelType;
463 break;
464 }
465 case '2':
466 {
cristybb503372010-05-27 20:51:26 +0000467 size_t
cristy3ed852e2009-09-05 21:47:34 +0000468 intensity;
469
470 /*
471 Convert PGM image to pixel packets.
472 */
cristyb3a73b52011-07-26 01:34:43 +0000473 image->colorspace=GRAYColorspace;
cristy3ed852e2009-09-05 21:47:34 +0000474 scale=(Quantum *) NULL;
475 if (max_value != (1U*QuantumRange))
476 {
477 /*
478 Compute pixel scaling table.
479 */
480 scale=(Quantum *) AcquireQuantumMemory((size_t) max_value+1UL,
481 sizeof(*scale));
482 if (scale == (Quantum *) NULL)
483 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000484 for (i=0; i <= (ssize_t) max_value; i++)
cristy3ed852e2009-09-05 21:47:34 +0000485 scale[i]=(Quantum) (((double) QuantumRange*i)/max_value+0.5);
486 }
cristybb503372010-05-27 20:51:26 +0000487 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000488 {
cristybb503372010-05-27 20:51:26 +0000489 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000490 x;
491
cristy4c08aed2011-07-01 19:47:50 +0000492 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000493 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000494
495 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyb3a73b52011-07-26 01:34:43 +0000496 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000497 break;
cristybb503372010-05-27 20:51:26 +0000498 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000499 {
cristyd15e6592011-10-15 00:13:06 +0000500 intensity=PNMInteger(image,10,exception);
cristy08528502012-01-01 00:52:17 +0000501 SetPixelGray(image,intensity,q);
cristyac23fd22010-05-11 14:48:58 +0000502 if (scale != (Quantum *) NULL)
cristy08528502012-01-01 00:52:17 +0000503 SetPixelGray(image,scale[ConstrainPixel(image,(ssize_t) intensity,
cristyc82a27b2011-10-21 01:07:16 +0000504 max_value,exception)],q);
cristyed231572011-07-14 02:18:59 +0000505 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000506 }
507 if (SyncAuthenticPixels(image,exception) == MagickFalse)
508 break;
509 if (image->previous == (Image *) NULL)
510 {
cristycee97112010-05-28 00:44:52 +0000511 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
512 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000513 if (status == MagickFalse)
514 break;
515 }
516 }
517 image->type=GrayscaleType;
518 if (scale != (Quantum *) NULL)
519 scale=(Quantum *) RelinquishMagickMemory(scale);
520 break;
521 }
522 case '3':
523 {
cristy4c08aed2011-07-01 19:47:50 +0000524 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +0000525 pixel;
526
527 /*
528 Convert PNM image to pixel packets.
529 */
530 scale=(Quantum *) NULL;
531 if (max_value != (1U*QuantumRange))
532 {
533 /*
534 Compute pixel scaling table.
535 */
536 scale=(Quantum *) AcquireQuantumMemory((size_t) max_value+1UL,
537 sizeof(*scale));
538 if (scale == (Quantum *) NULL)
539 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000540 for (i=0; i <= (ssize_t) max_value; i++)
cristy3ed852e2009-09-05 21:47:34 +0000541 scale[i]=(Quantum) (((double) QuantumRange*i)/max_value+0.5);
542 }
cristybb503372010-05-27 20:51:26 +0000543 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000544 {
cristybb503372010-05-27 20:51:26 +0000545 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000546 x;
547
cristy4c08aed2011-07-01 19:47:50 +0000548 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000549 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000550
551 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000552 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000553 break;
cristybb503372010-05-27 20:51:26 +0000554 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000555 {
cristyd15e6592011-10-15 00:13:06 +0000556 pixel.red=(MagickRealType) PNMInteger(image,10,exception);
557 pixel.green=(MagickRealType) PNMInteger(image,10,exception);
558 pixel.blue=(MagickRealType) PNMInteger(image,10,exception);
cristy3ed852e2009-09-05 21:47:34 +0000559 if (scale != (Quantum *) NULL)
560 {
cristybb503372010-05-27 20:51:26 +0000561 pixel.red=(MagickRealType) scale[ConstrainPixel(image,(ssize_t)
cristyc82a27b2011-10-21 01:07:16 +0000562 pixel.red,max_value,exception)];
cristy34575212010-11-06 12:39:23 +0000563 pixel.green=(MagickRealType) scale[ConstrainPixel(image,
cristyc82a27b2011-10-21 01:07:16 +0000564 (ssize_t) pixel.green,max_value,exception)];
cristybb503372010-05-27 20:51:26 +0000565 pixel.blue=(MagickRealType) scale[ConstrainPixel(image,(ssize_t)
cristyc82a27b2011-10-21 01:07:16 +0000566 pixel.blue,max_value,exception)];
cristy3ed852e2009-09-05 21:47:34 +0000567 }
cristy94b11832011-09-08 19:46:03 +0000568 SetPixelRed(image,ClampToQuantum(pixel.red),q);
569 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
570 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
cristyed231572011-07-14 02:18:59 +0000571 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000572 }
573 if (SyncAuthenticPixels(image,exception) == MagickFalse)
574 break;
575 if (image->previous == (Image *) NULL)
576 {
cristycee97112010-05-28 00:44:52 +0000577 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
578 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000579 if (status == MagickFalse)
580 break;
581 }
582 }
583 if (scale != (Quantum *) NULL)
584 scale=(Quantum *) RelinquishMagickMemory(scale);
585 break;
586 }
587 case '4':
588 {
589 /*
590 Convert PBM raw image to pixel packets.
591 */
cristyb3a73b52011-07-26 01:34:43 +0000592 image->colorspace=GRAYColorspace;
cristy3ed852e2009-09-05 21:47:34 +0000593 quantum_type=GrayQuantum;
594 if (image->storage_class == PseudoClass)
595 quantum_type=IndexQuantum;
596 quantum_info=AcquireQuantumInfo(image_info,image);
597 if (quantum_info == (QuantumInfo *) NULL)
598 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
599 SetQuantumMinIsWhite(quantum_info,MagickTrue);
600 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +0000601 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000602 {
cristy3ed852e2009-09-05 21:47:34 +0000603 MagickBooleanType
604 sync;
605
cristy4c08aed2011-07-01 19:47:50 +0000606 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000607 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000608
609 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000610 count,
611 offset;
cristy3ed852e2009-09-05 21:47:34 +0000612
613 size_t
614 length;
615
616 unsigned char
617 *pixels;
618
619 if (status == MagickFalse)
620 continue;
621 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000622 {
623 count=ReadBlob(image,extent,pixels);
624 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
625 (image->previous == (Image *) NULL))
626 {
627 MagickBooleanType
628 proceed;
629
cristycee97112010-05-28 00:44:52 +0000630 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
631 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000632 if (proceed == MagickFalse)
633 status=MagickFalse;
634 }
635 offset=row++;
636 }
637 if (count != (ssize_t) extent)
638 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000639 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000640 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000641 {
642 status=MagickFalse;
643 continue;
644 }
cristyaa740112010-03-30 17:58:44 +0000645 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
646 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +0000647 if (length != extent)
648 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000649 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000650 if (sync == MagickFalse)
651 status=MagickFalse;
652 }
cristy3ed852e2009-09-05 21:47:34 +0000653 quantum_info=DestroyQuantumInfo(quantum_info);
654 if (status == MagickFalse)
655 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
656 SetQuantumImageType(image,quantum_type);
657 break;
658 }
659 case '5':
660 {
661 QuantumAny
662 range;
663
664 /*
665 Convert PGM raw image to pixel packets.
666 */
cristyb3a73b52011-07-26 01:34:43 +0000667 image->colorspace=GRAYColorspace;
cristy3ed852e2009-09-05 21:47:34 +0000668 range=GetQuantumRange(image->depth);
669 quantum_type=GrayQuantum;
670 extent=(image->depth <= 8 ? 1 : 2)*image->columns;
671 quantum_info=AcquireQuantumInfo(image_info,image);
672 if (quantum_info == (QuantumInfo *) NULL)
673 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000674 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000675 {
cristy3ed852e2009-09-05 21:47:34 +0000676 MagickBooleanType
677 sync;
678
679 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000680 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000681
cristybb503372010-05-27 20:51:26 +0000682 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000683 x;
684
cristy4c08aed2011-07-01 19:47:50 +0000685 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000686 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000687
688 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000689 count,
690 offset;
cristy3ed852e2009-09-05 21:47:34 +0000691
692 unsigned char
693 *pixels;
694
695 if (status == MagickFalse)
696 continue;
697 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000698 {
699 count=ReadBlob(image,extent,pixels);
700 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
701 (image->previous == (Image *) NULL))
702 {
703 MagickBooleanType
704 proceed;
705
cristy34575212010-11-06 12:39:23 +0000706 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
707 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000708 if (proceed == MagickFalse)
709 status=MagickFalse;
710 }
711 offset=row++;
712 }
713 if (count != (ssize_t) extent)
714 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000715 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000716 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000717 {
718 status=MagickFalse;
719 continue;
720 }
721 p=pixels;
722 if ((image->depth == 8) || (image->depth == 16))
cristyaa740112010-03-30 17:58:44 +0000723 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3ed852e2009-09-05 21:47:34 +0000724 quantum_type,pixels,exception);
725 else
726 if (image->depth <= 8)
727 {
728 unsigned char
729 pixel;
730
cristybb503372010-05-27 20:51:26 +0000731 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000732 {
733 p=PushCharPixel(p,&pixel);
cristy08528502012-01-01 00:52:17 +0000734 SetPixelGray(image,ScaleAnyToQuantum(pixel,range),q);
cristyed231572011-07-14 02:18:59 +0000735 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000736 }
737 }
738 else
739 {
740 unsigned short
741 pixel;
742
cristybb503372010-05-27 20:51:26 +0000743 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000744 {
745 p=PushShortPixel(MSBEndian,p,&pixel);
cristy08528502012-01-01 00:52:17 +0000746 SetPixelGray(image,ScaleAnyToQuantum(pixel,range),q);
cristyed231572011-07-14 02:18:59 +0000747 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000748 }
749 }
cristyaa740112010-03-30 17:58:44 +0000750 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000751 if (sync == MagickFalse)
752 status=MagickFalse;
753 }
cristy3ed852e2009-09-05 21:47:34 +0000754 quantum_info=DestroyQuantumInfo(quantum_info);
755 if (status == MagickFalse)
756 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
757 SetQuantumImageType(image,quantum_type);
758 break;
759 }
760 case '6':
761 {
762 ImageType
763 type;
764
765 QuantumAny
766 range;
767
768 /*
769 Convert PNM raster image to pixel packets.
770 */
771 type=BilevelType;
772 quantum_type=RGBQuantum;
773 extent=3*(image->depth <= 8 ? 1 : 2)*image->columns;
774 range=GetQuantumRange(image->depth);
775 quantum_info=AcquireQuantumInfo(image_info,image);
776 if (quantum_info == (QuantumInfo *) NULL)
777 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000778 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000779 {
cristy3ed852e2009-09-05 21:47:34 +0000780 MagickBooleanType
781 sync;
782
783 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000784 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000785
cristybb503372010-05-27 20:51:26 +0000786 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000787 x;
788
cristy4c08aed2011-07-01 19:47:50 +0000789 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000790 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000791
792 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000793 count,
794 offset;
cristy3ed852e2009-09-05 21:47:34 +0000795
cristy3ed852e2009-09-05 21:47:34 +0000796 unsigned char
797 *pixels;
798
799 if (status == MagickFalse)
800 continue;
801 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000802 {
803 count=ReadBlob(image,extent,pixels);
804 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
805 (image->previous == (Image *) NULL))
806 {
807 MagickBooleanType
808 proceed;
809
cristy34575212010-11-06 12:39:23 +0000810 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
811 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000812 if (proceed == MagickFalse)
813 status=MagickFalse;
814 }
815 offset=row++;
816 }
817 if (count != (ssize_t) extent)
818 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000819 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000820 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000821 {
822 status=MagickFalse;
823 continue;
824 }
825 p=pixels;
cristye90d7402010-03-14 18:21:29 +0000826 if (image->depth == 8)
cristybb503372010-05-27 20:51:26 +0000827 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000828 {
cristy4c08aed2011-07-01 19:47:50 +0000829 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
830 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
831 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
832 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000833 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000834 }
835 else
cristye90d7402010-03-14 18:21:29 +0000836 if (image->depth == 16)
cristy3ed852e2009-09-05 21:47:34 +0000837 {
838 unsigned short
839 pixel;
840
cristybb503372010-05-27 20:51:26 +0000841 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000842 {
843 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000844 SetPixelRed(image,ScaleShortToQuantum(pixel),q);
cristy3ed852e2009-09-05 21:47:34 +0000845 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000846 SetPixelGreen(image,ScaleShortToQuantum(pixel),q);
cristy3ed852e2009-09-05 21:47:34 +0000847 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000848 SetPixelBlue(image,ScaleShortToQuantum(pixel),q);
849 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000850 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000851 }
852 }
cristye90d7402010-03-14 18:21:29 +0000853 else
854 if (image->depth <= 8)
855 {
856 unsigned char
857 pixel;
858
cristybb503372010-05-27 20:51:26 +0000859 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000860 {
861 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000862 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000863 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000864 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000865 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000866 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
867 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000868 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000869 }
870 }
871 else
872 {
873 unsigned short
874 pixel;
875
cristybb503372010-05-27 20:51:26 +0000876 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000877 {
878 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000879 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000880 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000881 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristye90d7402010-03-14 18:21:29 +0000882 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +0000883 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
884 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000885 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000886 }
887 }
cristy3ed852e2009-09-05 21:47:34 +0000888 if ((type == BilevelType) || (type == GrayscaleType))
cristy3ed852e2009-09-05 21:47:34 +0000889 {
cristyaa740112010-03-30 17:58:44 +0000890 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristybb503372010-05-27 20:51:26 +0000891 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000892 {
893 if ((type == BilevelType) &&
cristy4c08aed2011-07-01 19:47:50 +0000894 (IsPixelMonochrome(image,q) == MagickFalse))
895 type=IsPixelGray(image,q) == MagickFalse ? UndefinedType :
cristye90d7402010-03-14 18:21:29 +0000896 GrayscaleType;
cristy4c08aed2011-07-01 19:47:50 +0000897 if ((type == GrayscaleType) &&
898 (IsPixelGray(image,q) == MagickFalse))
cristy5f1c1ff2010-12-23 21:38:06 +0000899 type=UndefinedType;
cristye90d7402010-03-14 18:21:29 +0000900 if ((type != BilevelType) && (type != GrayscaleType))
901 break;
cristyed231572011-07-14 02:18:59 +0000902 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000903 }
cristy3ed852e2009-09-05 21:47:34 +0000904 }
cristyaa740112010-03-30 17:58:44 +0000905 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000906 if (sync == MagickFalse)
907 status=MagickFalse;
908 }
cristy3ed852e2009-09-05 21:47:34 +0000909 quantum_info=DestroyQuantumInfo(quantum_info);
910 if (status == MagickFalse)
911 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
cristy5f1c1ff2010-12-23 21:38:06 +0000912 if (type != UndefinedType)
cristy3ed852e2009-09-05 21:47:34 +0000913 image->type=type;
914 break;
915 }
916 case '7':
917 {
cristy3ed852e2009-09-05 21:47:34 +0000918 QuantumAny
919 range;
920
cristybb503372010-05-27 20:51:26 +0000921 size_t
cristy3ed852e2009-09-05 21:47:34 +0000922 channels;
923
924 /*
925 Convert PAM raster image to pixel packets.
926 */
927 range=GetQuantumRange(image->depth);
928 switch (quantum_type)
929 {
930 case GrayQuantum:
931 case GrayAlphaQuantum:
932 {
933 channels=1;
934 break;
935 }
936 case CMYKQuantum:
937 case CMYKAQuantum:
938 {
939 channels=4;
940 break;
941 }
942 default:
943 {
944 channels=3;
945 break;
946 }
947 }
948 if (image->matte != MagickFalse)
949 channels++;
950 extent=channels*(image->depth <= 8 ? 1 : 2)*image->columns;
951 quantum_info=AcquireQuantumInfo(image_info,image);
952 if (quantum_info == (QuantumInfo *) NULL)
953 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000954 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000955 {
cristy3ed852e2009-09-05 21:47:34 +0000956 MagickBooleanType
957 sync;
958
959 register const unsigned char
cristy3f2302b2010-03-11 03:16:37 +0000960 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000961
cristybb503372010-05-27 20:51:26 +0000962 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000963 x;
964
cristy4c08aed2011-07-01 19:47:50 +0000965 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000966 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000967
968 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000969 count,
970 offset;
cristy3ed852e2009-09-05 21:47:34 +0000971
972 unsigned char
973 *pixels;
974
975 if (status == MagickFalse)
976 continue;
977 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000978 {
979 count=ReadBlob(image,extent,pixels);
980 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
981 (image->previous == (Image *) NULL))
982 {
983 MagickBooleanType
984 proceed;
985
cristy34575212010-11-06 12:39:23 +0000986 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
987 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000988 if (proceed == MagickFalse)
989 status=MagickFalse;
990 }
991 offset=row++;
992 }
993 if (count != (ssize_t) extent)
994 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000995 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000996 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000997 {
998 status=MagickFalse;
999 continue;
1000 }
cristy3ed852e2009-09-05 21:47:34 +00001001 p=pixels;
1002 if ((image->depth == 8) || (image->depth == 16))
cristyaa740112010-03-30 17:58:44 +00001003 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy3ed852e2009-09-05 21:47:34 +00001004 quantum_type,pixels,exception);
1005 else
1006 switch (quantum_type)
1007 {
1008 case GrayQuantum:
1009 case GrayAlphaQuantum:
1010 {
1011 if (image->depth <= 8)
1012 {
1013 unsigned char
1014 pixel;
1015
cristybb503372010-05-27 20:51:26 +00001016 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001017 {
1018 p=PushCharPixel(p,&pixel);
cristy08528502012-01-01 00:52:17 +00001019 SetPixelGray(image,ScaleAnyToQuantum(pixel,range),q);
cristy4c08aed2011-07-01 19:47:50 +00001020 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001021 if (image->matte != MagickFalse)
1022 {
1023 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001024 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001025 }
cristyed231572011-07-14 02:18:59 +00001026 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001027 }
1028 }
1029 else
1030 {
1031 unsigned short
1032 pixel;
1033
cristybb503372010-05-27 20:51:26 +00001034 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001035 {
1036 p=PushShortPixel(MSBEndian,p,&pixel);
cristy08528502012-01-01 00:52:17 +00001037 SetPixelGray(image,ScaleAnyToQuantum(pixel,range),q);
cristy4c08aed2011-07-01 19:47:50 +00001038 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001039 if (image->matte != MagickFalse)
1040 {
1041 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001042 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001043 }
cristyed231572011-07-14 02:18:59 +00001044 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001045 }
1046 }
1047 break;
1048 }
1049 case CMYKQuantum:
1050 case CMYKAQuantum:
1051 {
1052 if (image->depth <= 8)
1053 {
1054 unsigned char
1055 pixel;
1056
cristybb503372010-05-27 20:51:26 +00001057 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001058 {
1059 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001060 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001061 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001062 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001063 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001064 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001065 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001066 SetPixelBlack(image,ScaleAnyToQuantum(pixel,range),q);
1067 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001068 if (image->matte != MagickFalse)
1069 {
1070 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001071 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001072 }
cristyed231572011-07-14 02:18:59 +00001073 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001074 }
1075 }
1076 else
1077 {
1078 unsigned short
1079 pixel;
1080
cristybb503372010-05-27 20:51:26 +00001081 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001082 {
1083 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001084 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001085 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001086 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001087 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001088 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001089 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001090 SetPixelBlack(image,ScaleAnyToQuantum(pixel,range),q);
1091 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001092 if (image->matte != MagickFalse)
1093 {
1094 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001095 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001096 }
cristyed231572011-07-14 02:18:59 +00001097 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001098 }
1099 }
1100 break;
1101 }
1102 default:
1103 {
1104 if (image->depth <= 8)
1105 {
1106 unsigned char
1107 pixel;
1108
cristybb503372010-05-27 20:51:26 +00001109 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001110 {
1111 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001112 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001113 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001114 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001115 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001116 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
1117 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001118 if (image->matte != MagickFalse)
1119 {
1120 p=PushCharPixel(p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001121 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001122 }
cristyed231572011-07-14 02:18:59 +00001123 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001124 }
1125 }
1126 else
1127 {
1128 unsigned short
1129 pixel;
1130
cristybb503372010-05-27 20:51:26 +00001131 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001132 {
1133 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001134 SetPixelRed(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001135 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001136 SetPixelGreen(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001137 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001138 SetPixelBlue(image,ScaleAnyToQuantum(pixel,range),q);
1139 SetPixelAlpha(image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +00001140 if (image->matte != MagickFalse)
1141 {
1142 p=PushShortPixel(MSBEndian,p,&pixel);
cristy4c08aed2011-07-01 19:47:50 +00001143 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,range),q);
cristy3ed852e2009-09-05 21:47:34 +00001144 }
cristyed231572011-07-14 02:18:59 +00001145 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001146 }
1147 }
1148 break;
1149 }
1150 }
cristyaa740112010-03-30 17:58:44 +00001151 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001152 if (sync == MagickFalse)
1153 status=MagickFalse;
1154 }
cristy3ed852e2009-09-05 21:47:34 +00001155 quantum_info=DestroyQuantumInfo(quantum_info);
1156 if (status == MagickFalse)
1157 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1158 SetQuantumImageType(image,quantum_type);
1159 break;
1160 }
1161 case 'F':
1162 case 'f':
1163 {
1164 /*
1165 Convert PFM raster image to pixel packets.
1166 */
cristyaf6eb932012-01-01 01:22:59 +00001167 if (format == 'f')
1168 image->colorspace=GRAYColorspace;
cristy3ed852e2009-09-05 21:47:34 +00001169 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
1170 image->endian=quantum_scale < 0.0 ? LSBEndian : MSBEndian;
1171 image->depth=32;
1172 quantum_info=AcquireQuantumInfo(image_info,image);
1173 if (quantum_info == (QuantumInfo *) NULL)
1174 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1175 status=SetQuantumDepth(image,quantum_info,32);
1176 if (status == MagickFalse)
1177 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1178 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1179 if (status == MagickFalse)
1180 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1181 SetQuantumScale(quantum_info,(MagickRealType) QuantumRange*
1182 fabs(quantum_scale));
1183 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +00001184 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001185 {
cristy3ed852e2009-09-05 21:47:34 +00001186 MagickBooleanType
1187 sync;
1188
cristy4c08aed2011-07-01 19:47:50 +00001189 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00001190 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001191
1192 ssize_t
cristyaff6d802011-04-26 01:46:31 +00001193 count,
1194 offset;
cristy3ed852e2009-09-05 21:47:34 +00001195
1196 size_t
1197 length;
1198
1199 unsigned char
1200 *pixels;
1201
1202 if (status == MagickFalse)
1203 continue;
1204 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001205 {
1206 count=ReadBlob(image,extent,pixels);
1207 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1208 (image->previous == (Image *) NULL))
1209 {
1210 MagickBooleanType
1211 proceed;
1212
cristy34575212010-11-06 12:39:23 +00001213 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1214 row,image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001215 if (proceed == MagickFalse)
1216 status=MagickFalse;
1217 }
1218 offset=row++;
1219 }
1220 if ((size_t) count != extent)
1221 status=MagickFalse;
cristybb503372010-05-27 20:51:26 +00001222 q=QueueAuthenticPixels(image,0,(ssize_t) (image->rows-offset-1),
cristyaa740112010-03-30 17:58:44 +00001223 image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00001224 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001225 {
1226 status=MagickFalse;
1227 continue;
1228 }
cristyaa740112010-03-30 17:58:44 +00001229 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1230 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001231 if (length != extent)
1232 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +00001233 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001234 if (sync == MagickFalse)
1235 status=MagickFalse;
1236 }
cristy3ed852e2009-09-05 21:47:34 +00001237 quantum_info=DestroyQuantumInfo(quantum_info);
1238 if (status == MagickFalse)
1239 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1240 SetQuantumImageType(image,quantum_type);
1241 break;
1242 }
1243 default:
1244 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1245 }
1246 if (EOFBlob(image) != MagickFalse)
1247 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
1248 "UnexpectedEndOfFile","`%s'",image->filename);
1249 /*
1250 Proceed to next image.
1251 */
1252 if (image_info->number_scenes != 0)
1253 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1254 break;
1255 if ((format == '1') || (format == '2') || (format == '3'))
1256 do
1257 {
1258 /*
1259 Skip to end of line.
1260 */
1261 count=ReadBlob(image,1,(unsigned char *) &format);
1262 if (count == 0)
1263 break;
1264 if ((count != 0) && (format == 'P'))
1265 break;
1266 } while (format != '\n');
1267 count=ReadBlob(image,1,(unsigned char *) &format);
1268 if ((count == 1) && (format == 'P'))
1269 {
1270 /*
1271 Allocate next image structure.
1272 */
cristy9950d572011-10-01 18:22:35 +00001273 AcquireNextImage(image_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001274 if (GetNextImageInList(image) == (Image *) NULL)
1275 {
1276 image=DestroyImageList(image);
1277 return((Image *) NULL);
1278 }
1279 image=SyncNextImageInList(image);
1280 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1281 GetBlobSize(image));
1282 if (status == MagickFalse)
1283 break;
1284 }
1285 } while ((count == 1) && (format == 'P'));
1286 (void) CloseBlob(image);
1287 return(GetFirstImageInList(image));
1288}
1289
1290/*
1291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1292% %
1293% %
1294% %
1295% R e g i s t e r P N M I m a g e %
1296% %
1297% %
1298% %
1299%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1300%
1301% RegisterPNMImage() adds properties for the PNM image format to
1302% the list of supported formats. The properties include the image format
1303% tag, a method to read and/or write the format, whether the format
1304% supports the saving of more than one frame to the same file or blob,
1305% whether the format supports native in-memory I/O, and a brief
1306% description of the format.
1307%
1308% The format of the RegisterPNMImage method is:
1309%
cristybb503372010-05-27 20:51:26 +00001310% size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001311%
1312*/
cristybb503372010-05-27 20:51:26 +00001313ModuleExport size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001314{
1315 MagickInfo
1316 *entry;
1317
1318 entry=SetMagickInfo("PAM");
1319 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1320 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1321 entry->description=ConstantString("Common 2-dimensional bitmap format");
1322 entry->module=ConstantString("PNM");
1323 (void) RegisterMagickInfo(entry);
1324 entry=SetMagickInfo("PBM");
1325 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1326 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1327 entry->description=ConstantString("Portable bitmap format (black and white)");
1328 entry->module=ConstantString("PNM");
1329 (void) RegisterMagickInfo(entry);
1330 entry=SetMagickInfo("PFM");
1331 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1332 entry->encoder=(EncodeImageHandler *) WritePNMImage;
cristye96405a2010-05-19 02:24:31 +00001333 entry->endian_support=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00001334 entry->description=ConstantString("Portable float format");
1335 entry->module=ConstantString("PFM");
1336 (void) RegisterMagickInfo(entry);
1337 entry=SetMagickInfo("PGM");
1338 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1339 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1340 entry->description=ConstantString("Portable graymap format (gray scale)");
1341 entry->module=ConstantString("PNM");
1342 (void) RegisterMagickInfo(entry);
1343 entry=SetMagickInfo("PNM");
1344 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1345 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1346 entry->magick=(IsImageFormatHandler *) IsPNM;
1347 entry->description=ConstantString("Portable anymap");
1348 entry->module=ConstantString("PNM");
1349 (void) RegisterMagickInfo(entry);
1350 entry=SetMagickInfo("PPM");
1351 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1352 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1353 entry->description=ConstantString("Portable pixmap format (color)");
1354 entry->module=ConstantString("PNM");
1355 (void) RegisterMagickInfo(entry);
1356 return(MagickImageCoderSignature);
1357}
1358
1359/*
1360%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1361% %
1362% %
1363% %
1364% U n r e g i s t e r P N M I m a g e %
1365% %
1366% %
1367% %
1368%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1369%
1370% UnregisterPNMImage() removes format registrations made by the
1371% PNM module from the list of supported formats.
1372%
1373% The format of the UnregisterPNMImage method is:
1374%
1375% UnregisterPNMImage(void)
1376%
1377*/
1378ModuleExport void UnregisterPNMImage(void)
1379{
1380 (void) UnregisterMagickInfo("PAM");
1381 (void) UnregisterMagickInfo("PBM");
1382 (void) UnregisterMagickInfo("PGM");
1383 (void) UnregisterMagickInfo("PNM");
1384 (void) UnregisterMagickInfo("PPM");
1385}
1386
1387/*
1388%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1389% %
1390% %
1391% %
1392% W r i t e P N M I m a g e %
1393% %
1394% %
1395% %
1396%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1397%
cristy661b5ad2010-01-13 00:54:42 +00001398% WritePNMImage() writes an image to a file in the PNM rasterfile format.
cristy3ed852e2009-09-05 21:47:34 +00001399%
1400% The format of the WritePNMImage method is:
1401%
cristy1e178e72011-08-28 19:44:34 +00001402% MagickBooleanType WritePNMImage(const ImageInfo *image_info,
1403% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001404%
1405% A description of each parameter follows.
1406%
1407% o image_info: the image info.
1408%
1409% o image: The image.
1410%
cristy1e178e72011-08-28 19:44:34 +00001411% o exception: return any errors or warnings in this structure.
1412%
cristy3ed852e2009-09-05 21:47:34 +00001413*/
cristy1e178e72011-08-28 19:44:34 +00001414static MagickBooleanType WritePNMImage(const ImageInfo *image_info,Image *image,
1415 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001416{
1417 char
1418 buffer[MaxTextExtent],
1419 format,
1420 magick[MaxTextExtent];
1421
1422 const char
1423 *value;
1424
cristy3ed852e2009-09-05 21:47:34 +00001425 MagickBooleanType
1426 status;
1427
1428 MagickOffsetType
1429 scene;
1430
cristy4c08aed2011-07-01 19:47:50 +00001431 Quantum
1432 index;
1433
cristy3ed852e2009-09-05 21:47:34 +00001434 QuantumAny
1435 pixel;
1436
1437 QuantumInfo
1438 *quantum_info;
1439
1440 QuantumType
1441 quantum_type;
1442
cristy3ed852e2009-09-05 21:47:34 +00001443 register unsigned char
1444 *pixels,
1445 *q;
1446
cristy3ed852e2009-09-05 21:47:34 +00001447 size_t
1448 extent,
1449 packet_size;
1450
cristy95802a72010-09-05 19:07:17 +00001451 ssize_t
cristyaff6d802011-04-26 01:46:31 +00001452 count,
1453 y;
cristy95802a72010-09-05 19:07:17 +00001454
cristy3ed852e2009-09-05 21:47:34 +00001455 /*
1456 Open output image file.
1457 */
1458 assert(image_info != (const ImageInfo *) NULL);
1459 assert(image_info->signature == MagickSignature);
1460 assert(image != (Image *) NULL);
1461 assert(image->signature == MagickSignature);
1462 if (image->debug != MagickFalse)
1463 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy3a37efd2011-08-28 20:31:03 +00001464 assert(exception != (ExceptionInfo *) NULL);
1465 assert(exception->signature == MagickSignature);
cristy1e178e72011-08-28 19:44:34 +00001466 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy3ed852e2009-09-05 21:47:34 +00001467 if (status == MagickFalse)
1468 return(status);
1469 scene=0;
1470 do
1471 {
1472 /*
1473 Write PNM file header.
1474 */
1475 packet_size=3;
1476 quantum_type=RGBQuantum;
1477 (void) CopyMagickString(magick,image_info->magick,MaxTextExtent);
1478 switch (magick[1])
1479 {
1480 case 'A':
1481 case 'a':
1482 {
1483 format='7';
1484 break;
1485 }
1486 case 'B':
1487 case 'b':
1488 {
1489 format='4';
1490 if (image_info->compression == NoCompression)
1491 format='1';
1492 break;
1493 }
1494 case 'F':
1495 case 'f':
1496 {
1497 format='F';
cristy1e178e72011-08-28 19:44:34 +00001498 if (IsImageGray(image,exception) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001499 format='f';
1500 break;
1501 }
1502 case 'G':
1503 case 'g':
1504 {
1505 format='5';
1506 if (image_info->compression == NoCompression)
1507 format='2';
1508 break;
1509 }
1510 case 'N':
1511 case 'n':
1512 {
1513 if ((image_info->type != TrueColorType) &&
cristy1e178e72011-08-28 19:44:34 +00001514 (IsImageGray(image,exception) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001515 {
1516 format='5';
1517 if (image_info->compression == NoCompression)
1518 format='2';
cristy1e178e72011-08-28 19:44:34 +00001519 if (IsImageMonochrome(image,exception) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001520 {
1521 format='4';
1522 if (image_info->compression == NoCompression)
1523 format='1';
1524 }
1525 break;
1526 }
1527 }
1528 default:
1529 {
1530 format='6';
1531 if (image_info->compression == NoCompression)
1532 format='3';
1533 break;
1534 }
1535 }
cristyb51dff52011-05-19 16:55:47 +00001536 (void) FormatLocaleString(buffer,MaxTextExtent,"P%c\n",format);
cristy3ed852e2009-09-05 21:47:34 +00001537 (void) WriteBlobString(image,buffer);
cristyd15e6592011-10-15 00:13:06 +00001538 value=GetImageProperty(image,"comment",exception);
cristy3ed852e2009-09-05 21:47:34 +00001539 if (value != (const char *) NULL)
1540 {
1541 register const char
1542 *p;
1543
1544 /*
1545 Write comments to file.
1546 */
1547 (void) WriteBlobByte(image,'#');
1548 for (p=value; *p != '\0'; p++)
1549 {
1550 (void) WriteBlobByte(image,(unsigned char) *p);
1551 if ((*p == '\r') && (*(p+1) != '\0'))
1552 (void) WriteBlobByte(image,'#');
1553 if ((*p == '\n') && (*(p+1) != '\0'))
1554 (void) WriteBlobByte(image,'#');
1555 }
1556 (void) WriteBlobByte(image,'\n');
1557 }
1558 if (format != '7')
1559 {
cristy510d06a2011-07-06 23:43:54 +00001560 if (IsRGBColorspace(image->colorspace) == MagickFalse)
cristye941a752011-10-15 01:52:48 +00001561 (void) TransformImageColorspace(image,RGBColorspace,exception);
cristyb51dff52011-05-19 16:55:47 +00001562 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n",
cristye8c25f92010-06-03 00:53:06 +00001563 (double) image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001564 (void) WriteBlobString(image,buffer);
1565 }
1566 else
1567 {
1568 char
1569 type[MaxTextExtent];
1570
1571 /*
1572 PAM header.
1573 */
cristyb51dff52011-05-19 16:55:47 +00001574 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00001575 "WIDTH %.20g\nHEIGHT %.20g\n",(double) image->columns,(double)
1576 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001577 (void) WriteBlobString(image,buffer);
cristy1e178e72011-08-28 19:44:34 +00001578 quantum_type=GetQuantumType(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001579 switch (quantum_type)
1580 {
1581 case CMYKQuantum:
1582 case CMYKAQuantum:
1583 {
1584 packet_size=4;
1585 (void) CopyMagickString(type,"CMYK",MaxTextExtent);
1586 break;
1587 }
1588 case GrayQuantum:
1589 case GrayAlphaQuantum:
1590 {
1591 packet_size=1;
1592 (void) CopyMagickString(type,"GRAYSCALE",MaxTextExtent);
1593 break;
1594 }
1595 default:
1596 {
1597 quantum_type=RGBQuantum;
1598 if (image->matte != MagickFalse)
1599 quantum_type=RGBAQuantum;
1600 packet_size=3;
1601 (void) CopyMagickString(type,"RGB",MaxTextExtent);
1602 break;
1603 }
1604 }
1605 if (image->matte != MagickFalse)
1606 {
1607 packet_size++;
1608 (void) ConcatenateMagickString(type,"_ALPHA",MaxTextExtent);
1609 }
1610 if (image->depth > 16)
1611 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001612 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00001613 "DEPTH %.20g\nMAXVAL %.20g\n",(double) packet_size,(double)
cristy2b9582a2011-07-04 17:38:56 +00001614 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001615 (void) WriteBlobString(image,buffer);
cristyb51dff52011-05-19 16:55:47 +00001616 (void) FormatLocaleString(buffer,MaxTextExtent,"TUPLTYPE %s\nENDHDR\n",
cristy3ed852e2009-09-05 21:47:34 +00001617 type);
1618 (void) WriteBlobString(image,buffer);
1619 }
1620 /*
1621 Convert runextent encoded to PNM raster pixels.
1622 */
1623 switch (format)
1624 {
1625 case '1':
1626 {
cristy661b5ad2010-01-13 00:54:42 +00001627 unsigned char
1628 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001629
1630 /*
1631 Convert image to a PBM image.
1632 */
cristy661b5ad2010-01-13 00:54:42 +00001633 q=pixels;
cristybb503372010-05-27 20:51:26 +00001634 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001635 {
cristy4c08aed2011-07-01 19:47:50 +00001636 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001637 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001638
cristybb503372010-05-27 20:51:26 +00001639 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001640 x;
1641
cristy1e178e72011-08-28 19:44:34 +00001642 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001643 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001644 break;
cristybb503372010-05-27 20:51:26 +00001645 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001646 {
cristy4c08aed2011-07-01 19:47:50 +00001647 pixel=GetPixelIntensity(image,p);
cristy661b5ad2010-01-13 00:54:42 +00001648 *q++=(unsigned char) (pixel >= (Quantum) (QuantumRange/2) ?
1649 '0' : '1');
1650 *q++=' ';
1651 if ((q-pixels+2) >= 80)
1652 {
1653 *q++='\n';
1654 (void) WriteBlob(image,q-pixels,pixels);
1655 q=pixels;
cristy661b5ad2010-01-13 00:54:42 +00001656 }
cristyed231572011-07-14 02:18:59 +00001657 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001658 }
1659 if (image->previous == (Image *) NULL)
1660 {
cristycee97112010-05-28 00:44:52 +00001661 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1662 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001663 if (status == MagickFalse)
1664 break;
1665 }
1666 }
cristy661b5ad2010-01-13 00:54:42 +00001667 if (q != pixels)
1668 {
1669 *q++='\n';
1670 (void) WriteBlob(image,q-pixels,pixels);
1671 }
cristy3ed852e2009-09-05 21:47:34 +00001672 break;
1673 }
1674 case '2':
1675 {
cristy661b5ad2010-01-13 00:54:42 +00001676 unsigned char
1677 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001678
1679 /*
1680 Convert image to a PGM image.
1681 */
1682 if (image->depth <= 8)
1683 (void) WriteBlobString(image,"255\n");
1684 else
1685 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001686 q=pixels;
cristybb503372010-05-27 20:51:26 +00001687 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001688 {
cristy4c08aed2011-07-01 19:47:50 +00001689 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001690 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001691
cristybb503372010-05-27 20:51:26 +00001692 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001693 x;
1694
cristy1e178e72011-08-28 19:44:34 +00001695 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001696 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001697 break;
cristybb503372010-05-27 20:51:26 +00001698 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001699 {
cristy4c08aed2011-07-01 19:47:50 +00001700 index=GetPixelIntensity(image,p);
cristy3ed852e2009-09-05 21:47:34 +00001701 if (image->depth <= 8)
cristyb51dff52011-05-19 16:55:47 +00001702 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,"%u ",
cristy3ed852e2009-09-05 21:47:34 +00001703 ScaleQuantumToChar(index));
1704 else
cristyb51dff52011-05-19 16:55:47 +00001705 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,"%u ",
cristy3ed852e2009-09-05 21:47:34 +00001706 ScaleQuantumToShort(index));
cristy661b5ad2010-01-13 00:54:42 +00001707 extent=(size_t) count;
1708 (void) strncpy((char *) q,buffer,extent);
1709 q+=extent;
1710 if ((q-pixels+extent) >= 80)
1711 {
1712 *q++='\n';
1713 (void) WriteBlob(image,q-pixels,pixels);
1714 q=pixels;
1715 }
cristyed231572011-07-14 02:18:59 +00001716 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001717 }
1718 if (image->previous == (Image *) NULL)
1719 {
cristycee97112010-05-28 00:44:52 +00001720 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1721 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001722 if (status == MagickFalse)
1723 break;
1724 }
1725 }
cristy661b5ad2010-01-13 00:54:42 +00001726 if (q != pixels)
1727 {
1728 *q++='\n';
1729 (void) WriteBlob(image,q-pixels,pixels);
1730 }
cristy3ed852e2009-09-05 21:47:34 +00001731 break;
1732 }
1733 case '3':
1734 {
cristy661b5ad2010-01-13 00:54:42 +00001735 unsigned char
1736 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001737
1738 /*
1739 Convert image to a PNM image.
1740 */
1741 if (image->depth <= 8)
1742 (void) WriteBlobString(image,"255\n");
1743 else
1744 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001745 q=pixels;
cristybb503372010-05-27 20:51:26 +00001746 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001747 {
cristy4c08aed2011-07-01 19:47:50 +00001748 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001749 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001750
cristybb503372010-05-27 20:51:26 +00001751 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001752 x;
1753
cristy1e178e72011-08-28 19:44:34 +00001754 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001755 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001756 break;
cristybb503372010-05-27 20:51:26 +00001757 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001758 {
1759 if (image->depth <= 8)
cristyb51dff52011-05-19 16:55:47 +00001760 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,
cristy4c08aed2011-07-01 19:47:50 +00001761 "%u %u %u ",ScaleQuantumToChar(GetPixelRed(image,p)),
1762 ScaleQuantumToChar(GetPixelGreen(image,p)),
1763 ScaleQuantumToChar(GetPixelBlue(image,p)));
cristy3ed852e2009-09-05 21:47:34 +00001764 else
cristyb51dff52011-05-19 16:55:47 +00001765 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,
cristy4c08aed2011-07-01 19:47:50 +00001766 "%u %u %u ",ScaleQuantumToShort(GetPixelRed(image,p)),
1767 ScaleQuantumToShort(GetPixelGreen(image,p)),
1768 ScaleQuantumToShort(GetPixelBlue(image,p)));
cristy661b5ad2010-01-13 00:54:42 +00001769 extent=(size_t) count;
1770 (void) strncpy((char *) q,buffer,extent);
1771 q+=extent;
1772 if ((q-pixels+extent) >= 80)
1773 {
1774 *q++='\n';
1775 (void) WriteBlob(image,q-pixels,pixels);
1776 q=pixels;
1777 }
cristyed231572011-07-14 02:18:59 +00001778 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001779 }
1780 if (image->previous == (Image *) NULL)
1781 {
cristycee97112010-05-28 00:44:52 +00001782 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1783 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001784 if (status == MagickFalse)
1785 break;
1786 }
1787 }
cristy661b5ad2010-01-13 00:54:42 +00001788 if (q != pixels)
1789 {
1790 *q++='\n';
1791 (void) WriteBlob(image,q-pixels,pixels);
1792 }
cristy3ed852e2009-09-05 21:47:34 +00001793 break;
1794 }
1795 case '4':
1796 {
1797 /*
1798 Convert image to a PBM image.
1799 */
1800 image->depth=1;
1801 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1802 if (quantum_info == (QuantumInfo *) NULL)
1803 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1804 quantum_info->min_is_white=MagickTrue;
1805 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00001806 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001807 {
cristy4c08aed2011-07-01 19:47:50 +00001808 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001809 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001810
cristy1e178e72011-08-28 19:44:34 +00001811 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001812 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001813 break;
cristy4c08aed2011-07-01 19:47:50 +00001814 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001815 GrayQuantum,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001816 count=WriteBlob(image,extent,pixels);
1817 if (count != (ssize_t) extent)
1818 break;
1819 if (image->previous == (Image *) NULL)
1820 {
cristycee97112010-05-28 00:44:52 +00001821 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1822 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001823 if (status == MagickFalse)
1824 break;
1825 }
1826 }
1827 quantum_info=DestroyQuantumInfo(quantum_info);
1828 break;
1829 }
1830 case '5':
1831 {
1832 QuantumAny
1833 range;
1834
1835 /*
1836 Convert image to a PGM image.
1837 */
1838 if (image->depth > 8)
1839 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001840 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g\n",(double)
cristy2b9582a2011-07-04 17:38:56 +00001841 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001842 (void) WriteBlobString(image,buffer);
1843 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1844 if (quantum_info == (QuantumInfo *) NULL)
1845 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1846 quantum_info->min_is_white=MagickTrue;
1847 pixels=GetQuantumPixels(quantum_info);
1848 extent=GetQuantumExtent(image,quantum_info,GrayQuantum);
1849 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001850 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001851 {
cristy4c08aed2011-07-01 19:47:50 +00001852 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001853 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001854
cristybb503372010-05-27 20:51:26 +00001855 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001856 x;
1857
cristy1e178e72011-08-28 19:44:34 +00001858 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001859 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001860 break;
1861 q=pixels;
1862 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00001863 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001864 GrayQuantum,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001865 else
1866 {
1867 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00001868 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001869 {
cristy4c08aed2011-07-01 19:47:50 +00001870 if (IsPixelGray(image,p) == MagickFalse)
1871 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001872 else
1873 {
1874 if (image->depth == 8)
cristy4c08aed2011-07-01 19:47:50 +00001875 pixel=ScaleQuantumToChar(GetPixelRed(image,p));
cristy3ed852e2009-09-05 21:47:34 +00001876 else
cristy4c08aed2011-07-01 19:47:50 +00001877 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001878 }
1879 q=PopCharPixel((unsigned char) pixel,q);
cristyed231572011-07-14 02:18:59 +00001880 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001881 }
1882 else
cristybb503372010-05-27 20:51:26 +00001883 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001884 {
cristy4c08aed2011-07-01 19:47:50 +00001885 if (IsPixelGray(image,p) == MagickFalse)
1886 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001887 else
1888 {
1889 if (image->depth == 16)
cristy4c08aed2011-07-01 19:47:50 +00001890 pixel=ScaleQuantumToShort(GetPixelRed(image,p));
cristy3ed852e2009-09-05 21:47:34 +00001891 else
cristy4c08aed2011-07-01 19:47:50 +00001892 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001893 }
1894 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyed231572011-07-14 02:18:59 +00001895 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001896 }
1897 extent=(size_t) (q-pixels);
1898 }
1899 count=WriteBlob(image,extent,pixels);
1900 if (count != (ssize_t) extent)
1901 break;
1902 if (image->previous == (Image *) NULL)
1903 {
cristycee97112010-05-28 00:44:52 +00001904 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1905 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001906 if (status == MagickFalse)
1907 break;
1908 }
1909 }
1910 quantum_info=DestroyQuantumInfo(quantum_info);
1911 break;
1912 }
1913 case '6':
1914 {
1915 QuantumAny
1916 range;
1917
1918 /*
1919 Convert image to a PNM image.
1920 */
1921 if (image->depth > 8)
1922 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001923 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g\n",(double)
cristy2b9582a2011-07-04 17:38:56 +00001924 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001925 (void) WriteBlobString(image,buffer);
1926 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1927 if (quantum_info == (QuantumInfo *) NULL)
1928 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1929 pixels=GetQuantumPixels(quantum_info);
1930 extent=GetQuantumExtent(image,quantum_info,quantum_type);
1931 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001932 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001933 {
cristy4c08aed2011-07-01 19:47:50 +00001934 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001935 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001936
cristybb503372010-05-27 20:51:26 +00001937 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001938 x;
1939
cristy1e178e72011-08-28 19:44:34 +00001940 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001941 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001942 break;
1943 q=pixels;
1944 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00001945 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001946 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001947 else
1948 {
1949 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00001950 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001951 {
cristy4c08aed2011-07-01 19:47:50 +00001952 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001953 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001954 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001955 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001956 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001957 q=PopCharPixel((unsigned char) pixel,q);
cristyed231572011-07-14 02:18:59 +00001958 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001959 }
1960 else
cristybb503372010-05-27 20:51:26 +00001961 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001962 {
cristy4c08aed2011-07-01 19:47:50 +00001963 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001964 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001965 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001966 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001967 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001968 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyed231572011-07-14 02:18:59 +00001969 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001970 }
1971 extent=(size_t) (q-pixels);
1972 }
1973 count=WriteBlob(image,extent,pixels);
1974 if (count != (ssize_t) extent)
1975 break;
1976 if (image->previous == (Image *) NULL)
1977 {
cristycee97112010-05-28 00:44:52 +00001978 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1979 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001980 if (status == MagickFalse)
1981 break;
1982 }
1983 }
1984 quantum_info=DestroyQuantumInfo(quantum_info);
1985 break;
1986 }
1987 case '7':
1988 {
1989 QuantumAny
1990 range;
1991
1992 /*
1993 Convert image to a PAM.
1994 */
1995 if (image->depth > 16)
1996 image->depth=16;
1997 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1998 pixels=GetQuantumPixels(quantum_info);
1999 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00002000 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002001 {
cristy4c08aed2011-07-01 19:47:50 +00002002 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00002003 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002004
cristybb503372010-05-27 20:51:26 +00002005 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002006 x;
2007
cristy1e178e72011-08-28 19:44:34 +00002008 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002009 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002010 break;
cristy3ed852e2009-09-05 21:47:34 +00002011 q=pixels;
2012 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00002013 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002014 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002015 else
2016 {
2017 switch (quantum_type)
2018 {
2019 case GrayQuantum:
2020 case GrayAlphaQuantum:
2021 {
2022 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002023 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002024 {
cristy4c08aed2011-07-01 19:47:50 +00002025 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002026 q=PopCharPixel((unsigned char) pixel,q);
2027 if (image->matte != MagickFalse)
2028 {
cristyaff6d802011-04-26 01:46:31 +00002029 pixel=(unsigned char) ScaleQuantumToAny(
cristy4c08aed2011-07-01 19:47:50 +00002030 GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002031 q=PopCharPixel((unsigned char) pixel,q);
2032 }
cristyed231572011-07-14 02:18:59 +00002033 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002034 }
2035 else
cristybb503372010-05-27 20:51:26 +00002036 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002037 {
cristy4c08aed2011-07-01 19:47:50 +00002038 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002039 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2040 if (image->matte != MagickFalse)
2041 {
cristyaff6d802011-04-26 01:46:31 +00002042 pixel=(unsigned char) ScaleQuantumToAny(
cristy4c08aed2011-07-01 19:47:50 +00002043 GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002044 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2045 }
cristyed231572011-07-14 02:18:59 +00002046 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002047 }
2048 break;
2049 }
2050 case CMYKQuantum:
2051 case CMYKAQuantum:
2052 {
2053 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002054 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002055 {
cristy4c08aed2011-07-01 19:47:50 +00002056 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002057 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002058 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002059 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002060 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002061 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002062 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002063 q=PopCharPixel((unsigned char) pixel,q);
2064 if (image->matte != MagickFalse)
2065 {
cristy4c08aed2011-07-01 19:47:50 +00002066 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002067 q=PopCharPixel((unsigned char) pixel,q);
2068 }
cristyed231572011-07-14 02:18:59 +00002069 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002070 }
2071 else
cristybb503372010-05-27 20:51:26 +00002072 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002073 {
cristy4c08aed2011-07-01 19:47:50 +00002074 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002075 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002076 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002077 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002078 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002079 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002080 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002081 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2082 if (image->matte != MagickFalse)
2083 {
cristy4c08aed2011-07-01 19:47:50 +00002084 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002085 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2086 }
cristyed231572011-07-14 02:18:59 +00002087 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002088 }
2089 break;
2090 }
2091 default:
2092 {
2093 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002094 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002095 {
cristy4c08aed2011-07-01 19:47:50 +00002096 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002097 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002098 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002099 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002100 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002101 q=PopCharPixel((unsigned char) pixel,q);
2102 if (image->matte != MagickFalse)
2103 {
cristy4c08aed2011-07-01 19:47:50 +00002104 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002105 q=PopCharPixel((unsigned char) pixel,q);
2106 }
cristyed231572011-07-14 02:18:59 +00002107 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002108 }
2109 else
cristybb503372010-05-27 20:51:26 +00002110 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002111 {
cristy4c08aed2011-07-01 19:47:50 +00002112 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002113 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002114 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002115 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002116 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002117 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2118 if (image->matte != MagickFalse)
2119 {
cristy4c08aed2011-07-01 19:47:50 +00002120 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002121 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2122 }
cristyed231572011-07-14 02:18:59 +00002123 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002124 }
2125 break;
2126 }
2127 }
2128 extent=(size_t) (q-pixels);
2129 }
2130 count=WriteBlob(image,extent,pixels);
2131 if (count != (ssize_t) extent)
2132 break;
2133 if (image->previous == (Image *) NULL)
2134 {
cristycee97112010-05-28 00:44:52 +00002135 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2136 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002137 if (status == MagickFalse)
2138 break;
2139 }
2140 }
2141 quantum_info=DestroyQuantumInfo(quantum_info);
2142 break;
2143 }
2144 case 'F':
2145 case 'f':
2146 {
2147 (void) WriteBlobString(image,image->endian != LSBEndian ? "1.0\n" :
2148 "-1.0\n");
2149 image->depth=32;
2150 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
2151 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
2152 if (quantum_info == (QuantumInfo *) NULL)
2153 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2154 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2155 if (status == MagickFalse)
2156 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2157 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002158 for (y=(ssize_t) image->rows-1; y >= 0; y--)
cristy3ed852e2009-09-05 21:47:34 +00002159 {
cristy4c08aed2011-07-01 19:47:50 +00002160 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00002161 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002162
cristy1e178e72011-08-28 19:44:34 +00002163 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002164 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002165 break;
cristy4c08aed2011-07-01 19:47:50 +00002166 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002167 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002168 (void) WriteBlob(image,extent,pixels);
2169 if (image->previous == (Image *) NULL)
2170 {
cristycee97112010-05-28 00:44:52 +00002171 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2172 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002173 if (status == MagickFalse)
2174 break;
2175 }
2176 }
2177 quantum_info=DestroyQuantumInfo(quantum_info);
2178 break;
2179 }
2180 }
2181 if (GetNextImageInList(image) == (Image *) NULL)
2182 break;
2183 image=SyncNextImageInList(image);
2184 status=SetImageProgress(image,SaveImagesTag,scene++,
2185 GetImageListLength(image));
2186 if (status == MagickFalse)
2187 break;
2188 } while (image_info->adjoin != MagickFalse);
2189 (void) CloseBlob(image);
2190 return(MagickTrue);
2191}