Panda3D
Loading...
Searching...
No Matches
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
21using std::istream;
22using std::ostream;
23using std::string;
24
25TypeHandle PNMFileTypePfm::_type_handle;
26
27/**
28 *
29 */
30PNMFileTypePfm::
31PNMFileTypePfm() {
32}
33
34/**
35 * Returns a few words describing the file type.
36 */
38get_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 */
47get_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 */
56get_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 */
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 */
74has_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 */
84matches_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 */
97make_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 */
107make_writer(ostream *file, bool owns_file) {
108 return new Writer(this, file, owns_file);
109}
110
111
112/**
113 *
114 */
115PNMFileTypePfm::Reader::
116Reader(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 */
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 */
178read_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
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 */
234PNMFileTypePfm::Writer::
235Writer(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 */
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 */
257 return false;
258}
259
260/**
261 * Writes floating-point data from the indicated PfmFile. Returns true on
262 * success, false on failure.
263 */
265write_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 */
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 */
330TypedWritable *PNMFileTypePfm::
331make_PNMFileTypePfm(const FactoryParams &params) {
333}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition bamReader.I:177
An instance of this class is passed to the Factory when requesting it to do its business and construc...
virtual bool is_floating_point()
Returns true if this PNMFileType represents a floating-point image type, false if it is a normal,...
virtual bool read_pfm(PfmFile &pfm)
Reads floating-point data directly into the indicated PfmFile.
virtual bool supports_integer()
Returns true if this PNMFileType can accept an integer image type, false if it can only accept a floa...
virtual bool supports_floating_point()
Returns true if this PNMFileType can accept a floating-point image type, false if it can only accept ...
virtual bool write_pfm(const PfmFile &pfm)
Writes floating-point data from the indicated PfmFile.
virtual std::string get_suggested_extension() const
Returns a suitable filename extension (without a leading dot) to suggest for files of this type,...
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.
virtual bool has_magic_number() const
Returns true if this particular file type uses a magic number to identify it, false otherwise.
static void register_with_read_factory()
Registers the current object as something that can be read from a Bam file.
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...
virtual std::string get_name() const
Returns a few words describing the file type.
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.
virtual int get_num_extensions() const
Returns the number of different possible filename extensions associated with this particular file typ...
PNMFileType * get_type_by_handle(TypeHandle handle) const
Returns the PNMFileType instance stored in the registry for the given TypeHandle, e....
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
This is the base class of a family of classes that represent particular image file types that PNMImag...
Definition pnmFileType.h:32
get_extension
Returns the nth possible filename extension associated with this particular file type,...
Definition pnmFileType.h:44
int get_x_size() const
Returns the number of pixels in the X direction.
get_num_channels
Returns the number of channels in the image.
int get_y_size() const
Returns the number of pixels in the Y direction.
This is an abstract base class that defines the interface for reading image files of various types.
Definition pnmReader.h:27
This is an abstract base class that defines the interface for writing image files of various types.
Definition pnmWriter.h:27
Defines a pfm file, a 2-d table of floating-point numbers, either 3-component or 1-component,...
Definition pfmFile.h:31
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
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
set_scale
The "scale" is reported in the pfm header and is probably meaningless.
Definition pfmFile.h:57
void clear()
Eliminates all data in the file.
Definition pfmFile.cxx:77
get_scale
The "scale" is reported in the pfm header and is probably meaningless.
Definition pfmFile.h:57
NativeNumericData and ReversedNumericData work together to provide a sneaky interface for automatical...
void store_value(void *dest, size_t length) const
Copies the data, with byte reversal if appropriate, into the indicated numeric variable,...
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
Base class for objects that can be written to and read from Bam files.
This is our own Panda specialization on the default STL vector.
Definition pvector.h:42
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.