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