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

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