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