• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                            PPPP   N   N  M   M                              %
7 %                            P   P  NN  N  MM MM                              %
8 %                            PPPP   N N N  M M M                              %
9 %                            P      N  NN  M   M                              %
10 %                            P      N   N  M   M                              %
11 %                                                                             %
12 %                                                                             %
13 %               Read/Write PBMPlus Portable Anymap Image Format               %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2016 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 
39 /*
40   Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/attribute.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/blob-private.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/color.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/colorspace.h"
50 #include "MagickCore/colorspace-private.h"
51 #include "MagickCore/exception.h"
52 #include "MagickCore/exception-private.h"
53 #include "MagickCore/image.h"
54 #include "MagickCore/image-private.h"
55 #include "MagickCore/list.h"
56 #include "MagickCore/magick.h"
57 #include "MagickCore/memory_.h"
58 #include "MagickCore/module.h"
59 #include "MagickCore/monitor.h"
60 #include "MagickCore/monitor-private.h"
61 #include "MagickCore/pixel-accessor.h"
62 #include "MagickCore/property.h"
63 #include "MagickCore/quantum-private.h"
64 #include "MagickCore/static.h"
65 #include "MagickCore/statistic.h"
66 #include "MagickCore/string_.h"
67 #include "MagickCore/string-private.h"
68 
69 /*
70   Forward declarations.
71 */
72 static MagickBooleanType
73   WritePNMImage(const ImageInfo *,Image *,ExceptionInfo *);
74 
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 */
IsPNM(const unsigned char * magick,const size_t extent)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 
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 
PNMComment(Image * image,ExceptionInfo * exception)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 
PNMInteger(Image * image,const unsigned int base,ExceptionInfo * exception)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 
ReadPNMImage(const ImageInfo * image_info,ExceptionInfo * exception)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 
1396 /*
1397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1398 %                                                                             %
1399 %                                                                             %
1400 %                                                                             %
1401 %   R e g i s t e r P N M I m a g e                                           %
1402 %                                                                             %
1403 %                                                                             %
1404 %                                                                             %
1405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1406 %
1407 %  RegisterPNMImage() adds properties for the PNM image format to
1408 %  the list of supported formats.  The properties include the image format
1409 %  tag, a method to read and/or write the format, whether the format
1410 %  supports the saving of more than one frame to the same file or blob,
1411 %  whether the format supports native in-memory I/O, and a brief
1412 %  description of the format.
1413 %
1414 %  The format of the RegisterPNMImage method is:
1415 %
1416 %      size_t RegisterPNMImage(void)
1417 %
1418 */
RegisterPNMImage(void)1419 ModuleExport size_t RegisterPNMImage(void)
1420 {
1421   MagickInfo
1422     *entry;
1423 
1424   entry=AcquireMagickInfo("PNM","PAM","Common 2-dimensional bitmap format");
1425   entry->decoder=(DecodeImageHandler *) ReadPNMImage;
1426   entry->encoder=(EncodeImageHandler *) WritePNMImage;
1427   entry->mime_type=ConstantString("image/x-portable-pixmap");
1428   (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 
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 */
UnregisterPNMImage(void)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 
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 */
WritePNMImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)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             break;
1694           }
1695           default:
1696           {
1697             quantum_type=RGBQuantum;
1698             if (image->alpha_trait != UndefinedPixelTrait)
1699               quantum_type=RGBAQuantum;
1700             packet_size=3;
1701             (void) CopyMagickString(type,"RGB",MagickPathExtent);
1702             break;
1703           }
1704         }
1705         if (image->alpha_trait != UndefinedPixelTrait)
1706           {
1707             packet_size++;
1708             (void) ConcatenateMagickString(type,"_ALPHA",MagickPathExtent);
1709           }
1710         if (image->depth > 32)
1711           image->depth=32;
1712         (void) FormatLocaleString(buffer,MagickPathExtent,
1713           "DEPTH %.20g\nMAXVAL %.20g\n",(double) packet_size,(double)
1714           ((MagickOffsetType) GetQuantumRange(image->depth)));
1715         (void) WriteBlobString(image,buffer);
1716         (void) FormatLocaleString(buffer,MagickPathExtent,"TUPLTYPE %s\nENDHDR\n",
1717           type);
1718         (void) WriteBlobString(image,buffer);
1719       }
1720     /*
1721       Convert runextent encoded to PNM raster pixels.
1722     */
1723     switch (format)
1724     {
1725       case '1':
1726       {
1727         unsigned char
1728           pixels[2048];
1729 
1730         /*
1731           Convert image to a PBM image.
1732         */
1733         (void) SetImageType(image,BilevelType,exception);
1734         q=pixels;
1735         for (y=0; y < (ssize_t) image->rows; y++)
1736         {
1737           register const Quantum
1738             *magick_restrict p;
1739 
1740           register ssize_t
1741             x;
1742 
1743           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1744           if (p == (const Quantum *) NULL)
1745             break;
1746           for (x=0; x < (ssize_t) image->columns; x++)
1747           {
1748             *q++=(unsigned char) (GetPixelLuma(image,p) >= (QuantumRange/2.0) ?
1749               '0' : '1');
1750             *q++=' ';
1751             if ((q-pixels+1) >= (ssize_t) sizeof(pixels))
1752               {
1753                 *q++='\n';
1754                 (void) WriteBlob(image,q-pixels,pixels);
1755                 q=pixels;
1756               }
1757             p+=GetPixelChannels(image);
1758           }
1759           *q++='\n';
1760           (void) WriteBlob(image,q-pixels,pixels);
1761           q=pixels;
1762           if (image->previous == (Image *) NULL)
1763             {
1764               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1765                 image->rows);
1766               if (status == MagickFalse)
1767                 break;
1768             }
1769         }
1770         if (q != pixels)
1771           {
1772             *q++='\n';
1773             (void) WriteBlob(image,q-pixels,pixels);
1774           }
1775         break;
1776       }
1777       case '2':
1778       {
1779         unsigned char
1780           pixels[2048];
1781 
1782         /*
1783           Convert image to a PGM image.
1784         */
1785         if (image->depth <= 8)
1786           (void) WriteBlobString(image,"255\n");
1787         else
1788           if (image->depth <= 16)
1789             (void) WriteBlobString(image,"65535\n");
1790           else
1791             (void) WriteBlobString(image,"4294967295\n");
1792         q=pixels;
1793         for (y=0; y < (ssize_t) image->rows; y++)
1794         {
1795           register const Quantum
1796             *magick_restrict p;
1797 
1798           register ssize_t
1799             x;
1800 
1801           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1802           if (p == (const Quantum *) NULL)
1803             break;
1804           for (x=0; x < (ssize_t) image->columns; x++)
1805           {
1806             index=ClampToQuantum(GetPixelLuma(image,p));
1807             if (image->depth <= 8)
1808               count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,"%u ",
1809                 ScaleQuantumToChar(index));
1810             else
1811               if (image->depth <= 16)
1812                 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
1813                   "%u ",ScaleQuantumToShort(index));
1814               else
1815                 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
1816                   "%u ",ScaleQuantumToLong(index));
1817             extent=(size_t) count;
1818             (void) strncpy((char *) q,buffer,extent);
1819             q+=extent;
1820             if ((q-pixels+extent+1) >= sizeof(pixels))
1821               {
1822                 *q++='\n';
1823                 (void) WriteBlob(image,q-pixels,pixels);
1824                 q=pixels;
1825               }
1826             p+=GetPixelChannels(image);
1827           }
1828           *q++='\n';
1829           (void) WriteBlob(image,q-pixels,pixels);
1830           q=pixels;
1831           if (image->previous == (Image *) NULL)
1832             {
1833               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1834                 image->rows);
1835               if (status == MagickFalse)
1836                 break;
1837             }
1838         }
1839         if (q != pixels)
1840           {
1841             *q++='\n';
1842             (void) WriteBlob(image,q-pixels,pixels);
1843           }
1844         break;
1845       }
1846       case '3':
1847       {
1848         unsigned char
1849           pixels[2048];
1850 
1851         /*
1852           Convert image to a PNM image.
1853         */
1854         (void) TransformImageColorspace(image,sRGBColorspace,exception);
1855         if (image->depth <= 8)
1856           (void) WriteBlobString(image,"255\n");
1857         else
1858           if (image->depth <= 16)
1859             (void) WriteBlobString(image,"65535\n");
1860           else
1861             (void) WriteBlobString(image,"4294967295\n");
1862         q=pixels;
1863         for (y=0; y < (ssize_t) image->rows; y++)
1864         {
1865           register const Quantum
1866             *magick_restrict p;
1867 
1868           register ssize_t
1869             x;
1870 
1871           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1872           if (p == (const Quantum *) NULL)
1873             break;
1874           for (x=0; x < (ssize_t) image->columns; x++)
1875           {
1876             if (image->depth <= 8)
1877               count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
1878                 "%u %u %u ",ScaleQuantumToChar(GetPixelRed(image,p)),
1879                 ScaleQuantumToChar(GetPixelGreen(image,p)),
1880                 ScaleQuantumToChar(GetPixelBlue(image,p)));
1881             else
1882               if (image->depth <= 16)
1883                 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
1884                   "%u %u %u ",ScaleQuantumToShort(GetPixelRed(image,p)),
1885                   ScaleQuantumToShort(GetPixelGreen(image,p)),
1886                   ScaleQuantumToShort(GetPixelBlue(image,p)));
1887               else
1888                 count=(ssize_t) FormatLocaleString(buffer,MagickPathExtent,
1889                   "%u %u %u ",ScaleQuantumToLong(GetPixelRed(image,p)),
1890                   ScaleQuantumToLong(GetPixelGreen(image,p)),
1891                   ScaleQuantumToLong(GetPixelBlue(image,p)));
1892             extent=(size_t) count;
1893             (void) strncpy((char *) q,buffer,extent);
1894             q+=extent;
1895             if ((q-pixels+extent+1) >= sizeof(pixels))
1896               {
1897                 *q++='\n';
1898                 (void) WriteBlob(image,q-pixels,pixels);
1899                 q=pixels;
1900               }
1901             p+=GetPixelChannels(image);
1902           }
1903           *q++='\n';
1904           (void) WriteBlob(image,q-pixels,pixels);
1905           q=pixels;
1906           if (image->previous == (Image *) NULL)
1907             {
1908               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1909                 image->rows);
1910               if (status == MagickFalse)
1911                 break;
1912             }
1913         }
1914         if (q != pixels)
1915           {
1916             *q++='\n';
1917             (void) WriteBlob(image,q-pixels,pixels);
1918           }
1919         break;
1920       }
1921       case '4':
1922       {
1923         /*
1924           Convert image to a PBM image.
1925         */
1926         (void) SetImageType(image,BilevelType,exception);
1927         image->depth=1;
1928         quantum_info=AcquireQuantumInfo(image_info,image);
1929         if (quantum_info == (QuantumInfo *) NULL)
1930           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1931         (void) SetQuantumEndian(image,quantum_info,MSBEndian);
1932         quantum_info->min_is_white=MagickTrue;
1933         pixels=GetQuantumPixels(quantum_info);
1934         for (y=0; y < (ssize_t) image->rows; y++)
1935         {
1936           register const Quantum
1937             *magick_restrict p;
1938 
1939           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1940           if (p == (const Quantum *) NULL)
1941             break;
1942           extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1943             GrayQuantum,pixels,exception);
1944           count=WriteBlob(image,extent,pixels);
1945           if (count != (ssize_t) extent)
1946             break;
1947           if (image->previous == (Image *) NULL)
1948             {
1949               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1950                 image->rows);
1951               if (status == MagickFalse)
1952                 break;
1953             }
1954         }
1955         quantum_info=DestroyQuantumInfo(quantum_info);
1956         break;
1957       }
1958       case '5':
1959       {
1960         /*
1961           Convert image to a PGM image.
1962         */
1963         if (image->depth > 32)
1964           image->depth=32;
1965         (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
1966           ((MagickOffsetType) GetQuantumRange(image->depth)));
1967         (void) WriteBlobString(image,buffer);
1968         quantum_info=AcquireQuantumInfo(image_info,image);
1969         if (quantum_info == (QuantumInfo *) NULL)
1970           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1971         (void) SetQuantumEndian(image,quantum_info,MSBEndian);
1972         quantum_info->min_is_white=MagickTrue;
1973         pixels=GetQuantumPixels(quantum_info);
1974         extent=GetQuantumExtent(image,quantum_info,GrayQuantum);
1975         for (y=0; y < (ssize_t) image->rows; y++)
1976         {
1977           register const Quantum
1978             *magick_restrict p;
1979 
1980           register ssize_t
1981             x;
1982 
1983           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1984           if (p == (const Quantum *) NULL)
1985             break;
1986           q=pixels;
1987           switch (image->depth)
1988           {
1989             case 8:
1990             case 16:
1991             case 32:
1992             {
1993               extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1994                 GrayQuantum,pixels,exception);
1995               break;
1996             }
1997             default:
1998             {
1999               if (image->depth <= 8)
2000                 {
2001                   for (x=0; x < (ssize_t) image->columns; x++)
2002                   {
2003                     if (IsPixelGray(image,p) == MagickFalse)
2004                       pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(
2005                         image,p)),max_value);
2006                     else
2007                       {
2008                         if (image->depth == 8)
2009                           pixel=ScaleQuantumToChar(GetPixelRed(image,p));
2010                         else
2011                           pixel=ScaleQuantumToAny(GetPixelRed(image,p),
2012                           max_value);
2013                       }
2014                     q=PopCharPixel((unsigned char) pixel,q);
2015                     p+=GetPixelChannels(image);
2016                   }
2017                   extent=(size_t) (q-pixels);
2018                   break;
2019                 }
2020               if (image->depth <= 16)
2021                 {
2022                   for (x=0; x < (ssize_t) image->columns; x++)
2023                   {
2024                     if (IsPixelGray(image,p) == MagickFalse)
2025                       pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(image,
2026                         p)),max_value);
2027                     else
2028                       {
2029                         if (image->depth == 16)
2030                           pixel=ScaleQuantumToShort(GetPixelRed(image,p));
2031                         else
2032                           pixel=ScaleQuantumToAny(GetPixelRed(image,p),
2033                             max_value);
2034                       }
2035                     q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2036                     p+=GetPixelChannels(image);
2037                   }
2038                   extent=(size_t) (q-pixels);
2039                   break;
2040                 }
2041               for (x=0; x < (ssize_t) image->columns; x++)
2042               {
2043                 if (IsPixelGray(image,p) == MagickFalse)
2044                   pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(image,p)),
2045                     max_value);
2046                 else
2047                   {
2048                     if (image->depth == 16)
2049                       pixel=ScaleQuantumToLong(GetPixelRed(image,p));
2050                     else
2051                       pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2052                   }
2053                 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2054                 p+=GetPixelChannels(image);
2055               }
2056               extent=(size_t) (q-pixels);
2057               break;
2058             }
2059           }
2060           count=WriteBlob(image,extent,pixels);
2061           if (count != (ssize_t) extent)
2062             break;
2063           if (image->previous == (Image *) NULL)
2064             {
2065               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2066                 image->rows);
2067               if (status == MagickFalse)
2068                 break;
2069             }
2070         }
2071         quantum_info=DestroyQuantumInfo(quantum_info);
2072         break;
2073       }
2074       case '6':
2075       {
2076         /*
2077           Convert image to a PNM image.
2078         */
2079         (void) TransformImageColorspace(image,sRGBColorspace,exception);
2080         if (image->depth > 32)
2081           image->depth=32;
2082         (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2083           ((MagickOffsetType) GetQuantumRange(image->depth)));
2084         (void) WriteBlobString(image,buffer);
2085         quantum_info=AcquireQuantumInfo(image_info,image);
2086         if (quantum_info == (QuantumInfo *) NULL)
2087           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2088         (void) SetQuantumEndian(image,quantum_info,MSBEndian);
2089         pixels=GetQuantumPixels(quantum_info);
2090         extent=GetQuantumExtent(image,quantum_info,quantum_type);
2091         for (y=0; y < (ssize_t) image->rows; y++)
2092         {
2093           register const Quantum
2094             *magick_restrict p;
2095 
2096           register ssize_t
2097             x;
2098 
2099           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2100           if (p == (const Quantum *) NULL)
2101             break;
2102           q=pixels;
2103           switch (image->depth)
2104           {
2105             case 8:
2106             case 16:
2107             case 32:
2108             {
2109               extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2110                 quantum_type,pixels,exception);
2111               break;
2112             }
2113             default:
2114             {
2115               if (image->depth <= 8)
2116                 {
2117                   for (x=0; x < (ssize_t) image->columns; x++)
2118                   {
2119                     pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2120                     q=PopCharPixel((unsigned char) pixel,q);
2121                     pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2122                     q=PopCharPixel((unsigned char) pixel,q);
2123                     pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2124                     q=PopCharPixel((unsigned char) pixel,q);
2125                     p+=GetPixelChannels(image);
2126                   }
2127                   extent=(size_t) (q-pixels);
2128                   break;
2129                 }
2130               if (image->depth <= 16)
2131                 {
2132                   for (x=0; x < (ssize_t) image->columns; x++)
2133                   {
2134                     pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2135                     q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2136                     pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2137                     q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2138                     pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2139                     q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2140                     p+=GetPixelChannels(image);
2141                   }
2142                   extent=(size_t) (q-pixels);
2143                   break;
2144                 }
2145               for (x=0; x < (ssize_t) image->columns; x++)
2146               {
2147                 pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2148                 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2149                 pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2150                 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2151                 pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2152                 q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2153                 p+=GetPixelChannels(image);
2154               }
2155               extent=(size_t) (q-pixels);
2156               break;
2157             }
2158           }
2159           count=WriteBlob(image,extent,pixels);
2160           if (count != (ssize_t) extent)
2161             break;
2162           if (image->previous == (Image *) NULL)
2163             {
2164               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2165                 image->rows);
2166               if (status == MagickFalse)
2167                 break;
2168             }
2169         }
2170         quantum_info=DestroyQuantumInfo(quantum_info);
2171         break;
2172       }
2173       case '7':
2174       {
2175         /*
2176           Convert image to a PAM.
2177         */
2178         if (image->depth > 32)
2179           image->depth=32;
2180         quantum_info=AcquireQuantumInfo(image_info,image);
2181         if (quantum_info == (QuantumInfo *) NULL)
2182           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2183         (void) SetQuantumEndian(image,quantum_info,MSBEndian);
2184         pixels=GetQuantumPixels(quantum_info);
2185         for (y=0; y < (ssize_t) image->rows; y++)
2186         {
2187           register const Quantum
2188             *magick_restrict p;
2189 
2190           register ssize_t
2191             x;
2192 
2193           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2194           if (p == (const Quantum *) NULL)
2195             break;
2196           q=pixels;
2197           switch (image->depth)
2198           {
2199             case 8:
2200             case 16:
2201             case 32:
2202             {
2203               extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2204                 quantum_type,pixels,exception);
2205               break;
2206             }
2207             default:
2208             {
2209               switch (quantum_type)
2210               {
2211                 case GrayQuantum:
2212                 case GrayAlphaQuantum:
2213                 {
2214                   if (image->depth <= 8)
2215                     {
2216                       for (x=0; x < (ssize_t) image->columns; x++)
2217                       {
2218                         pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(
2219                           image,p)),max_value);
2220                         q=PopCharPixel((unsigned char) pixel,q);
2221                         if (image->alpha_trait != UndefinedPixelTrait)
2222                           {
2223                             pixel=(unsigned char) ScaleQuantumToAny(
2224                               GetPixelAlpha(image,p),max_value);
2225                             q=PopCharPixel((unsigned char) pixel,q);
2226                           }
2227                         p+=GetPixelChannels(image);
2228                       }
2229                       break;
2230                     }
2231                   if (image->depth <= 16)
2232                     {
2233                       for (x=0; x < (ssize_t) image->columns; x++)
2234                       {
2235                         pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(
2236                           image,p)),max_value);
2237                         q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2238                         if (image->alpha_trait != UndefinedPixelTrait)
2239                           {
2240                             pixel=(unsigned char) ScaleQuantumToAny(
2241                               GetPixelAlpha(image,p),max_value);
2242                             q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2243                           }
2244                         p+=GetPixelChannels(image);
2245                       }
2246                       break;
2247                     }
2248                   for (x=0; x < (ssize_t) image->columns; x++)
2249                   {
2250                     pixel=ScaleQuantumToAny(ClampToQuantum(GetPixelLuma(image,
2251                       p)),max_value);
2252                     q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2253                     if (image->alpha_trait != UndefinedPixelTrait)
2254                       {
2255                         pixel=(unsigned char) ScaleQuantumToAny(
2256                           GetPixelAlpha(image,p),max_value);
2257                         q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2258                       }
2259                     p+=GetPixelChannels(image);
2260                   }
2261                   break;
2262                 }
2263                 case CMYKQuantum:
2264                 case CMYKAQuantum:
2265                 {
2266                   if (image->depth <= 8)
2267                     {
2268                       for (x=0; x < (ssize_t) image->columns; x++)
2269                       {
2270                         pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2271                         q=PopCharPixel((unsigned char) pixel,q);
2272                         pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2273                           max_value);
2274                         q=PopCharPixel((unsigned char) pixel,q);
2275                         pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2276                           max_value);
2277                         q=PopCharPixel((unsigned char) pixel,q);
2278                         pixel=ScaleQuantumToAny(GetPixelBlack(image,p),
2279                           max_value);
2280                         q=PopCharPixel((unsigned char) pixel,q);
2281                         if (image->alpha_trait != UndefinedPixelTrait)
2282                           {
2283                             pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2284                               max_value);
2285                             q=PopCharPixel((unsigned char) pixel,q);
2286                           }
2287                         p+=GetPixelChannels(image);
2288                       }
2289                       break;
2290                     }
2291                   if (image->depth <= 16)
2292                     {
2293                       for (x=0; x < (ssize_t) image->columns; x++)
2294                       {
2295                         pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2296                         q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2297                         pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2298                           max_value);
2299                         q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2300                         pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2301                           max_value);
2302                         q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2303                         pixel=ScaleQuantumToAny(GetPixelBlack(image,p),
2304                           max_value);
2305                         q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2306                         if (image->alpha_trait != UndefinedPixelTrait)
2307                           {
2308                             pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2309                               max_value);
2310                             q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2311                           }
2312                         p+=GetPixelChannels(image);
2313                       }
2314                       break;
2315                     }
2316                   for (x=0; x < (ssize_t) image->columns; x++)
2317                   {
2318                     pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2319                     q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2320                     pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2321                     q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2322                     pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2323                     q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2324                     pixel=ScaleQuantumToAny(GetPixelBlack(image,p),max_value);
2325                     q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2326                     if (image->alpha_trait != UndefinedPixelTrait)
2327                       {
2328                         pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2329                           max_value);
2330                         q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2331                       }
2332                     p+=GetPixelChannels(image);
2333                   }
2334                   break;
2335                 }
2336                 default:
2337                 {
2338                   if (image->depth <= 8)
2339                     {
2340                       for (x=0; x < (ssize_t) image->columns; x++)
2341                       {
2342                         pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2343                         q=PopCharPixel((unsigned char) pixel,q);
2344                         pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2345                           max_value);
2346                         q=PopCharPixel((unsigned char) pixel,q);
2347                         pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2348                           max_value);
2349                         q=PopCharPixel((unsigned char) pixel,q);
2350                         if (image->alpha_trait != UndefinedPixelTrait)
2351                           {
2352                             pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2353                               max_value);
2354                             q=PopCharPixel((unsigned char) pixel,q);
2355                           }
2356                         p+=GetPixelChannels(image);
2357                       }
2358                       break;
2359                     }
2360                   if (image->depth <= 16)
2361                     {
2362                       for (x=0; x < (ssize_t) image->columns; x++)
2363                       {
2364                         pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2365                         q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2366                         pixel=ScaleQuantumToAny(GetPixelGreen(image,p),
2367                           max_value);
2368                         q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2369                         pixel=ScaleQuantumToAny(GetPixelBlue(image,p),
2370                           max_value);
2371                         q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2372                         if (image->alpha_trait != UndefinedPixelTrait)
2373                           {
2374                             pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2375                               max_value);
2376                             q=PopShortPixel(MSBEndian,(unsigned short) pixel,q);
2377                           }
2378                         p+=GetPixelChannels(image);
2379                       }
2380                       break;
2381                     }
2382                   for (x=0; x < (ssize_t) image->columns; x++)
2383                   {
2384                     pixel=ScaleQuantumToAny(GetPixelRed(image,p),max_value);
2385                     q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2386                     pixel=ScaleQuantumToAny(GetPixelGreen(image,p),max_value);
2387                     q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2388                     pixel=ScaleQuantumToAny(GetPixelBlue(image,p),max_value);
2389                     q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2390                     if (image->alpha_trait != UndefinedPixelTrait)
2391                       {
2392                         pixel=ScaleQuantumToAny(GetPixelAlpha(image,p),
2393                           max_value);
2394                         q=PopLongPixel(MSBEndian,(unsigned int) pixel,q);
2395                       }
2396                     p+=GetPixelChannels(image);
2397                   }
2398                   break;
2399                 }
2400               }
2401               extent=(size_t) (q-pixels);
2402               break;
2403             }
2404           }
2405           count=WriteBlob(image,extent,pixels);
2406           if (count != (ssize_t) extent)
2407             break;
2408           if (image->previous == (Image *) NULL)
2409             {
2410               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2411                 image->rows);
2412               if (status == MagickFalse)
2413                 break;
2414             }
2415         }
2416         quantum_info=DestroyQuantumInfo(quantum_info);
2417         break;
2418       }
2419       case 'F':
2420       case 'f':
2421       {
2422         (void) WriteBlobString(image,image->endian == LSBEndian ? "-1.0\n" :
2423           "1.0\n");
2424         image->depth=32;
2425         quantum_type=format == 'f' ? GrayQuantum : RGBQuantum;
2426         quantum_info=AcquireQuantumInfo(image_info,image);
2427         if (quantum_info == (QuantumInfo *) NULL)
2428           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2429         status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2430         if (status == MagickFalse)
2431           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2432         pixels=GetQuantumPixels(quantum_info);
2433         for (y=(ssize_t) image->rows-1; y >= 0; y--)
2434         {
2435           register const Quantum
2436             *magick_restrict p;
2437 
2438           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2439           if (p == (const Quantum *) NULL)
2440             break;
2441           extent=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
2442             quantum_type,pixels,exception);
2443           (void) WriteBlob(image,extent,pixels);
2444           if (image->previous == (Image *) NULL)
2445             {
2446               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2447                 image->rows);
2448               if (status == MagickFalse)
2449                 break;
2450             }
2451         }
2452         quantum_info=DestroyQuantumInfo(quantum_info);
2453         break;
2454       }
2455     }
2456     if (GetNextImageInList(image) == (Image *) NULL)
2457       break;
2458     image=SyncNextImageInList(image);
2459     status=SetImageProgress(image,SaveImagesTag,scene++,
2460       GetImageListLength(image));
2461     if (status == MagickFalse)
2462       break;
2463   } while (image_info->adjoin != MagickFalse);
2464   (void) CloseBlob(image);
2465   return(MagickTrue);
2466 }
2467