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