source: ImageMagick/trunk/coders/pnm.c @ 4330

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