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