1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % PPPP N N M M %
7 % P P NN N MM MM %
8 % PPPP N N N M M M %
9 % P N NN M M %
10 % P N N M M %
11 % %
12 % %
13 % Read/Write PBMPlus Portable Anymap Image Format %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38
39 /*
40 Include declarations.
41 */
42 #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"
50 #include "MagickCore/colorspace-private.h"
51 #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"
68
69 /*
70 Typedef declarations.
71 */
72 typedef struct _CommentInfo
73 {
74 char
75 *comment;
76
77 size_t
78 extent;
79 } CommentInfo;
80
81 /*
82 Forward declarations.
83 */
84 static MagickBooleanType
85 WritePNMImage(const ImageInfo *,Image *,ExceptionInfo *);
86
87 /*
88 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89 % %
90 % %
91 % %
92 % I s P N M %
93 % %
94 % %
95 % %
96 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
97 %
98 % IsPNM() returns MagickTrue if the image format type, identified by the
99 % magick string, is PNM.
100 %
101 % The format of the IsPNM method is:
102 %
103 % MagickBooleanType IsPNM(const unsigned char *magick,const size_t extent)
104 %
105 % A description of each parameter follows:
106 %
107 % o magick: compare image format pattern against these bytes.
108 %
109 % o extent: Specifies the extent of the magick string.
110 %
111 */
IsPNM(const unsigned char * magick,const size_t extent)112 static MagickBooleanType IsPNM(const unsigned char *magick,const size_t extent)
113 {
114 if (extent < 2)
115 return(MagickFalse);
116 if ((*magick == (unsigned char) 'P') &&
117 ((magick[1] == '1') || (magick[1] == '2') || (magick[1] == '3') ||
118 (magick[1] == '4') || (magick[1] == '5') || (magick[1] == '6') ||
119 (magick[1] == '7') || (magick[1] == 'F') || (magick[1] == 'f') ||
120 (magick[1] == 'H') || (magick[1] == 'h')))
121 return(MagickTrue);
122 return(MagickFalse);
123 }
124
125 /*
126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
127 % %
128 % %
129 % %
130 % R e a d P N M I m a g e %
131 % %
132 % %
133 % %
134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135 %
136 % ReadPNMImage() reads a Portable Anymap image file and returns it.
137 % It allocates the memory necessary for the new Image structure and returns
138 % a pointer to the new image.
139 %
140 % The format of the ReadPNMImage method is:
141 %
142 % Image *ReadPNMImage(const ImageInfo *image_info,ExceptionInfo *exception)
143 %
144 % A description of each parameter follows:
145 %
146 % o image_info: the image info.
147 %
148 % o exception: return any errors or warnings in this structure.
149 %
150 */
151
PNMComment(Image * image,CommentInfo * comment_info,ExceptionInfo * exception)152 static int PNMComment(Image *image,CommentInfo *comment_info,
153 ExceptionInfo *exception)
154 {
155 int
156 c;
157
158 char
159 *p;
160
161 /*
162 Read comment.
163 */
164 (void) exception;
165 p=comment_info->comment+strlen(comment_info->comment);
166 for (c='#'; (c != EOF) && (c != (int) '\n') && (c != (int) '\r'); p++)
167 {
168 if ((size_t) (p-comment_info->comment+1) >= comment_info->extent)
169 {
170 comment_info->extent<<=1;
171 comment_info->comment=(char *) ResizeQuantumMemory(
172 comment_info->comment,comment_info->extent,
173 sizeof(*comment_info->comment));
174 if (comment_info->comment == (char *) NULL)
175 return(-1);
176 p=comment_info->comment+strlen(comment_info->comment);
177 }
178 c=ReadBlobByte(image);
179 if (c != EOF)
180 {
181 *p=(char) c;
182 *(p+1)='\0';
183 }
184 }
185 return(c);
186 }
187
PNMInteger(Image * image,CommentInfo * comment_info,const unsigned int base,ExceptionInfo * exception)188 static unsigned int PNMInteger(Image *image,CommentInfo *comment_info,
189 const unsigned int base,ExceptionInfo *exception)
190 {
191 int
192 c;
193
194 unsigned int
195 value;
196
197 /*
198 Skip any leading whitespace.
199 */
200 do
201 {
202 c=ReadBlobByte(image);
203 if (c == EOF)
204 return(0);
205 if (c == (int) '#')
206 c=PNMComment(image,comment_info,exception);
207 } while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'));
208 if (base == 2)
209 return((unsigned int) (c-(int) '0'));
210 /*
211 Evaluate number.
212 */
213 value=0;
214 while (isdigit((int) ((unsigned char) c)) != 0)
215 {
216 if (value <= (unsigned int) (INT_MAX/10))
217 {
218 value*=10;
219 if (value <= (unsigned int) (INT_MAX-(c-(int) '0')))
220 value+=c-(int) '0';
221 }
222 c=ReadBlobByte(image);
223 if (c == EOF)
224 return(0);
225 }
226 if (c == (int) '#')
227 c=PNMComment(image,comment_info,exception);
228 return(value);
229 }
230
PNMString(Image * image,char * string,const size_t extent)231 static char *PNMString(Image *image,char *string,const size_t extent)
232 {
233 int
234 c;
235
236 size_t
237 i;
238
239 for (i=0; i < (extent-1L); i++)
240 {
241 c=ReadBlobByte(image);
242 if (c == EOF)
243 {
244 if (i == 0)
245 return((char *) NULL);
246 break;
247 }
248 string[i]=c;
249 if (c == '\n' || c == '\r')
250 break;
251 }
252 string[i]='\0';
253 return(string);
254 }
255
ReadPNMImage(const ImageInfo * image_info,ExceptionInfo * exception)256 static Image *ReadPNMImage(const ImageInfo *image_info,ExceptionInfo *exception)
257 {
258 #define ThrowPNMException(exception,message) \
259 { \
260 if (comment_info.comment != (char *) NULL) \
261 comment_info.comment=DestroyString(comment_info.comment); \
262 ThrowReaderException((exception),(message)); \
263 }
264
265 char
266 format;
267
268 CommentInfo
269 comment_info;
270
271 const void
272 *stream;
273
274 double
275 quantum_scale;
276
277 Image
278 *image;
279
280 MagickBooleanType
281 status;
282
283 QuantumAny
284 max_value;
285
286 QuantumInfo
287 *quantum_info;
288
289 QuantumType
290 quantum_type;
291
292 size_t
293 depth,
294 extent,
295 packet_size;
296
297 ssize_t
298 count,
299 row,
300 y;
301
302 unsigned char
303 *pixels;
304
305 /*
306 Open image file.
307 */
308 assert(image_info != (const ImageInfo *) NULL);
309 assert(image_info->signature == MagickCoreSignature);
310 if (image_info->debug != MagickFalse)
311 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
312 image_info->filename);
313 assert(exception != (ExceptionInfo *) NULL);
314 assert(exception->signature == MagickCoreSignature);
315 image=AcquireImage(image_info,exception);
316 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
317 if (status == MagickFalse)
318 {
319 image=DestroyImageList(image);
320 return((Image *) NULL);
321 }
322 /*
323 Read PNM image.
324 */
325 count=ReadBlob(image,1,(unsigned char *) &format);
326 do
327 {
328 /*
329 Initialize image structure.
330 */
331 comment_info.comment=AcquireString(NULL);
332 comment_info.extent=MagickPathExtent;
333 if ((count != 1) || (format != 'P'))
334 ThrowPNMException(CorruptImageError,"ImproperImageHeader");
335 max_value=1;
336 quantum_type=UndefinedQuantum;
337 quantum_scale=1.0;
338 format=(char) ReadBlobByte(image);
339 if (format != '7')
340 {
341 /*
342 PBM, PGM, PPM, and PNM.
343 */
344 if (ReadBlobByte(image) == '4')
345 image->alpha_trait=BlendPixelTrait;
346 image->columns=(size_t) PNMInteger(image,&comment_info,10,exception);
347 image->rows=(size_t) PNMInteger(image,&comment_info,10,exception);
348 if ((format == 'f') || (format == 'F') || (format == 'h') ||
349 (format == 'H'))
350 {
351 char
352 scale[32];
353
354 if (PNMString(image,scale,sizeof(scale)) != (char *) NULL)
355 quantum_scale=StringToDouble(scale,(char **) NULL);
356 }
357 else
358 {
359 if ((format == '1') || (format == '4'))
360 max_value=1; /* bitmap */
361 else
362 max_value=(QuantumAny) PNMInteger(image,&comment_info,10,
363 exception);
364 }
365 }
366 else
367 {
368 char
369 keyword[MagickPathExtent],
370 value[MagickPathExtent];
371
372 int
373 c;
374
375 char
376 *p;
377
378 /*
379 PAM.
380 */
381 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
382 {
383 while (isspace((int) ((unsigned char) c)) != 0)
384 c=ReadBlobByte(image);
385 if (c == '#')
386 {
387 /*
388 Comment.
389 */
390 c=PNMComment(image,&comment_info,exception);
391 c=ReadBlobByte(image);
392 while (isspace((int) ((unsigned char) c)) != 0)
393 c=ReadBlobByte(image);
394 }
395 p=keyword;
396 do
397 {
398 if ((size_t) (p-keyword) < (MagickPathExtent-1))
399 *p++=c;
400 c=ReadBlobByte(image);
401 } while (isalnum((int) ((unsigned char) c)));
402 *p='\0';
403 if (LocaleCompare(keyword,"endhdr") == 0)
404 break;
405 while (isspace((int) ((unsigned char) c)) != 0)
406 c=ReadBlobByte(image);
407 p=value;
408 while (isalnum((int) ((unsigned char) c)) || (c == '_'))
409 {
410 if ((size_t) (p-value) < (MagickPathExtent-1))
411 *p++=c;
412 c=ReadBlobByte(image);
413 }
414 *p='\0';
415 /*
416 Assign a value to the specified keyword.
417 */
418 if (LocaleCompare(keyword,"depth") == 0)
419 packet_size=StringToUnsignedLong(value);
420 (void) packet_size;
421 if (LocaleCompare(keyword,"height") == 0)
422 image->rows=StringToUnsignedLong(value);
423 if (LocaleCompare(keyword,"maxval") == 0)
424 max_value=StringToUnsignedLong(value);
425 if ((quantum_type == UndefinedQuantum) &&
426 (LocaleCompare(keyword,"TUPLTYPE") == 0))
427 {
428 if (LocaleCompare(value,"BLACKANDWHITE") == 0)
429 {
430 (void) SetImageColorspace(image,GRAYColorspace,exception);
431 quantum_type=GrayQuantum;
432 }
433 if (LocaleCompare(value,"BLACKANDWHITE_ALPHA") == 0)
434 {
435 (void) SetImageColorspace(image,GRAYColorspace,exception);
436 image->alpha_trait=BlendPixelTrait;
437 quantum_type=GrayAlphaQuantum;
438 }
439 if (LocaleCompare(value,"GRAYSCALE") == 0)
440 {
441 quantum_type=GrayQuantum;
442 (void) SetImageColorspace(image,GRAYColorspace,exception);
443 }
444 if (LocaleCompare(value,"GRAYSCALE_ALPHA") == 0)
445 {
446 (void) SetImageColorspace(image,GRAYColorspace,exception);
447 image->alpha_trait=BlendPixelTrait;
448 quantum_type=GrayAlphaQuantum;
449 }
450 if (LocaleCompare(value,"RGB_ALPHA") == 0)
451 {
452 image->alpha_trait=BlendPixelTrait;
453 quantum_type=RGBAQuantum;
454 }
455 if (LocaleCompare(value,"CMYK") == 0)
456 {
457 (void) SetImageColorspace(image,CMYKColorspace,exception);
458 quantum_type=CMYKQuantum;
459 }
460 if (LocaleCompare(value,"CMYK_ALPHA") == 0)
461 {
462 (void) SetImageColorspace(image,CMYKColorspace,exception);
463 image->alpha_trait=BlendPixelTrait;
464 quantum_type=CMYKAQuantum;
465 }
466 }
467 if (LocaleCompare(keyword,"width") == 0)
468 image->columns=StringToUnsignedLong(value);
469 }
470 }
471 if (quantum_type == UndefinedQuantum)
472 quantum_type=RGBQuantum;
473 if ((image->columns == 0) || (image->rows == 0))
474 ThrowPNMException(CorruptImageError,"NegativeOrZeroImageSize");
475 if ((max_value == 0) || (max_value > 4294967295UL))
476 ThrowPNMException(CorruptImageError,"ImproperImageHeader");
477 for (depth=1; GetQuantumRange(depth) < max_value; depth++) ;
478 image->depth=depth;
479 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
480 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
481 break;
482 if ((MagickSizeType) (image->columns*image->rows/8) > GetBlobSize(image))
483 ThrowPNMException(CorruptImageError,"InsufficientImageDataInFile");
484 status=SetImageExtent(image,image->columns,image->rows,exception);
485 if (status == MagickFalse)
486 {
487 comment_info.comment=DestroyString(comment_info.comment); \
488 return(DestroyImageList(image));
489 }
490 (void) ResetImagePixels(image,exception);
491 /*
492 Convert PNM pixels to runextent-encoded MIFF packets.
493 */
494 row=0;
495 y=0;
496 switch (format)
497 {
498 case '1':
499 {
500 /*
501 Convert PBM image to pixel packets.
502 */
503 (void) SetImageColorspace(image,GRAYColorspace,exception);
504 for (y=0; y < (ssize_t) image->rows; y++)
505 {
506 ssize_t
507 x;
508
509 Quantum
510 *magick_restrict q;
511
512 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
513 if (q == (Quantum *) NULL)
514 break;
515 for (x=0; x < (ssize_t) image->columns; x++)
516 {
517 SetPixelGray(image,PNMInteger(image,&comment_info,2,exception) ==
518 0 ? QuantumRange : 0,q);
519 if (EOFBlob(image) != MagickFalse)
520 break;
521 q+=GetPixelChannels(image);
522 }
523 if (SyncAuthenticPixels(image,exception) == MagickFalse)
524 break;
525 if (image->previous == (Image *) NULL)
526 {
527 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
528 image->rows);
529 if (status == MagickFalse)
530 break;
531 }
532 if (EOFBlob(image) != MagickFalse)
533 break;
534 }
535 image->type=BilevelType;
536 break;
537 }
538 case '2':
539 {
540 Quantum
541 intensity;
542
543 /*
544 Convert PGM image to pixel packets.
545 */
546 (void) SetImageColorspace(image,GRAYColorspace,exception);
547 for (y=0; y < (ssize_t) image->rows; y++)
548 {
549 ssize_t
550 x;
551
552 Quantum
553 *magick_restrict q;
554
555 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
556 if (q == (Quantum *) NULL)
557 break;
558 for (x=0; x < (ssize_t) image->columns; x++)
559 {
560 intensity=ScaleAnyToQuantum(PNMInteger(image,&comment_info,10,
561 exception),max_value);
562 if (EOFBlob(image) != MagickFalse)
563 break;
564 SetPixelGray(image,intensity,q);
565 q+=GetPixelChannels(image);
566 }
567 if (SyncAuthenticPixels(image,exception) == MagickFalse)
568 break;
569 if (image->previous == (Image *) NULL)
570 {
571 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
572 image->rows);
573 if (status == MagickFalse)
574 break;
575 }
576 if (EOFBlob(image) != MagickFalse)
577 break;
578 }
579 image->type=GrayscaleType;
580 break;
581 }
582 case '3':
583 {
584 /*
585 Convert PNM image to pixel packets.
586 */
587 for (y=0; y < (ssize_t) image->rows; y++)
588 {
589 ssize_t
590 x;
591
592 Quantum
593 *magick_restrict q;
594
595 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
596 if (q == (Quantum *) NULL)
597 break;
598 for (x=0; x < (ssize_t) image->columns; x++)
599 {
600 Quantum
601 pixel;
602
603 pixel=ScaleAnyToQuantum(PNMInteger(image,&comment_info,10,
604 exception),max_value);
605 if (EOFBlob(image) != MagickFalse)
606 break;
607 SetPixelRed(image,pixel,q);
608 pixel=ScaleAnyToQuantum(PNMInteger(image,&comment_info,10,
609 exception),max_value);
610 SetPixelGreen(image,pixel,q);
611 pixel=ScaleAnyToQuantum(PNMInteger(image,&comment_info,10,
612 exception),max_value);
613 SetPixelBlue(image,pixel,q);
614 q+=GetPixelChannels(image);
615 }
616 if (SyncAuthenticPixels(image,exception) == MagickFalse)
617 break;
618 if (image->previous == (Image *) NULL)
619 {
620 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
621 image->rows);
622 if (status == MagickFalse)
623 break;
624 }
625 if (EOFBlob(image) != MagickFalse)
626 break;
627 }
628 break;
629 }
630 case '4':
631 {
632 /*
633 Convert PBM raw image to pixel packets.
634 */
635 (void) SetImageColorspace(image,GRAYColorspace,exception);
636 quantum_type=GrayQuantum;
637 if (image->storage_class == PseudoClass)
638 quantum_type=IndexQuantum;
639 quantum_info=AcquireQuantumInfo(image_info,image);
640 if (quantum_info == (QuantumInfo *) NULL)
641 ThrowPNMException(ResourceLimitError,"MemoryAllocationFailed");
642 SetQuantumMinIsWhite(quantum_info,MagickTrue);
643 extent=GetQuantumExtent(image,quantum_info,quantum_type);
644 pixels=GetQuantumPixels(quantum_info);
645 for (y=0; y < (ssize_t) image->rows; y++)
646 {
647 MagickBooleanType
648 sync;
649
650 Quantum
651 *magick_restrict q;
652
653 ssize_t
654 offset;
655
656 size_t
657 length;
658
659 stream=ReadBlobStream(image,extent,pixels,&count);
660 if (count != (ssize_t) extent)
661 break;
662 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
663 (image->previous == (Image *) NULL))
664 {
665 MagickBooleanType
666 proceed;
667
668 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
669 row,image->rows);
670 if (proceed == MagickFalse)
671 break;
672 }
673 offset=row++;
674 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
675 if (q == (Quantum *) NULL)
676 break;
677 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
678 quantum_type,(unsigned char *) stream,exception);
679 if (length != extent)
680 break;
681 sync=SyncAuthenticPixels(image,exception);
682 if (sync == MagickFalse)
683 break;
684 }
685 quantum_info=DestroyQuantumInfo(quantum_info);
686 SetQuantumImageType(image,quantum_type);
687 break;
688 }
689 case '5':
690 {
691 /*
692 Convert PGM raw image to pixel packets.
693 */
694 (void) SetImageColorspace(image,GRAYColorspace,exception);
695 quantum_type=GrayQuantum;
696 extent=(image->depth <= 8 ? 1 : image->depth <= 16 ? 2 : 4)*
697 image->columns;
698 quantum_info=AcquireQuantumInfo(image_info,image);
699 if (quantum_info == (QuantumInfo *) NULL)
700 ThrowPNMException(ResourceLimitError,"MemoryAllocationFailed");
701 pixels=GetQuantumPixels(quantum_info);
702 for (y=0; y < (ssize_t) image->rows; y++)
703 {
704 MagickBooleanType
705 sync;
706
707 const unsigned char
708 *magick_restrict p;
709
710 ssize_t
711 x;
712
713 Quantum
714 *magick_restrict q;
715
716 ssize_t
717 offset;
718
719 stream=ReadBlobStream(image,extent,pixels,&count);
720 if (count != (ssize_t) extent)
721 break;
722 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
723 (image->previous == (Image *) NULL))
724 {
725 MagickBooleanType
726 proceed;
727
728 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
729 row,image->rows);
730 if (proceed == MagickFalse)
731 break;
732 }
733 offset=row++;
734 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
735 if (q == (Quantum *) NULL)
736 break;
737 p=(unsigned char *) stream;
738 switch (image->depth)
739 {
740 case 8:
741 case 16:
742 case 32:
743 {
744 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
745 quantum_type,(unsigned char *) stream,exception);
746 break;
747 }
748 default:
749 {
750 if (image->depth <= 8)
751 {
752 unsigned char
753 pixel;
754
755 for (x=0; x < (ssize_t) image->columns; x++)
756 {
757 p=PushCharPixel(p,&pixel);
758 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
759 q+=GetPixelChannels(image);
760 }
761 }
762 else if (image->depth <= 16)
763 {
764 unsigned short
765 pixel;
766
767 for (x=0; x < (ssize_t) image->columns; x++)
768 {
769 p=PushShortPixel(MSBEndian,p,&pixel);
770 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
771 q+=GetPixelChannels(image);
772 }
773 }
774 else
775 {
776 unsigned int
777 pixel;
778
779 for (x=0; x < (ssize_t) image->columns; x++)
780 {
781 p=PushLongPixel(MSBEndian,p,&pixel);
782 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),q);
783 q+=GetPixelChannels(image);
784 }
785 }
786 break;
787 }
788 }
789 sync=SyncAuthenticPixels(image,exception);
790 if (sync == MagickFalse)
791 break;
792 }
793 quantum_info=DestroyQuantumInfo(quantum_info);
794 SetQuantumImageType(image,quantum_type);
795 break;
796 }
797 case '6':
798 {
799 /*
800 Convert PNM raster image to pixel packets.
801 */
802 quantum_type=RGBQuantum;
803 extent=3*(image->depth <= 8 ? 1 : image->depth <= 16 ? 2 : 4)*
804 image->columns;
805 quantum_info=AcquireQuantumInfo(image_info,image);
806 if (quantum_info == (QuantumInfo *) NULL)
807 ThrowPNMException(ResourceLimitError,"MemoryAllocationFailed");
808 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
809 pixels=GetQuantumPixels(quantum_info);
810 for (y=0; y < (ssize_t) image->rows; y++)
811 {
812 MagickBooleanType
813 sync;
814
815 const unsigned char
816 *magick_restrict p;
817
818 ssize_t
819 x;
820
821 Quantum
822 *magick_restrict q;
823
824 ssize_t
825 offset;
826
827 stream=ReadBlobStream(image,extent,pixels,&count);
828 if (count != (ssize_t) extent)
829 break;
830 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
831 (image->previous == (Image *) NULL))
832 {
833 MagickBooleanType
834 proceed;
835
836 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
837 row,image->rows);
838 if (proceed == MagickFalse)
839 break;
840 }
841 offset=row++;
842 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
843 if (q == (Quantum *) NULL)
844 break;
845 p=(unsigned char *) stream;
846 switch (image->depth)
847 {
848 case 8:
849 {
850 for (x=0; x < (ssize_t) image->columns; x++)
851 {
852 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
853 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
854 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
855 SetPixelAlpha(image,OpaqueAlpha,q);
856 q+=GetPixelChannels(image);
857 }
858 break;
859 }
860 case 16:
861 {
862 unsigned short
863 pixel;
864
865 for (x=0; x < (ssize_t) image->columns; x++)
866 {
867 p=PushShortPixel(MSBEndian,p,&pixel);
868 SetPixelRed(image,ScaleShortToQuantum(pixel),q);
869 p=PushShortPixel(MSBEndian,p,&pixel);
870 SetPixelGreen(image,ScaleShortToQuantum(pixel),q);
871 p=PushShortPixel(MSBEndian,p,&pixel);
872 SetPixelBlue(image,ScaleShortToQuantum(pixel),q);
873 SetPixelAlpha(image,OpaqueAlpha,q);
874 q+=GetPixelChannels(image);
875 }
876 break;
877 }
878 case 32:
879 {
880 unsigned int
881 pixel;
882
883 for (x=0; x < (ssize_t) image->columns; x++)
884 {
885 p=PushLongPixel(MSBEndian,p,&pixel);
886 SetPixelRed(image,ScaleLongToQuantum(pixel),q);
887 p=PushLongPixel(MSBEndian,p,&pixel);
888 SetPixelGreen(image,ScaleLongToQuantum(pixel),q);
889 p=PushLongPixel(MSBEndian,p,&pixel);
890 SetPixelBlue(image,ScaleLongToQuantum(pixel),q);
891 SetPixelAlpha(image,OpaqueAlpha,q);
892 q+=GetPixelChannels(image);
893 }
894 break;
895 }
896 default:
897 {
898 if (image->depth <= 8)
899 {
900 unsigned char
901 pixel;
902
903 for (x=0; x < (ssize_t) image->columns; x++)
904 {
905 p=PushCharPixel(p,&pixel);
906 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
907 p=PushCharPixel(p,&pixel);
908 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
909 p=PushCharPixel(p,&pixel);
910 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
911 SetPixelAlpha(image,OpaqueAlpha,q);
912 q+=GetPixelChannels(image);
913 }
914 }
915 else if (image->depth <= 16)
916 {
917 unsigned short
918 pixel;
919
920 for (x=0; x < (ssize_t) image->columns; x++)
921 {
922 p=PushShortPixel(MSBEndian,p,&pixel);
923 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
924 p=PushShortPixel(MSBEndian,p,&pixel);
925 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
926 p=PushShortPixel(MSBEndian,p,&pixel);
927 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
928 SetPixelAlpha(image,OpaqueAlpha,q);
929 q+=GetPixelChannels(image);
930 }
931 }
932 else
933 {
934 unsigned int
935 pixel;
936
937 for (x=0; x < (ssize_t) image->columns; x++)
938 {
939 p=PushLongPixel(MSBEndian,p,&pixel);
940 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
941 p=PushLongPixel(MSBEndian,p,&pixel);
942 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),q);
943 p=PushLongPixel(MSBEndian,p,&pixel);
944 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),q);
945 SetPixelAlpha(image,OpaqueAlpha,q);
946 q+=GetPixelChannels(image);
947 }
948 }
949 break;
950 }
951 }
952 sync=SyncAuthenticPixels(image,exception);
953 if (sync == MagickFalse)
954 break;
955 }
956 quantum_info=DestroyQuantumInfo(quantum_info);
957 break;
958 }
959 case '7':
960 {
961 size_t
962 channels;
963
964 /*
965 Convert PAM raster image to pixel packets.
966 */
967 switch (quantum_type)
968 {
969 case GrayQuantum:
970 case GrayAlphaQuantum:
971 {
972 channels=1;
973 break;
974 }
975 case CMYKQuantum:
976 case CMYKAQuantum:
977 {
978 channels=4;
979 break;
980 }
981 default:
982 {
983 channels=3;
984 break;
985 }
986 }
987 if (image->alpha_trait != UndefinedPixelTrait)
988 channels++;
989 extent=channels*(image->depth <= 8 ? 1 : image->depth <= 16 ? 2 : 4)*
990 image->columns;
991 quantum_info=AcquireQuantumInfo(image_info,image);
992 if (quantum_info == (QuantumInfo *) NULL)
993 ThrowPNMException(ResourceLimitError,"MemoryAllocationFailed");
994 pixels=GetQuantumPixels(quantum_info);
995 for (y=0; y < (ssize_t) image->rows; y++)
996 {
997 MagickBooleanType
998 sync;
999
1000 const unsigned char
1001 *magick_restrict p;
1002
1003 ssize_t
1004 x;
1005
1006 Quantum
1007 *magick_restrict q;
1008
1009 ssize_t
1010 offset;
1011
1012 stream=ReadBlobStream(image,extent,pixels,&count);
1013 if (count != (ssize_t) extent)
1014 break;
1015 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1016 (image->previous == (Image *) NULL))
1017 {
1018 MagickBooleanType
1019 proceed;
1020
1021 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1022 row,image->rows);
1023 if (proceed == MagickFalse)
1024 break;
1025 }
1026 offset=row++;
1027 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
1028 if (q == (Quantum *) NULL)
1029 break;
1030 p=(unsigned char *) stream;
1031 switch (image->depth)
1032 {
1033 case 8:
1034 case 16:
1035 case 32:
1036 {
1037 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1038 quantum_type,(unsigned char *) stream,exception);
1039 break;
1040 }
1041 default:
1042 {
1043 switch (quantum_type)
1044 {
1045 case GrayQuantum:
1046 case GrayAlphaQuantum:
1047 {
1048 if (image->depth <= 8)
1049 {
1050 unsigned char
1051 pixel;
1052
1053 for (x=0; x < (ssize_t) image->columns; x++)
1054 {
1055 p=PushCharPixel(p,&pixel);
1056 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),
1057 q);
1058 SetPixelAlpha(image,OpaqueAlpha,q);
1059 if (image->alpha_trait != UndefinedPixelTrait)
1060 {
1061 p=PushCharPixel(p,&pixel);
1062 if (image->depth != 1)
1063 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1064 max_value),q);
1065 else
1066 SetPixelAlpha(image,QuantumRange-
1067 ScaleAnyToQuantum(pixel,max_value),q);
1068 }
1069 q+=GetPixelChannels(image);
1070 }
1071 }
1072 else if (image->depth <= 16)
1073 {
1074 unsigned short
1075 pixel;
1076
1077 for (x=0; x < (ssize_t) image->columns; x++)
1078 {
1079 p=PushShortPixel(MSBEndian,p,&pixel);
1080 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),
1081 q);
1082 SetPixelAlpha(image,OpaqueAlpha,q);
1083 if (image->alpha_trait != UndefinedPixelTrait)
1084 {
1085 p=PushShortPixel(MSBEndian,p,&pixel);
1086 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1087 max_value),q);
1088 }
1089 q+=GetPixelChannels(image);
1090 }
1091 }
1092 else
1093 {
1094 unsigned int
1095 pixel;
1096
1097 for (x=0; x < (ssize_t) image->columns; x++)
1098 {
1099 p=PushLongPixel(MSBEndian,p,&pixel);
1100 SetPixelGray(image,ScaleAnyToQuantum(pixel,max_value),
1101 q);
1102 SetPixelAlpha(image,OpaqueAlpha,q);
1103 if (image->alpha_trait != UndefinedPixelTrait)
1104 {
1105 p=PushLongPixel(MSBEndian,p,&pixel);
1106 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1107 max_value),q);
1108 }
1109 q+=GetPixelChannels(image);
1110 }
1111 }
1112 break;
1113 }
1114 case CMYKQuantum:
1115 case CMYKAQuantum:
1116 {
1117 if (image->depth <= 8)
1118 {
1119 unsigned char
1120 pixel;
1121
1122 for (x=0; x < (ssize_t) image->columns; x++)
1123 {
1124 p=PushCharPixel(p,&pixel);
1125 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1126 p=PushCharPixel(p,&pixel);
1127 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
1128 q);
1129 p=PushCharPixel(p,&pixel);
1130 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
1131 q);
1132 p=PushCharPixel(p,&pixel);
1133 SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),
1134 q);
1135 SetPixelAlpha(image,OpaqueAlpha,q);
1136 if (image->alpha_trait != UndefinedPixelTrait)
1137 {
1138 p=PushCharPixel(p,&pixel);
1139 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1140 max_value),q);
1141 }
1142 q+=GetPixelChannels(image);
1143 }
1144 }
1145 else if (image->depth <= 16)
1146 {
1147 unsigned short
1148 pixel;
1149
1150 for (x=0; x < (ssize_t) image->columns; x++)
1151 {
1152 p=PushShortPixel(MSBEndian,p,&pixel);
1153 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1154 p=PushShortPixel(MSBEndian,p,&pixel);
1155 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
1156 q);
1157 p=PushShortPixel(MSBEndian,p,&pixel);
1158 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
1159 q);
1160 p=PushShortPixel(MSBEndian,p,&pixel);
1161 SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),
1162 q);
1163 SetPixelAlpha(image,OpaqueAlpha,q);
1164 if (image->alpha_trait != UndefinedPixelTrait)
1165 {
1166 p=PushShortPixel(MSBEndian,p,&pixel);
1167 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1168 max_value),q);
1169 }
1170 q+=GetPixelChannels(image);
1171 }
1172 }
1173 else
1174 {
1175 unsigned int
1176 pixel;
1177
1178 for (x=0; x < (ssize_t) image->columns; x++)
1179 {
1180 p=PushLongPixel(MSBEndian,p,&pixel);
1181 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),
1182 q);
1183 p=PushLongPixel(MSBEndian,p,&pixel);
1184 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
1185 q);
1186 p=PushLongPixel(MSBEndian,p,&pixel);
1187 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
1188 q);
1189 p=PushLongPixel(MSBEndian,p,&pixel);
1190 SetPixelBlack(image,ScaleAnyToQuantum(pixel,max_value),
1191 q);
1192 SetPixelAlpha(image,OpaqueAlpha,q);
1193 if (image->alpha_trait != UndefinedPixelTrait)
1194 {
1195 p=PushLongPixel(MSBEndian,p,&pixel);
1196 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1197 max_value),q);
1198 }
1199 q+=GetPixelChannels(image);
1200 }
1201 }
1202 break;
1203 }
1204 default:
1205 {
1206 if (image->depth <= 8)
1207 {
1208 unsigned char
1209 pixel;
1210
1211 for (x=0; x < (ssize_t) image->columns; x++)
1212 {
1213 p=PushCharPixel(p,&pixel);
1214 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1215 p=PushCharPixel(p,&pixel);
1216 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
1217 q);
1218 p=PushCharPixel(p,&pixel);
1219 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
1220 q);
1221 SetPixelAlpha(image,OpaqueAlpha,q);
1222 if (image->alpha_trait != UndefinedPixelTrait)
1223 {
1224 p=PushCharPixel(p,&pixel);
1225 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1226 max_value),q);
1227 }
1228 q+=GetPixelChannels(image);
1229 }
1230 }
1231 else if (image->depth <= 16)
1232 {
1233 unsigned short
1234 pixel;
1235
1236 for (x=0; x < (ssize_t) image->columns; x++)
1237 {
1238 p=PushShortPixel(MSBEndian,p,&pixel);
1239 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),q);
1240 p=PushShortPixel(MSBEndian,p,&pixel);
1241 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
1242 q);
1243 p=PushShortPixel(MSBEndian,p,&pixel);
1244 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
1245 q);
1246 SetPixelAlpha(image,OpaqueAlpha,q);
1247 if (image->alpha_trait != UndefinedPixelTrait)
1248 {
1249 p=PushShortPixel(MSBEndian,p,&pixel);
1250 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1251 max_value),q);
1252 }
1253 q+=GetPixelChannels(image);
1254 }
1255 }
1256 else
1257 {
1258 unsigned int
1259 pixel;
1260
1261 for (x=0; x < (ssize_t) image->columns; x++)
1262 {
1263 p=PushLongPixel(MSBEndian,p,&pixel);
1264 SetPixelRed(image,ScaleAnyToQuantum(pixel,max_value),
1265 q);
1266 p=PushLongPixel(MSBEndian,p,&pixel);
1267 SetPixelGreen(image,ScaleAnyToQuantum(pixel,max_value),
1268 q);
1269 p=PushLongPixel(MSBEndian,p,&pixel);
1270 SetPixelBlue(image,ScaleAnyToQuantum(pixel,max_value),
1271 q);
1272 SetPixelAlpha(image,OpaqueAlpha,q);
1273 if (image->alpha_trait != UndefinedPixelTrait)
1274 {
1275 p=PushLongPixel(MSBEndian,p,&pixel);
1276 SetPixelAlpha(image,ScaleAnyToQuantum(pixel,
1277 max_value),q);
1278 }
1279 q+=GetPixelChannels(image);
1280 }
1281 }
1282 break;
1283 }
1284 }
1285 }
1286 }
1287 sync=SyncAuthenticPixels(image,exception);
1288 if (sync == MagickFalse)
1289 break;
1290 }
1291 quantum_info=DestroyQuantumInfo(quantum_info);
1292 SetQuantumImageType(image,quantum_type);
1293 break;
1294 }
1295 case 'F':
1296 case 'f':
1297 {
1298 /*
1299 Convert PFM raster image to pixel packets.
1300 */
1301 if (format != 'f')
1302 quantum_type=image->alpha_trait != UndefinedPixelTrait ? RGBAQuantum :
1303 RGBQuantum;
1304 else
1305 {
1306 (void) SetImageColorspace(image,GRAYColorspace,exception);
1307 quantum_type=GrayQuantum;
1308 }
1309 image->endian=quantum_scale < 0.0 ? LSBEndian : MSBEndian;
1310 image->depth=32;
1311 quantum_info=AcquireQuantumInfo(image_info,image);
1312 if (quantum_info == (QuantumInfo *) NULL)
1313 ThrowPNMException(ResourceLimitError,"MemoryAllocationFailed");
1314 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1315 if (status == MagickFalse)
1316 ThrowPNMException(ResourceLimitError,"MemoryAllocationFailed");
1317 SetQuantumScale(quantum_info,(double) QuantumRange*fabs(quantum_scale));
1318 extent=GetQuantumExtent(image,quantum_info,quantum_type);
1319 pixels=GetQuantumPixels(quantum_info);
1320 for (y=0; y < (ssize_t) image->rows; y++)
1321 {
1322 MagickBooleanType
1323 sync;
1324
1325 Quantum
1326 *magick_restrict q;
1327
1328 ssize_t
1329 offset;
1330
1331 size_t
1332 length;
1333
1334 stream=ReadBlobStream(image,extent,pixels,&count);
1335 if (count != (ssize_t) extent)
1336 break;
1337 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1338 (image->previous == (Image *) NULL))
1339 {
1340 MagickBooleanType
1341 proceed;
1342
1343 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1344 row,image->rows);
1345 if (proceed == MagickFalse)
1346 break;
1347 }
1348 offset=row++;
1349 q=QueueAuthenticPixels(image,0,(ssize_t) (image->rows-offset-1),
1350 image->columns,1,exception);
1351 if (q == (Quantum *) NULL)
1352 break;
1353 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1354 quantum_type,(unsigned char *) stream,exception);
1355 if (length != extent)
1356 break;
1357 sync=SyncAuthenticPixels(image,exception);
1358 if (sync == MagickFalse)
1359 break;
1360 }
1361 quantum_info=DestroyQuantumInfo(quantum_info);
1362 SetQuantumImageType(image,quantum_type);
1363 break;
1364 }
1365 case 'H':
1366 case 'h':
1367 {
1368 /*
1369 Convert PFM raster image to pixel packets.
1370 */
1371 if (format != 'h')
1372 quantum_type=image->alpha_trait != UndefinedPixelTrait ? RGBAQuantum :
1373 RGBQuantum;
1374 else
1375 {
1376 (void) SetImageColorspace(image,GRAYColorspace,exception);
1377 quantum_type=GrayQuantum;
1378 }
1379 image->endian=quantum_scale < 0.0 ? LSBEndian : MSBEndian;
1380 image->depth=16;
1381 quantum_info=AcquireQuantumInfo(image_info,image);
1382 if (quantum_info == (QuantumInfo *) NULL)
1383 ThrowPNMException(ResourceLimitError,"MemoryAllocationFailed");
1384 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1385 if (status == MagickFalse)
1386 ThrowPNMException(ResourceLimitError,"MemoryAllocationFailed");
1387 SetQuantumScale(quantum_info,(double) QuantumRange*fabs(quantum_scale));
1388 extent=GetQuantumExtent(image,quantum_info,quantum_type);
1389 pixels=GetQuantumPixels(quantum_info);
1390 for (y=0; y < (ssize_t) image->rows; y++)
1391 {
1392 MagickBooleanType
1393 sync;
1394
1395 Quantum
1396 *magick_restrict q;
1397
1398 ssize_t
1399 offset;
1400
1401 size_t
1402 length;
1403
1404 stream=ReadBlobStream(image,extent,pixels,&count);
1405 if (count != (ssize_t) extent)
1406 break;
1407 if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1408 (image->previous == (Image *) NULL))
1409 {
1410 MagickBooleanType
1411 proceed;
1412
1413 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
1414 row,image->rows);
1415 if (proceed == MagickFalse)
1416 break;
1417 }
1418 offset=row++;
1419 q=QueueAuthenticPixels(image,0,(ssize_t) (image->rows-offset-1),
1420 image->columns,1,exception);
1421 if (q == (Quantum *) NULL)
1422 break;
1423 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1424 quantum_type,(unsigned char *) stream,exception);
1425 if (length != extent)
1426 break;
1427 sync=SyncAuthenticPixels(image,exception);
1428 if (sync == MagickFalse)
1429 break;
1430 }
1431 quantum_info=DestroyQuantumInfo(quantum_info);
1432 SetQuantumImageType(image,quantum_type);
1433 break;
1434 }
1435 default:
1436 ThrowPNMException(CorruptImageError,"ImproperImageHeader");
1437 }
1438 if (*comment_info.comment != '\0')
1439 (void) SetImageProperty(image,"comment",comment_info.comment,exception);
1440 comment_info.comment=DestroyString(comment_info.comment);
1441 if (y < (ssize_t) image->rows)
1442 ThrowPNMException(CorruptImageError,"UnableToReadImageData");
1443 if (EOFBlob(image) != MagickFalse)
1444 {
1445 (void) ThrowMagickException(exception,GetMagickModule(),
1446 CorruptImageError,"UnexpectedEndOfFile","`%s'",image->filename);
1447 break;
1448 }
1449 /*
1450 Proceed to next image.
1451 */
1452 if (image_info->number_scenes != 0)
1453 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1454 break;
1455 if ((format == '1') || (format == '2') || (format == '3'))
1456 do
1457 {
1458 /*
1459 Skip to end of line.
1460 */
1461 count=ReadBlob(image,1,(unsigned char *) &format);
1462 if (count != 1)
1463 break;
1464 if (format == 'P')
1465 break;
1466 } while (format != '\n');
1467 count=ReadBlob(image,1,(unsigned char *) &format);
1468 if ((count == 1) && (format == 'P'))
1469 {
1470 /*
1471 Allocate next image structure.
1472 */
1473 AcquireNextImage(image_info,image,exception);
1474 if (GetNextImageInList(image) == (Image *) NULL)
1475 {
1476 status=MagickFalse;
1477 break;
1478 }
1479 image=SyncNextImageInList(image);
1480 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1481 GetBlobSize(image));
1482 if (status == MagickFalse)
1483 break;
1484 }
1485 } while ((count == 1) && (format == 'P'));
1486 (void) CloseBlob(image);
1487 if (status == MagickFalse)
1488 return(DestroyImageList(image));
1489 return(GetFirstImageInList(image));
1490 }
1491
1492 /*
1493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1494 % %
1495 % %
1496 % %
1497 % R e g i s t e r P N M I m a g e %
1498 % %
1499 % %
1500 % %
1501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1502 %
1503 % RegisterPNMImage() adds properties for the PNM image format to
1504 % the list of supported formats. The properties include the image format
1505 % tag, a method to read and/or write the format, whether the format
1506 % supports the saving of more than one frame to the same file or blob,
1507 % whether the format supports native in-memory I/O, and a brief
1508 % description of the format.
1509 %
1510 % The format of the RegisterPNMImage method is:
1511 %
1512 % size_t RegisterPNMImage(void)
1513 %
1514 */
RegisterPNMImage(void)1515 ModuleExport size_t RegisterPNMImage(void)
1516 {
1517 MagickInfo
1518 *entry;
1519
1520 entry=AcquireMagickInfo("PNM","PAM","Common 2-dimensional bitmap format");
1521 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1522 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1523 entry->mime_type=ConstantString("image/x-portable-anymap");
1524 entry->flags|=CoderDecoderSeekableStreamFlag;
1525 (void) RegisterMagickInfo(entry);
1526 entry=AcquireMagickInfo("PNM","PBM",
1527 "Portable bitmap format (black and white)");
1528 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1529 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1530 entry->mime_type=ConstantString("image/x-portable-bitmap");
1531 entry->flags|=CoderDecoderSeekableStreamFlag;
1532 (void) RegisterMagickInfo(entry);
1533 entry=AcquireMagickInfo("PNM","PFM","Portable float format");
1534 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1535 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1536 entry->flags|=CoderEndianSupportFlag;
1537 entry->flags|=CoderDecoderSeekableStreamFlag;
1538 (void) RegisterMagickInfo(entry);
1539 entry=AcquireMagickInfo("PNM","PGM","Portable graymap format (gray scale)");
1540 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1541 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1542 entry->mime_type=ConstantString("image/x-portable-greymap");
1543 entry->flags|=CoderDecoderSeekableStreamFlag;
1544 (void) RegisterMagickInfo(entry);
1545 entry=AcquireMagickInfo("PNM","PHM","Portable half float format");
1546 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1547 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1548 entry->flags|=CoderEndianSupportFlag;
1549 entry->flags|=CoderDecoderSeekableStreamFlag;
1550 (void) RegisterMagickInfo(entry);
1551 entry=AcquireMagickInfo("PNM","PNM","Portable anymap");
1552 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1553 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1554 entry->magick=(IsImageFormatHandler *) IsPNM;
1555 entry->mime_type=ConstantString("image/x-portable-pixmap");
1556 entry->flags|=CoderDecoderSeekableStreamFlag;
1557 (void) RegisterMagickInfo(entry);
1558 entry=AcquireMagickInfo("PNM","PPM","Portable pixmap format (color)");
1559 entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1560 entry->encoder=(EncodeImageHandler *) WritePNMImage;
1561 entry->mime_type=ConstantString("image/x-portable-pixmap");
1562 entry->flags|=CoderDecoderSeekableStreamFlag;
1563 (void) RegisterMagickInfo(entry);
1564 return(MagickImageCoderSignature);
1565 }
1566
1567 /*
1568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1569 % %
1570 % %
1571 % %
1572 % U n r e g i s t e r P N M I m a g e %
1573 % %
1574 % %
1575 % %
1576 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1577 %
1578 % UnregisterPNMImage() removes format registrations made by the
1579 % PNM module from the list of supported formats.
1580 %
1581 % The format of the UnregisterPNMImage method is:
1582 %
1583 % UnregisterPNMImage(void)
1584 %
1585 */
UnregisterPNMImage(void)1586 ModuleExport void UnregisterPNMImage(void)
1587 {
1588 (void) UnregisterMagickInfo("PAM");
1589 (void) UnregisterMagickInfo("PBM");
1590 (void) UnregisterMagickInfo("PGM");
1591 (void) UnregisterMagickInfo("PNM");
1592 (void) UnregisterMagickInfo("PPM");
1593 }
1594
1595 /*
1596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1597 % %
1598 % %
1599 % %
1600 % W r i t e P N M I m a g e %
1601 % %
1602 % %
1603 % %
1604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1605 %
1606 % WritePNMImage() writes an image to a file in the PNM rasterfile format.
1607 %
1608 % The format of the WritePNMImage method is:
1609 %
1610 % MagickBooleanType WritePNMImage(const ImageInfo *image_info,
1611 % Image *image,ExceptionInfo *exception)
1612 %
1613 % A description of each parameter follows.
1614 %
1615 % o image_info: the image info.
1616 %
1617 % o image: The image.
1618 %
1619 % o exception: return any errors or warnings in this structure.
1620 %
1621 */
WritePNMImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)1622 static MagickBooleanType WritePNMImage(const ImageInfo *image_info,Image *image,
1623 ExceptionInfo *exception)
1624 {
1625 char
1626 buffer[MagickPathExtent],
1627 format,
1628 magick[MagickPathExtent];
1629
1630 const char
1631 *value;
1632
1633 MagickBooleanType
1634 status;
1635
1636 MagickOffsetType
1637 scene;
1638
1639 Quantum
1640 index;
1641
1642 QuantumAny
1643 pixel;
1644
1645 QuantumInfo
1646 *quantum_info;
1647
1648 QuantumType
1649 quantum_type;
1650
1651 unsigned char
1652 *q;
1653
1654 size_t
1655 extent,
1656 imageListLength,
1657 packet_size;
1658
1659 ssize_t
1660 count,
1661 y;
1662
1663 /*
1664 Open output image file.
1665 */
1666 assert(image_info != (const ImageInfo *) NULL);
1667 assert(image_info->signature == MagickCoreSignature);
1668 assert(image != (Image *) NULL);
1669 assert(image->signature == MagickCoreSignature);
1670 if (image->debug != MagickFalse)
1671 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1672 assert(exception != (ExceptionInfo *) NULL);
1673 assert(exception->signature == MagickCoreSignature);
1674 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1675 if (status == MagickFalse)
1676 return(status);
1677 scene=0;
1678 imageListLength=GetImageListLength(image);
1679 do
1680 {
1681 QuantumAny
1682 max_value;
1683
1684 /*
1685 Write PNM file header.
1686 */
1687 packet_size=3;
1688 quantum_type=RGBQuantum;
1689 (void) CopyMagickString(magick,image_info->magick,MagickPathExtent);
1690 max_value=GetQuantumRange(image->depth);
1691 switch (magick[1])
1692 {
1693 case 'A':
1694 case 'a':
1695 {
1696 format='7';
1697 break;
1698 }
1699 case 'B':
1700 case 'b':
1701 {
1702 format='4';
1703 if (image_info->compression == NoCompression)
1704 format='1';
1705 break;
1706 }
1707 case 'F':
1708 case 'f':
1709 {
1710 format='F';
1711 if ((image_info->type != TrueColorType) &&
1712 (SetImageGray(image,exception) != MagickFalse))
1713 format='f';
1714 break;
1715 }
1716 case 'G':
1717 case 'g':
1718 {
1719 format='5';
1720 if (image_info->compression == NoCompression)
1721 format='2';
1722 break;
1723 }
1724 case 'H':
1725 case 'h':
1726 {
1727 format='H';
1728 if ((image_info->type != TrueColorType) &&
1729 (SetImageGray(image,exception) != MagickFalse))
1730 format='h';
1731 break;
1732 }
1733 case 'N':
1734 case 'n':
1735 {
1736 if ((image_info->type != TrueColorType) &&
1737 (SetImageGray(image,exception) != MagickFalse))
1738 {
1739 format='5';
1740 if (image_info->compression == NoCompression)
1741 format='2';
1742 if (SetImageMonochrome(image,exception) != MagickFalse)
1743 {
1744 format='4';
1745 if (image_info->compression == NoCompression)
1746 format='1';
1747 }
1748 break;
1749 }
1750 }
1751 default:
1752 {
1753 format='6';
1754 if (image_info->compression == NoCompression)
1755 format='3';
1756 break;
1757 }
1758 }
1759 (void) FormatLocaleString(buffer,MagickPathExtent,"P%c\n",format);
1760 (void) WriteBlobString(image,buffer);
1761 value=GetImageProperty(image,"comment",exception);
1762 if (value != (const char *) NULL)
1763 {
1764 const char
1765 *p;
1766
1767 /*
1768 Write comments to file.
1769 */
1770 (void) WriteBlobByte(image,'#');
1771 for (p=value; *p != '\0'; p++)
1772 {
1773 (void) WriteBlobByte(image,(unsigned char) *p);
1774 if ((*p == '\n') || (*p == '\r'))
1775 (void) WriteBlobByte(image,'#');
1776 }
1777 (void) WriteBlobByte(image,'\n');
1778 }
1779 if (format != '7')
1780 {
1781 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g\n",
1782 (double) image->columns,(double) image->rows);
1783 (void) WriteBlobString(image,buffer);
1784 }
1785 else
1786 {
1787 char
1788 type[MagickPathExtent];
1789
1790 /*
1791 PAM header.
1792 */
1793 (void) FormatLocaleString(buffer,MagickPathExtent,
1794 "WIDTH %.20g\nHEIGHT %.20g\n",(double) image->columns,(double)
1795 image->rows);
1796 (void) WriteBlobString(image,buffer);
1797 quantum_type=GetQuantumType(image,exception);
1798 switch (quantum_type)
1799 {
1800 case CMYKQuantum:
1801 case CMYKAQuantum:
1802 {
1803 packet_size=4;
1804 (void) CopyMagickString(type,"CMYK",MagickPathExtent);
1805 break;
1806 }
1807 case GrayQuantum:
1808 case GrayAlphaQuantum:
1809 {
1810 packet_size=1;
1811 (void) CopyMagickString(type,"GRAYSCALE",MagickPathExtent);
1812 if (IdentifyImageMonochrome(image,exception) != MagickFalse)
1813 (void) CopyMagickString(type,"BLACKANDWHITE",MagickPathExtent);
1814 break;
1815 }
1816 default:
1817 {
1818 quantum_type=RGBQuantum;
1819 if (image->alpha_trait != UndefinedPixelTrait)
1820 quantum_type=RGBAQuantum;
1821 packet_size=3;
1822 (void) CopyMagickString(type,"RGB",MagickPathExtent);
1823 break;
1824 }
1825 }
1826 if (image->alpha_trait != UndefinedPixelTrait)
1827 {
1828 packet_size++;
1829 (void) ConcatenateMagickString(type,"_ALPHA",MagickPathExtent);
1830 }
1831 if (image->depth > 32)
1832 image->depth=32;
1833 (void) FormatLocaleString(buffer,MagickPathExtent,
1834 "DEPTH %.20g\nMAXVAL %.20g\n",(double) packet_size,(double)
1835 ((MagickOffsetType) GetQuantumRange(image->depth)));
1836 (void) WriteBlobString(image,buffer);
1837 (void) FormatLocaleString(buffer,MagickPathExtent,
1838 "TUPLTYPE %s\nENDHDR\n",type);
1839 (void) WriteBlobString(image,buffer);
1840 }
1841 /*
1842 Convert runextent encoded to PNM raster pixels.
1843 */
1844 switch (format)
1845 {
1846 case '1':
1847 {
1848 unsigned char
1849 pixels[2048];
1850
1851 /*
1852 Convert image to a PBM image.
1853 */
1854 (void) SetImageType(image,BilevelType,exception);
1855 q=pixels;
1856 for (y=0; y < (ssize_t) image->rows; y++)
1857 {
1858 const Quantum
1859 *magick_restrict p;
1860
1861 ssize_t
1862 x;
1863
1864 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1865 if (p == (const Quantum *) NULL)
1866 break;
1867 for (x=0; x < (ssize_t) image->columns; x++)
1868 {
1869 *q++=(unsigned char) (GetPixelLuma(image,p) >= (QuantumRange/2.0) ?
1870 '0' : '1');
1871 if ((q-pixels+2) >= (ssize_t) sizeof(pixels))
1872 {
1873 *q++='\n';
1874 (void) WriteBlob(image,q-pixels,pixels);
1875 q=pixels;
1876 }
1877 *q++=' ';
1878 p+=GetPixelChannels(image);
1879 }
1880 *q++='\n';
1881 (void) WriteBlob(image,q-pixels,pixels);
1882 q=pixels;
1883 if (image->previous == (Image *) NULL)
1884 {
1885 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1886 image->rows);
1887 if (status == MagickFalse)
1888 break;
1889 }
1890 }
1891 if (q != pixels)
1892 {
1893 *q++='\n';
1894 (void) WriteBlob(image,q-pixels,pixels);
1895 }
1896 break;
1897 }
1898 case '2':
1899 {
1900 unsigned char
1901 pixels[2048];
1902
1903 /*
1904 Convert image to a PGM image.
1905 */
1906 if (image->depth <= 8)
1907 (void) WriteBlobString(image,"255\n");
1908 else
1909 if (image->depth <= 16)
1910 (void) WriteBlobString(image,"65535\n");
1911 else
1912 (void) WriteBlobString(image,"4294967295\n");
1913 q=pixels;
1914 for (y=0; y < (ssize_t) image->rows; y++)
1915 {
1916 const Quantum
1917 *magick_restrict p;
1918
1919 ssize_t
1920 x;
1921
1922 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1923 if (p == (const Quantum *) NULL)
1924 break;
1925 for (x=0; x < (ssize_t) image->columns; x++)
1926 {
1927 index=ClampToQuantum(GetPixelLuma(image,p));
1928 if (image->depth <= 8)
1929 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,"%u ",
1930 ScaleQuantumToChar(index));
1931 else
1932 if (image->depth <= 16)
1933 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
1934 "%u ",ScaleQuantumToShort(index));
1935 else
1936 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
1937 "%u ",ScaleQuantumToLong(index));
1938 extent=(size_t) count;
1939 if ((q-pixels+extent+1) >= sizeof(pixels))
1940 {
1941 *q++='\n';
1942 (void) WriteBlob(image,q-pixels,pixels);
1943 q=pixels;
1944 }
1945 (void) memcpy((char *) q,buffer,extent);
1946 q+=extent;
1947 p+=GetPixelChannels(image);
1948 }
1949 *q++='\n';
1950 (void) WriteBlob(image,q-pixels,pixels);
1951 q=pixels;
1952 if (image->previous == (Image *) NULL)
1953 {
1954 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1955 image->rows);
1956 if (status == MagickFalse)
1957 break;
1958 }
1959 }
1960 if (q != pixels)
1961 {
1962 *q++='\n';
1963 (void) WriteBlob(image,q-pixels,pixels);
1964 }
1965 break;
1966 }
1967 case '3':
1968 {
1969 unsigned char
1970 pixels[2048];
1971
1972 /*
1973 Convert image to a PNM image.
1974 */
1975 (void) TransformImageColorspace(image,sRGBColorspace,exception);
1976 if (image->depth <= 8)
1977 (void) WriteBlobString(image,"255\n");
1978 else
1979 if (image->depth <= 16)
1980 (void) WriteBlobString(image,"65535\n");
1981 else
1982 (void) WriteBlobString(image,"4294967295\n");
1983 q=pixels;
1984 for (y=0; y < (ssize_t) image->rows; y++)
1985 {
1986 const Quantum
1987 *magick_restrict p;
1988
1989 ssize_t
1990 x;
1991
1992 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1993 if (p == (const Quantum *) NULL)
1994 break;
1995 for (x=0; x < (ssize_t) image->columns; x++)
1996 {
1997 if (image->depth <= 8)
1998 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
1999 "%u %u %u ",ScaleQuantumToChar(GetPixelRed(image,p)),
2000 ScaleQuantumToChar(GetPixelGreen(image,p)),
2001 ScaleQuantumToChar(GetPixelBlue(image,p)));
2002 else
2003 if (image->depth <= 16)
2004 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
2005 "%u %u %u ",ScaleQuantumToShort(GetPixelRed(image,p)),
2006 ScaleQuantumToShort(GetPixelGreen(image,p)),
2007 ScaleQuantumToShort(GetPixelBlue(image,p)));
2008 else
2009 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
2010 "%u %u %u ",ScaleQuantumToLong(GetPixelRed(image,p)),
2011 ScaleQuantumToLong(GetPixelGreen(image,p)),
2012 ScaleQuantumToLong(GetPixelBlue(image,p)));
2013 extent=(size_t) count;
2014 if ((q-pixels+extent+2) >= sizeof(pixels))
2015 {
2016 *q++='\n';
2017 (void) WriteBlob(image,q-pixels,pixels);
2018 q=pixels;
2019 }
2020 (void) memcpy((char *) q,buffer,extent);
2021 q+=extent;
2022 p+=GetPixelChannels(image);
2023 }
2024 *q++='\n';
2025 (void) WriteBlob(image,q-pixels,pixels);
2026 q=pixels;
2027 if (image->previous == (Image *) NULL)
2028 {
2029 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2030 image->rows);
2031 if (status == MagickFalse)
2032 break;
2033 }
2034 }
2035 if (q != pixels)
2036 {
2037 *q++='\n';
2038 (void) WriteBlob(image,q-pixels,pixels);
2039 }
2040 break;
2041 }
2042 case '4':
2043 {
2044 unsigned char
2045 *pixels;
2046
2047 /*
2048 Convert image to a PBM image.
2049 */
2050 (void) SetImageType(image,BilevelType,exception);
2051 image->depth=1;
2052 quantum_info=AcquireQuantumInfo(image_info,image);
2053 if (quantum_info == (QuantumInfo *) NULL)
2054 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2055 SetQuantumMinIsWhite(quantum_info,MagickTrue);
2056 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
2057 pixels=GetQuantumPixels(quantum_info);
2058 for (y=0; y < (ssize_t) image->rows; y++)
2059 {
2060 const Quantum
2061 *magick_restrict p;
2062
2063 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2064 if (p == (const Quantum *) NULL)
2065 break;
2066 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2067 GrayQuantum,pixels,exception);
2068 count=WriteBlob(image,extent,pixels);
2069 if (count != (ssize_t) extent)
2070 break;
2071 if (image->previous == (Image *) NULL)
2072 {
2073 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2074 image->rows);
2075 if (status == MagickFalse)
2076 break;
2077 }
2078 }
2079 quantum_info=DestroyQuantumInfo(quantum_info);
2080 break;
2081 }
2082 case '5':
2083 {
2084 unsigned char
2085 *pixels;
2086
2087 /*
2088 Convert image to a PGM image.
2089 */
2090 if (image->depth > 32)
2091 image->depth=32;
2092 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2093 ((MagickOffsetType) GetQuantumRange(image->depth)));
2094 (void) WriteBlobString(image,buffer);
2095 quantum_info=AcquireQuantumInfo(image_info,image);
2096 if (quantum_info == (QuantumInfo *) NULL)
2097 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2098 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
2099 pixels=GetQuantumPixels(quantum_info);
2100 extent=GetQuantumExtent(image,quantum_info,GrayQuantum);
2101 for (y=0; y < (ssize_t) image->rows; y++)
2102 {
2103 const Quantum
2104 *magick_restrict p;
2105
2106 ssize_t
2107 x;
2108
2109 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2110 if (p == (const Quantum *) NULL)
2111 break;
2112 q=pixels;
2113 switch (image->depth)
2114 {
2115 case 8:
2116 case 16:
2117 case 32:
2118 {
2119 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2120 GrayQuantum,pixels,exception);
2121 break;
2122 }
2123 default:
2124 {
2125 if (image->depth <= 8)
2126 {
2127 for (x=0; x < (ssize_t) image->columns; x++)
2128 {
2129 if (IsPixelGray(image,p) == MagickFalse)
2130 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(
2131 image,p)),max_value);
2132 else
2133 {
2134 if (image->depth == 8)
2135 pixel=ScaleQuantumToChar(GetPixelRed(image,p));
2136 else
2137 pixel=ScaleQuantumToAny(GetPixelRed(image,p),
2138 max_value);
2139 }
2140 q=PopCharPixel((unsigned char) pixel,q);
2141 p+=GetPixelChannels(image);
2142 }
2143 extent=(size_t) (q-pixels);
2144 break;
2145 }
2146 if (image->depth <= 16)
2147 {
2148 for (x=0; x < (ssize_t) image->columns; x++)
2149 {
2150 if (IsPixelGray(image,p) == MagickFalse)
2151 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(image,
2152 p)),max_value);
2153 else
2154 {
2155 if (image->depth == 16)
2156 pixel=ScaleQuantumToShort(GetPixelRed(image,p));
2157 else
2158 pixel=ScaleQuantumToAny(GetPixelRed(image,p),
2159 max_value);
2160 }
2161 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2162 p+=GetPixelChannels(image);
2163 }
2164 extent=(size_t) (q-pixels);
2165 break;
2166 }
2167 for (x=0; x < (ssize_t) image->columns; x++)
2168 {
2169 if (IsPixelGray(image,p) == MagickFalse)
2170 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(image,p)),
2171 max_value);
2172 else
2173 {
2174 if (image->depth == 16)
2175 pixel=ScaleQuantumToLong(GetPixelRed(image,p));
2176 else
2177 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2178 }
2179 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2180 p+=GetPixelChannels(image);
2181 }
2182 extent=(size_t) (q-pixels);
2183 break;
2184 }
2185 }
2186 count=WriteBlob(image,extent,pixels);
2187 if (count != (ssize_t) extent)
2188 break;
2189 if (image->previous == (Image *) NULL)
2190 {
2191 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2192 image->rows);
2193 if (status == MagickFalse)
2194 break;
2195 }
2196 }
2197 quantum_info=DestroyQuantumInfo(quantum_info);
2198 break;
2199 }
2200 case '6':
2201 {
2202 unsigned char
2203 *pixels;
2204
2205 /*
2206 Convert image to a PNM image.
2207 */
2208 (void) TransformImageColorspace(image,sRGBColorspace,exception);
2209 if (image->depth > 32)
2210 image->depth=32;
2211 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2212 ((MagickOffsetType) GetQuantumRange(image->depth)));
2213 (void) WriteBlobString(image,buffer);
2214 quantum_info=AcquireQuantumInfo(image_info,image);
2215 if (quantum_info == (QuantumInfo *) NULL)
2216 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2217 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
2218 pixels=GetQuantumPixels(quantum_info);
2219 extent=GetQuantumExtent(image,quantum_info,quantum_type);
2220 for (y=0; y < (ssize_t) image->rows; y++)
2221 {
2222 const Quantum
2223 *magick_restrict p;
2224
2225 ssize_t
2226 x;
2227
2228 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2229 if (p == (const Quantum *) NULL)
2230 break;
2231 q=pixels;
2232 switch (image->depth)
2233 {
2234 case 8:
2235 case 16:
2236 case 32:
2237 {
2238 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2239 quantum_type,pixels,exception);
2240 break;
2241 }
2242 default:
2243 {
2244 if (image->depth <= 8)
2245 {
2246 for (x=0; x < (ssize_t) image->columns; x++)
2247 {
2248 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2249 q=PopCharPixel((unsigned char) pixel,q);
2250 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2251 q=PopCharPixel((unsigned char) pixel,q);
2252 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2253 q=PopCharPixel((unsigned char) pixel,q);
2254 p+=GetPixelChannels(image);
2255 }
2256 extent=(size_t) (q-pixels);
2257 break;
2258 }
2259 if (image->depth <= 16)
2260 {
2261 for (x=0; x < (ssize_t) image->columns; x++)
2262 {
2263 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2264 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2265 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2266 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2267 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2268 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2269 p+=GetPixelChannels(image);
2270 }
2271 extent=(size_t) (q-pixels);
2272 break;
2273 }
2274 for (x=0; x < (ssize_t) image->columns; x++)
2275 {
2276 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2277 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2278 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2279 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2280 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2281 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2282 p+=GetPixelChannels(image);
2283 }
2284 extent=(size_t) (q-pixels);
2285 break;
2286 }
2287 }
2288 count=WriteBlob(image,extent,pixels);
2289 if (count != (ssize_t) extent)
2290 break;
2291 if (image->previous == (Image *) NULL)
2292 {
2293 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2294 image->rows);
2295 if (status == MagickFalse)
2296 break;
2297 }
2298 }
2299 quantum_info=DestroyQuantumInfo(quantum_info);
2300 break;
2301 }
2302 case '7':
2303 {
2304 unsigned char
2305 *pixels;
2306
2307 /*
2308 Convert image to a PAM.
2309 */
2310 if (image->depth > 32)
2311 image->depth=32;
2312 quantum_info=AcquireQuantumInfo(image_info,image);
2313 if (quantum_info == (QuantumInfo *) NULL)
2314 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2315 (void) SetQuantumEndian(image,quantum_info,MSBEndian);
2316 pixels=GetQuantumPixels(quantum_info);
2317 for (y=0; y < (ssize_t) image->rows; y++)
2318 {
2319 const Quantum
2320 *magick_restrict p;
2321
2322 ssize_t
2323 x;
2324
2325 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2326 if (p == (const Quantum *) NULL)
2327 break;
2328 q=pixels;
2329 switch (image->depth)
2330 {
2331 case 8:
2332 case 16:
2333 case 32:
2334 {
2335 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2336 quantum_type,pixels,exception);
2337 break;
2338 }
2339 default:
2340 {
2341 switch (quantum_type)
2342 {
2343 case GrayQuantum:
2344 case GrayAlphaQuantum:
2345 {
2346 if (image->depth <= 8)
2347 {
2348 for (x=0; x < (ssize_t) image->columns; x++)
2349 {
2350 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(
2351 image,p)),max_value);
2352 q=PopCharPixel((unsigned char) pixel,q);
2353 if (image->alpha_trait != UndefinedPixelTrait)
2354 {
2355 pixel=(unsigned char) ScaleQuantumToAny(
2356 GetPixelAlpha(image,p),max_value);
2357 q=PopCharPixel((unsigned char) pixel,q);
2358 }
2359 p+=GetPixelChannels(image);
2360 }
2361 break;
2362 }
2363 if (image->depth <= 16)
2364 {
2365 for (x=0; x < (ssize_t) image->columns; x++)
2366 {
2367 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(
2368 image,p)),max_value);
2369 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2370 if (image->alpha_trait != UndefinedPixelTrait)
2371 {
2372 pixel=(unsigned char) ScaleQuantumToAny(
2373 GetPixelAlpha(image,p),max_value);
2374 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2375 }
2376 p+=GetPixelChannels(image);
2377 }
2378 break;
2379 }
2380 for (x=0; x < (ssize_t) image->columns; x++)
2381 {
2382 pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(image,
2383 p)),max_value);
2384 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2385 if (image->alpha_trait != UndefinedPixelTrait)
2386 {
2387 pixel=(unsigned char) ScaleQuantumToAny(
2388 GetPixelAlpha(image,p),max_value);
2389 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2390 }
2391 p+=GetPixelChannels(image);
2392 }
2393 break;
2394 }
2395 case CMYKQuantum:
2396 case CMYKAQuantum:
2397 {
2398 if (image->depth <= 8)
2399 {
2400 for (x=0; x < (ssize_t) image->columns; x++)
2401 {
2402 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2403 q=PopCharPixel((unsigned char) pixel,q);
2404 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2405 max_value);
2406 q=PopCharPixel((unsigned char) pixel,q);
2407 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2408 max_value);
2409 q=PopCharPixel((unsigned char) pixel,q);
2410 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),
2411 max_value);
2412 q=PopCharPixel((unsigned char) pixel,q);
2413 if (image->alpha_trait != UndefinedPixelTrait)
2414 {
2415 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2416 max_value);
2417 q=PopCharPixel((unsigned char) pixel,q);
2418 }
2419 p+=GetPixelChannels(image);
2420 }
2421 break;
2422 }
2423 if (image->depth <= 16)
2424 {
2425 for (x=0; x < (ssize_t) image->columns; x++)
2426 {
2427 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2428 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2429 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2430 max_value);
2431 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2432 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2433 max_value);
2434 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2435 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),
2436 max_value);
2437 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2438 if (image->alpha_trait != UndefinedPixelTrait)
2439 {
2440 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2441 max_value);
2442 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2443 }
2444 p+=GetPixelChannels(image);
2445 }
2446 break;
2447 }
2448 for (x=0; x < (ssize_t) image->columns; x++)
2449 {
2450 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2451 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2452 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2453 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2454 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2455 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2456 pixel=ScaleQuantumToAny(GetPixelBlack(image,p),max_value);
2457 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2458 if (image->alpha_trait != UndefinedPixelTrait)
2459 {
2460 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2461 max_value);
2462 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2463 }
2464 p+=GetPixelChannels(image);
2465 }
2466 break;
2467 }
2468 default:
2469 {
2470 if (image->depth <= 8)
2471 {
2472 for (x=0; x < (ssize_t) image->columns; x++)
2473 {
2474 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2475 q=PopCharPixel((unsigned char) pixel,q);
2476 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2477 max_value);
2478 q=PopCharPixel((unsigned char) pixel,q);
2479 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2480 max_value);
2481 q=PopCharPixel((unsigned char) pixel,q);
2482 if (image->alpha_trait != UndefinedPixelTrait)
2483 {
2484 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2485 max_value);
2486 q=PopCharPixel((unsigned char) pixel,q);
2487 }
2488 p+=GetPixelChannels(image);
2489 }
2490 break;
2491 }
2492 if (image->depth <= 16)
2493 {
2494 for (x=0; x < (ssize_t) image->columns; x++)
2495 {
2496 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2497 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2498 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2499 max_value);
2500 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2501 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2502 max_value);
2503 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2504 if (image->alpha_trait != UndefinedPixelTrait)
2505 {
2506 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2507 max_value);
2508 q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2509 }
2510 p+=GetPixelChannels(image);
2511 }
2512 break;
2513 }
2514 for (x=0; x < (ssize_t) image->columns; x++)
2515 {
2516 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2517 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2518 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2519 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2520 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2521 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2522 if (image->alpha_trait != UndefinedPixelTrait)
2523 {
2524 pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2525 max_value);
2526 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2527 }
2528 p+=GetPixelChannels(image);
2529 }
2530 break;
2531 }
2532 }
2533 extent=(size_t) (q-pixels);
2534 break;
2535 }
2536 }
2537 count=WriteBlob(image,extent,pixels);
2538 if (count != (ssize_t) extent)
2539 break;
2540 if (image->previous == (Image *) NULL)
2541 {
2542 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2543 image->rows);
2544 if (status == MagickFalse)
2545 break;
2546 }
2547 }
2548 quantum_info=DestroyQuantumInfo(quantum_info);
2549 break;
2550 }
2551 case 'F':
2552 case 'f':
2553 {
2554 unsigned char
2555 *pixels;
2556
2557 (void) WriteBlobString(image,image->endian == LSBEndian ? "-1.0\n" :
2558 "1.0\n");
2559 image->depth=32;
2560 quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
2561 quantum_info=AcquireQuantumInfo(image_info,image);
2562 if (quantum_info == (QuantumInfo *) NULL)
2563 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2564 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2565 if (status == MagickFalse)
2566 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2567 pixels=GetQuantumPixels(quantum_info);
2568 for (y=(ssize_t) image->rows-1; y >= 0; y--)
2569 {
2570 const Quantum
2571 *magick_restrict p;
2572
2573 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2574 if (p == (const Quantum *) NULL)
2575 break;
2576 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2577 quantum_type,pixels,exception);
2578 (void) WriteBlob(image,extent,pixels);
2579 if (image->previous == (Image *) NULL)
2580 {
2581 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2582 image->rows);
2583 if (status == MagickFalse)
2584 break;
2585 }
2586 }
2587 quantum_info=DestroyQuantumInfo(quantum_info);
2588 break;
2589 }
2590 case 'H':
2591 case 'h':
2592 {
2593 unsigned char
2594 *pixels;
2595
2596 (void) WriteBlobString(image,image->endian == LSBEndian ? "-1.0\n" :
2597 "1.0\n");
2598 image->depth=16;
2599 quantum_type=format == 'h' ? GrayQuantum : RGBQuantum;
2600 quantum_info=AcquireQuantumInfo(image_info,image);
2601 if (quantum_info == (QuantumInfo *) NULL)
2602 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2603 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2604 if (status == MagickFalse)
2605 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2606 pixels=GetQuantumPixels(quantum_info);
2607 for (y=(ssize_t) image->rows-1; y >= 0; y--)
2608 {
2609 const Quantum
2610 *magick_restrict p;
2611
2612 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2613 if (p == (const Quantum *) NULL)
2614 break;
2615 extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2616 quantum_type,pixels,exception);
2617 (void) WriteBlob(image,extent,pixels);
2618 if (image->previous == (Image *) NULL)
2619 {
2620 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2621 image->rows);
2622 if (status == MagickFalse)
2623 break;
2624 }
2625 }
2626 quantum_info=DestroyQuantumInfo(quantum_info);
2627 break;
2628 }
2629 default:
2630 break;
2631 }
2632 if (GetNextImageInList(image) == (Image *) NULL)
2633 break;
2634 image=SyncNextImageInList(image);
2635 status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);
2636 if (status == MagickFalse)
2637 break;
2638 } while (image_info->adjoin != MagickFalse);
2639 (void) CloseBlob(image);
2640 return(MagickTrue);
2641 }
2642