blob: 0f320fbaa4d9e92880de81c5415543ea7be13b5f [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)
cristy5d792232012-01-31 17:02:45 +00001247 {
1248 (void) ThrowMagickException(exception,GetMagickModule(),
1249 CorruptImageError,"UnexpectedEndOfFile","`%s'",image->filename);
1250 break;
1251 }
cristy3ed852e2009-09-05 21:47:34 +00001252 /*
1253 Proceed to next image.
1254 */
1255 if (image_info->number_scenes != 0)
1256 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1257 break;
1258 if ((format == '1') || (format == '2') || (format == '3'))
1259 do
1260 {
1261 /*
1262 Skip to end of line.
1263 */
1264 count=ReadBlob(image,1,(unsigned char *) &format);
1265 if (count == 0)
1266 break;
1267 if ((count != 0) && (format == 'P'))
1268 break;
1269 } while (format != '\n');
1270 count=ReadBlob(image,1,(unsigned char *) &format);
1271 if ((count == 1) && (format == 'P'))
1272 {
1273 /*
1274 Allocate next image structure.
1275 */
cristy9950d572011-10-01 18:22:35 +00001276 AcquireNextImage(image_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001277 if (GetNextImageInList(image) == (Image *) NULL)
1278 {
1279 image=DestroyImageList(image);
1280 return((Image *) NULL);
1281 }
1282 image=SyncNextImageInList(image);
1283 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1284 GetBlobSize(image));
1285 if (status == MagickFalse)
1286 break;
1287 }
1288 } while ((count == 1) && (format == 'P'));
1289 (void) CloseBlob(image);
1290 return(GetFirstImageInList(image));
1291}
1292
1293/*
1294%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1295% %
1296% %
1297% %
1298% R e g i s t e r P N M I m a g e %
1299% %
1300% %
1301% %
1302%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1303%
1304% RegisterPNMImage() adds properties for the PNM image format to
1305% the list of supported formats. The properties include the image format
1306% tag, a method to read and/or write the format, whether the format
1307% supports the saving of more than one frame to the same file or blob,
1308% whether the format supports native in-memory I/O, and a brief
1309% description of the format.
1310%
1311% The format of the RegisterPNMImage method is:
1312%
cristybb503372010-05-27 20:51:26 +00001313% size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001314%
1315*/
cristybb503372010-05-27 20:51:26 +00001316ModuleExport size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001317{
1318 MagickInfo
1319 *entry;
1320
1321 entry=SetMagickInfo("PAM");
1322 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1323 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1324 entry->description=ConstantString("Common 2-dimensional bitmap format");
1325 entry->module=ConstantString("PNM");
1326 (void) RegisterMagickInfo(entry);
1327 entry=SetMagickInfo("PBM");
1328 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1329 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1330 entry->description=ConstantString("Portable bitmap format (black and white)");
1331 entry->module=ConstantString("PNM");
1332 (void) RegisterMagickInfo(entry);
1333 entry=SetMagickInfo("PFM");
1334 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1335 entry->encoder=(EncodeImageHandler *) WritePNMImage;
cristye96405a2010-05-19 02:24:31 +00001336 entry->endian_support=MagickTrue;
cristy3ed852e2009-09-05 21:47:34 +00001337 entry->description=ConstantString("Portable float format");
1338 entry->module=ConstantString("PFM");
1339 (void) RegisterMagickInfo(entry);
1340 entry=SetMagickInfo("PGM");
1341 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1342 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1343 entry->description=ConstantString("Portable graymap format (gray scale)");
1344 entry->module=ConstantString("PNM");
1345 (void) RegisterMagickInfo(entry);
1346 entry=SetMagickInfo("PNM");
1347 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1348 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1349 entry->magick=(IsImageFormatHandler *) IsPNM;
1350 entry->description=ConstantString("Portable anymap");
1351 entry->module=ConstantString("PNM");
1352 (void) RegisterMagickInfo(entry);
1353 entry=SetMagickInfo("PPM");
1354 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1355 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1356 entry->description=ConstantString("Portable pixmap format (color)");
1357 entry->module=ConstantString("PNM");
1358 (void) RegisterMagickInfo(entry);
1359 return(MagickImageCoderSignature);
1360}
1361
1362/*
1363%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1364% %
1365% %
1366% %
1367% U n r e g i s t e r P N M I m a g e %
1368% %
1369% %
1370% %
1371%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1372%
1373% UnregisterPNMImage() removes format registrations made by the
1374% PNM module from the list of supported formats.
1375%
1376% The format of the UnregisterPNMImage method is:
1377%
1378% UnregisterPNMImage(void)
1379%
1380*/
1381ModuleExport void UnregisterPNMImage(void)
1382{
1383 (void) UnregisterMagickInfo("PAM");
1384 (void) UnregisterMagickInfo("PBM");
1385 (void) UnregisterMagickInfo("PGM");
1386 (void) UnregisterMagickInfo("PNM");
1387 (void) UnregisterMagickInfo("PPM");
1388}
1389
1390/*
1391%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1392% %
1393% %
1394% %
1395% W r i t e P N M I m a g e %
1396% %
1397% %
1398% %
1399%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1400%
cristy661b5ad2010-01-13 00:54:42 +00001401% WritePNMImage() writes an image to a file in the PNM rasterfile format.
cristy3ed852e2009-09-05 21:47:34 +00001402%
1403% The format of the WritePNMImage method is:
1404%
cristy1e178e72011-08-28 19:44:34 +00001405% MagickBooleanType WritePNMImage(const ImageInfo *image_info,
1406% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001407%
1408% A description of each parameter follows.
1409%
1410% o image_info: the image info.
1411%
1412% o image: The image.
1413%
cristy1e178e72011-08-28 19:44:34 +00001414% o exception: return any errors or warnings in this structure.
1415%
cristy3ed852e2009-09-05 21:47:34 +00001416*/
cristy1e178e72011-08-28 19:44:34 +00001417static MagickBooleanType WritePNMImage(const ImageInfo *image_info,Image *image,
1418 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001419{
1420 char
1421 buffer[MaxTextExtent],
1422 format,
1423 magick[MaxTextExtent];
1424
1425 const char
1426 *value;
1427
cristy3ed852e2009-09-05 21:47:34 +00001428 MagickBooleanType
1429 status;
1430
1431 MagickOffsetType
1432 scene;
1433
cristy4c08aed2011-07-01 19:47:50 +00001434 Quantum
1435 index;
1436
cristy3ed852e2009-09-05 21:47:34 +00001437 QuantumAny
1438 pixel;
1439
1440 QuantumInfo
1441 *quantum_info;
1442
1443 QuantumType
1444 quantum_type;
1445
cristy3ed852e2009-09-05 21:47:34 +00001446 register unsigned char
1447 *pixels,
1448 *q;
1449
cristy3ed852e2009-09-05 21:47:34 +00001450 size_t
1451 extent,
1452 packet_size;
1453
cristy95802a72010-09-05 19:07:17 +00001454 ssize_t
cristyaff6d802011-04-26 01:46:31 +00001455 count,
1456 y;
cristy95802a72010-09-05 19:07:17 +00001457
cristy3ed852e2009-09-05 21:47:34 +00001458 /*
1459 Open output image file.
1460 */
1461 assert(image_info != (const ImageInfo *) NULL);
1462 assert(image_info->signature == MagickSignature);
1463 assert(image != (Image *) NULL);
1464 assert(image->signature == MagickSignature);
1465 if (image->debug != MagickFalse)
1466 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy3a37efd2011-08-28 20:31:03 +00001467 assert(exception != (ExceptionInfo *) NULL);
1468 assert(exception->signature == MagickSignature);
cristy1e178e72011-08-28 19:44:34 +00001469 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy3ed852e2009-09-05 21:47:34 +00001470 if (status == MagickFalse)
1471 return(status);
1472 scene=0;
1473 do
1474 {
1475 /*
1476 Write PNM file header.
1477 */
1478 packet_size=3;
1479 quantum_type=RGBQuantum;
1480 (void) CopyMagickString(magick,image_info->magick,MaxTextExtent);
1481 switch (magick[1])
1482 {
1483 case 'A':
1484 case 'a':
1485 {
1486 format='7';
1487 break;
1488 }
1489 case 'B':
1490 case 'b':
1491 {
1492 format='4';
1493 if (image_info->compression == NoCompression)
1494 format='1';
1495 break;
1496 }
1497 case 'F':
1498 case 'f':
1499 {
1500 format='F';
cristy1e178e72011-08-28 19:44:34 +00001501 if (IsImageGray(image,exception) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001502 format='f';
1503 break;
1504 }
1505 case 'G':
1506 case 'g':
1507 {
1508 format='5';
1509 if (image_info->compression == NoCompression)
1510 format='2';
1511 break;
1512 }
1513 case 'N':
1514 case 'n':
1515 {
1516 if ((image_info->type != TrueColorType) &&
cristy1e178e72011-08-28 19:44:34 +00001517 (IsImageGray(image,exception) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001518 {
1519 format='5';
1520 if (image_info->compression == NoCompression)
1521 format='2';
cristy1e178e72011-08-28 19:44:34 +00001522 if (IsImageMonochrome(image,exception) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001523 {
1524 format='4';
1525 if (image_info->compression == NoCompression)
1526 format='1';
1527 }
1528 break;
1529 }
1530 }
1531 default:
1532 {
1533 format='6';
1534 if (image_info->compression == NoCompression)
1535 format='3';
1536 break;
1537 }
1538 }
cristyb51dff52011-05-19 16:55:47 +00001539 (void) FormatLocaleString(buffer,MaxTextExtent,"P%c\n",format);
cristy3ed852e2009-09-05 21:47:34 +00001540 (void) WriteBlobString(image,buffer);
cristyd15e6592011-10-15 00:13:06 +00001541 value=GetImageProperty(image,"comment",exception);
cristy3ed852e2009-09-05 21:47:34 +00001542 if (value != (const char *) NULL)
1543 {
1544 register const char
1545 *p;
1546
1547 /*
1548 Write comments to file.
1549 */
1550 (void) WriteBlobByte(image,'#');
1551 for (p=value; *p != '\0'; p++)
1552 {
1553 (void) WriteBlobByte(image,(unsigned char) *p);
1554 if ((*p == '\r') && (*(p+1) != '\0'))
1555 (void) WriteBlobByte(image,'#');
1556 if ((*p == '\n') && (*(p+1) != '\0'))
1557 (void) WriteBlobByte(image,'#');
1558 }
1559 (void) WriteBlobByte(image,'\n');
1560 }
1561 if (format != '7')
1562 {
cristy510d06a2011-07-06 23:43:54 +00001563 if (IsRGBColorspace(image->colorspace) == MagickFalse)
cristye941a752011-10-15 01:52:48 +00001564 (void) TransformImageColorspace(image,RGBColorspace,exception);
cristyb51dff52011-05-19 16:55:47 +00001565 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n",
cristye8c25f92010-06-03 00:53:06 +00001566 (double) image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001567 (void) WriteBlobString(image,buffer);
1568 }
1569 else
1570 {
1571 char
1572 type[MaxTextExtent];
1573
1574 /*
1575 PAM header.
1576 */
cristyb51dff52011-05-19 16:55:47 +00001577 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00001578 "WIDTH %.20g\nHEIGHT %.20g\n",(double) image->columns,(double)
1579 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001580 (void) WriteBlobString(image,buffer);
cristy1e178e72011-08-28 19:44:34 +00001581 quantum_type=GetQuantumType(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001582 switch (quantum_type)
1583 {
1584 case CMYKQuantum:
1585 case CMYKAQuantum:
1586 {
1587 packet_size=4;
1588 (void) CopyMagickString(type,"CMYK",MaxTextExtent);
1589 break;
1590 }
1591 case GrayQuantum:
1592 case GrayAlphaQuantum:
1593 {
1594 packet_size=1;
1595 (void) CopyMagickString(type,"GRAYSCALE",MaxTextExtent);
1596 break;
1597 }
1598 default:
1599 {
1600 quantum_type=RGBQuantum;
1601 if (image->matte != MagickFalse)
1602 quantum_type=RGBAQuantum;
1603 packet_size=3;
1604 (void) CopyMagickString(type,"RGB",MaxTextExtent);
1605 break;
1606 }
1607 }
1608 if (image->matte != MagickFalse)
1609 {
1610 packet_size++;
1611 (void) ConcatenateMagickString(type,"_ALPHA",MaxTextExtent);
1612 }
1613 if (image->depth > 16)
1614 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001615 (void) FormatLocaleString(buffer,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00001616 "DEPTH %.20g\nMAXVAL %.20g\n",(double) packet_size,(double)
cristy2b9582a2011-07-04 17:38:56 +00001617 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001618 (void) WriteBlobString(image,buffer);
cristyb51dff52011-05-19 16:55:47 +00001619 (void) FormatLocaleString(buffer,MaxTextExtent,"TUPLTYPE %s\nENDHDR\n",
cristy3ed852e2009-09-05 21:47:34 +00001620 type);
1621 (void) WriteBlobString(image,buffer);
1622 }
1623 /*
1624 Convert runextent encoded to PNM raster pixels.
1625 */
1626 switch (format)
1627 {
1628 case '1':
1629 {
cristy661b5ad2010-01-13 00:54:42 +00001630 unsigned char
1631 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001632
1633 /*
1634 Convert image to a PBM image.
1635 */
cristy661b5ad2010-01-13 00:54:42 +00001636 q=pixels;
cristybb503372010-05-27 20:51:26 +00001637 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001638 {
cristy4c08aed2011-07-01 19:47:50 +00001639 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001640 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001641
cristybb503372010-05-27 20:51:26 +00001642 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001643 x;
1644
cristy1e178e72011-08-28 19:44:34 +00001645 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001646 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001647 break;
cristybb503372010-05-27 20:51:26 +00001648 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001649 {
cristy4c08aed2011-07-01 19:47:50 +00001650 pixel=GetPixelIntensity(image,p);
cristy661b5ad2010-01-13 00:54:42 +00001651 *q++=(unsigned char) (pixel >= (Quantum) (QuantumRange/2) ?
1652 '0' : '1');
1653 *q++=' ';
1654 if ((q-pixels+2) >= 80)
1655 {
1656 *q++='\n';
1657 (void) WriteBlob(image,q-pixels,pixels);
1658 q=pixels;
cristy661b5ad2010-01-13 00:54:42 +00001659 }
cristyed231572011-07-14 02:18:59 +00001660 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001661 }
1662 if (image->previous == (Image *) NULL)
1663 {
cristycee97112010-05-28 00:44:52 +00001664 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1665 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001666 if (status == MagickFalse)
1667 break;
1668 }
1669 }
cristy661b5ad2010-01-13 00:54:42 +00001670 if (q != pixels)
1671 {
1672 *q++='\n';
1673 (void) WriteBlob(image,q-pixels,pixels);
1674 }
cristy3ed852e2009-09-05 21:47:34 +00001675 break;
1676 }
1677 case '2':
1678 {
cristy661b5ad2010-01-13 00:54:42 +00001679 unsigned char
1680 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001681
1682 /*
1683 Convert image to a PGM image.
1684 */
1685 if (image->depth <= 8)
1686 (void) WriteBlobString(image,"255\n");
1687 else
1688 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001689 q=pixels;
cristybb503372010-05-27 20:51:26 +00001690 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001691 {
cristy4c08aed2011-07-01 19:47:50 +00001692 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001693 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001694
cristybb503372010-05-27 20:51:26 +00001695 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001696 x;
1697
cristy1e178e72011-08-28 19:44:34 +00001698 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001699 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001700 break;
cristybb503372010-05-27 20:51:26 +00001701 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001702 {
cristy4c08aed2011-07-01 19:47:50 +00001703 index=GetPixelIntensity(image,p);
cristy3ed852e2009-09-05 21:47:34 +00001704 if (image->depth <= 8)
cristyb51dff52011-05-19 16:55:47 +00001705 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,"%u ",
cristy3ed852e2009-09-05 21:47:34 +00001706 ScaleQuantumToChar(index));
1707 else
cristyb51dff52011-05-19 16:55:47 +00001708 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,"%u ",
cristy3ed852e2009-09-05 21:47:34 +00001709 ScaleQuantumToShort(index));
cristy661b5ad2010-01-13 00:54:42 +00001710 extent=(size_t) count;
1711 (void) strncpy((char *) q,buffer,extent);
1712 q+=extent;
1713 if ((q-pixels+extent) >= 80)
1714 {
1715 *q++='\n';
1716 (void) WriteBlob(image,q-pixels,pixels);
1717 q=pixels;
1718 }
cristyed231572011-07-14 02:18:59 +00001719 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001720 }
1721 if (image->previous == (Image *) NULL)
1722 {
cristycee97112010-05-28 00:44:52 +00001723 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1724 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001725 if (status == MagickFalse)
1726 break;
1727 }
1728 }
cristy661b5ad2010-01-13 00:54:42 +00001729 if (q != pixels)
1730 {
1731 *q++='\n';
1732 (void) WriteBlob(image,q-pixels,pixels);
1733 }
cristy3ed852e2009-09-05 21:47:34 +00001734 break;
1735 }
1736 case '3':
1737 {
cristy661b5ad2010-01-13 00:54:42 +00001738 unsigned char
1739 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001740
1741 /*
1742 Convert image to a PNM image.
1743 */
1744 if (image->depth <= 8)
1745 (void) WriteBlobString(image,"255\n");
1746 else
1747 (void) WriteBlobString(image,"65535\n");
cristy661b5ad2010-01-13 00:54:42 +00001748 q=pixels;
cristybb503372010-05-27 20:51:26 +00001749 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001750 {
cristy4c08aed2011-07-01 19:47:50 +00001751 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001752 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001753
cristybb503372010-05-27 20:51:26 +00001754 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001755 x;
1756
cristy1e178e72011-08-28 19:44:34 +00001757 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001758 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001759 break;
cristybb503372010-05-27 20:51:26 +00001760 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001761 {
1762 if (image->depth <= 8)
cristyb51dff52011-05-19 16:55:47 +00001763 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,
cristy4c08aed2011-07-01 19:47:50 +00001764 "%u %u %u ",ScaleQuantumToChar(GetPixelRed(image,p)),
1765 ScaleQuantumToChar(GetPixelGreen(image,p)),
1766 ScaleQuantumToChar(GetPixelBlue(image,p)));
cristy3ed852e2009-09-05 21:47:34 +00001767 else
cristyb51dff52011-05-19 16:55:47 +00001768 count=(ssize_t) FormatLocaleString(buffer,MaxTextExtent,
cristy4c08aed2011-07-01 19:47:50 +00001769 "%u %u %u ",ScaleQuantumToShort(GetPixelRed(image,p)),
1770 ScaleQuantumToShort(GetPixelGreen(image,p)),
1771 ScaleQuantumToShort(GetPixelBlue(image,p)));
cristy661b5ad2010-01-13 00:54:42 +00001772 extent=(size_t) count;
1773 (void) strncpy((char *) q,buffer,extent);
1774 q+=extent;
1775 if ((q-pixels+extent) >= 80)
1776 {
1777 *q++='\n';
1778 (void) WriteBlob(image,q-pixels,pixels);
1779 q=pixels;
1780 }
cristyed231572011-07-14 02:18:59 +00001781 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001782 }
1783 if (image->previous == (Image *) NULL)
1784 {
cristycee97112010-05-28 00:44:52 +00001785 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1786 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001787 if (status == MagickFalse)
1788 break;
1789 }
1790 }
cristy661b5ad2010-01-13 00:54:42 +00001791 if (q != pixels)
1792 {
1793 *q++='\n';
1794 (void) WriteBlob(image,q-pixels,pixels);
1795 }
cristy3ed852e2009-09-05 21:47:34 +00001796 break;
1797 }
1798 case '4':
1799 {
1800 /*
1801 Convert image to a PBM image.
1802 */
1803 image->depth=1;
1804 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1805 if (quantum_info == (QuantumInfo *) NULL)
1806 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1807 quantum_info->min_is_white=MagickTrue;
1808 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00001809 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001810 {
cristy4c08aed2011-07-01 19:47:50 +00001811 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001812 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001813
cristy1e178e72011-08-28 19:44:34 +00001814 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001815 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001816 break;
cristy4c08aed2011-07-01 19:47:50 +00001817 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001818 GrayQuantum,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001819 count=WriteBlob(image,extent,pixels);
1820 if (count != (ssize_t) extent)
1821 break;
1822 if (image->previous == (Image *) NULL)
1823 {
cristycee97112010-05-28 00:44:52 +00001824 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1825 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001826 if (status == MagickFalse)
1827 break;
1828 }
1829 }
1830 quantum_info=DestroyQuantumInfo(quantum_info);
1831 break;
1832 }
1833 case '5':
1834 {
1835 QuantumAny
1836 range;
1837
1838 /*
1839 Convert image to a PGM image.
1840 */
1841 if (image->depth > 8)
1842 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001843 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g\n",(double)
cristy2b9582a2011-07-04 17:38:56 +00001844 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001845 (void) WriteBlobString(image,buffer);
1846 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1847 if (quantum_info == (QuantumInfo *) NULL)
1848 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1849 quantum_info->min_is_white=MagickTrue;
1850 pixels=GetQuantumPixels(quantum_info);
1851 extent=GetQuantumExtent(image,quantum_info,GrayQuantum);
1852 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001853 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001854 {
cristy4c08aed2011-07-01 19:47:50 +00001855 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001856 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001857
cristybb503372010-05-27 20:51:26 +00001858 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001859 x;
1860
cristy1e178e72011-08-28 19:44:34 +00001861 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001862 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001863 break;
1864 q=pixels;
1865 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00001866 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001867 GrayQuantum,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001868 else
1869 {
1870 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00001871 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001872 {
cristy4c08aed2011-07-01 19:47:50 +00001873 if (IsPixelGray(image,p) == MagickFalse)
1874 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001875 else
1876 {
1877 if (image->depth == 8)
cristy4c08aed2011-07-01 19:47:50 +00001878 pixel=ScaleQuantumToChar(GetPixelRed(image,p));
cristy3ed852e2009-09-05 21:47:34 +00001879 else
cristy4c08aed2011-07-01 19:47:50 +00001880 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001881 }
1882 q=PopCharPixel((unsigned char) pixel,q);
cristyed231572011-07-14 02:18:59 +00001883 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001884 }
1885 else
cristybb503372010-05-27 20:51:26 +00001886 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001887 {
cristy4c08aed2011-07-01 19:47:50 +00001888 if (IsPixelGray(image,p) == MagickFalse)
1889 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001890 else
1891 {
1892 if (image->depth == 16)
cristy4c08aed2011-07-01 19:47:50 +00001893 pixel=ScaleQuantumToShort(GetPixelRed(image,p));
cristy3ed852e2009-09-05 21:47:34 +00001894 else
cristy4c08aed2011-07-01 19:47:50 +00001895 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001896 }
1897 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyed231572011-07-14 02:18:59 +00001898 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001899 }
1900 extent=(size_t) (q-pixels);
1901 }
1902 count=WriteBlob(image,extent,pixels);
1903 if (count != (ssize_t) extent)
1904 break;
1905 if (image->previous == (Image *) NULL)
1906 {
cristycee97112010-05-28 00:44:52 +00001907 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1908 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001909 if (status == MagickFalse)
1910 break;
1911 }
1912 }
1913 quantum_info=DestroyQuantumInfo(quantum_info);
1914 break;
1915 }
1916 case '6':
1917 {
1918 QuantumAny
1919 range;
1920
1921 /*
1922 Convert image to a PNM image.
1923 */
1924 if (image->depth > 8)
1925 image->depth=16;
cristyb51dff52011-05-19 16:55:47 +00001926 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g\n",(double)
cristy2b9582a2011-07-04 17:38:56 +00001927 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001928 (void) WriteBlobString(image,buffer);
1929 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
1930 if (quantum_info == (QuantumInfo *) NULL)
1931 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1932 pixels=GetQuantumPixels(quantum_info);
1933 extent=GetQuantumExtent(image,quantum_info,quantum_type);
1934 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00001935 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001936 {
cristy4c08aed2011-07-01 19:47:50 +00001937 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00001938 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001939
cristybb503372010-05-27 20:51:26 +00001940 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001941 x;
1942
cristy1e178e72011-08-28 19:44:34 +00001943 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001944 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001945 break;
1946 q=pixels;
1947 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00001948 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001949 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001950 else
1951 {
1952 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00001953 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001954 {
cristy4c08aed2011-07-01 19:47:50 +00001955 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001956 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001957 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001958 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001959 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001960 q=PopCharPixel((unsigned char) pixel,q);
cristyed231572011-07-14 02:18:59 +00001961 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001962 }
1963 else
cristybb503372010-05-27 20:51:26 +00001964 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001965 {
cristy4c08aed2011-07-01 19:47:50 +00001966 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001967 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001968 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001969 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00001970 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00001971 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyed231572011-07-14 02:18:59 +00001972 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001973 }
1974 extent=(size_t) (q-pixels);
1975 }
1976 count=WriteBlob(image,extent,pixels);
1977 if (count != (ssize_t) extent)
1978 break;
1979 if (image->previous == (Image *) NULL)
1980 {
cristycee97112010-05-28 00:44:52 +00001981 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1982 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001983 if (status == MagickFalse)
1984 break;
1985 }
1986 }
1987 quantum_info=DestroyQuantumInfo(quantum_info);
1988 break;
1989 }
1990 case '7':
1991 {
1992 QuantumAny
1993 range;
1994
1995 /*
1996 Convert image to a PAM.
1997 */
1998 if (image->depth > 16)
1999 image->depth=16;
2000 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
2001 pixels=GetQuantumPixels(quantum_info);
2002 range=GetQuantumRange(image->depth);
cristybb503372010-05-27 20:51:26 +00002003 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002004 {
cristy4c08aed2011-07-01 19:47:50 +00002005 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00002006 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002007
cristybb503372010-05-27 20:51:26 +00002008 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002009 x;
2010
cristy1e178e72011-08-28 19:44:34 +00002011 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002012 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002013 break;
cristy3ed852e2009-09-05 21:47:34 +00002014 q=pixels;
2015 if ((image->depth == 8) || (image->depth == 16))
cristy4c08aed2011-07-01 19:47:50 +00002016 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002017 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002018 else
2019 {
2020 switch (quantum_type)
2021 {
2022 case GrayQuantum:
2023 case GrayAlphaQuantum:
2024 {
2025 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002026 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002027 {
cristy4c08aed2011-07-01 19:47:50 +00002028 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002029 q=PopCharPixel((unsigned char) pixel,q);
2030 if (image->matte != MagickFalse)
2031 {
cristyaff6d802011-04-26 01:46:31 +00002032 pixel=(unsigned char) ScaleQuantumToAny(
cristy4c08aed2011-07-01 19:47:50 +00002033 GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002034 q=PopCharPixel((unsigned char) pixel,q);
2035 }
cristyed231572011-07-14 02:18:59 +00002036 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002037 }
2038 else
cristybb503372010-05-27 20:51:26 +00002039 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002040 {
cristy4c08aed2011-07-01 19:47:50 +00002041 pixel=ScaleQuantumToAny(GetPixelIntensity(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002042 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2043 if (image->matte != MagickFalse)
2044 {
cristyaff6d802011-04-26 01:46:31 +00002045 pixel=(unsigned char) ScaleQuantumToAny(
cristy4c08aed2011-07-01 19:47:50 +00002046 GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002047 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2048 }
cristyed231572011-07-14 02:18:59 +00002049 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002050 }
2051 break;
2052 }
2053 case CMYKQuantum:
2054 case CMYKAQuantum:
2055 {
2056 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002057 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002058 {
cristy4c08aed2011-07-01 19:47:50 +00002059 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002060 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002061 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002062 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002063 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002064 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002065 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002066 q=PopCharPixel((unsigned char) pixel,q);
2067 if (image->matte != MagickFalse)
2068 {
cristy4c08aed2011-07-01 19:47:50 +00002069 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002070 q=PopCharPixel((unsigned char) pixel,q);
2071 }
cristyed231572011-07-14 02:18:59 +00002072 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002073 }
2074 else
cristybb503372010-05-27 20:51:26 +00002075 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002076 {
cristy4c08aed2011-07-01 19:47:50 +00002077 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002078 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002079 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002080 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002081 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002082 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002083 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002084 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2085 if (image->matte != MagickFalse)
2086 {
cristy4c08aed2011-07-01 19:47:50 +00002087 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002088 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2089 }
cristyed231572011-07-14 02:18:59 +00002090 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002091 }
2092 break;
2093 }
2094 default:
2095 {
2096 if (image->depth <= 8)
cristybb503372010-05-27 20:51:26 +00002097 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002098 {
cristy4c08aed2011-07-01 19:47:50 +00002099 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002100 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002101 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002102 q=PopCharPixel((unsigned char) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002103 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002104 q=PopCharPixel((unsigned char) pixel,q);
2105 if (image->matte != MagickFalse)
2106 {
cristy4c08aed2011-07-01 19:47:50 +00002107 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002108 q=PopCharPixel((unsigned char) pixel,q);
2109 }
cristyed231572011-07-14 02:18:59 +00002110 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002111 }
2112 else
cristybb503372010-05-27 20:51:26 +00002113 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002114 {
cristy4c08aed2011-07-01 19:47:50 +00002115 pixel=ScaleQuantumToAny(GetPixelRed(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002116 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002117 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002118 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy4c08aed2011-07-01 19:47:50 +00002119 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002120 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2121 if (image->matte != MagickFalse)
2122 {
cristy4c08aed2011-07-01 19:47:50 +00002123 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),range);
cristy3ed852e2009-09-05 21:47:34 +00002124 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2125 }
cristyed231572011-07-14 02:18:59 +00002126 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002127 }
2128 break;
2129 }
2130 }
2131 extent=(size_t) (q-pixels);
2132 }
2133 count=WriteBlob(image,extent,pixels);
2134 if (count != (ssize_t) extent)
2135 break;
2136 if (image->previous == (Image *) NULL)
2137 {
cristycee97112010-05-28 00:44:52 +00002138 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2139 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002140 if (status == MagickFalse)
2141 break;
2142 }
2143 }
2144 quantum_info=DestroyQuantumInfo(quantum_info);
2145 break;
2146 }
2147 case 'F':
2148 case 'f':
2149 {
2150 (void) WriteBlobString(image,image->endian != LSBEndian ? "1.0\n" :
2151 "-1.0\n");
2152 image->depth=32;
2153 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
2154 quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image);
2155 if (quantum_info == (QuantumInfo *) NULL)
2156 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2157 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2158 if (status == MagickFalse)
2159 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2160 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002161 for (y=(ssize_t) image->rows-1; y >= 0; y--)
cristy3ed852e2009-09-05 21:47:34 +00002162 {
cristy4c08aed2011-07-01 19:47:50 +00002163 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +00002164 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002165
cristy1e178e72011-08-28 19:44:34 +00002166 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002167 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002168 break;
cristy4c08aed2011-07-01 19:47:50 +00002169 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002170 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002171 (void) WriteBlob(image,extent,pixels);
2172 if (image->previous == (Image *) NULL)
2173 {
cristycee97112010-05-28 00:44:52 +00002174 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2175 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002176 if (status == MagickFalse)
2177 break;
2178 }
2179 }
2180 quantum_info=DestroyQuantumInfo(quantum_info);
2181 break;
2182 }
2183 }
2184 if (GetNextImageInList(image) == (Image *) NULL)
2185 break;
2186 image=SyncNextImageInList(image);
2187 status=SetImageProgress(image,SaveImagesTag,scene++,
2188 GetImageListLength(image));
2189 if (status == MagickFalse)
2190 break;
2191 } while (image_info->adjoin != MagickFalse);
2192 (void) CloseBlob(image);
2193 return(MagickTrue);
2194}