1 {
2 $Id: ImagingPortableMaps.pas 163 2009-07-28 21:44:10Z galfar $
3 Vampyre Imaging Library
4 by Marek Mauder
5 http://imaginglib.sourceforge.net
7 The contents of this file are used with permission, subject to the Mozilla
8 Public License Version 1.1 (the "License"); you may not use this file except
9 in compliance with the License. You may obtain a copy of the License at
10 http://www.mozilla.org/MPL/MPL-1.1.html
12 Software distributed under the License is distributed on an "AS IS" basis,
13 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
14 the specific language governing rights and limitations under the License.
16 Alternatively, the contents of this file may be used under the terms of the
17 GNU Lesser General Public License (the "LGPL License"), in which case the
18 provisions of the LGPL License are applicable instead of those above.
19 If you wish to allow use of your version of this file only under the terms
20 of the LGPL License and not to allow others to use your version of this file
21 under the MPL, indicate your decision by deleting the provisions above and
22 replace them with the notice and other provisions required by the LGPL
23 License. If you do not delete the provisions above, a recipient may use
24 your version of this file under either the MPL or the LGPL License.
26 For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html
27 }
29 { This unit contains loader/saver for Portable Maps file format family (or PNM).
30 That includes PBM, PGM, PPM, PAM, and PFM formats.}
33 {$I ImagingOptions.inc}
35 interface
37 uses
40 type
41 { Types of pixels of PNM images.}
45 { Record with info about PNM image used in both loading and saving functions.}
59 { Base class for Portable Map file formats (or Portable AnyMaps or PNM).
60 There are several types of PNM file formats that share common
61 (simple) structure. This class can actually load all supported PNM formats.
62 Saving is also done by this class but descendants (each for different PNM
63 format) control it.}
65 protected
72 public
75 published
76 { If set to True images will be saved in binary format. If it is False
77 they will be saved in text format (which could result in 5-10x bigger file).
78 Default is value True. Note that PAM and PFM files are always saved in binary.}
82 { Portable Bit Map is used to store monochrome 1bit images. Raster data
83 can be saved as text or binary data. Either way value of 0 represents white
84 and 1 is black. As Imaging does not have support for 1bit data formats
85 PBM images can be loaded but not saved. Loaded images are returned in
86 ifGray8 format (witch pixel values scaled from 1bit to 8bit).}
88 public
92 { Portable Gray Map is used to store grayscale 8bit or 16bit images.
93 Raster data can be saved as text or binary data.}
95 protected
100 public
104 { Portable Pixel Map is used to store RGB images with 8bit or 16bit channels.
105 Raster data can be saved as text or binary data.}
107 protected
112 public
116 { Portable Arbitrary Map is format that can store image data formats
117 of PBM, PGM, and PPM formats with optional alpha channel. Raster data
118 can be stored only in binary format. All data formats supported
119 by this format are ifGray8, ifGray16, ifA8Gray8, ifA16Gray16,
120 ifR8G8B8, ifR16G16R16, ifA8R8G8B8, and ifA16R16G16B16.}
122 protected
127 public
131 { Portable Float Map is unofficial extension of PNM format family which
132 can store images with floating point pixels. Raster data is saved in
133 binary format as array of IEEE 32 bit floating point numbers. One channel
134 or RGB images are supported by PFM format (so no alpha).}
136 protected
141 public
145 implementation
147 const
166 const
167 { TAB, CR, LF, and Space are used as seperators in Portable map headers and data.}
176 { Size of buffer used to speed up text PNM loading/saving.}
184 { TPortableMapFileFormat }
187 begin
197 var
209 begin
211 begin
212 // Reload buffer if its is empty or its end was reached
219 begin
220 // Sets input's position to its real pos as it would be without buffering
222 begin
229 var
232 begin
233 // First skip all whitespace chars
235 repeat
236 CheckBuffer;
240 repeat
241 // Comment detected, skip everything until next line is reached
242 CheckBuffer;
247 // Now we have reached some chars other than white space, read them until
248 // there is whitespace again
249 repeat
251 CheckBuffer;
254 // Repeat until current char is whitespace or end of file is reached
255 // (Line buffer has 0 bytes which happens only on EOF)
257 // Get rid of last char - whitespace or null
259 // Move position to the beginning of next string (skip white space - needed
260 // to make the loader stop at the right input position)
261 repeat
262 CheckBuffer;
266 // Dec pos, current is the begining of the the string
273 begin
278 var
280 begin
282 repeat
283 CheckBuffer;
294 var
300 begin
303 begin
306 FindLineBreak;
309 begin
310 // Read header for PBM, PGM, and PPM files
315 begin
318 end
319 else
320 begin
321 // Read channel max value, <=255 for 8bit images, >255 for 16bit images
322 // but some programs think its max colors so put <=256 here
332 begin
337 end
339 begin
340 // Read values from PAM header
341 // WIDTH
344 // HEIGHT
347 // DEPTH
350 // MAXVAL
354 // TUPLETYPE
359 begin
361 Break;
363 // ENDHDR
365 end
367 begin
368 // Read header of PFM file
378 else
384 FixInputPos;
388 begin
389 // Mimic the behaviour of Photoshop and other editors/viewers:
390 // If linenreaks in file are DOS CR/LF 16bit binary values are
391 // little endian, Unix LF only linebreak indicates big endian.
395 // Check if values found in header are valid
398 // Now check if image has proper number of channels (PAM)
409 begin
415 begin
417 // Try to parse file header
419 // Select appropriate data format based on values read from file header
430 // Exit if no matching data format was found
436 // Now read pixels from file to dest image
438 begin
441 begin
443 ifGray8:
444 begin
447 // If source is 1bit mono image (where 0=white, 1=black)
448 // we must scale it to 8bits
452 ifR8G8B8:
454 begin
459 ifR16G16B16:
461 begin
469 end
470 else
471 begin
473 begin
475 begin
476 // Just copy bytes from binary Portable Maps (non 1bit, non FP)
478 end
479 else
480 begin
482 // FP images are in BGR order and endian swap maybe needed.
483 // Some programs store scanlines in bottom-up order but
484 // I will stick with Photoshops behaviour here
486 begin
490 begin
497 end
498 else
499 begin
509 begin
510 // Black and white PAM files must be scaled to 8bits. Note that
511 // in PAM files 1=white, 0=black (reverse of PBM)
514 end
516 begin
517 // Swap channels of RGB/ARGB images. Binary RGB image files use BGR order.
521 // Swap byte order if needed
524 end
525 else
526 begin
527 // Handle binary PBM files (ttBlackAndWhite 1bit)
529 // Get total binary data size, read it from file to temp
530 // buffer and convert the data to Gray8
533 try
536 // 1bit mono images must be scaled to 8bit (where 0=white, 1=black)
539 finally
545 FixInputPos;
549 begin
551 // Scale color values according to MaxVal we got from header
552 // if necessary.
554 begin
557 else
569 const
570 // Use Unix linebreak, for many viewers/editors it means that
571 // 16bit samples are stored as big endian - so we need to swap byte order
572 // before saving
575 var
586 begin
589 {$IF Defined(DCC) and Defined(UNICODE)}
591 {$ELSE}
593 {$IFEND}
598 var
600 begin
603 begin
604 // Write header of PGM, PPM, and PFM files
610 begin
613 // Negative value indicates that raster data is saved in little endian
618 end
619 else
620 begin
621 // Write PAM file header
631 begin
635 try
637 // Fill values of MapInfo record that were not filled by
638 // descendants in their SaveData methods
642 begin
644 begin
647 else
649 end
650 else
651 begin
654 else
658 // Write file header
659 WriteHeader;
662 begin
665 // For each pixel find its text representation and write it to file
667 begin
671 ifR8G8B8:
674 ifR16G16B16:
678 // Lines in text PNM images should have length <70
680 begin
686 end
687 else
688 begin
689 // Write binary images
691 begin
692 // Save integer binary images
694 begin
696 begin
697 // 8bit grayscale images can be written in one Write call
699 end
700 else
701 begin
702 // 8bit RGB/ARGB images: read and blue must be swapped and
703 // 3 or 4 bytes must be written
707 begin
717 end
718 else
719 begin
720 // Images with 16bit channels: make sure that channel values are saved in big endian
723 begin
724 // 16bit grayscale image
726 begin
731 end
732 else
733 begin
734 // RGB images with 16bit channels: swap RB and endian too
737 begin
748 end
749 else
750 begin
751 // Floating point images (no need to swap endian here - little
752 // endian is specified in file header)
754 begin
755 // Grayscale images can be written in one Write call
757 end
758 else
759 begin
760 // Expected data format of PFM RGB file is B32G32R32F which is not
761 // supported by Imaging. We must write pixels one by one and
762 // write only RGB part of A32B32G32B32 image.
765 begin
773 finally
780 var
783 begin
787 begin
795 { TPBMFileFormat }
798 begin
806 { TPGMFileFormat }
809 begin
820 var
822 begin
826 else
834 var
836 begin
838 // All FP images go to 16bit
839 ConvFormat := ifGray16
841 // Grayscale will be 8 or 16 bit - depends on input's bitcount
845 // Large bitcounts -> 16bit
846 ConvFormat := ifGray16
847 else
848 // Rest of the formats -> 8bit
854 { TPPMFileFormat }
857 begin
868 var
870 begin
874 else
882 var
884 begin
886 // All FP images go to 48bit RGB
887 ConvFormat := ifR16G16B16
889 // Grayscale will be 24 or 48 bit RGB - depends on input's bitcount
893 // Large bitcounts -> 48bit RGB
894 ConvFormat := ifR16G16B16
895 else
896 // Rest of the formats -> 24bit RGB
902 { TPAMFileFormat }
905 begin
915 var
917 begin
927 var
929 begin
934 else
935 begin
938 else
944 { TPFMFileFormat }
947 begin
957 var
960 begin
966 else
971 else
980 begin
983 else
987 initialization
994 {
995 File Notes:
997 -- TODOS ----------------------------------------------------
998 - nothing now
1000 -- 0.26.3 Changes/Bug Fixes -----------------------------------
1001 - Fixed D2009 Unicode related bug in PNM saving.
1003 -- 0.24.3 Changes/Bug Fixes -----------------------------------
1004 - Improved compatibility of 16bit/component image loading.
1005 - Changes for better thread safety.
1007 -- 0.21 Changes/Bug Fixes -----------------------------------
1008 - Made modifications to ASCII PNM loading to be more "stream-safe".
1009 - Fixed bug: indexed images saved as grayscale in PFM.
1010 - Changed converting to supported formats little bit.
1011 - Added scaling of channel values (non-FP and non-mono images) according
1012 to MaxVal.
1013 - Added buffering to loading of PNM files. More than 10x faster now
1014 for text files.
1015 - Added saving support to PGM, PPM, PAM, and PFM format.
1016 - Added PFM file format.
1017 - Initial version created.
1018 }