Panda3D

pnmFileTypePfm.cxx
Go to the documentation of this file.
1 /**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file pnmFileTypePfm.cxx
10 * @author drose
11 * @date 1998-04-04
12 */
13
14 #include "pnmFileTypePfm.h"
15 #include "pfmFile.h"
16 #include "config_pnmimage.h"
17
18 #include "pnmFileTypeRegistry.h"
19 #include "bamReader.h"
20
21 using std::istream;
22 using std::ostream;
23 using std::string;
24
25 TypeHandle PNMFileTypePfm::_type_handle;
26
27 /**
28 *
29 */
30 PNMFileTypePfm::
31 PNMFileTypePfm() {
32 }
33
34 /**
35 * Returns a few words describing the file type.
36 */
37 string PNMFileTypePfm::
38 get_name() const {
39 return "Portable Float Map";
40 }
41
42 /**
43 * Returns the number of different possible filename extensions associated
44 * with this particular file type.
45 */
46 int PNMFileTypePfm::
47 get_num_extensions() const {
48 return 1;
49 }
50
51 /**
52 * Returns the nth possible filename extension associated with this particular
53 * file type, without a leading dot.
54 */
55 string PNMFileTypePfm::
56 get_extension(int n) const {
57 return "pfm";
58 }
59
60 /**
61 * Returns a suitable filename extension (without a leading dot) to suggest
62 * for files of this type, or empty string if no suggestions are available.
63 */
64 string PNMFileTypePfm::
65 get_suggested_extension() const {
66 return "pfm";
67 }
68
69 /**
70 * Returns true if this particular file type uses a magic number to identify
71 * it, false otherwise.
72 */
73 bool PNMFileTypePfm::
74 has_magic_number() const {
75 return true;
76 }
77
78 /**
79 * Returns true if the indicated "magic number" byte stream (the initial few
80 * bytes read from the file) matches this particular file type, false
81 * otherwise.
82 */
83 bool PNMFileTypePfm::
84 matches_magic_number(const string &magic_number) const {
85 return (magic_number.size() >= 2) &&
86 (magic_number.substr(0, 2) == "PF" ||
87 magic_number.substr(0, 2) == "Pf" ||
88 magic_number.substr(0, 2) == "pf");
89 }
90
91 /**
92 * Allocates and returns a new PNMReader suitable for reading from this file
93 * type, if possible. If reading from this file type is not supported,
94 * returns NULL.
95 */
96 PNMReader *PNMFileTypePfm::
97 make_reader(istream *file, bool owns_file, const string &magic_number) {
98 return new Reader(this, file, owns_file, magic_number);
99 }
100
101 /**
102 * Allocates and returns a new PNMWriter suitable for reading from this file
103 * type, if possible. If writing files of this type is not supported, returns
104 * NULL.
105 */
106 PNMWriter *PNMFileTypePfm::
107 make_writer(ostream *file, bool owns_file) {
108 return new Writer(this, file, owns_file);
109 }
110
111
112 /**
113 *
114 */
115 PNMFileTypePfm::Reader::
116 Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
117 PNMReader(type, file, owns_file)
118 {
119 read_magic_number(_file, magic_number, 2);
120
121 if (magic_number == "pf") {
122 // In this case, we're probably reading a special-extension 4-channel pfm
123 // file, and we need a four-byte magic number to confirm this and fully
124 // identify the file format.
125 read_magic_number(_file, magic_number, 4);
126 }
127
128 if (magic_number == "PF") {
129 _num_channels = 3;
130
131 } else if (magic_number == "Pf") {
132 _num_channels = 1;
133
134 } else if (magic_number == "pf2c") {
135 // Special DRZ extension.
136 _num_channels = 2;
137
138 } else if (magic_number == "pf4c") {
139 // Special DRZ extension.
140 _num_channels = 4;
141
142 } else {
143 pnmimage_cat.debug()
144 << "Not a PFM file\n";
145 _is_valid = false;
146 return;
147 }
148
149 _maxval = PGM_MAXMAXVAL;
150
151 (*_file) >> _x_size >> _y_size >> _scale;
152 if (!(*_file)) {
153 pnmimage_cat.debug()
154 << "Error parsing PFM header\n";
155 _is_valid = false;
156 return;
157 }
158
159 // Skip the last newlinewhitespace character before the raw data begins.
160 (*_file).get();
161 }
162
163 /**
164 * Returns true if this PNMFileType represents a floating-point image type,
165 * false if it is a normal, integer type. If this returns true, read_pfm() is
166 * implemented instead of read_data().
167 */
168 bool PNMFileTypePfm::Reader::
169 is_floating_point() {
170 return true;
171 }
172
173 /**
174 * Reads floating-point data directly into the indicated PfmFile. Returns
175 * true on success, false on failure.
176 */
177 bool PNMFileTypePfm::Reader::
178 read_pfm(PfmFile &pfm) {
179 if (!is_valid()) {
180 return false;
181 }
182
183 bool little_endian = false;
184 if (_scale < 0) {
185 _scale = -_scale;
186 little_endian = true;
187 }
188 if (pfm_force_littleendian) {
189 little_endian = true;
190 }
191 if (pfm_reverse_dimensions) {
192 int t = _x_size;
193 _x_size = _y_size;
194 _y_size = t;
195 }
196
197 pfm.clear(_x_size, _y_size, _num_channels);
198 pfm.set_scale(_scale);
199
200 // So far, so good. Now read the data.
201 int size = _x_size * _y_size * _num_channels;
202
203 pvector<PN_float32> table;
204 pfm.swap_table(table);
205
206 (*_file).read((char *)&table[0], sizeof(PN_float32) * size);
207 if ((*_file).fail() && !(*_file).eof()) {
208 pfm.clear();
209 return false;
210 }
211
212 // Now we may have to endian-reverse the data.
213 #ifdef WORDS_BIGENDIAN
214 bool endian_reversed = little_endian;
215 #else
216 bool endian_reversed = !little_endian;
217 #endif
218
219 if (endian_reversed) {
220 for (int ti = 0; ti < size; ++ti) {
221 ReversedNumericData nd(&table[ti], sizeof(PN_float32));
222 nd.store_value(&table[ti], sizeof(PN_float32));
223 }
224 }
225
226 pfm.swap_table(table);
227 return true;
228 }
229
230
231 /**
232 *
233 */
234 PNMFileTypePfm::Writer::
235 Writer(PNMFileType *type, ostream *file, bool owns_file) :
236 PNMWriter(type, file, owns_file)
237 {
238 }
239
240 /**
241 * Returns true if this PNMFileType can accept a floating-point image type,
242 * false if it can only accept a normal, integer type. If this returns true,
243 * write_pfm() is implemented.
244 */
245 bool PNMFileTypePfm::Writer::
246 supports_floating_point() {
247 return true;
248 }
249
250 /**
251 * Returns true if this PNMFileType can accept an integer image type, false if
252 * it can only accept a floating-point type. If this returns true,
253 * write_data() or write_row() is implemented.
254 */
255 bool PNMFileTypePfm::Writer::
256 supports_integer() {
257 return false;
258 }
259
260 /**
261 * Writes floating-point data from the indicated PfmFile. Returns true on
262 * success, false on failure.
263 */
264 bool PNMFileTypePfm::Writer::
265 write_pfm(const PfmFile &pfm) {
266 nassertr(pfm.is_valid(), false);
267
268 switch (pfm.get_num_channels()) {
269 case 1:
270 (*_file) << "Pf\n";
271 break;
272
273 case 2:
274 (*_file) << "pf2c\n";
275 break;
276
277 case 3:
278 (*_file) << "PF\n";
279 break;
280
281 case 4:
282 (*_file) << "pf4c\n";
283 break;
284
285 default:
286 nassert_raise("unexpected channel count");
287 return false;
288 }
289 (*_file) << pfm.get_x_size() << " " << pfm.get_y_size() << "\n";
290
291 PN_float32 scale = cabs(pfm.get_scale());
292 if (scale == 0.0f) {
293 scale = 1.0f;
294 }
295 #ifndef WORDS_BIGENDIAN
296 // Little-endian computers must write a negative scale to indicate the
297 // little-endian nature of the output.
298 scale = -scale;
299 #endif
300 (*_file) << scale << "\n";
301
302 int size = pfm.get_x_size() * pfm.get_y_size() * pfm.get_num_channels();
303 const pvector<PN_float32> &table = pfm.get_table();
304 (*_file).write((const char *)&table[0], sizeof(PN_float32) * size);
305
306 if ((*_file).fail()) {
307 return false;
308 }
309 nassertr(sizeof(PN_float32) == 4, false);
310 return true;
311 }
312
313 /**
314 * Registers the current object as something that can be read from a Bam file.
315 */
316 void PNMFileTypePfm::
317 register_with_read_factory() {
318 BamReader::get_factory()->
319 register_factory(get_class_type(), make_PNMFileTypePfm);
320 }
321
322 /**
323 * This method is called by the BamReader when an object of this type is
324 * encountered in a Bam file; it should allocate and return a new object with
325 * all the data read.
326 *
327 * In the case of the PNMFileType objects, since these objects are all shared,
328 * we just pull the object from the registry.
329 */
330 TypedWritable *PNMFileTypePfm::
331 make_PNMFileTypePfm(const FactoryParams &params) {
332 return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type());
333 }
bamReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamReader::get_factory
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
FactoryParams
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
PNMFileTypePfm::Reader
Definition: pnmFileTypePfm.h:46
PNMFileTypePfm::Reader::is_floating_point
virtual bool is_floating_point()
Returns true if this PNMFileType represents a floating-point image type, false if it is a normal,...
Definition: pnmFileTypePfm.cxx:169
PNMFileTypePfm::Reader::read_pfm
virtual bool read_pfm(PfmFile &pfm)
Reads floating-point data directly into the indicated PfmFile.
Definition: pnmFileTypePfm.cxx:178
PNMFileTypePfm::Writer
Definition: pnmFileTypePfm.h:57
PNMFileTypePfm::Writer::supports_integer
virtual bool supports_integer()
Returns true if this PNMFileType can accept an integer image type, false if it can only accept a floa...
Definition: pnmFileTypePfm.cxx:256
PNMFileTypePfm::Writer::supports_floating_point
virtual bool supports_floating_point()
Returns true if this PNMFileType can accept a floating-point image type, false if it can only accept ...
Definition: pnmFileTypePfm.cxx:246
PNMFileTypePfm::Writer::write_pfm
virtual bool write_pfm(const PfmFile &pfm)
Writes floating-point data from the indicated PfmFile.
Definition: pnmFileTypePfm.cxx:265
PNMFileTypePfm::get_suggested_extension
virtual std::string get_suggested_extension() const
Returns a suitable filename extension (without a leading dot) to suggest for files of this type,...
Definition: pnmFileTypePfm.cxx:65
PNMFileTypePfm::make_reader
virtual PNMReader * make_reader(std::istream *file, bool owns_file=true, const std::string &magic_number=std::string())
Allocates and returns a new PNMReader suitable for reading from this file type, if possible.
Definition: pnmFileTypePfm.cxx:97
PNMFileTypePfm::has_magic_number
virtual bool has_magic_number() const
Returns true if this particular file type uses a magic number to identify it, false otherwise.
Definition: pnmFileTypePfm.cxx:74
PNMFileTypePfm::register_with_read_factory
static void register_with_read_factory()
Registers the current object as something that can be read from a Bam file.
Definition: pnmFileTypePfm.cxx:317
PNMFileTypePfm::matches_magic_number
virtual bool matches_magic_number(const std::string &magic_number) const
Returns true if the indicated "magic number" byte stream (the initial few bytes read from the file) m...
Definition: pnmFileTypePfm.cxx:84
PNMFileTypePfm::get_name
virtual std::string get_name() const
Returns a few words describing the file type.
Definition: pnmFileTypePfm.cxx:38
PNMFileTypePfm::make_writer
virtual PNMWriter * make_writer(std::ostream *file, bool owns_file=true)
Allocates and returns a new PNMWriter suitable for reading from this file type, if possible.
Definition: pnmFileTypePfm.cxx:107
PNMFileTypePfm::get_num_extensions
virtual int get_num_extensions() const
Returns the number of different possible filename extensions associated with this particular file typ...
Definition: pnmFileTypePfm.cxx:47
PNMFileTypeRegistry::get_type_by_handle
PNMFileType * get_type_by_handle(TypeHandle handle) const
Returns the PNMFileType instance stored in the registry for the given TypeHandle, e....
Definition: pnmFileTypeRegistry.cxx:233
PNMFileTypeRegistry::get_global_ptr
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
Definition: pnmFileTypeRegistry.cxx:277
PNMFileType
This is the base class of a family of classes that represent particular image file types that PNMImag...
Definition: pnmFileType.h:32
PNMFileType::get_extension
get_extension
Returns the nth possible filename extension associated with this particular file type,...
Definition: pnmFileType.h:44
PNMImageHeader::get_x_size
int get_x_size() const
Returns the number of pixels in the X direction.
Definition: pnmImageHeader.I:144
PNMImageHeader::get_num_channels
get_num_channels
Returns the number of channels in the image.
Definition: pnmImageHeader.h:60
PNMImageHeader::get_y_size
int get_y_size() const
Returns the number of pixels in the Y direction.
Definition: pnmImageHeader.I:153
PNMReader
This is an abstract base class that defines the interface for reading image files of various types.
Definition: pnmReader.h:27
PNMWriter
This is an abstract base class that defines the interface for writing image files of various types.
Definition: pnmWriter.h:27
PfmFile
Defines a pfm file, a 2-d table of floating-point numbers, either 3-component or 1-component,...
Definition: pfmFile.h:31
PfmFile::swap_table
void swap_table(vector_float &table)
This is a very low-level function that completely exchanges the PfmFile's internal table of floating-...
Definition: pfmFile.I:549
PfmFile::get_table
const vector_float & get_table() const
This is a very low-level function that returns a read-only reference to the internal table of floatin...
Definition: pfmFile.I:538
PfmFile::set_scale
set_scale
The "scale" is reported in the pfm header and is probably meaningless.
Definition: pfmFile.h:57
PfmFile::clear
void clear()
Eliminates all data in the file.
Definition: pfmFile.cxx:77
PfmFile::get_scale
get_scale
The "scale" is reported in the pfm header and is probably meaningless.
Definition: pfmFile.h:57
ReversedNumericData
NativeNumericData and ReversedNumericData work together to provide a sneaky interface for automatical...
Definition: reversedNumericData.h:42
ReversedNumericData::store_value
void store_value(void *dest, size_t length) const
Copies the data, with byte reversal if appropriate, into the indicated numeric variable,...
Definition: reversedNumericData.I:41
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
TypedWritable
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
pvector
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
config_pnmimage.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pfmFile.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pnmFileTypePfm.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pnmFileTypeRegistry.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.