blob: 0d1a72ed4c2f6255376ea9dc13303ceae2892325 [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 %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000017% July 1992 %
18% %
19% %
Cristy7ce65e72015-12-12 18:03:16 -050020% Copyright 1999-2016 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*/
cristy035f58b2014-12-18 00:51:37 +0000138
cristy029b9c82014-12-18 00:51:12 +0000139static int PNMComment(Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000140{
cristy3ed852e2009-09-05 21:47:34 +0000141 int
142 c;
143
cristy542ea782013-05-24 15:53:01 +0000144 char
145 *comment;
146
cristy3ed852e2009-09-05 21:47:34 +0000147 register char
148 *p;
149
150 size_t
cristy542ea782013-05-24 15:53:01 +0000151 extent;
152
153 /*
154 Read comment.
155 */
156 comment=AcquireString(GetImageProperty(image,"comment",exception));
cristy542ea782013-05-24 15:53:01 +0000157 p=comment+strlen(comment);
cristy151b66d2015-04-15 10:50:31 +0000158 extent=strlen(comment)+MagickPathExtent;
cristy542ea782013-05-24 15:53:01 +0000159 for (c='#'; (c != EOF) && (c != (int) '\n'); p++)
160 {
161 if ((size_t) (p-comment+1) >= extent)
162 {
163 extent<<=1;
cristy151b66d2015-04-15 10:50:31 +0000164 comment=(char *) ResizeQuantumMemory(comment,extent+MagickPathExtent,
cristy542ea782013-05-24 15:53:01 +0000165 sizeof(*comment));
166 if (comment == (char *) NULL)
167 break;
168 p=comment+strlen(comment);
169 }
170 c=ReadBlobByte(image);
171 if (c != EOF)
172 {
173 *p=(char) c;
174 *(p+1)='\0';
175 }
176 }
177 if (comment == (char *) NULL)
cristy029b9c82014-12-18 00:51:12 +0000178 return(c);
cristy542ea782013-05-24 15:53:01 +0000179 (void) SetImageProperty(image,"comment",comment,exception);
180 comment=DestroyString(comment);
cristy029b9c82014-12-18 00:51:12 +0000181 return(c);
cristy542ea782013-05-24 15:53:01 +0000182}
183
cristy93344732014-12-13 22:21:44 +0000184static unsigned int PNMInteger(Image *image,const unsigned int base,
cristy542ea782013-05-24 15:53:01 +0000185 ExceptionInfo *exception)
186{
187 int
188 c;
189
cristy93344732014-12-13 22:21:44 +0000190 unsigned int
cristy3ed852e2009-09-05 21:47:34 +0000191 value;
192
193 /*
194 Skip any leading whitespace.
195 */
cristy3ed852e2009-09-05 21:47:34 +0000196 do
197 {
198 c=ReadBlobByte(image);
199 if (c == EOF)
200 return(0);
201 if (c == (int) '#')
cristy029b9c82014-12-18 00:51:12 +0000202 c=PNMComment(image,exception);
cristyd178f432014-12-15 11:03:40 +0000203 } while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'));
cristy3ed852e2009-09-05 21:47:34 +0000204 if (base == 2)
cristy93344732014-12-13 22:21:44 +0000205 return((unsigned int) (c-(int) '0'));
cristy3ed852e2009-09-05 21:47:34 +0000206 /*
207 Evaluate number.
208 */
209 value=0;
cristy4039d1f2014-12-15 11:07:08 +0000210 while (isdigit(c) != 0) {
cristy93344732014-12-13 22:21:44 +0000211 if (value > (unsigned int) (INT_MAX/10))
cristy0c44bb52014-12-13 22:15:35 +0000212 break;
cristy3ed852e2009-09-05 21:47:34 +0000213 value*=10;
cristy40a5c452014-12-15 22:13:06 +0000214 if (value > (unsigned int) (INT_MAX-(c-(int) '0')))
cristydee34692014-12-15 01:31:53 +0000215 break;
cristy3ed852e2009-09-05 21:47:34 +0000216 value+=c-(int) '0';
217 c=ReadBlobByte(image);
cristyd178f432014-12-15 11:03:40 +0000218 if (c == EOF)
219 return(0);
cristy4039d1f2014-12-15 11:07:08 +0000220 }
cristy3ed852e2009-09-05 21:47:34 +0000221 return(value);
222}
223
224static Image *ReadPNMImage(const ImageInfo *image_info,ExceptionInfo *exception)
225{
226 char
227 format;
228
229 double
230 quantum_scale;
231
232 Image
233 *image;
234
cristy3ed852e2009-09-05 21:47:34 +0000235 MagickBooleanType
236 status;
237
cristy92beec62013-08-26 12:23:46 +0000238 QuantumAny
239 max_value;
240
cristy3ed852e2009-09-05 21:47:34 +0000241 QuantumInfo
242 *quantum_info;
243
244 QuantumType
245 quantum_type;
246
cristy3ed852e2009-09-05 21:47:34 +0000247 size_t
cristyaff6d802011-04-26 01:46:31 +0000248 depth,
cristy3ed852e2009-09-05 21:47:34 +0000249 extent,
250 packet_size;
251
252 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000253 count,
254 row,
255 y;
cristy3ed852e2009-09-05 21:47:34 +0000256
cristy3ed852e2009-09-05 21:47:34 +0000257 /*
258 Open image file.
259 */
260 assert(image_info != (const ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000261 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000262 if (image_info->debug != MagickFalse)
263 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
264 image_info->filename);
265 assert(exception != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000266 assert(exception->signature == MagickCoreSignature);
cristy9950d572011-10-01 18:22:35 +0000267 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000268 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
269 if (status == MagickFalse)
270 {
271 image=DestroyImageList(image);
272 return((Image *) NULL);
273 }
274 /*
275 Read PNM image.
276 */
277 count=ReadBlob(image,1,(unsigned char *) &format);
278 do
279 {
280 /*
281 Initialize image structure.
282 */
283 if ((count != 1) || (format != 'P'))
284 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
285 max_value=1;
286 quantum_type=RGBQuantum;
287 quantum_scale=1.0;
288 format=(char) ReadBlobByte(image);
289 if (format != '7')
290 {
291 /*
292 PBM, PGM, PPM, and PNM.
293 */
cristy0c44bb52014-12-13 22:15:35 +0000294 image->columns=(size_t) PNMInteger(image,10,exception);
295 image->rows=(size_t) PNMInteger(image,10,exception);
cristy3ed852e2009-09-05 21:47:34 +0000296 if ((format == 'f') || (format == 'F'))
297 {
298 char
cristy151b66d2015-04-15 10:50:31 +0000299 scale[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000300
301 (void) ReadBlobString(image,scale);
cristydbdd0e32011-11-04 23:29:40 +0000302 quantum_scale=StringToDouble(scale,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000303 }
304 else
305 {
306 if ((format == '1') || (format == '4'))
307 max_value=1; /* bitmap */
308 else
cristy0c44bb52014-12-13 22:15:35 +0000309 max_value=(QuantumAny) PNMInteger(image,10,exception);
cristy3ed852e2009-09-05 21:47:34 +0000310 }
311 }
312 else
313 {
314 char
cristy151b66d2015-04-15 10:50:31 +0000315 keyword[MagickPathExtent],
316 value[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000317
318 int
319 c;
320
321 register char
322 *p;
323
324 /*
325 PAM.
326 */
327 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
328 {
329 while (isspace((int) ((unsigned char) c)) != 0)
330 c=ReadBlobByte(image);
cristya4068ab2013-05-19 11:51:07 +0000331 if (c == '#')
332 {
333 /*
334 Comment.
335 */
cristy029b9c82014-12-18 00:51:12 +0000336 c=PNMComment(image,exception);
cristy542ea782013-05-24 15:53:01 +0000337 c=ReadBlobByte(image);
cristya4068ab2013-05-19 11:51:07 +0000338 while (isspace((int) ((unsigned char) c)) != 0)
339 c=ReadBlobByte(image);
340 }
cristy3ed852e2009-09-05 21:47:34 +0000341 p=keyword;
342 do
343 {
cristy151b66d2015-04-15 10:50:31 +0000344 if ((size_t) (p-keyword) < (MagickPathExtent-1))
cristy3ed852e2009-09-05 21:47:34 +0000345 *p++=c;
346 c=ReadBlobByte(image);
347 } while (isalnum(c));
348 *p='\0';
349 if (LocaleCompare(keyword,"endhdr") == 0)
350 break;
351 while (isspace((int) ((unsigned char) c)) != 0)
cristy4e285b92013-05-24 17:42:57 +0000352 c=ReadBlobByte(image);
cristy3ed852e2009-09-05 21:47:34 +0000353 p=value;
354 while (isalnum(c) || (c == '_'))
355 {
cristy151b66d2015-04-15 10:50:31 +0000356 if ((size_t) (p-value) < (MagickPathExtent-1))
cristy3ed852e2009-09-05 21:47:34 +0000357 *p++=c;
358 c=ReadBlobByte(image);
359 }
360 *p='\0';
361 /*
362 Assign a value to the specified keyword.
363 */
364 if (LocaleCompare(keyword,"depth") == 0)
cristye27293e2009-12-18 02:53:20 +0000365 packet_size=StringToUnsignedLong(value);
cristyda16f162011-02-19 23:52:17 +0000366 (void) packet_size;
cristy3ed852e2009-09-05 21:47:34 +0000367 if (LocaleCompare(keyword,"height") == 0)
cristye27293e2009-12-18 02:53:20 +0000368 image->rows=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000369 if (LocaleCompare(keyword,"maxval") == 0)
cristye27293e2009-12-18 02:53:20 +0000370 max_value=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000371 if (LocaleCompare(keyword,"TUPLTYPE") == 0)
372 {
373 if (LocaleCompare(value,"BLACKANDWHITE") == 0)
cristyb3a73b52011-07-26 01:34:43 +0000374 {
cristy542ea782013-05-24 15:53:01 +0000375 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristyb3a73b52011-07-26 01:34:43 +0000376 quantum_type=GrayQuantum;
377 }
cristy7a201992012-05-12 23:30:43 +0000378 if (LocaleCompare(value,"BLACKANDWHITE_ALPHA") == 0)
379 {
cristy542ea782013-05-24 15:53:01 +0000380 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy8a46d822012-08-28 23:32:39 +0000381 image->alpha_trait=BlendPixelTrait;
cristy7a201992012-05-12 23:30:43 +0000382 quantum_type=GrayAlphaQuantum;
383 }
384 if (LocaleCompare(value,"GRAYSCALE") == 0)
385 {
386 quantum_type=GrayQuantum;
cristy542ea782013-05-24 15:53:01 +0000387 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy7a201992012-05-12 23:30:43 +0000388 }
cristy3ed852e2009-09-05 21:47:34 +0000389 if (LocaleCompare(value,"GRAYSCALE_ALPHA") == 0)
390 {
cristy542ea782013-05-24 15:53:01 +0000391 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy8a46d822012-08-28 23:32:39 +0000392 image->alpha_trait=BlendPixelTrait;
cristyb3a73b52011-07-26 01:34:43 +0000393 quantum_type=GrayAlphaQuantum;
cristy3ed852e2009-09-05 21:47:34 +0000394 }
395 if (LocaleCompare(value,"RGB_ALPHA") == 0)
396 {
cristy8a46d822012-08-28 23:32:39 +0000397 image->alpha_trait=BlendPixelTrait;
cristy7a201992012-05-12 23:30:43 +0000398 quantum_type=RGBAQuantum;
cristy3ed852e2009-09-05 21:47:34 +0000399 }
400 if (LocaleCompare(value,"CMYK") == 0)
401 {
cristy542ea782013-05-24 15:53:01 +0000402 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy7a201992012-05-12 23:30:43 +0000403 quantum_type=CMYKQuantum;
cristy3ed852e2009-09-05 21:47:34 +0000404 }
405 if (LocaleCompare(value,"CMYK_ALPHA") == 0)
406 {
cristy542ea782013-05-24 15:53:01 +0000407 (void) SetImageColorspace(image,CMYKColorspace,exception);
cristy8a46d822012-08-28 23:32:39 +0000408 image->alpha_trait=BlendPixelTrait;
cristy7a201992012-05-12 23:30:43 +0000409 quantum_type=CMYKAQuantum;
cristy3ed852e2009-09-05 21:47:34 +0000410 }
411 }
412 if (LocaleCompare(keyword,"width") == 0)
cristye27293e2009-12-18 02:53:20 +0000413 image->columns=StringToUnsignedLong(value);
cristy3ed852e2009-09-05 21:47:34 +0000414 }
415 }
416 if ((image->columns == 0) || (image->rows == 0))
417 ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
cristyefbf04c2014-10-28 13:12:17 +0000418 if ((max_value == 0) || (max_value > 4294967295))
cristy3ed852e2009-09-05 21:47:34 +0000419 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
cristy3f1ee592011-06-15 23:03:58 +0000420 for (depth=1; GetQuantumRange(depth) < max_value; depth++) ;
cristy3ed852e2009-09-05 21:47:34 +0000421 image->depth=depth;
422 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
423 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
424 break;
cristy832bf412014-12-14 21:22:30 +0000425 status=SetImageExtent(image,image->columns,image->rows,exception);
426 if (status == MagickFalse)
427 return(DestroyImageList(image));
cristy3ed852e2009-09-05 21:47:34 +0000428 /*
429 Convert PNM pixels to runextent-encoded MIFF packets.
430 */
cristy3ed852e2009-09-05 21:47:34 +0000431 row=0;
432 switch (format)
433 {
434 case '1':
435 {
436 /*
437 Convert PBM image to pixel packets.
438 */
cristy4e285b92013-05-24 17:42:57 +0000439 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristybb503372010-05-27 20:51:26 +0000440 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000441 {
cristybb503372010-05-27 20:51:26 +0000442 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000443 x;
444
cristy4c08aed2011-07-01 19:47:50 +0000445 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100446 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000447
448 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000449 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000450 break;
cristybb503372010-05-27 20:51:26 +0000451 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000452 {
cristy08528502012-01-01 00:52:17 +0000453 SetPixelGray(image,PNMInteger(image,2,exception) == 0 ?
cristyd15e6592011-10-15 00:13:06 +0000454 QuantumRange : 0,q);
cristyed231572011-07-14 02:18:59 +0000455 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000456 }
457 if (SyncAuthenticPixels(image,exception) == MagickFalse)
458 break;
459 if (image->previous == (Image *) NULL)
460 {
cristycee97112010-05-28 00:44:52 +0000461 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
462 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000463 if (status == MagickFalse)
464 break;
465 }
466 }
467 image->type=BilevelType;
468 break;
469 }
470 case '2':
471 {
cristy93344732014-12-13 22:21:44 +0000472 Quantum
cristy3ed852e2009-09-05 21:47:34 +0000473 intensity;
474
475 /*
476 Convert PGM image to pixel packets.
477 */
cristy542ea782013-05-24 15:53:01 +0000478 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristybb503372010-05-27 20:51:26 +0000479 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000480 {
cristybb503372010-05-27 20:51:26 +0000481 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000482 x;
483
cristy4c08aed2011-07-01 19:47:50 +0000484 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100485 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000486
487 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyb3a73b52011-07-26 01:34:43 +0000488 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000489 break;
cristybb503372010-05-27 20:51:26 +0000490 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000491 {
cristy0c44bb52014-12-13 22:15:35 +0000492 intensity=ScaleAnyToQuantum(PNMInteger(image,10,exception),
493 max_value);
cristy67d16d92013-09-29 18:31:17 +0000494 SetPixelGray(image,intensity,q);
cristyed231572011-07-14 02:18:59 +0000495 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000496 }
497 if (SyncAuthenticPixels(image,exception) == MagickFalse)
498 break;
499 if (image->previous == (Image *) NULL)
500 {
cristycee97112010-05-28 00:44:52 +0000501 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
502 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000503 if (status == MagickFalse)
504 break;
505 }
506 }
507 image->type=GrayscaleType;
cristy3ed852e2009-09-05 21:47:34 +0000508 break;
509 }
510 case '3':
511 {
cristy3ed852e2009-09-05 21:47:34 +0000512 /*
513 Convert PNM image to pixel packets.
514 */
cristybb503372010-05-27 20:51:26 +0000515 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000516 {
cristybb503372010-05-27 20:51:26 +0000517 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000518 x;
519
cristy4c08aed2011-07-01 19:47:50 +0000520 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100521 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000522
523 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000524 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000525 break;
cristybb503372010-05-27 20:51:26 +0000526 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000527 {
cristy93344732014-12-13 22:21:44 +0000528 Quantum
cristy67d16d92013-09-29 18:31:17 +0000529 pixel;
530
531 pixel=ScaleAnyToQuantum(PNMInteger(image,10,exception),max_value);
532 SetPixelRed(image,pixel,q);
533 pixel=ScaleAnyToQuantum(PNMInteger(image,10,exception),max_value);
534 SetPixelGreen(image,pixel,q);
535 pixel=ScaleAnyToQuantum(PNMInteger(image,10,exception),max_value);
536 SetPixelBlue(image,pixel,q);
cristyed231572011-07-14 02:18:59 +0000537 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000538 }
539 if (SyncAuthenticPixels(image,exception) == MagickFalse)
540 break;
541 if (image->previous == (Image *) NULL)
542 {
cristycee97112010-05-28 00:44:52 +0000543 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
544 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000545 if (status == MagickFalse)
546 break;
547 }
548 }
cristy3ed852e2009-09-05 21:47:34 +0000549 break;
550 }
551 case '4':
552 {
553 /*
554 Convert PBM raw image to pixel packets.
555 */
cristy542ea782013-05-24 15:53:01 +0000556 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +0000557 quantum_type=GrayQuantum;
558 if (image->storage_class == PseudoClass)
559 quantum_type=IndexQuantum;
cristy5f766ef2014-12-14 21:12:47 +0000560 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +0000561 if (quantum_info == (QuantumInfo *) NULL)
562 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
563 SetQuantumMinIsWhite(quantum_info,MagickTrue);
564 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +0000565 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000566 {
cristyb1253cd2015-05-31 01:06:54 +0000567 const unsigned char
cristybd797f12015-01-24 20:42:32 +0000568 *pixels;
569
cristy3ed852e2009-09-05 21:47:34 +0000570 MagickBooleanType
571 sync;
572
cristy4c08aed2011-07-01 19:47:50 +0000573 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100574 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000575
576 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000577 count,
578 offset;
cristy3ed852e2009-09-05 21:47:34 +0000579
580 size_t
581 length;
582
cristy3ed852e2009-09-05 21:47:34 +0000583 if (status == MagickFalse)
584 continue;
cristyb1253cd2015-05-31 01:06:54 +0000585 pixels=(unsigned char *) ReadBlobStream(image,extent,
586 GetQuantumPixels(quantum_info),&count);
cristy3ed852e2009-09-05 21:47:34 +0000587 if (count != (ssize_t) extent)
588 status=MagickFalse;
cristybd797f12015-01-24 20:42:32 +0000589 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
590 (image->previous == (Image *) NULL))
591 {
592 MagickBooleanType
593 proceed;
594
595 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
596 row,image->rows);
597 if (proceed == MagickFalse)
598 status=MagickFalse;
599 }
600 offset=row++;
cristyaa740112010-03-30 17:58:44 +0000601 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000602 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000603 {
604 status=MagickFalse;
605 continue;
606 }
cristyaa740112010-03-30 17:58:44 +0000607 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
608 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +0000609 if (length != extent)
610 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +0000611 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000612 if (sync == MagickFalse)
613 status=MagickFalse;
614 }
cristy3ed852e2009-09-05 21:47:34 +0000615 quantum_info=DestroyQuantumInfo(quantum_info);
616 if (status == MagickFalse)
617 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
618 SetQuantumImageType(image,quantum_type);
619 break;
620 }
621 case '5':
622 {
cristy3ed852e2009-09-05 21:47:34 +0000623 /*
624 Convert PGM raw image to pixel packets.
625 */
cristy542ea782013-05-24 15:53:01 +0000626 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +0000627 quantum_type=GrayQuantum;
cristy67d16d92013-09-29 18:31:17 +0000628 if (image->depth <= 8)
629 extent=image->columns;
630 else
631 if (image->depth <= 16)
632 extent=2*image->columns;
633 else
634 extent=4*image->columns;
cristy5f766ef2014-12-14 21:12:47 +0000635 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +0000636 if (quantum_info == (QuantumInfo *) NULL)
637 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000638 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000639 {
cristyb1253cd2015-05-31 01:06:54 +0000640 const unsigned char
cristybd797f12015-01-24 20:42:32 +0000641 *pixels;
642
cristy3ed852e2009-09-05 21:47:34 +0000643 MagickBooleanType
644 sync;
645
646 register const unsigned char
dirk05d2ff72015-11-18 23:13:43 +0100647 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000648
cristybb503372010-05-27 20:51:26 +0000649 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000650 x;
651
cristy4c08aed2011-07-01 19:47:50 +0000652 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100653 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000654
655 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000656 count,
657 offset;
cristy3ed852e2009-09-05 21:47:34 +0000658
cristy3ed852e2009-09-05 21:47:34 +0000659 if (status == MagickFalse)
660 continue;
cristyb1253cd2015-05-31 01:06:54 +0000661 pixels=(unsigned char *) ReadBlobStream(image,extent,
662 GetQuantumPixels(quantum_info),&count);
cristy3ed852e2009-09-05 21:47:34 +0000663 if (count != (ssize_t) extent)
664 status=MagickFalse;
cristybd797f12015-01-24 20:42:32 +0000665 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
666 (image->previous == (Image *) NULL))
667 {
668 MagickBooleanType
669 proceed;
670
671 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
672 row,image->rows);
673 if (proceed == MagickFalse)
674 status=MagickFalse;
675 }
676 offset=row++;
cristyaa740112010-03-30 17:58:44 +0000677 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000678 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000679 {
680 status=MagickFalse;
681 continue;
682 }
683 p=pixels;
cristy67d16d92013-09-29 18:31:17 +0000684 switch (image->depth)
685 {
686 case 8:
687 case 16:
688 case 32:
689 {
690 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
691 quantum_type,pixels,exception);
692 break;
693 }
694 default:
695 {
696 unsigned int
697 pixel;
cristy3ed852e2009-09-05 21:47:34 +0000698
cristy67d16d92013-09-29 18:31:17 +0000699 if (image->depth <= 8)
cristy3ed852e2009-09-05 21:47:34 +0000700 {
cristy67d16d92013-09-29 18:31:17 +0000701 unsigned char
702 pixel;
cristy3ed852e2009-09-05 21:47:34 +0000703
cristy67d16d92013-09-29 18:31:17 +0000704 for (x=0; x < (ssize_t) image->columns; x++)
705 {
706 p=PushCharPixel(p,&pixel);
707 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
708 q+=GetPixelChannels(image);
709 }
710 break;
cristy3ed852e2009-09-05 21:47:34 +0000711 }
cristy67d16d92013-09-29 18:31:17 +0000712 if (image->depth <= 16)
713 {
714 unsigned short
715 pixel;
716
717 for (x=0; x < (ssize_t) image->columns; x++)
718 {
719 p=PushShortPixel(MSBEndian,p,&pixel);
720 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
721 q+=GetPixelChannels(image);
722 }
723 break;
724 }
725 for (x=0; x < (ssize_t) image->columns; x++)
726 {
727 p=PushLongPixel(MSBEndian,p,&pixel);
728 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
729 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000730 }
cristy67d16d92013-09-29 18:31:17 +0000731 break;
732 }
733 }
cristyaa740112010-03-30 17:58:44 +0000734 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000735 if (sync == MagickFalse)
736 status=MagickFalse;
737 }
cristy3ed852e2009-09-05 21:47:34 +0000738 quantum_info=DestroyQuantumInfo(quantum_info);
739 if (status == MagickFalse)
740 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
741 SetQuantumImageType(image,quantum_type);
742 break;
743 }
744 case '6':
745 {
cristy3ed852e2009-09-05 21:47:34 +0000746 /*
747 Convert PNM raster image to pixel packets.
748 */
cristy3ed852e2009-09-05 21:47:34 +0000749 quantum_type=RGBQuantum;
750 extent=3*(image->depth <= 8 ? 1 : 2)*image->columns;
cristy5f766ef2014-12-14 21:12:47 +0000751 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +0000752 if (quantum_info == (QuantumInfo *) NULL)
753 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristy70d7eae2012-11-17 19:40:21 +0000754 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
cristybb503372010-05-27 20:51:26 +0000755 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000756 {
cristyb1253cd2015-05-31 01:06:54 +0000757 const unsigned char
cristybd797f12015-01-24 20:42:32 +0000758 *pixels;
759
cristy3ed852e2009-09-05 21:47:34 +0000760 MagickBooleanType
761 sync;
762
763 register const unsigned char
dirk05d2ff72015-11-18 23:13:43 +0100764 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000765
cristybb503372010-05-27 20:51:26 +0000766 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000767 x;
768
cristy4c08aed2011-07-01 19:47:50 +0000769 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100770 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000771
772 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000773 count,
774 offset;
cristy3ed852e2009-09-05 21:47:34 +0000775
cristy3ed852e2009-09-05 21:47:34 +0000776 if (status == MagickFalse)
777 continue;
cristyb1253cd2015-05-31 01:06:54 +0000778 pixels=(unsigned char *) ReadBlobStream(image,extent,
779 GetQuantumPixels(quantum_info),&count);
cristy3ed852e2009-09-05 21:47:34 +0000780 if (count != (ssize_t) extent)
781 status=MagickFalse;
cristybd797f12015-01-24 20:42:32 +0000782 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
783 (image->previous == (Image *) NULL))
784 {
785 MagickBooleanType
786 proceed;
787
788 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
789 row,image->rows);
790 if (proceed == MagickFalse)
791 status=MagickFalse;
792 }
793 offset=row++;
cristyaa740112010-03-30 17:58:44 +0000794 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000795 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000796 {
797 status=MagickFalse;
798 continue;
799 }
800 p=pixels;
cristy67d16d92013-09-29 18:31:17 +0000801 switch (image->depth)
802 {
803 case 8:
cristy3ed852e2009-09-05 21:47:34 +0000804 {
cristy67d16d92013-09-29 18:31:17 +0000805 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000806 {
cristy67d16d92013-09-29 18:31:17 +0000807 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
808 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
809 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
810 SetPixelAlpha(image,OpaqueAlpha,q);
811 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000812 }
cristy67d16d92013-09-29 18:31:17 +0000813 break;
814 }
815 case 16:
816 {
817 unsigned short
818 pixel;
819
820 for (x=0; x < (ssize_t) image->columns; x++)
821 {
822 p=PushShortPixel(MSBEndian,p,&pixel);
823 SetPixelRed(image,ScaleShortToQuantum(pixel),q);
824 p=PushShortPixel(MSBEndian,p,&pixel);
825 SetPixelGreen(image,ScaleShortToQuantum(pixel),q);
826 p=PushShortPixel(MSBEndian,p,&pixel);
827 SetPixelBlue(image,ScaleShortToQuantum(pixel),q);
828 SetPixelAlpha(image,OpaqueAlpha,q);
829 q+=GetPixelChannels(image);
830 }
831 break;
832 }
833 case 32:
834 {
835 unsigned int
836 pixel;
837
838 for (x=0; x < (ssize_t) image->columns; x++)
839 {
840 p=PushLongPixel(MSBEndian,p,&pixel);
841 SetPixelRed(image,ScaleLongToQuantum(pixel),q);
842 p=PushLongPixel(MSBEndian,p,&pixel);
843 SetPixelGreen(image,ScaleLongToQuantum(pixel),q);
844 p=PushLongPixel(MSBEndian,p,&pixel);
845 SetPixelBlue(image,ScaleLongToQuantum(pixel),q);
846 SetPixelAlpha(image,OpaqueAlpha,q);
847 q+=GetPixelChannels(image);
848 }
849 break;
850 }
851 default:
852 {
853 unsigned int
854 pixel;
855
cristye90d7402010-03-14 18:21:29 +0000856 if (image->depth <= 8)
857 {
858 unsigned char
859 pixel;
860
cristybb503372010-05-27 20:51:26 +0000861 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000862 {
863 p=PushCharPixel(p,&pixel);
cristy92beec62013-08-26 12:23:46 +0000864 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
cristye90d7402010-03-14 18:21:29 +0000865 p=PushCharPixel(p,&pixel);
cristy92beec62013-08-26 12:23:46 +0000866 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
cristye90d7402010-03-14 18:21:29 +0000867 p=PushCharPixel(p,&pixel);
cristy92beec62013-08-26 12:23:46 +0000868 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
cristy4c08aed2011-07-01 19:47:50 +0000869 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000870 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000871 }
cristy67d16d92013-09-29 18:31:17 +0000872 break;
cristye90d7402010-03-14 18:21:29 +0000873 }
cristy67d16d92013-09-29 18:31:17 +0000874 if (image->depth <= 16)
cristye90d7402010-03-14 18:21:29 +0000875 {
876 unsigned short
877 pixel;
878
cristybb503372010-05-27 20:51:26 +0000879 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000880 {
881 p=PushShortPixel(MSBEndian,p,&pixel);
cristy92beec62013-08-26 12:23:46 +0000882 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
cristye90d7402010-03-14 18:21:29 +0000883 p=PushShortPixel(MSBEndian,p,&pixel);
cristy92beec62013-08-26 12:23:46 +0000884 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
cristye90d7402010-03-14 18:21:29 +0000885 p=PushShortPixel(MSBEndian,p,&pixel);
cristy92beec62013-08-26 12:23:46 +0000886 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
cristy4c08aed2011-07-01 19:47:50 +0000887 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000888 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000889 }
cristy67d16d92013-09-29 18:31:17 +0000890 break;
cristye90d7402010-03-14 18:21:29 +0000891 }
cristy67d16d92013-09-29 18:31:17 +0000892 for (x=0; x < (ssize_t) image->columns; x++)
893 {
894 p=PushLongPixel(MSBEndian,p,&pixel);
895 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
896 p=PushLongPixel(MSBEndian,p,&pixel);
897 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
898 p=PushLongPixel(MSBEndian,p,&pixel);
899 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
900 SetPixelAlpha(image,OpaqueAlpha,q);
901 q+=GetPixelChannels(image);
902 }
903 break;
904 }
905 }
cristyaa740112010-03-30 17:58:44 +0000906 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000907 if (sync == MagickFalse)
908 status=MagickFalse;
909 }
cristy3ed852e2009-09-05 21:47:34 +0000910 quantum_info=DestroyQuantumInfo(quantum_info);
911 if (status == MagickFalse)
912 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
cristy3ed852e2009-09-05 21:47:34 +0000913 break;
914 }
915 case '7':
916 {
cristybb503372010-05-27 20:51:26 +0000917 size_t
cristy3ed852e2009-09-05 21:47:34 +0000918 channels;
919
920 /*
921 Convert PAM raster image to pixel packets.
922 */
cristy3ed852e2009-09-05 21:47:34 +0000923 switch (quantum_type)
924 {
925 case GrayQuantum:
926 case GrayAlphaQuantum:
927 {
928 channels=1;
929 break;
930 }
931 case CMYKQuantum:
932 case CMYKAQuantum:
933 {
934 channels=4;
935 break;
936 }
937 default:
938 {
939 channels=3;
940 break;
941 }
942 }
cristy17f11b02014-12-20 19:37:04 +0000943 if (image->alpha_trait != UndefinedPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +0000944 channels++;
cristy67d16d92013-09-29 18:31:17 +0000945 if (image->depth <= 8)
946 extent=channels*image->columns;
947 else
948 if (image->depth <= 16)
949 extent=2*channels*image->columns;
950 else
951 extent=4*channels*image->columns;
cristy5f766ef2014-12-14 21:12:47 +0000952 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +0000953 if (quantum_info == (QuantumInfo *) NULL)
954 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000955 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000956 {
cristyb1253cd2015-05-31 01:06:54 +0000957 const unsigned char
cristybd797f12015-01-24 20:42:32 +0000958 *pixels;
959
cristy3ed852e2009-09-05 21:47:34 +0000960 MagickBooleanType
961 sync;
962
963 register const unsigned char
dirk05d2ff72015-11-18 23:13:43 +0100964 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000965
cristybb503372010-05-27 20:51:26 +0000966 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000967 x;
968
cristy4c08aed2011-07-01 19:47:50 +0000969 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100970 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000971
972 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000973 count,
974 offset;
cristy3ed852e2009-09-05 21:47:34 +0000975
cristy3ed852e2009-09-05 21:47:34 +0000976 if (status == MagickFalse)
977 continue;
cristyb1253cd2015-05-31 01:06:54 +0000978 pixels=(unsigned char *) ReadBlobStream(image,extent,
979 GetQuantumPixels(quantum_info),&count);
cristy3ed852e2009-09-05 21:47:34 +0000980 if (count != (ssize_t) extent)
981 status=MagickFalse;
cristybd797f12015-01-24 20:42:32 +0000982 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
983 (image->previous == (Image *) NULL))
984 {
985 MagickBooleanType
986 proceed;
987
988 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
989 row,image->rows);
990 if (proceed == MagickFalse)
991 status=MagickFalse;
992 }
993 offset=row++;
cristyaa740112010-03-30 17:58:44 +0000994 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000995 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000996 {
997 status=MagickFalse;
998 continue;
999 }
cristy3ed852e2009-09-05 21:47:34 +00001000 p=pixels;
cristy67d16d92013-09-29 18:31:17 +00001001 switch (image->depth)
1002 {
1003 case 8:
1004 case 16:
1005 case 32:
cristy3ed852e2009-09-05 21:47:34 +00001006 {
cristy67d16d92013-09-29 18:31:17 +00001007 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1008 quantum_type,pixels,exception);
1009 break;
1010 }
1011 default:
1012 {
1013 switch (quantum_type)
cristy3ed852e2009-09-05 21:47:34 +00001014 {
cristy67d16d92013-09-29 18:31:17 +00001015 case GrayQuantum:
1016 case GrayAlphaQuantum:
1017 {
1018 unsigned int
1019 pixel;
cristy3ed852e2009-09-05 21:47:34 +00001020
cristy67d16d92013-09-29 18:31:17 +00001021 if (image->depth <= 8)
cristy3ed852e2009-09-05 21:47:34 +00001022 {
cristy67d16d92013-09-29 18:31:17 +00001023 unsigned char
1024 pixel;
cristy3ed852e2009-09-05 21:47:34 +00001025
cristy67d16d92013-09-29 18:31:17 +00001026 for (x=0; x < (ssize_t) image->columns; x++)
1027 {
1028 p=PushCharPixel(p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001029 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),
1030 q);
cristy67d16d92013-09-29 18:31:17 +00001031 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001032 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001033 {
1034 p=PushCharPixel(p,&pixel);
cristyfbcb8172014-03-01 13:21:16 +00001035 if (image->depth != 1)
1036 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1037 max_value),q);
1038 else
1039 SetPixelAlpha(image,QuantumRange-
1040 ScaleAnyToQuantum(pixel,max_value),q);
cristy67d16d92013-09-29 18:31:17 +00001041 }
1042 q+=GetPixelChannels(image);
1043 }
1044 break;
cristy3ed852e2009-09-05 21:47:34 +00001045 }
cristy67d16d92013-09-29 18:31:17 +00001046 if (image->depth <= 16)
1047 {
1048 unsigned short
1049 pixel;
cristy3ed852e2009-09-05 21:47:34 +00001050
cristy67d16d92013-09-29 18:31:17 +00001051 for (x=0; x < (ssize_t) image->columns; x++)
1052 {
1053 p=PushShortPixel(MSBEndian,p,&pixel);
cristyfbcb8172014-03-01 13:21:16 +00001054 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),
1055 q);
cristy67d16d92013-09-29 18:31:17 +00001056 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001057 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001058 {
1059 p=PushShortPixel(MSBEndian,p,&pixel);
1060 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1061 max_value),q);
1062 }
1063 q+=GetPixelChannels(image);
1064 }
1065 break;
cristy3ed852e2009-09-05 21:47:34 +00001066 }
cristy67d16d92013-09-29 18:31:17 +00001067 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001068 {
cristy67d16d92013-09-29 18:31:17 +00001069 p=PushLongPixel(MSBEndian,p,&pixel);
1070 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
1071 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001072 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001073 {
1074 p=PushLongPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001075 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,max_value),
1076 q);
cristy67d16d92013-09-29 18:31:17 +00001077 }
1078 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001079 }
cristy67d16d92013-09-29 18:31:17 +00001080 break;
1081 }
1082 case CMYKQuantum:
1083 case CMYKAQuantum:
1084 {
1085 unsigned int
1086 pixel;
1087
1088 if (image->depth <= 8)
1089 {
1090 unsigned char
1091 pixel;
1092
1093 for (x=0; x < (ssize_t) image->columns; x++)
1094 {
1095 p=PushCharPixel(p,&pixel);
1096 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1097 p=PushCharPixel(p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001098 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
1099 q);
cristy67d16d92013-09-29 18:31:17 +00001100 p=PushCharPixel(p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001101 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
1102 q);
cristy67d16d92013-09-29 18:31:17 +00001103 p=PushCharPixel(p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001104 SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),
1105 q);
cristy67d16d92013-09-29 18:31:17 +00001106 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001107 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001108 {
1109 p=PushCharPixel(p,&pixel);
1110 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1111 max_value),q);
1112 }
1113 q+=GetPixelChannels(image);
1114 }
1115 break;
1116 }
1117 if (image->depth <= 16)
1118 {
1119 unsigned short
1120 pixel;
1121
1122 for (x=0; x < (ssize_t) image->columns; x++)
1123 {
1124 p=PushShortPixel(MSBEndian,p,&pixel);
1125 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1126 p=PushShortPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001127 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
1128 q);
cristy67d16d92013-09-29 18:31:17 +00001129 p=PushShortPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001130 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
1131 q);
cristy67d16d92013-09-29 18:31:17 +00001132 p=PushShortPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001133 SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),
1134 q);
cristy67d16d92013-09-29 18:31:17 +00001135 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001136 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001137 {
1138 p=PushShortPixel(MSBEndian,p,&pixel);
1139 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1140 max_value),q);
1141 }
1142 q+=GetPixelChannels(image);
1143 }
1144 }
1145 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001146 {
cristy67d16d92013-09-29 18:31:17 +00001147 p=PushLongPixel(MSBEndian,p,&pixel);
1148 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1149 p=PushLongPixel(MSBEndian,p,&pixel);
1150 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
1151 p=PushLongPixel(MSBEndian,p,&pixel);
1152 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
1153 p=PushLongPixel(MSBEndian,p,&pixel);
1154 SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),q);
1155 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001156 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001157 {
1158 p=PushLongPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001159 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,max_value),
1160 q);
cristy67d16d92013-09-29 18:31:17 +00001161 }
1162 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001163 }
cristy67d16d92013-09-29 18:31:17 +00001164 break;
1165 }
1166 default:
1167 {
1168 unsigned int
1169 pixel;
1170
1171 if (image->depth <= 8)
1172 {
1173 unsigned char
1174 pixel;
1175
1176 for (x=0; x < (ssize_t) image->columns; x++)
1177 {
1178 p=PushCharPixel(p,&pixel);
1179 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1180 p=PushCharPixel(p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001181 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
1182 q);
cristy67d16d92013-09-29 18:31:17 +00001183 p=PushCharPixel(p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001184 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
1185 q);
cristy67d16d92013-09-29 18:31:17 +00001186 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001187 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001188 {
1189 p=PushCharPixel(p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001190 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1191 max_value),q);
cristy67d16d92013-09-29 18:31:17 +00001192 }
1193 q+=GetPixelChannels(image);
1194 }
1195 break;
1196 }
1197 if (image->depth <= 16)
1198 {
1199 unsigned short
1200 pixel;
1201
1202 for (x=0; x < (ssize_t) image->columns; x++)
1203 {
1204 p=PushShortPixel(MSBEndian,p,&pixel);
1205 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1206 p=PushShortPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001207 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
1208 q);
cristy67d16d92013-09-29 18:31:17 +00001209 p=PushShortPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001210 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
1211 q);
cristy67d16d92013-09-29 18:31:17 +00001212 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001213 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001214 {
1215 p=PushShortPixel(MSBEndian,p,&pixel);
1216 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1217 max_value),q);
1218 }
1219 q+=GetPixelChannels(image);
1220 }
1221 break;
1222 }
1223 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001224 {
cristy67d16d92013-09-29 18:31:17 +00001225 p=PushLongPixel(MSBEndian,p,&pixel);
1226 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1227 p=PushLongPixel(MSBEndian,p,&pixel);
1228 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
1229 p=PushLongPixel(MSBEndian,p,&pixel);
1230 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
1231 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001232 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001233 {
1234 p=PushLongPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001235 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,max_value),
1236 q);
cristy67d16d92013-09-29 18:31:17 +00001237 }
1238 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001239 }
cristy67d16d92013-09-29 18:31:17 +00001240 break;
1241 }
cristy3ed852e2009-09-05 21:47:34 +00001242 }
1243 }
cristy67d16d92013-09-29 18:31:17 +00001244 }
cristyaa740112010-03-30 17:58:44 +00001245 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001246 if (sync == MagickFalse)
1247 status=MagickFalse;
1248 }
cristy3ed852e2009-09-05 21:47:34 +00001249 quantum_info=DestroyQuantumInfo(quantum_info);
1250 if (status == MagickFalse)
1251 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1252 SetQuantumImageType(image,quantum_type);
1253 break;
1254 }
1255 case 'F':
1256 case 'f':
1257 {
1258 /*
1259 Convert PFM raster image to pixel packets.
1260 */
cristyaf6eb932012-01-01 01:22:59 +00001261 if (format == 'f')
cristy4e285b92013-05-24 17:42:57 +00001262 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +00001263 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
1264 image->endian=quantum_scale < 0.0 ? LSBEndian : MSBEndian;
1265 image->depth=32;
cristy5f766ef2014-12-14 21:12:47 +00001266 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +00001267 if (quantum_info == (QuantumInfo *) NULL)
1268 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1269 status=SetQuantumDepth(image,quantum_info,32);
1270 if (status == MagickFalse)
1271 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1272 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1273 if (status == MagickFalse)
1274 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristy243166e2012-11-03 19:16:10 +00001275 SetQuantumScale(quantum_info,(double) QuantumRange*fabs(quantum_scale));
cristy3ed852e2009-09-05 21:47:34 +00001276 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +00001277 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001278 {
cristyb1253cd2015-05-31 01:06:54 +00001279 const unsigned char
cristybd797f12015-01-24 20:42:32 +00001280 *pixels;
1281
cristy3ed852e2009-09-05 21:47:34 +00001282 MagickBooleanType
1283 sync;
1284
cristy4c08aed2011-07-01 19:47:50 +00001285 register Quantum
dirk05d2ff72015-11-18 23:13:43 +01001286 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001287
1288 ssize_t
cristyaff6d802011-04-26 01:46:31 +00001289 count,
1290 offset;
cristy3ed852e2009-09-05 21:47:34 +00001291
1292 size_t
1293 length;
1294
cristy3ed852e2009-09-05 21:47:34 +00001295 if (status == MagickFalse)
1296 continue;
cristyb1253cd2015-05-31 01:06:54 +00001297 pixels=(unsigned char *) ReadBlobStream(image,extent,
1298 GetQuantumPixels(quantum_info),&count);
cristy3ed852e2009-09-05 21:47:34 +00001299 if ((size_t) count != extent)
1300 status=MagickFalse;
cristybd797f12015-01-24 20:42:32 +00001301 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1302 (image->previous == (Image *) NULL))
1303 {
1304 MagickBooleanType
1305 proceed;
1306
1307 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1308 row,image->rows);
1309 if (proceed == MagickFalse)
1310 status=MagickFalse;
1311 }
1312 offset=row++;
cristybb503372010-05-27 20:51:26 +00001313 q=QueueAuthenticPixels(image,0,(ssize_t) (image->rows-offset-1),
cristyaa740112010-03-30 17:58:44 +00001314 image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00001315 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001316 {
1317 status=MagickFalse;
1318 continue;
1319 }
cristyaa740112010-03-30 17:58:44 +00001320 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1321 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001322 if (length != extent)
1323 status=MagickFalse;
cristyaa740112010-03-30 17:58:44 +00001324 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001325 if (sync == MagickFalse)
1326 status=MagickFalse;
1327 }
cristy3ed852e2009-09-05 21:47:34 +00001328 quantum_info=DestroyQuantumInfo(quantum_info);
1329 if (status == MagickFalse)
1330 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1331 SetQuantumImageType(image,quantum_type);
1332 break;
1333 }
1334 default:
1335 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1336 }
1337 if (EOFBlob(image) != MagickFalse)
cristy5d792232012-01-31 17:02:45 +00001338 {
1339 (void) ThrowMagickException(exception,GetMagickModule(),
1340 CorruptImageError,"UnexpectedEndOfFile","`%s'",image->filename);
1341 break;
1342 }
cristy3ed852e2009-09-05 21:47:34 +00001343 /*
1344 Proceed to next image.
1345 */
1346 if (image_info->number_scenes != 0)
1347 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1348 break;
1349 if ((format == '1') || (format == '2') || (format == '3'))
1350 do
1351 {
1352 /*
1353 Skip to end of line.
1354 */
1355 count=ReadBlob(image,1,(unsigned char *) &format);
cristy771c8842015-01-09 12:13:22 +00001356 if (count != 1)
cristy3ed852e2009-09-05 21:47:34 +00001357 break;
cristy771c8842015-01-09 12:13:22 +00001358 if (format == 'P')
cristy3ed852e2009-09-05 21:47:34 +00001359 break;
1360 } while (format != '\n');
1361 count=ReadBlob(image,1,(unsigned char *) &format);
1362 if ((count == 1) && (format == 'P'))
1363 {
1364 /*
1365 Allocate next image structure.
1366 */
cristy9950d572011-10-01 18:22:35 +00001367 AcquireNextImage(image_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001368 if (GetNextImageInList(image) == (Image *) NULL)
1369 {
1370 image=DestroyImageList(image);
1371 return((Image *) NULL);
1372 }
1373 image=SyncNextImageInList(image);
1374 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1375 GetBlobSize(image));
1376 if (status == MagickFalse)
1377 break;
1378 }
1379 } while ((count == 1) && (format == 'P'));
1380 (void) CloseBlob(image);
1381 return(GetFirstImageInList(image));
1382}
1383
1384/*
1385%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1386% %
1387% %
1388% %
1389% R e g i s t e r P N M I m a g e %
1390% %
1391% %
1392% %
1393%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1394%
1395% RegisterPNMImage() adds properties for the PNM image format to
1396% the list of supported formats. The properties include the image format
1397% tag, a method to read and/or write the format, whether the format
1398% supports the saving of more than one frame to the same file or blob,
1399% whether the format supports native in-memory I/O, and a brief
1400% description of the format.
1401%
1402% The format of the RegisterPNMImage method is:
1403%
cristybb503372010-05-27 20:51:26 +00001404% size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001405%
1406*/
cristybb503372010-05-27 20:51:26 +00001407ModuleExport size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001408{
1409 MagickInfo
1410 *entry;
1411
dirk06b627a2015-04-06 18:59:17 +00001412 entry=AcquireMagickInfo("PNM","PAM","Common 2-dimensional bitmap format");
cristy3ed852e2009-09-05 21:47:34 +00001413 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1414 entry->encoder=(EncodeImageHandler *) WritePNMImage;
cristyf0d061c2013-08-09 12:17:54 +00001415 entry->mime_type=ConstantString("image/x-portable-pixmap");
cristy3ed852e2009-09-05 21:47:34 +00001416 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +00001417 entry=AcquireMagickInfo("PNM","PBM",
1418 "Portable bitmap format (black and white)");
cristy3ed852e2009-09-05 21:47:34 +00001419 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1420 entry->encoder=(EncodeImageHandler *) WritePNMImage;
cristyf0d061c2013-08-09 12:17:54 +00001421 entry->mime_type=ConstantString("image/x-portable-bitmap");
cristy3ed852e2009-09-05 21:47:34 +00001422 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +00001423 entry=AcquireMagickInfo("PNM","PFM","Portable float format");
cristy3ed852e2009-09-05 21:47:34 +00001424 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1425 entry->encoder=(EncodeImageHandler *) WritePNMImage;
dirk08e9a112015-02-22 01:51:41 +00001426 entry->flags|=CoderEndianSupportFlag;
cristy3ed852e2009-09-05 21:47:34 +00001427 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +00001428 entry=AcquireMagickInfo("PNM","PGM","Portable graymap format (gray scale)");
cristy3ed852e2009-09-05 21:47:34 +00001429 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1430 entry->encoder=(EncodeImageHandler *) WritePNMImage;
cristyf0d061c2013-08-09 12:17:54 +00001431 entry->mime_type=ConstantString("image/x-portable-greymap");
cristy3ed852e2009-09-05 21:47:34 +00001432 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +00001433 entry=AcquireMagickInfo("PNM","PNM","Portable anymap");
cristy3ed852e2009-09-05 21:47:34 +00001434 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1435 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1436 entry->magick=(IsImageFormatHandler *) IsPNM;
cristyf0d061c2013-08-09 12:17:54 +00001437 entry->mime_type=ConstantString("image/x-portable-pixmap");
cristy3ed852e2009-09-05 21:47:34 +00001438 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +00001439 entry=AcquireMagickInfo("PNM","PPM","Portable pixmap format (color)");
cristy3ed852e2009-09-05 21:47:34 +00001440 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1441 entry->encoder=(EncodeImageHandler *) WritePNMImage;
cristyf0d061c2013-08-09 12:17:54 +00001442 entry->mime_type=ConstantString("image/x-portable-pixmap");
cristy3ed852e2009-09-05 21:47:34 +00001443 (void) RegisterMagickInfo(entry);
1444 return(MagickImageCoderSignature);
1445}
1446
1447/*
1448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1449% %
1450% %
1451% %
1452% U n r e g i s t e r P N M I m a g e %
1453% %
1454% %
1455% %
1456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1457%
1458% UnregisterPNMImage() removes format registrations made by the
1459% PNM module from the list of supported formats.
1460%
1461% The format of the UnregisterPNMImage method is:
1462%
1463% UnregisterPNMImage(void)
1464%
1465*/
1466ModuleExport void UnregisterPNMImage(void)
1467{
1468 (void) UnregisterMagickInfo("PAM");
1469 (void) UnregisterMagickInfo("PBM");
1470 (void) UnregisterMagickInfo("PGM");
1471 (void) UnregisterMagickInfo("PNM");
1472 (void) UnregisterMagickInfo("PPM");
1473}
1474
1475/*
1476%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1477% %
1478% %
1479% %
1480% W r i t e P N M I m a g e %
1481% %
1482% %
1483% %
1484%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1485%
cristy661b5ad2010-01-13 00:54:42 +00001486% WritePNMImage() writes an image to a file in the PNM rasterfile format.
cristy3ed852e2009-09-05 21:47:34 +00001487%
1488% The format of the WritePNMImage method is:
1489%
cristy1e178e72011-08-28 19:44:34 +00001490% MagickBooleanType WritePNMImage(const ImageInfo *image_info,
1491% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001492%
1493% A description of each parameter follows.
1494%
1495% o image_info: the image info.
1496%
1497% o image: The image.
1498%
cristy1e178e72011-08-28 19:44:34 +00001499% o exception: return any errors or warnings in this structure.
1500%
cristy3ed852e2009-09-05 21:47:34 +00001501*/
cristy1e178e72011-08-28 19:44:34 +00001502static MagickBooleanType WritePNMImage(const ImageInfo *image_info,Image *image,
1503 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001504{
1505 char
cristy151b66d2015-04-15 10:50:31 +00001506 buffer[MagickPathExtent],
cristy3ed852e2009-09-05 21:47:34 +00001507 format,
cristy151b66d2015-04-15 10:50:31 +00001508 magick[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00001509
1510 const char
1511 *value;
1512
cristy3ed852e2009-09-05 21:47:34 +00001513 MagickBooleanType
1514 status;
1515
1516 MagickOffsetType
1517 scene;
1518
cristy4c08aed2011-07-01 19:47:50 +00001519 Quantum
1520 index;
1521
cristy3ed852e2009-09-05 21:47:34 +00001522 QuantumAny
1523 pixel;
1524
1525 QuantumInfo
1526 *quantum_info;
1527
1528 QuantumType
1529 quantum_type;
1530
cristy3ed852e2009-09-05 21:47:34 +00001531 register unsigned char
1532 *pixels,
1533 *q;
1534
cristy3ed852e2009-09-05 21:47:34 +00001535 size_t
1536 extent,
1537 packet_size;
1538
cristy95802a72010-09-05 19:07:17 +00001539 ssize_t
cristyaff6d802011-04-26 01:46:31 +00001540 count,
1541 y;
cristy95802a72010-09-05 19:07:17 +00001542
cristy3ed852e2009-09-05 21:47:34 +00001543 /*
1544 Open output image file.
1545 */
1546 assert(image_info != (const ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001547 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001548 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001549 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001550 if (image->debug != MagickFalse)
1551 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy3a37efd2011-08-28 20:31:03 +00001552 assert(exception != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001553 assert(exception->signature == MagickCoreSignature);
cristy1e178e72011-08-28 19:44:34 +00001554 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy3ed852e2009-09-05 21:47:34 +00001555 if (status == MagickFalse)
1556 return(status);
1557 scene=0;
1558 do
1559 {
cristy92beec62013-08-26 12:23:46 +00001560 QuantumAny
1561 max_value;
1562
cristy3ed852e2009-09-05 21:47:34 +00001563 /*
1564 Write PNM file header.
1565 */
1566 packet_size=3;
1567 quantum_type=RGBQuantum;
cristy151b66d2015-04-15 10:50:31 +00001568 (void) CopyMagickString(magick,image_info->magick,MagickPathExtent);
cristy92beec62013-08-26 12:23:46 +00001569 max_value=GetQuantumRange(image->depth);
cristy3ed852e2009-09-05 21:47:34 +00001570 switch (magick[1])
1571 {
1572 case 'A':
1573 case 'a':
1574 {
1575 format='7';
1576 break;
1577 }
1578 case 'B':
1579 case 'b':
1580 {
1581 format='4';
1582 if (image_info->compression == NoCompression)
1583 format='1';
1584 break;
1585 }
1586 case 'F':
1587 case 'f':
1588 {
1589 format='F';
dirkf1d85482015-04-06 00:36:00 +00001590 if (SetImageGray(image,exception) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001591 format='f';
1592 break;
1593 }
1594 case 'G':
1595 case 'g':
1596 {
1597 format='5';
1598 if (image_info->compression == NoCompression)
1599 format='2';
1600 break;
1601 }
1602 case 'N':
1603 case 'n':
1604 {
1605 if ((image_info->type != TrueColorType) &&
dirkf1d85482015-04-06 00:36:00 +00001606 (SetImageGray(image,exception) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001607 {
1608 format='5';
1609 if (image_info->compression == NoCompression)
1610 format='2';
dirkf1d85482015-04-06 00:36:00 +00001611 if (SetImageMonochrome(image,exception) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001612 {
1613 format='4';
1614 if (image_info->compression == NoCompression)
1615 format='1';
1616 }
1617 break;
1618 }
1619 }
1620 default:
1621 {
1622 format='6';
1623 if (image_info->compression == NoCompression)
1624 format='3';
1625 break;
1626 }
1627 }
cristy151b66d2015-04-15 10:50:31 +00001628 (void) FormatLocaleString(buffer,MagickPathExtent,"P%c\n",format);
cristy3ed852e2009-09-05 21:47:34 +00001629 (void) WriteBlobString(image,buffer);
cristyd15e6592011-10-15 00:13:06 +00001630 value=GetImageProperty(image,"comment",exception);
cristy3ed852e2009-09-05 21:47:34 +00001631 if (value != (const char *) NULL)
1632 {
1633 register const char
1634 *p;
1635
1636 /*
1637 Write comments to file.
1638 */
1639 (void) WriteBlobByte(image,'#');
1640 for (p=value; *p != '\0'; p++)
1641 {
1642 (void) WriteBlobByte(image,(unsigned char) *p);
cristy542ea782013-05-24 15:53:01 +00001643 if ((*p == '\n') || (*p == '\r'))
cristy3ed852e2009-09-05 21:47:34 +00001644 (void) WriteBlobByte(image,'#');
1645 }
1646 (void) WriteBlobByte(image,'\n');
1647 }
1648 if (format != '7')
1649 {
cristy151b66d2015-04-15 10:50:31 +00001650 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g\n",
cristye8c25f92010-06-03 00:53:06 +00001651 (double) image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001652 (void) WriteBlobString(image,buffer);
1653 }
1654 else
1655 {
1656 char
cristy151b66d2015-04-15 10:50:31 +00001657 type[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00001658
1659 /*
1660 PAM header.
1661 */
cristy151b66d2015-04-15 10:50:31 +00001662 (void) FormatLocaleString(buffer,MagickPathExtent,
cristye8c25f92010-06-03 00:53:06 +00001663 "WIDTH %.20g\nHEIGHT %.20g\n",(double) image->columns,(double)
1664 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001665 (void) WriteBlobString(image,buffer);
cristy1e178e72011-08-28 19:44:34 +00001666 quantum_type=GetQuantumType(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001667 switch (quantum_type)
1668 {
1669 case CMYKQuantum:
1670 case CMYKAQuantum:
1671 {
1672 packet_size=4;
cristy151b66d2015-04-15 10:50:31 +00001673 (void) CopyMagickString(type,"CMYK",MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001674 break;
1675 }
1676 case GrayQuantum:
1677 case GrayAlphaQuantum:
1678 {
1679 packet_size=1;
cristy151b66d2015-04-15 10:50:31 +00001680 (void) CopyMagickString(type,"GRAYSCALE",MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001681 break;
1682 }
1683 default:
1684 {
1685 quantum_type=RGBQuantum;
cristy17f11b02014-12-20 19:37:04 +00001686 if (image->alpha_trait != UndefinedPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00001687 quantum_type=RGBAQuantum;
1688 packet_size=3;
cristy151b66d2015-04-15 10:50:31 +00001689 (void) CopyMagickString(type,"RGB",MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001690 break;
1691 }
1692 }
cristy17f11b02014-12-20 19:37:04 +00001693 if (image->alpha_trait != UndefinedPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00001694 {
1695 packet_size++;
cristy151b66d2015-04-15 10:50:31 +00001696 (void) ConcatenateMagickString(type,"_ALPHA",MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001697 }
cristy67d16d92013-09-29 18:31:17 +00001698 if (image->depth > 32)
1699 image->depth=32;
cristy151b66d2015-04-15 10:50:31 +00001700 (void) FormatLocaleString(buffer,MagickPathExtent,
cristye8c25f92010-06-03 00:53:06 +00001701 "DEPTH %.20g\nMAXVAL %.20g\n",(double) packet_size,(double)
cristy2b9582a2011-07-04 17:38:56 +00001702 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001703 (void) WriteBlobString(image,buffer);
cristy6b675d12015-05-22 22:15:18 +00001704 (void) FormatLocaleString(buffer,MagickPathExtent,"TUPLTYPE %s\nENDHDR\n",
1705 type);
cristy3ed852e2009-09-05 21:47:34 +00001706 (void) WriteBlobString(image,buffer);
1707 }
1708 /*
1709 Convert runextent encoded to PNM raster pixels.
1710 */
1711 switch (format)
1712 {
1713 case '1':
1714 {
cristy661b5ad2010-01-13 00:54:42 +00001715 unsigned char
1716 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001717
1718 /*
1719 Convert image to a PBM image.
1720 */
cristy7a4c0972013-11-22 17:48:43 +00001721 (void) SetImageType(image,BilevelType,exception);
cristy661b5ad2010-01-13 00:54:42 +00001722 q=pixels;
cristybb503372010-05-27 20:51:26 +00001723 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001724 {
cristy4c08aed2011-07-01 19:47:50 +00001725 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001726 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001727
cristybb503372010-05-27 20:51:26 +00001728 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001729 x;
1730
cristy1e178e72011-08-28 19:44:34 +00001731 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001732 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001733 break;
cristybb503372010-05-27 20:51:26 +00001734 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001735 {
cristy7a4c0972013-11-22 17:48:43 +00001736 *q++=(unsigned char) (GetPixelLuma(image,p) >= (QuantumRange/2.0) ?
cristy661b5ad2010-01-13 00:54:42 +00001737 '0' : '1');
1738 *q++=' ';
cristyb1253cd2015-05-31 01:06:54 +00001739 if ((q-pixels+1) >= (ssize_t) sizeof(pixels))
cristy6b675d12015-05-22 22:15:18 +00001740 {
1741 *q++='\n';
1742 (void) WriteBlob(image,q-pixels,pixels);
1743 q=pixels;
1744 }
cristyed231572011-07-14 02:18:59 +00001745 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001746 }
cristy1446bc92015-05-22 21:32:42 +00001747 *q++='\n';
1748 (void) WriteBlob(image,q-pixels,pixels);
1749 q=pixels;
cristy3ed852e2009-09-05 21:47:34 +00001750 if (image->previous == (Image *) NULL)
1751 {
cristycee97112010-05-28 00:44:52 +00001752 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1753 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001754 if (status == MagickFalse)
1755 break;
1756 }
1757 }
cristy661b5ad2010-01-13 00:54:42 +00001758 if (q != pixels)
1759 {
1760 *q++='\n';
1761 (void) WriteBlob(image,q-pixels,pixels);
1762 }
cristy3ed852e2009-09-05 21:47:34 +00001763 break;
1764 }
1765 case '2':
1766 {
cristy661b5ad2010-01-13 00:54:42 +00001767 unsigned char
1768 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001769
1770 /*
1771 Convert image to a PGM image.
1772 */
1773 if (image->depth <= 8)
1774 (void) WriteBlobString(image,"255\n");
1775 else
cristy67d16d92013-09-29 18:31:17 +00001776 if (image->depth <= 16)
1777 (void) WriteBlobString(image,"65535\n");
1778 else
1779 (void) WriteBlobString(image,"4294967295\n");
cristy661b5ad2010-01-13 00:54:42 +00001780 q=pixels;
cristybb503372010-05-27 20:51:26 +00001781 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001782 {
cristy4c08aed2011-07-01 19:47:50 +00001783 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001784 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001785
cristybb503372010-05-27 20:51:26 +00001786 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001787 x;
1788
cristy1e178e72011-08-28 19:44:34 +00001789 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001790 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001791 break;
cristybb503372010-05-27 20:51:26 +00001792 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001793 {
cristyd0323222013-04-07 16:13:21 +00001794 index=ClampToQuantum(GetPixelLuma(image,p));
cristy3ed852e2009-09-05 21:47:34 +00001795 if (image->depth <= 8)
cristy151b66d2015-04-15 10:50:31 +00001796 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,"%u ",
cristy3ed852e2009-09-05 21:47:34 +00001797 ScaleQuantumToChar(index));
1798 else
cristy67d16d92013-09-29 18:31:17 +00001799 if (image->depth <= 16)
cristy1446bc92015-05-22 21:32:42 +00001800 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
1801 "%u ",ScaleQuantumToShort(index));
cristy67d16d92013-09-29 18:31:17 +00001802 else
cristy1446bc92015-05-22 21:32:42 +00001803 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
1804 "%u ",ScaleQuantumToLong(index));
cristy661b5ad2010-01-13 00:54:42 +00001805 extent=(size_t) count;
1806 (void) strncpy((char *) q,buffer,extent);
1807 q+=extent;
cristy6b675d12015-05-22 22:15:18 +00001808 if ((q-pixels+extent+1) >= sizeof(pixels))
cristy661b5ad2010-01-13 00:54:42 +00001809 {
1810 *q++='\n';
1811 (void) WriteBlob(image,q-pixels,pixels);
1812 q=pixels;
1813 }
cristyed231572011-07-14 02:18:59 +00001814 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001815 }
cristy6b675d12015-05-22 22:15:18 +00001816 *q++='\n';
1817 (void) WriteBlob(image,q-pixels,pixels);
1818 q=pixels;
cristy3ed852e2009-09-05 21:47:34 +00001819 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 }
cristy661b5ad2010-01-13 00:54:42 +00001827 if (q != pixels)
1828 {
1829 *q++='\n';
1830 (void) WriteBlob(image,q-pixels,pixels);
1831 }
cristy3ed852e2009-09-05 21:47:34 +00001832 break;
1833 }
1834 case '3':
1835 {
cristy661b5ad2010-01-13 00:54:42 +00001836 unsigned char
1837 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001838
1839 /*
1840 Convert image to a PNM image.
1841 */
cristyaf8d3912014-02-21 14:50:33 +00001842 (void) TransformImageColorspace(image,sRGBColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +00001843 if (image->depth <= 8)
1844 (void) WriteBlobString(image,"255\n");
1845 else
cristy67d16d92013-09-29 18:31:17 +00001846 if (image->depth <= 16)
1847 (void) WriteBlobString(image,"65535\n");
1848 else
1849 (void) WriteBlobString(image,"4294967295\n");
cristy661b5ad2010-01-13 00:54:42 +00001850 q=pixels;
cristybb503372010-05-27 20:51:26 +00001851 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001852 {
cristy4c08aed2011-07-01 19:47:50 +00001853 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001854 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001855
cristybb503372010-05-27 20:51:26 +00001856 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001857 x;
1858
cristy1e178e72011-08-28 19:44:34 +00001859 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001860 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001861 break;
cristybb503372010-05-27 20:51:26 +00001862 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001863 {
1864 if (image->depth <= 8)
cristy151b66d2015-04-15 10:50:31 +00001865 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
cristy4c08aed2011-07-01 19:47:50 +00001866 "%u %u %u ",ScaleQuantumToChar(GetPixelRed(image,p)),
1867 ScaleQuantumToChar(GetPixelGreen(image,p)),
1868 ScaleQuantumToChar(GetPixelBlue(image,p)));
cristy3ed852e2009-09-05 21:47:34 +00001869 else
cristy67d16d92013-09-29 18:31:17 +00001870 if (image->depth <= 16)
cristy151b66d2015-04-15 10:50:31 +00001871 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
cristy67d16d92013-09-29 18:31:17 +00001872 "%u %u %u ",ScaleQuantumToShort(GetPixelRed(image,p)),
1873 ScaleQuantumToShort(GetPixelGreen(image,p)),
1874 ScaleQuantumToShort(GetPixelBlue(image,p)));
1875 else
cristy151b66d2015-04-15 10:50:31 +00001876 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
cristy67d16d92013-09-29 18:31:17 +00001877 "%u %u %u ",ScaleQuantumToLong(GetPixelRed(image,p)),
1878 ScaleQuantumToLong(GetPixelGreen(image,p)),
1879 ScaleQuantumToLong(GetPixelBlue(image,p)));
cristy661b5ad2010-01-13 00:54:42 +00001880 extent=(size_t) count;
1881 (void) strncpy((char *) q,buffer,extent);
1882 q+=extent;
cristy6b675d12015-05-22 22:15:18 +00001883 if ((q-pixels+extent+1) >= sizeof(pixels))
cristy661b5ad2010-01-13 00:54:42 +00001884 {
1885 *q++='\n';
1886 (void) WriteBlob(image,q-pixels,pixels);
1887 q=pixels;
1888 }
cristyed231572011-07-14 02:18:59 +00001889 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001890 }
cristy6b675d12015-05-22 22:15:18 +00001891 *q++='\n';
1892 (void) WriteBlob(image,q-pixels,pixels);
1893 q=pixels;
cristy3ed852e2009-09-05 21:47:34 +00001894 if (image->previous == (Image *) NULL)
1895 {
cristycee97112010-05-28 00:44:52 +00001896 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1897 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001898 if (status == MagickFalse)
1899 break;
1900 }
1901 }
cristy661b5ad2010-01-13 00:54:42 +00001902 if (q != pixels)
1903 {
1904 *q++='\n';
1905 (void) WriteBlob(image,q-pixels,pixels);
1906 }
cristy3ed852e2009-09-05 21:47:34 +00001907 break;
1908 }
1909 case '4':
1910 {
1911 /*
1912 Convert image to a PBM image.
1913 */
cristy7a4c0972013-11-22 17:48:43 +00001914 (void) SetImageType(image,BilevelType,exception);
cristy3ed852e2009-09-05 21:47:34 +00001915 image->depth=1;
cristy5f766ef2014-12-14 21:12:47 +00001916 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +00001917 if (quantum_info == (QuantumInfo *) NULL)
1918 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
cristy5b4868f2014-12-14 17:43:35 +00001919 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
cristy3ed852e2009-09-05 21:47:34 +00001920 quantum_info->min_is_white=MagickTrue;
cristy6b675d12015-05-22 22:15:18 +00001921 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00001922 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001923 {
cristy4c08aed2011-07-01 19:47:50 +00001924 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001925 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001926
cristy1e178e72011-08-28 19:44:34 +00001927 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001928 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001929 break;
cristy4c08aed2011-07-01 19:47:50 +00001930 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001931 GrayQuantum,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001932 count=WriteBlob(image,extent,pixels);
1933 if (count != (ssize_t) extent)
1934 break;
1935 if (image->previous == (Image *) NULL)
1936 {
cristycee97112010-05-28 00:44:52 +00001937 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1938 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001939 if (status == MagickFalse)
1940 break;
1941 }
1942 }
1943 quantum_info=DestroyQuantumInfo(quantum_info);
1944 break;
1945 }
1946 case '5':
1947 {
cristy3ed852e2009-09-05 21:47:34 +00001948 /*
1949 Convert image to a PGM image.
1950 */
cristy67d16d92013-09-29 18:31:17 +00001951 if (image->depth > 32)
cristyeff7fcc2013-09-30 10:27:08 +00001952 image->depth=32;
cristy151b66d2015-04-15 10:50:31 +00001953 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
cristy2b9582a2011-07-04 17:38:56 +00001954 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001955 (void) WriteBlobString(image,buffer);
cristy5f766ef2014-12-14 21:12:47 +00001956 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +00001957 if (quantum_info == (QuantumInfo *) NULL)
1958 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
cristy5b4868f2014-12-14 17:43:35 +00001959 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
cristy3ed852e2009-09-05 21:47:34 +00001960 quantum_info->min_is_white=MagickTrue;
cristy6b675d12015-05-22 22:15:18 +00001961 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001962 extent=GetQuantumExtent(image,quantum_info,GrayQuantum);
cristybb503372010-05-27 20:51:26 +00001963 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001964 {
cristy4c08aed2011-07-01 19:47:50 +00001965 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001966 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001967
cristybb503372010-05-27 20:51:26 +00001968 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001969 x;
1970
cristy1e178e72011-08-28 19:44:34 +00001971 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001972 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001973 break;
1974 q=pixels;
cristy67d16d92013-09-29 18:31:17 +00001975 switch (image->depth)
1976 {
1977 case 8:
1978 case 16:
1979 case 32:
1980 {
1981 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1982 GrayQuantum,pixels,exception);
1983 break;
1984 }
1985 default:
cristy3ed852e2009-09-05 21:47:34 +00001986 {
1987 if (image->depth <= 8)
cristy3ed852e2009-09-05 21:47:34 +00001988 {
cristy67d16d92013-09-29 18:31:17 +00001989 for (x=0; x < (ssize_t) image->columns; x++)
1990 {
1991 if (IsPixelGray(image,p) == MagickFalse)
1992 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(
1993 image,p)),max_value);
1994 else
1995 {
1996 if (image->depth == 8)
1997 pixel=ScaleQuantumToChar(GetPixelRed(image,p));
1998 else
cristyeff7fcc2013-09-30 10:27:08 +00001999 pixel=ScaleQuantumToAny(GetPixelRed(image,p),
2000 max_value);
cristy67d16d92013-09-29 18:31:17 +00002001 }
2002 q=PopCharPixel((unsigned char) pixel,q);
2003 p+=GetPixelChannels(image);
2004 }
cristy66d892b2013-10-03 11:39:44 +00002005 extent=(size_t) (q-pixels);
cristy67d16d92013-09-29 18:31:17 +00002006 break;
cristy3ed852e2009-09-05 21:47:34 +00002007 }
cristy67d16d92013-09-29 18:31:17 +00002008 if (image->depth <= 16)
cristy3ed852e2009-09-05 21:47:34 +00002009 {
cristy67d16d92013-09-29 18:31:17 +00002010 for (x=0; x < (ssize_t) image->columns; x++)
2011 {
2012 if (IsPixelGray(image,p) == MagickFalse)
cristyeff7fcc2013-09-30 10:27:08 +00002013 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(image,
2014 p)),max_value);
cristy67d16d92013-09-29 18:31:17 +00002015 else
2016 {
2017 if (image->depth == 16)
2018 pixel=ScaleQuantumToShort(GetPixelRed(image,p));
2019 else
cristyeff7fcc2013-09-30 10:27:08 +00002020 pixel=ScaleQuantumToAny(GetPixelRed(image,p),
2021 max_value);
cristy67d16d92013-09-29 18:31:17 +00002022 }
2023 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2024 p+=GetPixelChannels(image);
2025 }
cristy66d892b2013-10-03 11:39:44 +00002026 extent=(size_t) (q-pixels);
cristy67d16d92013-09-29 18:31:17 +00002027 break;
cristy3ed852e2009-09-05 21:47:34 +00002028 }
cristy67d16d92013-09-29 18:31:17 +00002029 for (x=0; x < (ssize_t) image->columns; x++)
2030 {
2031 if (IsPixelGray(image,p) == MagickFalse)
cristyeff7fcc2013-09-30 10:27:08 +00002032 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(image,p)),
2033 max_value);
cristy67d16d92013-09-29 18:31:17 +00002034 else
2035 {
2036 if (image->depth == 16)
2037 pixel=ScaleQuantumToLong(GetPixelRed(image,p));
2038 else
2039 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2040 }
2041 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2042 p+=GetPixelChannels(image);
2043 }
cristy3ed852e2009-09-05 21:47:34 +00002044 extent=(size_t) (q-pixels);
cristy67d16d92013-09-29 18:31:17 +00002045 break;
cristy3ed852e2009-09-05 21:47:34 +00002046 }
cristy67d16d92013-09-29 18:31:17 +00002047 }
cristy3ed852e2009-09-05 21:47:34 +00002048 count=WriteBlob(image,extent,pixels);
2049 if (count != (ssize_t) extent)
2050 break;
2051 if (image->previous == (Image *) NULL)
2052 {
cristycee97112010-05-28 00:44:52 +00002053 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2054 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002055 if (status == MagickFalse)
2056 break;
2057 }
2058 }
2059 quantum_info=DestroyQuantumInfo(quantum_info);
2060 break;
2061 }
2062 case '6':
2063 {
cristy3ed852e2009-09-05 21:47:34 +00002064 /*
2065 Convert image to a PNM image.
2066 */
cristyaf8d3912014-02-21 14:50:33 +00002067 (void) TransformImageColorspace(image,sRGBColorspace,exception);
cristy67d16d92013-09-29 18:31:17 +00002068 if (image->depth > 32)
2069 image->depth=32;
cristy151b66d2015-04-15 10:50:31 +00002070 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
cristy2b9582a2011-07-04 17:38:56 +00002071 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00002072 (void) WriteBlobString(image,buffer);
cristy5f766ef2014-12-14 21:12:47 +00002073 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +00002074 if (quantum_info == (QuantumInfo *) NULL)
2075 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
cristy70d7eae2012-11-17 19:40:21 +00002076 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
cristy6b675d12015-05-22 22:15:18 +00002077 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00002078 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +00002079 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002080 {
cristy4c08aed2011-07-01 19:47:50 +00002081 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01002082 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002083
cristybb503372010-05-27 20:51:26 +00002084 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002085 x;
2086
cristy1e178e72011-08-28 19:44:34 +00002087 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002088 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002089 break;
2090 q=pixels;
cristy67d16d92013-09-29 18:31:17 +00002091 switch (image->depth)
2092 {
2093 case 8:
2094 case 16:
2095 case 32:
2096 {
2097 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2098 quantum_type,pixels,exception);
2099 break;
2100 }
2101 default:
cristy3ed852e2009-09-05 21:47:34 +00002102 {
2103 if (image->depth <= 8)
cristy3ed852e2009-09-05 21:47:34 +00002104 {
cristy67d16d92013-09-29 18:31:17 +00002105 for (x=0; x < (ssize_t) image->columns; x++)
2106 {
2107 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2108 q=PopCharPixel((unsigned char) pixel,q);
2109 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2110 q=PopCharPixel((unsigned char) pixel,q);
2111 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2112 q=PopCharPixel((unsigned char) pixel,q);
2113 p+=GetPixelChannels(image);
2114 }
cristy5838dba2013-10-03 11:42:05 +00002115 extent=(size_t) (q-pixels);
cristy67d16d92013-09-29 18:31:17 +00002116 break;
cristy3ed852e2009-09-05 21:47:34 +00002117 }
cristy67d16d92013-09-29 18:31:17 +00002118 if (image->depth <= 16)
cristy3ed852e2009-09-05 21:47:34 +00002119 {
cristy67d16d92013-09-29 18:31:17 +00002120 for (x=0; x < (ssize_t) image->columns; x++)
2121 {
2122 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2123 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2124 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2125 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2126 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2127 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2128 p+=GetPixelChannels(image);
2129 }
cristy5838dba2013-10-03 11:42:05 +00002130 extent=(size_t) (q-pixels);
cristy67d16d92013-09-29 18:31:17 +00002131 break;
cristy3ed852e2009-09-05 21:47:34 +00002132 }
cristy67d16d92013-09-29 18:31:17 +00002133 for (x=0; x < (ssize_t) image->columns; x++)
2134 {
2135 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2136 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2137 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2138 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2139 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2140 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2141 p+=GetPixelChannels(image);
2142 }
cristy3ed852e2009-09-05 21:47:34 +00002143 extent=(size_t) (q-pixels);
cristy67d16d92013-09-29 18:31:17 +00002144 break;
cristy3ed852e2009-09-05 21:47:34 +00002145 }
cristy67d16d92013-09-29 18:31:17 +00002146 }
cristy3ed852e2009-09-05 21:47:34 +00002147 count=WriteBlob(image,extent,pixels);
2148 if (count != (ssize_t) extent)
2149 break;
2150 if (image->previous == (Image *) NULL)
2151 {
cristycee97112010-05-28 00:44:52 +00002152 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2153 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002154 if (status == MagickFalse)
2155 break;
2156 }
2157 }
2158 quantum_info=DestroyQuantumInfo(quantum_info);
2159 break;
2160 }
2161 case '7':
2162 {
cristy3ed852e2009-09-05 21:47:34 +00002163 /*
2164 Convert image to a PAM.
2165 */
cristy67d16d92013-09-29 18:31:17 +00002166 if (image->depth > 32)
2167 image->depth=32;
cristy5f766ef2014-12-14 21:12:47 +00002168 quantum_info=AcquireQuantumInfo(image_info,image);
cristy5b4868f2014-12-14 17:43:35 +00002169 if (quantum_info == (QuantumInfo *) NULL)
2170 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2171 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
cristy6b675d12015-05-22 22:15:18 +00002172 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002173 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002174 {
cristy4c08aed2011-07-01 19:47:50 +00002175 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01002176 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002177
cristybb503372010-05-27 20:51:26 +00002178 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002179 x;
2180
cristy1e178e72011-08-28 19:44:34 +00002181 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002182 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002183 break;
cristy3ed852e2009-09-05 21:47:34 +00002184 q=pixels;
cristy67d16d92013-09-29 18:31:17 +00002185 switch (image->depth)
2186 {
2187 case 8:
2188 case 16:
2189 case 32:
2190 {
2191 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2192 quantum_type,pixels,exception);
2193 break;
2194 }
2195 default:
cristy3ed852e2009-09-05 21:47:34 +00002196 {
2197 switch (quantum_type)
2198 {
2199 case GrayQuantum:
2200 case GrayAlphaQuantum:
2201 {
2202 if (image->depth <= 8)
cristy3ed852e2009-09-05 21:47:34 +00002203 {
cristy67d16d92013-09-29 18:31:17 +00002204 for (x=0; x < (ssize_t) image->columns; x++)
2205 {
2206 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(
2207 image,p)),max_value);
2208 q=PopCharPixel((unsigned char) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002209 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002210 {
2211 pixel=(unsigned char) ScaleQuantumToAny(
2212 GetPixelAlpha(image,p),max_value);
2213 q=PopCharPixel((unsigned char) pixel,q);
2214 }
2215 p+=GetPixelChannels(image);
2216 }
2217 break;
cristy3ed852e2009-09-05 21:47:34 +00002218 }
cristy67d16d92013-09-29 18:31:17 +00002219 if (image->depth <= 16)
cristy3ed852e2009-09-05 21:47:34 +00002220 {
cristy67d16d92013-09-29 18:31:17 +00002221 for (x=0; x < (ssize_t) image->columns; x++)
2222 {
2223 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(
2224 image,p)),max_value);
2225 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002226 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002227 {
2228 pixel=(unsigned char) ScaleQuantumToAny(
2229 GetPixelAlpha(image,p),max_value);
2230 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2231 }
2232 p+=GetPixelChannels(image);
2233 }
2234 break;
cristy3ed852e2009-09-05 21:47:34 +00002235 }
cristy67d16d92013-09-29 18:31:17 +00002236 for (x=0; x < (ssize_t) image->columns; x++)
2237 {
cristyeff7fcc2013-09-30 10:27:08 +00002238 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(image,
2239 p)),max_value);
cristy67d16d92013-09-29 18:31:17 +00002240 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002241 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002242 {
2243 pixel=(unsigned char) ScaleQuantumToAny(
2244 GetPixelAlpha(image,p),max_value);
2245 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2246 }
2247 p+=GetPixelChannels(image);
2248 }
cristy3ed852e2009-09-05 21:47:34 +00002249 break;
2250 }
2251 case CMYKQuantum:
2252 case CMYKAQuantum:
2253 {
2254 if (image->depth <= 8)
cristy3ed852e2009-09-05 21:47:34 +00002255 {
cristy67d16d92013-09-29 18:31:17 +00002256 for (x=0; x < (ssize_t) image->columns; x++)
2257 {
2258 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2259 q=PopCharPixel((unsigned char) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002260 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2261 max_value);
cristy67d16d92013-09-29 18:31:17 +00002262 q=PopCharPixel((unsigned char) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002263 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2264 max_value);
cristy67d16d92013-09-29 18:31:17 +00002265 q=PopCharPixel((unsigned char) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002266 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),
2267 max_value);
cristy67d16d92013-09-29 18:31:17 +00002268 q=PopCharPixel((unsigned char) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002269 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002270 {
2271 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2272 max_value);
2273 q=PopCharPixel((unsigned char) pixel,q);
2274 }
2275 p+=GetPixelChannels(image);
2276 }
2277 break;
cristy3ed852e2009-09-05 21:47:34 +00002278 }
cristy67d16d92013-09-29 18:31:17 +00002279 if (image->depth <= 16)
cristy3ed852e2009-09-05 21:47:34 +00002280 {
cristy67d16d92013-09-29 18:31:17 +00002281 for (x=0; x < (ssize_t) image->columns; x++)
2282 {
2283 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2284 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002285 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2286 max_value);
cristy67d16d92013-09-29 18:31:17 +00002287 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002288 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2289 max_value);
cristy67d16d92013-09-29 18:31:17 +00002290 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002291 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),
2292 max_value);
cristy67d16d92013-09-29 18:31:17 +00002293 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002294 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002295 {
2296 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2297 max_value);
2298 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2299 }
2300 p+=GetPixelChannels(image);
2301 }
2302 break;
cristy3ed852e2009-09-05 21:47:34 +00002303 }
cristy67d16d92013-09-29 18:31:17 +00002304 for (x=0; x < (ssize_t) image->columns; x++)
2305 {
2306 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2307 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2308 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2309 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2310 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2311 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2312 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),max_value);
2313 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002314 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002315 {
cristyeff7fcc2013-09-30 10:27:08 +00002316 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2317 max_value);
cristy67d16d92013-09-29 18:31:17 +00002318 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2319 }
2320 p+=GetPixelChannels(image);
2321 }
cristy3ed852e2009-09-05 21:47:34 +00002322 break;
2323 }
2324 default:
2325 {
2326 if (image->depth <= 8)
cristy3ed852e2009-09-05 21:47:34 +00002327 {
cristy67d16d92013-09-29 18:31:17 +00002328 for (x=0; x < (ssize_t) image->columns; x++)
2329 {
2330 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2331 q=PopCharPixel((unsigned char) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002332 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2333 max_value);
cristy67d16d92013-09-29 18:31:17 +00002334 q=PopCharPixel((unsigned char) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002335 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2336 max_value);
cristy67d16d92013-09-29 18:31:17 +00002337 q=PopCharPixel((unsigned char) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002338 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002339 {
2340 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2341 max_value);
2342 q=PopCharPixel((unsigned char) pixel,q);
2343 }
2344 p+=GetPixelChannels(image);
2345 }
2346 break;
cristy3ed852e2009-09-05 21:47:34 +00002347 }
cristy67d16d92013-09-29 18:31:17 +00002348 if (image->depth <= 16)
cristy3ed852e2009-09-05 21:47:34 +00002349 {
cristy67d16d92013-09-29 18:31:17 +00002350 for (x=0; x < (ssize_t) image->columns; x++)
2351 {
2352 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2353 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002354 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2355 max_value);
cristy67d16d92013-09-29 18:31:17 +00002356 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002357 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2358 max_value);
cristy67d16d92013-09-29 18:31:17 +00002359 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002360 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002361 {
2362 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2363 max_value);
2364 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2365 }
2366 p+=GetPixelChannels(image);
2367 }
2368 break;
cristy3ed852e2009-09-05 21:47:34 +00002369 }
cristy67d16d92013-09-29 18:31:17 +00002370 for (x=0; x < (ssize_t) image->columns; x++)
2371 {
2372 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2373 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2374 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2375 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2376 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2377 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002378 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002379 {
cristyeff7fcc2013-09-30 10:27:08 +00002380 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2381 max_value);
cristy67d16d92013-09-29 18:31:17 +00002382 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2383 }
2384 p+=GetPixelChannels(image);
2385 }
cristy3ed852e2009-09-05 21:47:34 +00002386 break;
2387 }
2388 }
2389 extent=(size_t) (q-pixels);
cristy67d16d92013-09-29 18:31:17 +00002390 break;
cristy3ed852e2009-09-05 21:47:34 +00002391 }
cristy67d16d92013-09-29 18:31:17 +00002392 }
cristy3ed852e2009-09-05 21:47:34 +00002393 count=WriteBlob(image,extent,pixels);
2394 if (count != (ssize_t) extent)
2395 break;
2396 if (image->previous == (Image *) NULL)
2397 {
cristycee97112010-05-28 00:44:52 +00002398 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2399 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002400 if (status == MagickFalse)
2401 break;
2402 }
2403 }
2404 quantum_info=DestroyQuantumInfo(quantum_info);
2405 break;
2406 }
2407 case 'F':
2408 case 'f':
2409 {
cristy1715f792012-11-22 16:56:12 +00002410 (void) WriteBlobString(image,image->endian == LSBEndian ? "-1.0\n" :
2411 "1.0\n");
cristy3ed852e2009-09-05 21:47:34 +00002412 image->depth=32;
2413 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
cristy5f766ef2014-12-14 21:12:47 +00002414 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +00002415 if (quantum_info == (QuantumInfo *) NULL)
2416 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2417 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2418 if (status == MagickFalse)
2419 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
cristy6b675d12015-05-22 22:15:18 +00002420 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002421 for (y=(ssize_t) image->rows-1; y >= 0; y--)
cristy3ed852e2009-09-05 21:47:34 +00002422 {
cristy4c08aed2011-07-01 19:47:50 +00002423 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01002424 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002425
cristy1e178e72011-08-28 19:44:34 +00002426 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002427 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002428 break;
cristy4c08aed2011-07-01 19:47:50 +00002429 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002430 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002431 (void) WriteBlob(image,extent,pixels);
2432 if (image->previous == (Image *) NULL)
2433 {
cristycee97112010-05-28 00:44:52 +00002434 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2435 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002436 if (status == MagickFalse)
2437 break;
2438 }
2439 }
2440 quantum_info=DestroyQuantumInfo(quantum_info);
2441 break;
2442 }
2443 }
2444 if (GetNextImageInList(image) == (Image *) NULL)
2445 break;
2446 image=SyncNextImageInList(image);
2447 status=SetImageProgress(image,SaveImagesTag,scene++,
2448 GetImageListLength(image));
2449 if (status == MagickFalse)
2450 break;
2451 } while (image_info->adjoin != MagickFalse);
2452 (void) CloseBlob(image);
2453 return(MagickTrue);
2454}