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