blob: 8f417cb18557a07ea9fa0bb93a8dab02273a0fde [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% %
Cristyf6ff9ea2016-12-05 09:53:35 -050020% Copyright 1999-2017 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% %
Cristyf19d4142017-04-24 11:34:30 -040026% https://www.imagemagick.org/script/license.php %
cristy3ed852e2009-09-05 21:47:34 +000027% %
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;
Cristyd0eb5832017-03-01 17:41:53 -0500432 y=0;
cristy3ed852e2009-09-05 21:47:34 +0000433 switch (format)
434 {
435 case '1':
436 {
437 /*
438 Convert PBM image to pixel packets.
439 */
cristy4e285b92013-05-24 17:42:57 +0000440 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristybb503372010-05-27 20:51:26 +0000441 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000442 {
cristybb503372010-05-27 20:51:26 +0000443 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000444 x;
445
cristy4c08aed2011-07-01 19:47:50 +0000446 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100447 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000448
449 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000450 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000451 break;
cristybb503372010-05-27 20:51:26 +0000452 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000453 {
cristy08528502012-01-01 00:52:17 +0000454 SetPixelGray(image,PNMInteger(image,2,exception) == 0 ?
cristyd15e6592011-10-15 00:13:06 +0000455 QuantumRange : 0,q);
Cristyc1cf4802016-06-03 16:48:12 -0400456 if (EOFBlob(image) != MagickFalse)
457 break;
cristyed231572011-07-14 02:18:59 +0000458 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000459 }
460 if (SyncAuthenticPixels(image,exception) == MagickFalse)
461 break;
462 if (image->previous == (Image *) NULL)
463 {
cristycee97112010-05-28 00:44:52 +0000464 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
465 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000466 if (status == MagickFalse)
467 break;
468 }
Cristyc1cf4802016-06-03 16:48:12 -0400469 if (EOFBlob(image) != MagickFalse)
470 break;
cristy3ed852e2009-09-05 21:47:34 +0000471 }
472 image->type=BilevelType;
473 break;
474 }
475 case '2':
476 {
cristy93344732014-12-13 22:21:44 +0000477 Quantum
cristy3ed852e2009-09-05 21:47:34 +0000478 intensity;
479
480 /*
481 Convert PGM image to pixel packets.
482 */
cristy542ea782013-05-24 15:53:01 +0000483 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristybb503372010-05-27 20:51:26 +0000484 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000485 {
cristybb503372010-05-27 20:51:26 +0000486 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000487 x;
488
cristy4c08aed2011-07-01 19:47:50 +0000489 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100490 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000491
492 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyb3a73b52011-07-26 01:34:43 +0000493 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000494 break;
cristybb503372010-05-27 20:51:26 +0000495 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000496 {
cristy0c44bb52014-12-13 22:15:35 +0000497 intensity=ScaleAnyToQuantum(PNMInteger(image,10,exception),
498 max_value);
Cristyc1cf4802016-06-03 16:48:12 -0400499 if (EOFBlob(image) != MagickFalse)
500 break;
cristy67d16d92013-09-29 18:31:17 +0000501 SetPixelGray(image,intensity,q);
cristyed231572011-07-14 02:18:59 +0000502 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000503 }
504 if (SyncAuthenticPixels(image,exception) == MagickFalse)
505 break;
506 if (image->previous == (Image *) NULL)
507 {
cristycee97112010-05-28 00:44:52 +0000508 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
509 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000510 if (status == MagickFalse)
511 break;
512 }
Cristyc1cf4802016-06-03 16:48:12 -0400513 if (EOFBlob(image) != MagickFalse)
514 break;
cristy3ed852e2009-09-05 21:47:34 +0000515 }
516 image->type=GrayscaleType;
cristy3ed852e2009-09-05 21:47:34 +0000517 break;
518 }
519 case '3':
520 {
cristy3ed852e2009-09-05 21:47:34 +0000521 /*
522 Convert PNM image to pixel packets.
523 */
cristybb503372010-05-27 20:51:26 +0000524 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000525 {
cristybb503372010-05-27 20:51:26 +0000526 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000527 x;
528
cristy4c08aed2011-07-01 19:47:50 +0000529 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100530 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000531
532 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000533 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000534 break;
cristybb503372010-05-27 20:51:26 +0000535 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000536 {
cristy93344732014-12-13 22:21:44 +0000537 Quantum
cristy67d16d92013-09-29 18:31:17 +0000538 pixel;
539
540 pixel=ScaleAnyToQuantum(PNMInteger(image,10,exception),max_value);
Cristyc1cf4802016-06-03 16:48:12 -0400541 if (EOFBlob(image) != MagickFalse)
542 break;
cristy67d16d92013-09-29 18:31:17 +0000543 SetPixelRed(image,pixel,q);
544 pixel=ScaleAnyToQuantum(PNMInteger(image,10,exception),max_value);
545 SetPixelGreen(image,pixel,q);
546 pixel=ScaleAnyToQuantum(PNMInteger(image,10,exception),max_value);
547 SetPixelBlue(image,pixel,q);
cristyed231572011-07-14 02:18:59 +0000548 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000549 }
550 if (SyncAuthenticPixels(image,exception) == MagickFalse)
551 break;
552 if (image->previous == (Image *) NULL)
553 {
cristycee97112010-05-28 00:44:52 +0000554 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
555 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000556 if (status == MagickFalse)
557 break;
558 }
Cristyc1cf4802016-06-03 16:48:12 -0400559 if (EOFBlob(image) != MagickFalse)
560 break;
cristy3ed852e2009-09-05 21:47:34 +0000561 }
cristy3ed852e2009-09-05 21:47:34 +0000562 break;
563 }
564 case '4':
565 {
566 /*
567 Convert PBM raw image to pixel packets.
568 */
cristy542ea782013-05-24 15:53:01 +0000569 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +0000570 quantum_type=GrayQuantum;
571 if (image->storage_class == PseudoClass)
572 quantum_type=IndexQuantum;
cristy5f766ef2014-12-14 21:12:47 +0000573 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +0000574 if (quantum_info == (QuantumInfo *) NULL)
575 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
576 SetQuantumMinIsWhite(quantum_info,MagickTrue);
577 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +0000578 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000579 {
cristyb1253cd2015-05-31 01:06:54 +0000580 const unsigned char
cristybd797f12015-01-24 20:42:32 +0000581 *pixels;
582
cristy3ed852e2009-09-05 21:47:34 +0000583 MagickBooleanType
584 sync;
585
cristy4c08aed2011-07-01 19:47:50 +0000586 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100587 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000588
589 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000590 count,
591 offset;
cristy3ed852e2009-09-05 21:47:34 +0000592
593 size_t
594 length;
595
cristyb1253cd2015-05-31 01:06:54 +0000596 pixels=(unsigned char *) ReadBlobStream(image,extent,
597 GetQuantumPixels(quantum_info),&count);
cristy3ed852e2009-09-05 21:47:34 +0000598 if (count != (ssize_t) extent)
Cristyd0eb5832017-03-01 17:41:53 -0500599 break;
cristybd797f12015-01-24 20:42:32 +0000600 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
601 (image->previous == (Image *) NULL))
602 {
603 MagickBooleanType
604 proceed;
605
606 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
607 row,image->rows);
608 if (proceed == MagickFalse)
Cristyd0eb5832017-03-01 17:41:53 -0500609 break;
cristybd797f12015-01-24 20:42:32 +0000610 }
611 offset=row++;
cristyaa740112010-03-30 17:58:44 +0000612 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000613 if (q == (Quantum *) NULL)
Cristyd0eb5832017-03-01 17:41:53 -0500614 break;
cristyaa740112010-03-30 17:58:44 +0000615 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
616 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +0000617 if (length != extent)
Cristyd0eb5832017-03-01 17:41:53 -0500618 break;
cristyaa740112010-03-30 17:58:44 +0000619 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000620 if (sync == MagickFalse)
Cristyd0eb5832017-03-01 17:41:53 -0500621 break;
cristy3ed852e2009-09-05 21:47:34 +0000622 }
cristy3ed852e2009-09-05 21:47:34 +0000623 quantum_info=DestroyQuantumInfo(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000624 SetQuantumImageType(image,quantum_type);
625 break;
626 }
627 case '5':
628 {
cristy3ed852e2009-09-05 21:47:34 +0000629 /*
630 Convert PGM raw image to pixel packets.
631 */
cristy542ea782013-05-24 15:53:01 +0000632 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +0000633 quantum_type=GrayQuantum;
cristy67d16d92013-09-29 18:31:17 +0000634 if (image->depth <= 8)
635 extent=image->columns;
636 else
637 if (image->depth <= 16)
638 extent=2*image->columns;
639 else
640 extent=4*image->columns;
cristy5f766ef2014-12-14 21:12:47 +0000641 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +0000642 if (quantum_info == (QuantumInfo *) NULL)
643 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000644 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000645 {
cristyb1253cd2015-05-31 01:06:54 +0000646 const unsigned char
cristybd797f12015-01-24 20:42:32 +0000647 *pixels;
648
cristy3ed852e2009-09-05 21:47:34 +0000649 MagickBooleanType
650 sync;
651
652 register const unsigned char
dirk05d2ff72015-11-18 23:13:43 +0100653 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000654
cristybb503372010-05-27 20:51:26 +0000655 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000656 x;
657
cristy4c08aed2011-07-01 19:47:50 +0000658 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100659 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000660
661 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000662 count,
663 offset;
cristy3ed852e2009-09-05 21:47:34 +0000664
cristyb1253cd2015-05-31 01:06:54 +0000665 pixels=(unsigned char *) ReadBlobStream(image,extent,
666 GetQuantumPixels(quantum_info),&count);
cristy3ed852e2009-09-05 21:47:34 +0000667 if (count != (ssize_t) extent)
Cristyd0eb5832017-03-01 17:41:53 -0500668 break;
cristybd797f12015-01-24 20:42:32 +0000669 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
670 (image->previous == (Image *) NULL))
671 {
672 MagickBooleanType
673 proceed;
674
675 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
676 row,image->rows);
677 if (proceed == MagickFalse)
Cristyd0eb5832017-03-01 17:41:53 -0500678 break;
cristybd797f12015-01-24 20:42:32 +0000679 }
680 offset=row++;
cristyaa740112010-03-30 17:58:44 +0000681 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000682 if (q == (Quantum *) NULL)
Cristyd0eb5832017-03-01 17:41:53 -0500683 break;
cristy3ed852e2009-09-05 21:47:34 +0000684 p=pixels;
cristy67d16d92013-09-29 18:31:17 +0000685 switch (image->depth)
686 {
687 case 8:
688 case 16:
689 case 32:
690 {
691 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
692 quantum_type,pixels,exception);
693 break;
694 }
695 default:
696 {
697 unsigned int
698 pixel;
cristy3ed852e2009-09-05 21:47:34 +0000699
cristy67d16d92013-09-29 18:31:17 +0000700 if (image->depth <= 8)
cristy3ed852e2009-09-05 21:47:34 +0000701 {
cristy67d16d92013-09-29 18:31:17 +0000702 unsigned char
703 pixel;
cristy3ed852e2009-09-05 21:47:34 +0000704
cristy67d16d92013-09-29 18:31:17 +0000705 for (x=0; x < (ssize_t) image->columns; x++)
706 {
707 p=PushCharPixel(p,&pixel);
708 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
709 q+=GetPixelChannels(image);
710 }
711 break;
cristy3ed852e2009-09-05 21:47:34 +0000712 }
cristy67d16d92013-09-29 18:31:17 +0000713 if (image->depth <= 16)
714 {
715 unsigned short
716 pixel;
717
718 for (x=0; x < (ssize_t) image->columns; x++)
719 {
720 p=PushShortPixel(MSBEndian,p,&pixel);
721 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
722 q+=GetPixelChannels(image);
723 }
724 break;
725 }
726 for (x=0; x < (ssize_t) image->columns; x++)
727 {
728 p=PushLongPixel(MSBEndian,p,&pixel);
729 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
730 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000731 }
cristy67d16d92013-09-29 18:31:17 +0000732 break;
733 }
734 }
cristyaa740112010-03-30 17:58:44 +0000735 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000736 if (sync == MagickFalse)
Cristyd0eb5832017-03-01 17:41:53 -0500737 break;
cristy3ed852e2009-09-05 21:47:34 +0000738 }
cristy3ed852e2009-09-05 21:47:34 +0000739 quantum_info=DestroyQuantumInfo(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000740 SetQuantumImageType(image,quantum_type);
741 break;
742 }
743 case '6':
744 {
cristy3ed852e2009-09-05 21:47:34 +0000745 /*
746 Convert PNM raster image to pixel packets.
747 */
cristy3ed852e2009-09-05 21:47:34 +0000748 quantum_type=RGBQuantum;
749 extent=3*(image->depth <= 8 ? 1 : 2)*image->columns;
cristy5f766ef2014-12-14 21:12:47 +0000750 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +0000751 if (quantum_info == (QuantumInfo *) NULL)
752 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristy70d7eae2012-11-17 19:40:21 +0000753 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
cristybb503372010-05-27 20:51:26 +0000754 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000755 {
cristyb1253cd2015-05-31 01:06:54 +0000756 const unsigned char
cristybd797f12015-01-24 20:42:32 +0000757 *pixels;
758
cristy3ed852e2009-09-05 21:47:34 +0000759 MagickBooleanType
760 sync;
761
762 register const unsigned char
dirk05d2ff72015-11-18 23:13:43 +0100763 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000764
cristybb503372010-05-27 20:51:26 +0000765 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000766 x;
767
cristy4c08aed2011-07-01 19:47:50 +0000768 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100769 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000770
771 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000772 count,
773 offset;
cristy3ed852e2009-09-05 21:47:34 +0000774
cristyb1253cd2015-05-31 01:06:54 +0000775 pixels=(unsigned char *) ReadBlobStream(image,extent,
776 GetQuantumPixels(quantum_info),&count);
cristy3ed852e2009-09-05 21:47:34 +0000777 if (count != (ssize_t) extent)
Cristyd0eb5832017-03-01 17:41:53 -0500778 break;
cristybd797f12015-01-24 20:42:32 +0000779 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
780 (image->previous == (Image *) NULL))
781 {
782 MagickBooleanType
783 proceed;
784
785 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
786 row,image->rows);
787 if (proceed == MagickFalse)
Cristyd0eb5832017-03-01 17:41:53 -0500788 break;
cristybd797f12015-01-24 20:42:32 +0000789 }
790 offset=row++;
cristyaa740112010-03-30 17:58:44 +0000791 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000792 if (q == (Quantum *) NULL)
Cristyd0eb5832017-03-01 17:41:53 -0500793 break;
cristy3ed852e2009-09-05 21:47:34 +0000794 p=pixels;
cristy67d16d92013-09-29 18:31:17 +0000795 switch (image->depth)
796 {
797 case 8:
cristy3ed852e2009-09-05 21:47:34 +0000798 {
cristy67d16d92013-09-29 18:31:17 +0000799 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000800 {
cristy67d16d92013-09-29 18:31:17 +0000801 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
802 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
803 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
804 SetPixelAlpha(image,OpaqueAlpha,q);
805 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000806 }
cristy67d16d92013-09-29 18:31:17 +0000807 break;
808 }
809 case 16:
810 {
811 unsigned short
812 pixel;
813
814 for (x=0; x < (ssize_t) image->columns; x++)
815 {
816 p=PushShortPixel(MSBEndian,p,&pixel);
817 SetPixelRed(image,ScaleShortToQuantum(pixel),q);
818 p=PushShortPixel(MSBEndian,p,&pixel);
819 SetPixelGreen(image,ScaleShortToQuantum(pixel),q);
820 p=PushShortPixel(MSBEndian,p,&pixel);
821 SetPixelBlue(image,ScaleShortToQuantum(pixel),q);
822 SetPixelAlpha(image,OpaqueAlpha,q);
823 q+=GetPixelChannels(image);
824 }
825 break;
826 }
827 case 32:
828 {
829 unsigned int
830 pixel;
831
832 for (x=0; x < (ssize_t) image->columns; x++)
833 {
834 p=PushLongPixel(MSBEndian,p,&pixel);
835 SetPixelRed(image,ScaleLongToQuantum(pixel),q);
836 p=PushLongPixel(MSBEndian,p,&pixel);
837 SetPixelGreen(image,ScaleLongToQuantum(pixel),q);
838 p=PushLongPixel(MSBEndian,p,&pixel);
839 SetPixelBlue(image,ScaleLongToQuantum(pixel),q);
840 SetPixelAlpha(image,OpaqueAlpha,q);
841 q+=GetPixelChannels(image);
842 }
843 break;
844 }
845 default:
846 {
847 unsigned int
848 pixel;
849
cristye90d7402010-03-14 18:21:29 +0000850 if (image->depth <= 8)
851 {
852 unsigned char
853 pixel;
854
cristybb503372010-05-27 20:51:26 +0000855 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000856 {
857 p=PushCharPixel(p,&pixel);
cristy92beec62013-08-26 12:23:46 +0000858 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
cristye90d7402010-03-14 18:21:29 +0000859 p=PushCharPixel(p,&pixel);
cristy92beec62013-08-26 12:23:46 +0000860 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
cristye90d7402010-03-14 18:21:29 +0000861 p=PushCharPixel(p,&pixel);
cristy92beec62013-08-26 12:23:46 +0000862 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
cristy4c08aed2011-07-01 19:47:50 +0000863 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000864 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000865 }
cristy67d16d92013-09-29 18:31:17 +0000866 break;
cristye90d7402010-03-14 18:21:29 +0000867 }
cristy67d16d92013-09-29 18:31:17 +0000868 if (image->depth <= 16)
cristye90d7402010-03-14 18:21:29 +0000869 {
870 unsigned short
871 pixel;
872
cristybb503372010-05-27 20:51:26 +0000873 for (x=0; x < (ssize_t) image->columns; x++)
cristye90d7402010-03-14 18:21:29 +0000874 {
875 p=PushShortPixel(MSBEndian,p,&pixel);
cristy92beec62013-08-26 12:23:46 +0000876 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
cristye90d7402010-03-14 18:21:29 +0000877 p=PushShortPixel(MSBEndian,p,&pixel);
cristy92beec62013-08-26 12:23:46 +0000878 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
cristye90d7402010-03-14 18:21:29 +0000879 p=PushShortPixel(MSBEndian,p,&pixel);
cristy92beec62013-08-26 12:23:46 +0000880 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
cristy4c08aed2011-07-01 19:47:50 +0000881 SetPixelAlpha(image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +0000882 q+=GetPixelChannels(image);
cristye90d7402010-03-14 18:21:29 +0000883 }
cristy67d16d92013-09-29 18:31:17 +0000884 break;
cristye90d7402010-03-14 18:21:29 +0000885 }
cristy67d16d92013-09-29 18:31:17 +0000886 for (x=0; x < (ssize_t) image->columns; x++)
887 {
888 p=PushLongPixel(MSBEndian,p,&pixel);
889 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
890 p=PushLongPixel(MSBEndian,p,&pixel);
891 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
892 p=PushLongPixel(MSBEndian,p,&pixel);
893 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
894 SetPixelAlpha(image,OpaqueAlpha,q);
895 q+=GetPixelChannels(image);
896 }
897 break;
898 }
899 }
cristyaa740112010-03-30 17:58:44 +0000900 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000901 if (sync == MagickFalse)
Cristyd0eb5832017-03-01 17:41:53 -0500902 break;
cristy3ed852e2009-09-05 21:47:34 +0000903 }
cristy3ed852e2009-09-05 21:47:34 +0000904 quantum_info=DestroyQuantumInfo(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +0000905 break;
906 }
907 case '7':
908 {
cristybb503372010-05-27 20:51:26 +0000909 size_t
cristy3ed852e2009-09-05 21:47:34 +0000910 channels;
911
912 /*
913 Convert PAM raster image to pixel packets.
914 */
cristy3ed852e2009-09-05 21:47:34 +0000915 switch (quantum_type)
916 {
917 case GrayQuantum:
918 case GrayAlphaQuantum:
919 {
920 channels=1;
921 break;
922 }
923 case CMYKQuantum:
924 case CMYKAQuantum:
925 {
926 channels=4;
927 break;
928 }
929 default:
930 {
931 channels=3;
932 break;
933 }
934 }
cristy17f11b02014-12-20 19:37:04 +0000935 if (image->alpha_trait != UndefinedPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +0000936 channels++;
cristy67d16d92013-09-29 18:31:17 +0000937 if (image->depth <= 8)
938 extent=channels*image->columns;
939 else
940 if (image->depth <= 16)
941 extent=2*channels*image->columns;
942 else
943 extent=4*channels*image->columns;
cristy5f766ef2014-12-14 21:12:47 +0000944 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +0000945 if (quantum_info == (QuantumInfo *) NULL)
946 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000947 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000948 {
cristyb1253cd2015-05-31 01:06:54 +0000949 const unsigned char
cristybd797f12015-01-24 20:42:32 +0000950 *pixels;
951
cristy3ed852e2009-09-05 21:47:34 +0000952 MagickBooleanType
953 sync;
954
955 register const unsigned char
dirk05d2ff72015-11-18 23:13:43 +0100956 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000957
cristybb503372010-05-27 20:51:26 +0000958 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000959 x;
960
cristy4c08aed2011-07-01 19:47:50 +0000961 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100962 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000963
964 ssize_t
cristyaff6d802011-04-26 01:46:31 +0000965 count,
966 offset;
cristy3ed852e2009-09-05 21:47:34 +0000967
cristyb1253cd2015-05-31 01:06:54 +0000968 pixels=(unsigned char *) ReadBlobStream(image,extent,
969 GetQuantumPixels(quantum_info),&count);
cristy3ed852e2009-09-05 21:47:34 +0000970 if (count != (ssize_t) extent)
Cristyd0eb5832017-03-01 17:41:53 -0500971 break;
cristybd797f12015-01-24 20:42:32 +0000972 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
973 (image->previous == (Image *) NULL))
974 {
975 MagickBooleanType
976 proceed;
977
978 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
979 row,image->rows);
980 if (proceed == MagickFalse)
Cristyd0eb5832017-03-01 17:41:53 -0500981 break;
cristybd797f12015-01-24 20:42:32 +0000982 }
983 offset=row++;
cristyaa740112010-03-30 17:58:44 +0000984 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000985 if (q == (Quantum *) NULL)
Cristyd0eb5832017-03-01 17:41:53 -0500986 break;
cristy3ed852e2009-09-05 21:47:34 +0000987 p=pixels;
cristy67d16d92013-09-29 18:31:17 +0000988 switch (image->depth)
989 {
990 case 8:
991 case 16:
992 case 32:
cristy3ed852e2009-09-05 21:47:34 +0000993 {
cristy67d16d92013-09-29 18:31:17 +0000994 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
995 quantum_type,pixels,exception);
996 break;
997 }
998 default:
999 {
1000 switch (quantum_type)
cristy3ed852e2009-09-05 21:47:34 +00001001 {
cristy67d16d92013-09-29 18:31:17 +00001002 case GrayQuantum:
1003 case GrayAlphaQuantum:
1004 {
1005 unsigned int
1006 pixel;
cristy3ed852e2009-09-05 21:47:34 +00001007
cristy67d16d92013-09-29 18:31:17 +00001008 if (image->depth <= 8)
cristy3ed852e2009-09-05 21:47:34 +00001009 {
cristy67d16d92013-09-29 18:31:17 +00001010 unsigned char
1011 pixel;
cristy3ed852e2009-09-05 21:47:34 +00001012
cristy67d16d92013-09-29 18:31:17 +00001013 for (x=0; x < (ssize_t) image->columns; x++)
1014 {
1015 p=PushCharPixel(p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001016 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),
1017 q);
cristy67d16d92013-09-29 18:31:17 +00001018 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001019 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001020 {
1021 p=PushCharPixel(p,&pixel);
cristyfbcb8172014-03-01 13:21:16 +00001022 if (image->depth != 1)
1023 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1024 max_value),q);
1025 else
1026 SetPixelAlpha(image,QuantumRange-
1027 ScaleAnyToQuantum(pixel,max_value),q);
cristy67d16d92013-09-29 18:31:17 +00001028 }
1029 q+=GetPixelChannels(image);
1030 }
1031 break;
cristy3ed852e2009-09-05 21:47:34 +00001032 }
cristy67d16d92013-09-29 18:31:17 +00001033 if (image->depth <= 16)
1034 {
1035 unsigned short
1036 pixel;
cristy3ed852e2009-09-05 21:47:34 +00001037
cristy67d16d92013-09-29 18:31:17 +00001038 for (x=0; x < (ssize_t) image->columns; x++)
1039 {
1040 p=PushShortPixel(MSBEndian,p,&pixel);
cristyfbcb8172014-03-01 13:21:16 +00001041 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),
1042 q);
cristy67d16d92013-09-29 18:31:17 +00001043 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001044 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001045 {
1046 p=PushShortPixel(MSBEndian,p,&pixel);
1047 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1048 max_value),q);
1049 }
1050 q+=GetPixelChannels(image);
1051 }
1052 break;
cristy3ed852e2009-09-05 21:47:34 +00001053 }
cristy67d16d92013-09-29 18:31:17 +00001054 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001055 {
cristy67d16d92013-09-29 18:31:17 +00001056 p=PushLongPixel(MSBEndian,p,&pixel);
1057 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
1058 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001059 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001060 {
1061 p=PushLongPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001062 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,max_value),
1063 q);
cristy67d16d92013-09-29 18:31:17 +00001064 }
1065 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001066 }
cristy67d16d92013-09-29 18:31:17 +00001067 break;
1068 }
1069 case CMYKQuantum:
1070 case CMYKAQuantum:
1071 {
1072 unsigned int
1073 pixel;
1074
1075 if (image->depth <= 8)
1076 {
1077 unsigned char
1078 pixel;
1079
1080 for (x=0; x < (ssize_t) image->columns; x++)
1081 {
1082 p=PushCharPixel(p,&pixel);
1083 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1084 p=PushCharPixel(p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001085 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
1086 q);
cristy67d16d92013-09-29 18:31:17 +00001087 p=PushCharPixel(p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001088 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
1089 q);
cristy67d16d92013-09-29 18:31:17 +00001090 p=PushCharPixel(p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001091 SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),
1092 q);
cristy67d16d92013-09-29 18:31:17 +00001093 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001094 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001095 {
1096 p=PushCharPixel(p,&pixel);
1097 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1098 max_value),q);
1099 }
1100 q+=GetPixelChannels(image);
1101 }
1102 break;
1103 }
1104 if (image->depth <= 16)
1105 {
1106 unsigned short
1107 pixel;
1108
1109 for (x=0; x < (ssize_t) image->columns; x++)
1110 {
1111 p=PushShortPixel(MSBEndian,p,&pixel);
1112 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1113 p=PushShortPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001114 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
1115 q);
cristy67d16d92013-09-29 18:31:17 +00001116 p=PushShortPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001117 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
1118 q);
cristy67d16d92013-09-29 18:31:17 +00001119 p=PushShortPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001120 SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),
1121 q);
cristy67d16d92013-09-29 18:31:17 +00001122 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001123 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001124 {
1125 p=PushShortPixel(MSBEndian,p,&pixel);
1126 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1127 max_value),q);
1128 }
1129 q+=GetPixelChannels(image);
1130 }
1131 }
1132 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001133 {
cristy67d16d92013-09-29 18:31:17 +00001134 p=PushLongPixel(MSBEndian,p,&pixel);
1135 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1136 p=PushLongPixel(MSBEndian,p,&pixel);
1137 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
1138 p=PushLongPixel(MSBEndian,p,&pixel);
1139 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
1140 p=PushLongPixel(MSBEndian,p,&pixel);
1141 SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),q);
1142 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001143 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001144 {
1145 p=PushLongPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001146 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,max_value),
1147 q);
cristy67d16d92013-09-29 18:31:17 +00001148 }
1149 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001150 }
cristy67d16d92013-09-29 18:31:17 +00001151 break;
1152 }
1153 default:
1154 {
1155 unsigned int
1156 pixel;
1157
1158 if (image->depth <= 8)
1159 {
1160 unsigned char
1161 pixel;
1162
1163 for (x=0; x < (ssize_t) image->columns; x++)
1164 {
1165 p=PushCharPixel(p,&pixel);
1166 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1167 p=PushCharPixel(p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001168 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
1169 q);
cristy67d16d92013-09-29 18:31:17 +00001170 p=PushCharPixel(p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001171 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
1172 q);
cristy67d16d92013-09-29 18:31:17 +00001173 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001174 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001175 {
1176 p=PushCharPixel(p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001177 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1178 max_value),q);
cristy67d16d92013-09-29 18:31:17 +00001179 }
1180 q+=GetPixelChannels(image);
1181 }
1182 break;
1183 }
1184 if (image->depth <= 16)
1185 {
1186 unsigned short
1187 pixel;
1188
1189 for (x=0; x < (ssize_t) image->columns; x++)
1190 {
1191 p=PushShortPixel(MSBEndian,p,&pixel);
1192 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1193 p=PushShortPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001194 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
1195 q);
cristy67d16d92013-09-29 18:31:17 +00001196 p=PushShortPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001197 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
1198 q);
cristy67d16d92013-09-29 18:31:17 +00001199 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001200 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001201 {
1202 p=PushShortPixel(MSBEndian,p,&pixel);
1203 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1204 max_value),q);
1205 }
1206 q+=GetPixelChannels(image);
1207 }
1208 break;
1209 }
1210 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001211 {
cristy67d16d92013-09-29 18:31:17 +00001212 p=PushLongPixel(MSBEndian,p,&pixel);
1213 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1214 p=PushLongPixel(MSBEndian,p,&pixel);
1215 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
1216 p=PushLongPixel(MSBEndian,p,&pixel);
1217 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
1218 SetPixelAlpha(image,OpaqueAlpha,q);
cristy17f11b02014-12-20 19:37:04 +00001219 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00001220 {
1221 p=PushLongPixel(MSBEndian,p,&pixel);
cristybd797f12015-01-24 20:42:32 +00001222 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,max_value),
1223 q);
cristy67d16d92013-09-29 18:31:17 +00001224 }
1225 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001226 }
cristy67d16d92013-09-29 18:31:17 +00001227 break;
1228 }
cristy3ed852e2009-09-05 21:47:34 +00001229 }
1230 }
cristy67d16d92013-09-29 18:31:17 +00001231 }
cristyaa740112010-03-30 17:58:44 +00001232 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001233 if (sync == MagickFalse)
Cristyd0eb5832017-03-01 17:41:53 -05001234 break;
cristy3ed852e2009-09-05 21:47:34 +00001235 }
cristy3ed852e2009-09-05 21:47:34 +00001236 quantum_info=DestroyQuantumInfo(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001237 SetQuantumImageType(image,quantum_type);
1238 break;
1239 }
1240 case 'F':
1241 case 'f':
1242 {
1243 /*
1244 Convert PFM raster image to pixel packets.
1245 */
cristyaf6eb932012-01-01 01:22:59 +00001246 if (format == 'f')
cristy4e285b92013-05-24 17:42:57 +00001247 (void) SetImageColorspace(image,GRAYColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +00001248 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
1249 image->endian=quantum_scale < 0.0 ? LSBEndian : MSBEndian;
1250 image->depth=32;
cristy5f766ef2014-12-14 21:12:47 +00001251 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +00001252 if (quantum_info == (QuantumInfo *) NULL)
1253 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1254 status=SetQuantumDepth(image,quantum_info,32);
1255 if (status == MagickFalse)
1256 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1257 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1258 if (status == MagickFalse)
1259 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristy243166e2012-11-03 19:16:10 +00001260 SetQuantumScale(quantum_info,(double) QuantumRange*fabs(quantum_scale));
cristy3ed852e2009-09-05 21:47:34 +00001261 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +00001262 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001263 {
cristyb1253cd2015-05-31 01:06:54 +00001264 const unsigned char
cristybd797f12015-01-24 20:42:32 +00001265 *pixels;
1266
cristy3ed852e2009-09-05 21:47:34 +00001267 MagickBooleanType
1268 sync;
1269
cristy4c08aed2011-07-01 19:47:50 +00001270 register Quantum
dirk05d2ff72015-11-18 23:13:43 +01001271 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001272
1273 ssize_t
cristyaff6d802011-04-26 01:46:31 +00001274 count,
1275 offset;
cristy3ed852e2009-09-05 21:47:34 +00001276
1277 size_t
1278 length;
1279
cristyb1253cd2015-05-31 01:06:54 +00001280 pixels=(unsigned char *) ReadBlobStream(image,extent,
1281 GetQuantumPixels(quantum_info),&count);
cristy3ed852e2009-09-05 21:47:34 +00001282 if ((size_t) count != extent)
Cristyd0eb5832017-03-01 17:41:53 -05001283 break;
cristybd797f12015-01-24 20:42:32 +00001284 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1285 (image->previous == (Image *) NULL))
1286 {
1287 MagickBooleanType
1288 proceed;
1289
1290 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1291 row,image->rows);
1292 if (proceed == MagickFalse)
Cristyd0eb5832017-03-01 17:41:53 -05001293 break;
cristybd797f12015-01-24 20:42:32 +00001294 }
1295 offset=row++;
cristybb503372010-05-27 20:51:26 +00001296 q=QueueAuthenticPixels(image,0,(ssize_t) (image->rows-offset-1),
cristyaa740112010-03-30 17:58:44 +00001297 image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00001298 if (q == (Quantum *) NULL)
Cristyd0eb5832017-03-01 17:41:53 -05001299 break;
cristyaa740112010-03-30 17:58:44 +00001300 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1301 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001302 if (length != extent)
Cristyd0eb5832017-03-01 17:41:53 -05001303 break;
cristyaa740112010-03-30 17:58:44 +00001304 sync=SyncAuthenticPixels(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001305 if (sync == MagickFalse)
Cristyd0eb5832017-03-01 17:41:53 -05001306 break;
cristy3ed852e2009-09-05 21:47:34 +00001307 }
cristy3ed852e2009-09-05 21:47:34 +00001308 quantum_info=DestroyQuantumInfo(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001309 SetQuantumImageType(image,quantum_type);
1310 break;
1311 }
1312 default:
1313 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1314 }
Cristyd0eb5832017-03-01 17:41:53 -05001315 if (y < (ssize_t) image->rows)
1316 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
cristy3ed852e2009-09-05 21:47:34 +00001317 if (EOFBlob(image) != MagickFalse)
cristy5d792232012-01-31 17:02:45 +00001318 {
1319 (void) ThrowMagickException(exception,GetMagickModule(),
1320 CorruptImageError,"UnexpectedEndOfFile","`%s'",image->filename);
1321 break;
1322 }
cristy3ed852e2009-09-05 21:47:34 +00001323 /*
1324 Proceed to next image.
1325 */
1326 if (image_info->number_scenes != 0)
1327 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1328 break;
1329 if ((format == '1') || (format == '2') || (format == '3'))
1330 do
1331 {
1332 /*
1333 Skip to end of line.
1334 */
1335 count=ReadBlob(image,1,(unsigned char *) &format);
cristy771c8842015-01-09 12:13:22 +00001336 if (count != 1)
cristy3ed852e2009-09-05 21:47:34 +00001337 break;
cristy771c8842015-01-09 12:13:22 +00001338 if (format == 'P')
cristy3ed852e2009-09-05 21:47:34 +00001339 break;
1340 } while (format != '\n');
1341 count=ReadBlob(image,1,(unsigned char *) &format);
1342 if ((count == 1) && (format == 'P'))
1343 {
1344 /*
1345 Allocate next image structure.
1346 */
cristy9950d572011-10-01 18:22:35 +00001347 AcquireNextImage(image_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001348 if (GetNextImageInList(image) == (Image *) NULL)
1349 {
1350 image=DestroyImageList(image);
1351 return((Image *) NULL);
1352 }
1353 image=SyncNextImageInList(image);
1354 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1355 GetBlobSize(image));
1356 if (status == MagickFalse)
1357 break;
1358 }
1359 } while ((count == 1) && (format == 'P'));
1360 (void) CloseBlob(image);
1361 return(GetFirstImageInList(image));
1362}
1363
1364/*
1365%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1366% %
1367% %
1368% %
1369% R e g i s t e r P N M I m a g e %
1370% %
1371% %
1372% %
1373%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1374%
1375% RegisterPNMImage() adds properties for the PNM image format to
1376% the list of supported formats. The properties include the image format
1377% tag, a method to read and/or write the format, whether the format
1378% supports the saving of more than one frame to the same file or blob,
1379% whether the format supports native in-memory I/O, and a brief
1380% description of the format.
1381%
1382% The format of the RegisterPNMImage method is:
1383%
cristybb503372010-05-27 20:51:26 +00001384% size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001385%
1386*/
cristybb503372010-05-27 20:51:26 +00001387ModuleExport size_t RegisterPNMImage(void)
cristy3ed852e2009-09-05 21:47:34 +00001388{
1389 MagickInfo
1390 *entry;
1391
dirk06b627a2015-04-06 18:59:17 +00001392 entry=AcquireMagickInfo("PNM","PAM","Common 2-dimensional bitmap format");
cristy3ed852e2009-09-05 21:47:34 +00001393 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1394 entry->encoder=(EncodeImageHandler *) WritePNMImage;
cristyf0d061c2013-08-09 12:17:54 +00001395 entry->mime_type=ConstantString("image/x-portable-pixmap");
cristy3ed852e2009-09-05 21:47:34 +00001396 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +00001397 entry=AcquireMagickInfo("PNM","PBM",
1398 "Portable bitmap format (black and white)");
cristy3ed852e2009-09-05 21:47:34 +00001399 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1400 entry->encoder=(EncodeImageHandler *) WritePNMImage;
cristyf0d061c2013-08-09 12:17:54 +00001401 entry->mime_type=ConstantString("image/x-portable-bitmap");
cristy3ed852e2009-09-05 21:47:34 +00001402 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +00001403 entry=AcquireMagickInfo("PNM","PFM","Portable float format");
cristy3ed852e2009-09-05 21:47:34 +00001404 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1405 entry->encoder=(EncodeImageHandler *) WritePNMImage;
dirk08e9a112015-02-22 01:51:41 +00001406 entry->flags|=CoderEndianSupportFlag;
cristy3ed852e2009-09-05 21:47:34 +00001407 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +00001408 entry=AcquireMagickInfo("PNM","PGM","Portable graymap format (gray scale)");
cristy3ed852e2009-09-05 21:47:34 +00001409 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1410 entry->encoder=(EncodeImageHandler *) WritePNMImage;
cristyf0d061c2013-08-09 12:17:54 +00001411 entry->mime_type=ConstantString("image/x-portable-greymap");
cristy3ed852e2009-09-05 21:47:34 +00001412 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +00001413 entry=AcquireMagickInfo("PNM","PNM","Portable anymap");
cristy3ed852e2009-09-05 21:47:34 +00001414 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1415 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1416 entry->magick=(IsImageFormatHandler *) IsPNM;
cristyf0d061c2013-08-09 12:17:54 +00001417 entry->mime_type=ConstantString("image/x-portable-pixmap");
cristy3ed852e2009-09-05 21:47:34 +00001418 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +00001419 entry=AcquireMagickInfo("PNM","PPM","Portable pixmap format (color)");
cristy3ed852e2009-09-05 21:47:34 +00001420 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1421 entry->encoder=(EncodeImageHandler *) WritePNMImage;
cristyf0d061c2013-08-09 12:17:54 +00001422 entry->mime_type=ConstantString("image/x-portable-pixmap");
cristy3ed852e2009-09-05 21:47:34 +00001423 (void) RegisterMagickInfo(entry);
1424 return(MagickImageCoderSignature);
1425}
1426
1427/*
1428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1429% %
1430% %
1431% %
1432% U n r e g i s t e r P N M I m a g e %
1433% %
1434% %
1435% %
1436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1437%
1438% UnregisterPNMImage() removes format registrations made by the
1439% PNM module from the list of supported formats.
1440%
1441% The format of the UnregisterPNMImage method is:
1442%
1443% UnregisterPNMImage(void)
1444%
1445*/
1446ModuleExport void UnregisterPNMImage(void)
1447{
1448 (void) UnregisterMagickInfo("PAM");
1449 (void) UnregisterMagickInfo("PBM");
1450 (void) UnregisterMagickInfo("PGM");
1451 (void) UnregisterMagickInfo("PNM");
1452 (void) UnregisterMagickInfo("PPM");
1453}
1454
1455/*
1456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1457% %
1458% %
1459% %
1460% W r i t e P N M I m a g e %
1461% %
1462% %
1463% %
1464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1465%
cristy661b5ad2010-01-13 00:54:42 +00001466% WritePNMImage() writes an image to a file in the PNM rasterfile format.
cristy3ed852e2009-09-05 21:47:34 +00001467%
1468% The format of the WritePNMImage method is:
1469%
cristy1e178e72011-08-28 19:44:34 +00001470% MagickBooleanType WritePNMImage(const ImageInfo *image_info,
1471% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001472%
1473% A description of each parameter follows.
1474%
1475% o image_info: the image info.
1476%
1477% o image: The image.
1478%
cristy1e178e72011-08-28 19:44:34 +00001479% o exception: return any errors or warnings in this structure.
1480%
cristy3ed852e2009-09-05 21:47:34 +00001481*/
cristy1e178e72011-08-28 19:44:34 +00001482static MagickBooleanType WritePNMImage(const ImageInfo *image_info,Image *image,
1483 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001484{
1485 char
cristy151b66d2015-04-15 10:50:31 +00001486 buffer[MagickPathExtent],
cristy3ed852e2009-09-05 21:47:34 +00001487 format,
cristy151b66d2015-04-15 10:50:31 +00001488 magick[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00001489
1490 const char
1491 *value;
1492
cristy3ed852e2009-09-05 21:47:34 +00001493 MagickBooleanType
1494 status;
1495
1496 MagickOffsetType
1497 scene;
1498
cristy4c08aed2011-07-01 19:47:50 +00001499 Quantum
1500 index;
1501
cristy3ed852e2009-09-05 21:47:34 +00001502 QuantumAny
1503 pixel;
1504
1505 QuantumInfo
1506 *quantum_info;
1507
1508 QuantumType
1509 quantum_type;
1510
cristy3ed852e2009-09-05 21:47:34 +00001511 register unsigned char
1512 *pixels,
1513 *q;
1514
cristy3ed852e2009-09-05 21:47:34 +00001515 size_t
1516 extent,
1517 packet_size;
1518
cristy95802a72010-09-05 19:07:17 +00001519 ssize_t
cristyaff6d802011-04-26 01:46:31 +00001520 count,
1521 y;
cristy95802a72010-09-05 19:07:17 +00001522
cristy3ed852e2009-09-05 21:47:34 +00001523 /*
1524 Open output image file.
1525 */
1526 assert(image_info != (const ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001527 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001528 assert(image != (Image *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001529 assert(image->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001530 if (image->debug != MagickFalse)
1531 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy3a37efd2011-08-28 20:31:03 +00001532 assert(exception != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001533 assert(exception->signature == MagickCoreSignature);
cristy1e178e72011-08-28 19:44:34 +00001534 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy3ed852e2009-09-05 21:47:34 +00001535 if (status == MagickFalse)
1536 return(status);
1537 scene=0;
1538 do
1539 {
cristy92beec62013-08-26 12:23:46 +00001540 QuantumAny
1541 max_value;
1542
cristy3ed852e2009-09-05 21:47:34 +00001543 /*
1544 Write PNM file header.
1545 */
1546 packet_size=3;
1547 quantum_type=RGBQuantum;
cristy151b66d2015-04-15 10:50:31 +00001548 (void) CopyMagickString(magick,image_info->magick,MagickPathExtent);
cristy92beec62013-08-26 12:23:46 +00001549 max_value=GetQuantumRange(image->depth);
cristy3ed852e2009-09-05 21:47:34 +00001550 switch (magick[1])
1551 {
1552 case 'A':
1553 case 'a':
1554 {
1555 format='7';
1556 break;
1557 }
1558 case 'B':
1559 case 'b':
1560 {
1561 format='4';
1562 if (image_info->compression == NoCompression)
1563 format='1';
1564 break;
1565 }
1566 case 'F':
1567 case 'f':
1568 {
1569 format='F';
dirkf1d85482015-04-06 00:36:00 +00001570 if (SetImageGray(image,exception) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001571 format='f';
1572 break;
1573 }
1574 case 'G':
1575 case 'g':
1576 {
1577 format='5';
1578 if (image_info->compression == NoCompression)
1579 format='2';
1580 break;
1581 }
1582 case 'N':
1583 case 'n':
1584 {
1585 if ((image_info->type != TrueColorType) &&
dirkf1d85482015-04-06 00:36:00 +00001586 (SetImageGray(image,exception) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00001587 {
1588 format='5';
1589 if (image_info->compression == NoCompression)
1590 format='2';
dirkf1d85482015-04-06 00:36:00 +00001591 if (SetImageMonochrome(image,exception) != MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001592 {
1593 format='4';
1594 if (image_info->compression == NoCompression)
1595 format='1';
1596 }
1597 break;
1598 }
1599 }
1600 default:
1601 {
1602 format='6';
1603 if (image_info->compression == NoCompression)
1604 format='3';
1605 break;
1606 }
1607 }
cristy151b66d2015-04-15 10:50:31 +00001608 (void) FormatLocaleString(buffer,MagickPathExtent,"P%c\n",format);
cristy3ed852e2009-09-05 21:47:34 +00001609 (void) WriteBlobString(image,buffer);
cristyd15e6592011-10-15 00:13:06 +00001610 value=GetImageProperty(image,"comment",exception);
cristy3ed852e2009-09-05 21:47:34 +00001611 if (value != (const char *) NULL)
1612 {
1613 register const char
1614 *p;
1615
1616 /*
1617 Write comments to file.
1618 */
1619 (void) WriteBlobByte(image,'#');
1620 for (p=value; *p != '\0'; p++)
1621 {
1622 (void) WriteBlobByte(image,(unsigned char) *p);
cristy542ea782013-05-24 15:53:01 +00001623 if ((*p == '\n') || (*p == '\r'))
cristy3ed852e2009-09-05 21:47:34 +00001624 (void) WriteBlobByte(image,'#');
1625 }
1626 (void) WriteBlobByte(image,'\n');
1627 }
1628 if (format != '7')
1629 {
cristy151b66d2015-04-15 10:50:31 +00001630 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g\n",
cristye8c25f92010-06-03 00:53:06 +00001631 (double) image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001632 (void) WriteBlobString(image,buffer);
1633 }
1634 else
1635 {
1636 char
cristy151b66d2015-04-15 10:50:31 +00001637 type[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00001638
1639 /*
1640 PAM header.
1641 */
cristy151b66d2015-04-15 10:50:31 +00001642 (void) FormatLocaleString(buffer,MagickPathExtent,
cristye8c25f92010-06-03 00:53:06 +00001643 "WIDTH %.20g\nHEIGHT %.20g\n",(double) image->columns,(double)
1644 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001645 (void) WriteBlobString(image,buffer);
cristy1e178e72011-08-28 19:44:34 +00001646 quantum_type=GetQuantumType(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00001647 switch (quantum_type)
1648 {
1649 case CMYKQuantum:
1650 case CMYKAQuantum:
1651 {
1652 packet_size=4;
cristy151b66d2015-04-15 10:50:31 +00001653 (void) CopyMagickString(type,"CMYK",MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001654 break;
1655 }
1656 case GrayQuantum:
1657 case GrayAlphaQuantum:
1658 {
1659 packet_size=1;
cristy151b66d2015-04-15 10:50:31 +00001660 (void) CopyMagickString(type,"GRAYSCALE",MagickPathExtent);
Cristye84a1652017-01-01 14:42:22 -05001661 if (IsImageMonochrome(image) != MagickFalse)
1662 (void) CopyMagickString(type,"BLACKANDWHITE",MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001663 break;
1664 }
1665 default:
1666 {
1667 quantum_type=RGBQuantum;
cristy17f11b02014-12-20 19:37:04 +00001668 if (image->alpha_trait != UndefinedPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00001669 quantum_type=RGBAQuantum;
1670 packet_size=3;
cristy151b66d2015-04-15 10:50:31 +00001671 (void) CopyMagickString(type,"RGB",MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001672 break;
1673 }
1674 }
cristy17f11b02014-12-20 19:37:04 +00001675 if (image->alpha_trait != UndefinedPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00001676 {
1677 packet_size++;
cristy151b66d2015-04-15 10:50:31 +00001678 (void) ConcatenateMagickString(type,"_ALPHA",MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001679 }
cristy67d16d92013-09-29 18:31:17 +00001680 if (image->depth > 32)
1681 image->depth=32;
cristy151b66d2015-04-15 10:50:31 +00001682 (void) FormatLocaleString(buffer,MagickPathExtent,
cristye8c25f92010-06-03 00:53:06 +00001683 "DEPTH %.20g\nMAXVAL %.20g\n",(double) packet_size,(double)
cristy2b9582a2011-07-04 17:38:56 +00001684 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001685 (void) WriteBlobString(image,buffer);
Cristye84a1652017-01-01 14:42:22 -05001686 (void) FormatLocaleString(buffer,MagickPathExtent,
1687 "TUPLTYPE %s\nENDHDR\n",type);
cristy3ed852e2009-09-05 21:47:34 +00001688 (void) WriteBlobString(image,buffer);
1689 }
1690 /*
1691 Convert runextent encoded to PNM raster pixels.
1692 */
1693 switch (format)
1694 {
1695 case '1':
1696 {
cristy661b5ad2010-01-13 00:54:42 +00001697 unsigned char
1698 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001699
1700 /*
1701 Convert image to a PBM image.
1702 */
cristy7a4c0972013-11-22 17:48:43 +00001703 (void) SetImageType(image,BilevelType,exception);
cristy661b5ad2010-01-13 00:54:42 +00001704 q=pixels;
cristybb503372010-05-27 20:51:26 +00001705 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001706 {
cristy4c08aed2011-07-01 19:47:50 +00001707 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001708 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001709
cristybb503372010-05-27 20:51:26 +00001710 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001711 x;
1712
cristy1e178e72011-08-28 19:44:34 +00001713 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001714 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001715 break;
cristybb503372010-05-27 20:51:26 +00001716 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001717 {
cristy7a4c0972013-11-22 17:48:43 +00001718 *q++=(unsigned char) (GetPixelLuma(image,p) >= (QuantumRange/2.0) ?
cristy661b5ad2010-01-13 00:54:42 +00001719 '0' : '1');
1720 *q++=' ';
cristyb1253cd2015-05-31 01:06:54 +00001721 if ((q-pixels+1) >= (ssize_t) sizeof(pixels))
cristy6b675d12015-05-22 22:15:18 +00001722 {
1723 *q++='\n';
1724 (void) WriteBlob(image,q-pixels,pixels);
1725 q=pixels;
1726 }
cristyed231572011-07-14 02:18:59 +00001727 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001728 }
cristy1446bc92015-05-22 21:32:42 +00001729 *q++='\n';
1730 (void) WriteBlob(image,q-pixels,pixels);
1731 q=pixels;
cristy3ed852e2009-09-05 21:47:34 +00001732 if (image->previous == (Image *) NULL)
1733 {
cristycee97112010-05-28 00:44:52 +00001734 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1735 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001736 if (status == MagickFalse)
1737 break;
1738 }
1739 }
cristy661b5ad2010-01-13 00:54:42 +00001740 if (q != pixels)
1741 {
1742 *q++='\n';
1743 (void) WriteBlob(image,q-pixels,pixels);
1744 }
cristy3ed852e2009-09-05 21:47:34 +00001745 break;
1746 }
1747 case '2':
1748 {
cristy661b5ad2010-01-13 00:54:42 +00001749 unsigned char
1750 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001751
1752 /*
1753 Convert image to a PGM image.
1754 */
1755 if (image->depth <= 8)
1756 (void) WriteBlobString(image,"255\n");
1757 else
cristy67d16d92013-09-29 18:31:17 +00001758 if (image->depth <= 16)
1759 (void) WriteBlobString(image,"65535\n");
1760 else
1761 (void) WriteBlobString(image,"4294967295\n");
cristy661b5ad2010-01-13 00:54:42 +00001762 q=pixels;
cristybb503372010-05-27 20:51:26 +00001763 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001764 {
cristy4c08aed2011-07-01 19:47:50 +00001765 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001766 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001767
cristybb503372010-05-27 20:51:26 +00001768 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001769 x;
1770
cristy1e178e72011-08-28 19:44:34 +00001771 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001772 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001773 break;
cristybb503372010-05-27 20:51:26 +00001774 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001775 {
cristyd0323222013-04-07 16:13:21 +00001776 index=ClampToQuantum(GetPixelLuma(image,p));
cristy3ed852e2009-09-05 21:47:34 +00001777 if (image->depth <= 8)
cristy151b66d2015-04-15 10:50:31 +00001778 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,"%u ",
cristy3ed852e2009-09-05 21:47:34 +00001779 ScaleQuantumToChar(index));
1780 else
cristy67d16d92013-09-29 18:31:17 +00001781 if (image->depth <= 16)
cristy1446bc92015-05-22 21:32:42 +00001782 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
1783 "%u ",ScaleQuantumToShort(index));
cristy67d16d92013-09-29 18:31:17 +00001784 else
cristy1446bc92015-05-22 21:32:42 +00001785 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
1786 "%u ",ScaleQuantumToLong(index));
cristy661b5ad2010-01-13 00:54:42 +00001787 extent=(size_t) count;
1788 (void) strncpy((char *) q,buffer,extent);
1789 q+=extent;
cristy6b675d12015-05-22 22:15:18 +00001790 if ((q-pixels+extent+1) >= sizeof(pixels))
cristy661b5ad2010-01-13 00:54:42 +00001791 {
1792 *q++='\n';
1793 (void) WriteBlob(image,q-pixels,pixels);
1794 q=pixels;
1795 }
cristyed231572011-07-14 02:18:59 +00001796 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001797 }
cristy6b675d12015-05-22 22:15:18 +00001798 *q++='\n';
1799 (void) WriteBlob(image,q-pixels,pixels);
1800 q=pixels;
cristy3ed852e2009-09-05 21:47:34 +00001801 if (image->previous == (Image *) NULL)
1802 {
cristycee97112010-05-28 00:44:52 +00001803 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1804 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001805 if (status == MagickFalse)
1806 break;
1807 }
1808 }
cristy661b5ad2010-01-13 00:54:42 +00001809 if (q != pixels)
1810 {
1811 *q++='\n';
1812 (void) WriteBlob(image,q-pixels,pixels);
1813 }
cristy3ed852e2009-09-05 21:47:34 +00001814 break;
1815 }
1816 case '3':
1817 {
cristy661b5ad2010-01-13 00:54:42 +00001818 unsigned char
1819 pixels[2048];
cristy3ed852e2009-09-05 21:47:34 +00001820
1821 /*
1822 Convert image to a PNM image.
1823 */
cristyaf8d3912014-02-21 14:50:33 +00001824 (void) TransformImageColorspace(image,sRGBColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +00001825 if (image->depth <= 8)
1826 (void) WriteBlobString(image,"255\n");
1827 else
cristy67d16d92013-09-29 18:31:17 +00001828 if (image->depth <= 16)
1829 (void) WriteBlobString(image,"65535\n");
1830 else
1831 (void) WriteBlobString(image,"4294967295\n");
cristy661b5ad2010-01-13 00:54:42 +00001832 q=pixels;
cristybb503372010-05-27 20:51:26 +00001833 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001834 {
cristy4c08aed2011-07-01 19:47:50 +00001835 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001836 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001837
cristybb503372010-05-27 20:51:26 +00001838 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001839 x;
1840
cristy1e178e72011-08-28 19:44:34 +00001841 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001842 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001843 break;
cristybb503372010-05-27 20:51:26 +00001844 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001845 {
1846 if (image->depth <= 8)
cristy151b66d2015-04-15 10:50:31 +00001847 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
cristy4c08aed2011-07-01 19:47:50 +00001848 "%u %u %u ",ScaleQuantumToChar(GetPixelRed(image,p)),
1849 ScaleQuantumToChar(GetPixelGreen(image,p)),
1850 ScaleQuantumToChar(GetPixelBlue(image,p)));
cristy3ed852e2009-09-05 21:47:34 +00001851 else
cristy67d16d92013-09-29 18:31:17 +00001852 if (image->depth <= 16)
cristy151b66d2015-04-15 10:50:31 +00001853 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
cristy67d16d92013-09-29 18:31:17 +00001854 "%u %u %u ",ScaleQuantumToShort(GetPixelRed(image,p)),
1855 ScaleQuantumToShort(GetPixelGreen(image,p)),
1856 ScaleQuantumToShort(GetPixelBlue(image,p)));
1857 else
cristy151b66d2015-04-15 10:50:31 +00001858 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
cristy67d16d92013-09-29 18:31:17 +00001859 "%u %u %u ",ScaleQuantumToLong(GetPixelRed(image,p)),
1860 ScaleQuantumToLong(GetPixelGreen(image,p)),
1861 ScaleQuantumToLong(GetPixelBlue(image,p)));
cristy661b5ad2010-01-13 00:54:42 +00001862 extent=(size_t) count;
1863 (void) strncpy((char *) q,buffer,extent);
1864 q+=extent;
cristy6b675d12015-05-22 22:15:18 +00001865 if ((q-pixels+extent+1) >= sizeof(pixels))
cristy661b5ad2010-01-13 00:54:42 +00001866 {
1867 *q++='\n';
1868 (void) WriteBlob(image,q-pixels,pixels);
1869 q=pixels;
1870 }
cristyed231572011-07-14 02:18:59 +00001871 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00001872 }
cristy6b675d12015-05-22 22:15:18 +00001873 *q++='\n';
1874 (void) WriteBlob(image,q-pixels,pixels);
1875 q=pixels;
cristy3ed852e2009-09-05 21:47:34 +00001876 if (image->previous == (Image *) NULL)
1877 {
cristycee97112010-05-28 00:44:52 +00001878 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1879 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001880 if (status == MagickFalse)
1881 break;
1882 }
1883 }
cristy661b5ad2010-01-13 00:54:42 +00001884 if (q != pixels)
1885 {
1886 *q++='\n';
1887 (void) WriteBlob(image,q-pixels,pixels);
1888 }
cristy3ed852e2009-09-05 21:47:34 +00001889 break;
1890 }
1891 case '4':
1892 {
1893 /*
1894 Convert image to a PBM image.
1895 */
cristy7a4c0972013-11-22 17:48:43 +00001896 (void) SetImageType(image,BilevelType,exception);
cristy3ed852e2009-09-05 21:47:34 +00001897 image->depth=1;
cristy5f766ef2014-12-14 21:12:47 +00001898 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +00001899 if (quantum_info == (QuantumInfo *) NULL)
1900 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
cristy5b4868f2014-12-14 17:43:35 +00001901 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
cristy3ed852e2009-09-05 21:47:34 +00001902 quantum_info->min_is_white=MagickTrue;
cristy6b675d12015-05-22 22:15:18 +00001903 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00001904 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001905 {
cristy4c08aed2011-07-01 19:47:50 +00001906 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001907 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001908
cristy1e178e72011-08-28 19:44:34 +00001909 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001910 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001911 break;
cristy4c08aed2011-07-01 19:47:50 +00001912 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001913 GrayQuantum,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001914 count=WriteBlob(image,extent,pixels);
1915 if (count != (ssize_t) extent)
1916 break;
1917 if (image->previous == (Image *) NULL)
1918 {
cristycee97112010-05-28 00:44:52 +00001919 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1920 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001921 if (status == MagickFalse)
1922 break;
1923 }
1924 }
1925 quantum_info=DestroyQuantumInfo(quantum_info);
1926 break;
1927 }
1928 case '5':
1929 {
cristy3ed852e2009-09-05 21:47:34 +00001930 /*
1931 Convert image to a PGM image.
1932 */
cristy67d16d92013-09-29 18:31:17 +00001933 if (image->depth > 32)
cristyeff7fcc2013-09-30 10:27:08 +00001934 image->depth=32;
cristy151b66d2015-04-15 10:50:31 +00001935 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
cristy2b9582a2011-07-04 17:38:56 +00001936 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00001937 (void) WriteBlobString(image,buffer);
cristy5f766ef2014-12-14 21:12:47 +00001938 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +00001939 if (quantum_info == (QuantumInfo *) NULL)
1940 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
cristy5b4868f2014-12-14 17:43:35 +00001941 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
cristy3ed852e2009-09-05 21:47:34 +00001942 quantum_info->min_is_white=MagickTrue;
cristy6b675d12015-05-22 22:15:18 +00001943 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00001944 extent=GetQuantumExtent(image,quantum_info,GrayQuantum);
cristybb503372010-05-27 20:51:26 +00001945 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001946 {
cristy4c08aed2011-07-01 19:47:50 +00001947 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01001948 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001949
cristybb503372010-05-27 20:51:26 +00001950 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001951 x;
1952
cristy1e178e72011-08-28 19:44:34 +00001953 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001954 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001955 break;
1956 q=pixels;
cristy67d16d92013-09-29 18:31:17 +00001957 switch (image->depth)
1958 {
1959 case 8:
1960 case 16:
1961 case 32:
1962 {
1963 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1964 GrayQuantum,pixels,exception);
1965 break;
1966 }
1967 default:
cristy3ed852e2009-09-05 21:47:34 +00001968 {
1969 if (image->depth <= 8)
cristy3ed852e2009-09-05 21:47:34 +00001970 {
cristy67d16d92013-09-29 18:31:17 +00001971 for (x=0; x < (ssize_t) image->columns; x++)
1972 {
1973 if (IsPixelGray(image,p) == MagickFalse)
1974 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(
1975 image,p)),max_value);
1976 else
1977 {
1978 if (image->depth == 8)
1979 pixel=ScaleQuantumToChar(GetPixelRed(image,p));
1980 else
cristyeff7fcc2013-09-30 10:27:08 +00001981 pixel=ScaleQuantumToAny(GetPixelRed(image,p),
Cristyb2181172017-03-31 15:24:33 -04001982 max_value);
cristy67d16d92013-09-29 18:31:17 +00001983 }
1984 q=PopCharPixel((unsigned char) pixel,q);
1985 p+=GetPixelChannels(image);
1986 }
cristy66d892b2013-10-03 11:39:44 +00001987 extent=(size_t) (q-pixels);
cristy67d16d92013-09-29 18:31:17 +00001988 break;
cristy3ed852e2009-09-05 21:47:34 +00001989 }
cristy67d16d92013-09-29 18:31:17 +00001990 if (image->depth <= 16)
cristy3ed852e2009-09-05 21:47:34 +00001991 {
cristy67d16d92013-09-29 18:31:17 +00001992 for (x=0; x < (ssize_t) image->columns; x++)
1993 {
1994 if (IsPixelGray(image,p) == MagickFalse)
cristyeff7fcc2013-09-30 10:27:08 +00001995 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(image,
1996 p)),max_value);
cristy67d16d92013-09-29 18:31:17 +00001997 else
1998 {
1999 if (image->depth == 16)
2000 pixel=ScaleQuantumToShort(GetPixelRed(image,p));
2001 else
cristyeff7fcc2013-09-30 10:27:08 +00002002 pixel=ScaleQuantumToAny(GetPixelRed(image,p),
2003 max_value);
cristy67d16d92013-09-29 18:31:17 +00002004 }
2005 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2006 p+=GetPixelChannels(image);
2007 }
cristy66d892b2013-10-03 11:39:44 +00002008 extent=(size_t) (q-pixels);
cristy67d16d92013-09-29 18:31:17 +00002009 break;
cristy3ed852e2009-09-05 21:47:34 +00002010 }
cristy67d16d92013-09-29 18:31:17 +00002011 for (x=0; x < (ssize_t) image->columns; x++)
2012 {
2013 if (IsPixelGray(image,p) == MagickFalse)
cristyeff7fcc2013-09-30 10:27:08 +00002014 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(image,p)),
2015 max_value);
cristy67d16d92013-09-29 18:31:17 +00002016 else
2017 {
2018 if (image->depth == 16)
2019 pixel=ScaleQuantumToLong(GetPixelRed(image,p));
2020 else
2021 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2022 }
2023 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2024 p+=GetPixelChannels(image);
2025 }
cristy3ed852e2009-09-05 21:47:34 +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 }
cristy3ed852e2009-09-05 21:47:34 +00002030 count=WriteBlob(image,extent,pixels);
2031 if (count != (ssize_t) extent)
2032 break;
2033 if (image->previous == (Image *) NULL)
2034 {
cristycee97112010-05-28 00:44:52 +00002035 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2036 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002037 if (status == MagickFalse)
2038 break;
2039 }
2040 }
2041 quantum_info=DestroyQuantumInfo(quantum_info);
2042 break;
2043 }
2044 case '6':
2045 {
cristy3ed852e2009-09-05 21:47:34 +00002046 /*
2047 Convert image to a PNM image.
2048 */
cristyaf8d3912014-02-21 14:50:33 +00002049 (void) TransformImageColorspace(image,sRGBColorspace,exception);
cristy67d16d92013-09-29 18:31:17 +00002050 if (image->depth > 32)
2051 image->depth=32;
cristy151b66d2015-04-15 10:50:31 +00002052 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
cristy2b9582a2011-07-04 17:38:56 +00002053 ((MagickOffsetType) GetQuantumRange(image->depth)));
cristy3ed852e2009-09-05 21:47:34 +00002054 (void) WriteBlobString(image,buffer);
cristy5f766ef2014-12-14 21:12:47 +00002055 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +00002056 if (quantum_info == (QuantumInfo *) NULL)
2057 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
cristy70d7eae2012-11-17 19:40:21 +00002058 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
cristy6b675d12015-05-22 22:15:18 +00002059 pixels=GetQuantumPixels(quantum_info);
cristy3ed852e2009-09-05 21:47:34 +00002060 extent=GetQuantumExtent(image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +00002061 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002062 {
cristy4c08aed2011-07-01 19:47:50 +00002063 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01002064 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002065
cristybb503372010-05-27 20:51:26 +00002066 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002067 x;
2068
cristy1e178e72011-08-28 19:44:34 +00002069 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002070 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002071 break;
2072 q=pixels;
cristy67d16d92013-09-29 18:31:17 +00002073 switch (image->depth)
2074 {
2075 case 8:
2076 case 16:
2077 case 32:
2078 {
2079 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2080 quantum_type,pixels,exception);
2081 break;
2082 }
2083 default:
cristy3ed852e2009-09-05 21:47:34 +00002084 {
2085 if (image->depth <= 8)
cristy3ed852e2009-09-05 21:47:34 +00002086 {
cristy67d16d92013-09-29 18:31:17 +00002087 for (x=0; x < (ssize_t) image->columns; x++)
2088 {
2089 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2090 q=PopCharPixel((unsigned char) pixel,q);
2091 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2092 q=PopCharPixel((unsigned char) pixel,q);
2093 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2094 q=PopCharPixel((unsigned char) pixel,q);
2095 p+=GetPixelChannels(image);
2096 }
cristy5838dba2013-10-03 11:42:05 +00002097 extent=(size_t) (q-pixels);
cristy67d16d92013-09-29 18:31:17 +00002098 break;
cristy3ed852e2009-09-05 21:47:34 +00002099 }
cristy67d16d92013-09-29 18:31:17 +00002100 if (image->depth <= 16)
cristy3ed852e2009-09-05 21:47:34 +00002101 {
cristy67d16d92013-09-29 18:31:17 +00002102 for (x=0; x < (ssize_t) image->columns; x++)
2103 {
2104 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2105 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2106 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2107 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2108 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2109 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2110 p+=GetPixelChannels(image);
2111 }
cristy5838dba2013-10-03 11:42:05 +00002112 extent=(size_t) (q-pixels);
cristy67d16d92013-09-29 18:31:17 +00002113 break;
cristy3ed852e2009-09-05 21:47:34 +00002114 }
cristy67d16d92013-09-29 18:31:17 +00002115 for (x=0; x < (ssize_t) image->columns; x++)
2116 {
2117 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2118 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2119 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2120 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2121 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2122 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2123 p+=GetPixelChannels(image);
2124 }
cristy3ed852e2009-09-05 21:47:34 +00002125 extent=(size_t) (q-pixels);
cristy67d16d92013-09-29 18:31:17 +00002126 break;
cristy3ed852e2009-09-05 21:47:34 +00002127 }
cristy67d16d92013-09-29 18:31:17 +00002128 }
cristy3ed852e2009-09-05 21:47:34 +00002129 count=WriteBlob(image,extent,pixels);
2130 if (count != (ssize_t) extent)
2131 break;
2132 if (image->previous == (Image *) NULL)
2133 {
cristycee97112010-05-28 00:44:52 +00002134 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2135 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002136 if (status == MagickFalse)
2137 break;
2138 }
2139 }
2140 quantum_info=DestroyQuantumInfo(quantum_info);
2141 break;
2142 }
2143 case '7':
2144 {
cristy3ed852e2009-09-05 21:47:34 +00002145 /*
2146 Convert image to a PAM.
2147 */
cristy67d16d92013-09-29 18:31:17 +00002148 if (image->depth > 32)
2149 image->depth=32;
cristy5f766ef2014-12-14 21:12:47 +00002150 quantum_info=AcquireQuantumInfo(image_info,image);
cristy5b4868f2014-12-14 17:43:35 +00002151 if (quantum_info == (QuantumInfo *) NULL)
2152 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2153 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
cristy6b675d12015-05-22 22:15:18 +00002154 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002155 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002156 {
cristy4c08aed2011-07-01 19:47:50 +00002157 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01002158 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002159
cristybb503372010-05-27 20:51:26 +00002160 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002161 x;
2162
cristy1e178e72011-08-28 19:44:34 +00002163 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002164 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002165 break;
cristy3ed852e2009-09-05 21:47:34 +00002166 q=pixels;
cristy67d16d92013-09-29 18:31:17 +00002167 switch (image->depth)
2168 {
2169 case 8:
2170 case 16:
2171 case 32:
2172 {
2173 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2174 quantum_type,pixels,exception);
2175 break;
2176 }
2177 default:
cristy3ed852e2009-09-05 21:47:34 +00002178 {
2179 switch (quantum_type)
2180 {
2181 case GrayQuantum:
2182 case GrayAlphaQuantum:
2183 {
2184 if (image->depth <= 8)
cristy3ed852e2009-09-05 21:47:34 +00002185 {
cristy67d16d92013-09-29 18:31:17 +00002186 for (x=0; x < (ssize_t) image->columns; x++)
2187 {
2188 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(
2189 image,p)),max_value);
2190 q=PopCharPixel((unsigned char) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002191 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002192 {
2193 pixel=(unsigned char) ScaleQuantumToAny(
2194 GetPixelAlpha(image,p),max_value);
2195 q=PopCharPixel((unsigned char) pixel,q);
2196 }
2197 p+=GetPixelChannels(image);
2198 }
2199 break;
cristy3ed852e2009-09-05 21:47:34 +00002200 }
cristy67d16d92013-09-29 18:31:17 +00002201 if (image->depth <= 16)
cristy3ed852e2009-09-05 21:47:34 +00002202 {
cristy67d16d92013-09-29 18:31:17 +00002203 for (x=0; x < (ssize_t) image->columns; x++)
2204 {
2205 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(
2206 image,p)),max_value);
2207 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002208 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002209 {
2210 pixel=(unsigned char) ScaleQuantumToAny(
2211 GetPixelAlpha(image,p),max_value);
2212 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2213 }
2214 p+=GetPixelChannels(image);
2215 }
2216 break;
cristy3ed852e2009-09-05 21:47:34 +00002217 }
cristy67d16d92013-09-29 18:31:17 +00002218 for (x=0; x < (ssize_t) image->columns; x++)
2219 {
cristyeff7fcc2013-09-30 10:27:08 +00002220 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(image,
2221 p)),max_value);
cristy67d16d92013-09-29 18:31:17 +00002222 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002223 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002224 {
2225 pixel=(unsigned char) ScaleQuantumToAny(
2226 GetPixelAlpha(image,p),max_value);
2227 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2228 }
2229 p+=GetPixelChannels(image);
2230 }
cristy3ed852e2009-09-05 21:47:34 +00002231 break;
2232 }
2233 case CMYKQuantum:
2234 case CMYKAQuantum:
2235 {
2236 if (image->depth <= 8)
cristy3ed852e2009-09-05 21:47:34 +00002237 {
cristy67d16d92013-09-29 18:31:17 +00002238 for (x=0; x < (ssize_t) image->columns; x++)
2239 {
2240 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2241 q=PopCharPixel((unsigned char) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002242 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2243 max_value);
cristy67d16d92013-09-29 18:31:17 +00002244 q=PopCharPixel((unsigned char) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002245 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2246 max_value);
cristy67d16d92013-09-29 18:31:17 +00002247 q=PopCharPixel((unsigned char) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002248 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),
2249 max_value);
cristy67d16d92013-09-29 18:31:17 +00002250 q=PopCharPixel((unsigned char) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002251 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002252 {
2253 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2254 max_value);
2255 q=PopCharPixel((unsigned char) pixel,q);
2256 }
2257 p+=GetPixelChannels(image);
2258 }
2259 break;
cristy3ed852e2009-09-05 21:47:34 +00002260 }
cristy67d16d92013-09-29 18:31:17 +00002261 if (image->depth <= 16)
cristy3ed852e2009-09-05 21:47:34 +00002262 {
cristy67d16d92013-09-29 18:31:17 +00002263 for (x=0; x < (ssize_t) image->columns; x++)
2264 {
2265 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2266 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002267 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2268 max_value);
cristy67d16d92013-09-29 18:31:17 +00002269 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002270 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2271 max_value);
cristy67d16d92013-09-29 18:31:17 +00002272 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002273 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),
2274 max_value);
cristy67d16d92013-09-29 18:31:17 +00002275 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002276 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002277 {
2278 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2279 max_value);
2280 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2281 }
2282 p+=GetPixelChannels(image);
2283 }
2284 break;
cristy3ed852e2009-09-05 21:47:34 +00002285 }
cristy67d16d92013-09-29 18:31:17 +00002286 for (x=0; x < (ssize_t) image->columns; x++)
2287 {
2288 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2289 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2290 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2291 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2292 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2293 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2294 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),max_value);
2295 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002296 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002297 {
cristyeff7fcc2013-09-30 10:27:08 +00002298 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2299 max_value);
cristy67d16d92013-09-29 18:31:17 +00002300 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2301 }
2302 p+=GetPixelChannels(image);
2303 }
cristy3ed852e2009-09-05 21:47:34 +00002304 break;
2305 }
2306 default:
2307 {
2308 if (image->depth <= 8)
cristy3ed852e2009-09-05 21:47:34 +00002309 {
cristy67d16d92013-09-29 18:31:17 +00002310 for (x=0; x < (ssize_t) image->columns; x++)
2311 {
2312 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2313 q=PopCharPixel((unsigned char) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002314 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2315 max_value);
cristy67d16d92013-09-29 18:31:17 +00002316 q=PopCharPixel((unsigned char) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002317 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2318 max_value);
cristy67d16d92013-09-29 18:31:17 +00002319 q=PopCharPixel((unsigned char) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002320 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002321 {
2322 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2323 max_value);
2324 q=PopCharPixel((unsigned char) pixel,q);
2325 }
2326 p+=GetPixelChannels(image);
2327 }
2328 break;
cristy3ed852e2009-09-05 21:47:34 +00002329 }
cristy67d16d92013-09-29 18:31:17 +00002330 if (image->depth <= 16)
cristy3ed852e2009-09-05 21:47:34 +00002331 {
cristy67d16d92013-09-29 18:31:17 +00002332 for (x=0; x < (ssize_t) image->columns; x++)
2333 {
2334 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2335 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002336 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2337 max_value);
cristy67d16d92013-09-29 18:31:17 +00002338 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristyeff7fcc2013-09-30 10:27:08 +00002339 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2340 max_value);
cristy67d16d92013-09-29 18:31:17 +00002341 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002342 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002343 {
2344 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2345 max_value);
2346 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2347 }
2348 p+=GetPixelChannels(image);
2349 }
2350 break;
cristy3ed852e2009-09-05 21:47:34 +00002351 }
cristy67d16d92013-09-29 18:31:17 +00002352 for (x=0; x < (ssize_t) image->columns; x++)
2353 {
2354 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2355 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2356 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2357 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2358 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2359 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
cristy17f11b02014-12-20 19:37:04 +00002360 if (image->alpha_trait != UndefinedPixelTrait)
cristy67d16d92013-09-29 18:31:17 +00002361 {
cristyeff7fcc2013-09-30 10:27:08 +00002362 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2363 max_value);
cristy67d16d92013-09-29 18:31:17 +00002364 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2365 }
2366 p+=GetPixelChannels(image);
2367 }
cristy3ed852e2009-09-05 21:47:34 +00002368 break;
2369 }
2370 }
2371 extent=(size_t) (q-pixels);
cristy67d16d92013-09-29 18:31:17 +00002372 break;
cristy3ed852e2009-09-05 21:47:34 +00002373 }
cristy67d16d92013-09-29 18:31:17 +00002374 }
cristy3ed852e2009-09-05 21:47:34 +00002375 count=WriteBlob(image,extent,pixels);
2376 if (count != (ssize_t) extent)
2377 break;
2378 if (image->previous == (Image *) NULL)
2379 {
cristycee97112010-05-28 00:44:52 +00002380 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2381 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002382 if (status == MagickFalse)
2383 break;
2384 }
2385 }
2386 quantum_info=DestroyQuantumInfo(quantum_info);
2387 break;
2388 }
2389 case 'F':
2390 case 'f':
2391 {
cristy1715f792012-11-22 16:56:12 +00002392 (void) WriteBlobString(image,image->endian == LSBEndian ? "-1.0\n" :
2393 "1.0\n");
cristy3ed852e2009-09-05 21:47:34 +00002394 image->depth=32;
2395 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
cristy5f766ef2014-12-14 21:12:47 +00002396 quantum_info=AcquireQuantumInfo(image_info,image);
cristy3ed852e2009-09-05 21:47:34 +00002397 if (quantum_info == (QuantumInfo *) NULL)
2398 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2399 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2400 if (status == MagickFalse)
2401 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
cristy6b675d12015-05-22 22:15:18 +00002402 pixels=GetQuantumPixels(quantum_info);
cristybb503372010-05-27 20:51:26 +00002403 for (y=(ssize_t) image->rows-1; y >= 0; y--)
cristy3ed852e2009-09-05 21:47:34 +00002404 {
cristy4c08aed2011-07-01 19:47:50 +00002405 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01002406 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00002407
cristy1e178e72011-08-28 19:44:34 +00002408 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002409 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002410 break;
cristy4c08aed2011-07-01 19:47:50 +00002411 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00002412 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00002413 (void) WriteBlob(image,extent,pixels);
2414 if (image->previous == (Image *) NULL)
2415 {
cristycee97112010-05-28 00:44:52 +00002416 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2417 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00002418 if (status == MagickFalse)
2419 break;
2420 }
2421 }
2422 quantum_info=DestroyQuantumInfo(quantum_info);
2423 break;
2424 }
2425 }
2426 if (GetNextImageInList(image) == (Image *) NULL)
2427 break;
2428 image=SyncNextImageInList(image);
2429 status=SetImageProgress(image,SaveImagesTag,scene++,
2430 GetImageListLength(image));
2431 if (status == MagickFalse)
2432 break;
2433 } while (image_info->adjoin != MagickFalse);
2434 (void) CloseBlob(image);
2435 return(MagickTrue);
2436}