source: ImageMagick/branches/ImageMagick-6/coders/pnm.c @ 7887

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