mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -04:00
support for 4-channel pfm files
This commit is contained in:
parent
bd6100bcab
commit
8cc85e4024
@ -20,7 +20,7 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PfmFile::
|
||||
is_valid() const {
|
||||
return _num_channels != 0 && (_x_size * _y_size == (int)_table.size());
|
||||
return _num_channels != 0 && (_x_size * _y_size * _num_channels == (int)_table.size());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -49,7 +49,7 @@ get_y_size() const {
|
||||
// Description: The "scale" is reported in the pfm header and is
|
||||
// probably meaningless.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_stdfloat PfmFile::
|
||||
INLINE PN_float32 PfmFile::
|
||||
get_scale() const {
|
||||
return _scale;
|
||||
}
|
||||
@ -79,11 +79,7 @@ get_num_channels() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PfmFile::
|
||||
has_point(int x, int y) const {
|
||||
if ((x >= 0 && x < _x_size) &&
|
||||
(y >= 0 && y < _y_size)) {
|
||||
return (!_has_no_data_value || _table[y * _x_size + x] != _no_data_value);
|
||||
}
|
||||
return false;
|
||||
return _has_point(this, x, y);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -93,11 +89,11 @@ has_point(int x, int y) const {
|
||||
// point. In a 1-channel image, the channel value is in
|
||||
// the x component.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LPoint3 &PfmFile::
|
||||
INLINE const LPoint3f &PfmFile::
|
||||
get_point(int x, int y) const {
|
||||
nassertr(x >= 0 && x < _x_size, LPoint3::zero());
|
||||
nassertr(y >= 0 && y < _y_size, LPoint3::zero());
|
||||
return _table[y * _x_size + x];
|
||||
nassertr(x >= 0 && x < _x_size, LPoint3f::zero());
|
||||
nassertr(y >= 0 && y < _y_size, LPoint3f::zero());
|
||||
return *(LPoint3f *)&_table[(y * _x_size + x) * _num_channels];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -108,11 +104,20 @@ get_point(int x, int y) const {
|
||||
// the x component.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PfmFile::
|
||||
set_point(int x, int y, const LVecBase3 &point) {
|
||||
set_point(int x, int y, const LVecBase3f &point) {
|
||||
nassertv(!point.is_nan());
|
||||
nassertv(x >= 0 && x < _x_size);
|
||||
nassertv(y >= 0 && y < _y_size);
|
||||
_table[y * _x_size + x] = point;
|
||||
switch (_num_channels) {
|
||||
case 1:
|
||||
_table[(y * _x_size + x)] = point[0];
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case 4:
|
||||
*(LPoint3f *)&_table[(y * _x_size + x) * _num_channels] = point;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -121,15 +126,73 @@ set_point(int x, int y, const LVecBase3 &point) {
|
||||
// Description: Returns a modifiable 3-component point value at the
|
||||
// indicated point.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE LPoint3 &PfmFile::
|
||||
INLINE LPoint3f &PfmFile::
|
||||
modify_point(int x, int y) {
|
||||
#ifndef NDEBUG
|
||||
static LPoint3 dummy_value = LPoint3::zero();
|
||||
static LPoint3f dummy_value = LPoint3f::zero();
|
||||
nassertr(x >= 0 && x < _x_size, dummy_value);
|
||||
nassertr(y >= 0 && y < _y_size, dummy_value);
|
||||
#endif
|
||||
|
||||
return _table[y * _x_size + x];
|
||||
return *(LPoint3f *)&_table[(y * _x_size + x) * _num_channels];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmFile::get_point4
|
||||
// Access: Published
|
||||
// Description: Returns the 4-component point value at the indicated
|
||||
// point. In a 1-channel image, the channel value is in
|
||||
// the x component.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LPoint4f &PfmFile::
|
||||
get_point4(int x, int y) const {
|
||||
nassertr(x >= 0 && x < _x_size, LPoint4f::zero());
|
||||
nassertr(y >= 0 && y < _y_size, LPoint4f::zero());
|
||||
return *(LPoint4f *)&_table[(y * _x_size + x) * _num_channels];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmFile::set_point4
|
||||
// Access: Published
|
||||
// Description: Replaces the 4-component point value at the indicated
|
||||
// point. In a 1-channel image, the channel value is in
|
||||
// the x component.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PfmFile::
|
||||
set_point4(int x, int y, const LVecBase4f &point) {
|
||||
nassertv(!point.is_nan());
|
||||
nassertv(x >= 0 && x < _x_size);
|
||||
nassertv(y >= 0 && y < _y_size);
|
||||
switch (_num_channels) {
|
||||
case 1:
|
||||
_table[(y * _x_size + x)] = point[0];
|
||||
break;
|
||||
|
||||
case 3:
|
||||
(*(LPoint3f *)&_table[(y * _x_size + x) * _num_channels]).set(point[0], point[1], point[2]);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
*(LPoint4f *)&_table[(y * _x_size + x) * _num_channels] = point;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmFile::modify_point4
|
||||
// Access: Published
|
||||
// Description: Returns a modifiable 4-component point value at the
|
||||
// indicated point.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE LPoint4f &PfmFile::
|
||||
modify_point4(int x, int y) {
|
||||
#ifndef NDEBUG
|
||||
static LPoint4f dummy_value = LPoint4f::zero();
|
||||
nassertr(x >= 0 && x < _x_size, dummy_value);
|
||||
nassertr(y >= 0 && y < _y_size, dummy_value);
|
||||
#endif
|
||||
|
||||
return *(LPoint4f *)&_table[(y * _x_size + x) * _num_channels];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -161,22 +224,32 @@ calc_autocrop(LVecBase4 &range) const {
|
||||
INLINE void PfmFile::
|
||||
set_zero_special(bool zero_special) {
|
||||
if (zero_special) {
|
||||
set_no_data_value(LPoint3::zero());
|
||||
set_no_data_value(LPoint4f::zero());
|
||||
} else {
|
||||
clear_no_data_value();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmFile::set_no_data_value
|
||||
// Function: PfmFile::set_no_data_chan4
|
||||
// Access: Published
|
||||
// Description: Sets the special value that means "no data" when it
|
||||
// appears in the pfm file.
|
||||
// Description: Sets the no_data_chan4 flag. When this flag is true,
|
||||
// and the pfm file has 4 channels, then a negative
|
||||
// value in the fourth channel indicates no data. When
|
||||
// it is false, a zero or positive value in the fourth
|
||||
// channel indicates valid data.
|
||||
//
|
||||
// This is a special case of set_no_data_value().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PfmFile::
|
||||
set_no_data_value(const LPoint3 &no_data_value) {
|
||||
set_no_data_chan4(bool chan4) {
|
||||
if (chan4 && _num_channels == 4) {
|
||||
_has_no_data_value = true;
|
||||
_no_data_value = no_data_value;
|
||||
_no_data_value = LPoint4f::zero();
|
||||
_has_point = has_point_chan4;
|
||||
} else {
|
||||
clear_no_data_value();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -189,7 +262,8 @@ set_no_data_value(const LPoint3 &no_data_value) {
|
||||
INLINE void PfmFile::
|
||||
clear_no_data_value() {
|
||||
_has_no_data_value = false;
|
||||
_no_data_value = LPoint3::zero();
|
||||
_no_data_value = LPoint4f::zero();
|
||||
_has_point = has_point_noop;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -209,9 +283,9 @@ has_no_data_value() const {
|
||||
// Description: If has_no_data_value() returns true, this returns the
|
||||
// particular "no data" value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LPoint3 &PfmFile::
|
||||
INLINE const LPoint4f &PfmFile::
|
||||
get_no_data_value() const {
|
||||
nassertr(_has_no_data_value, LPoint3::zero());
|
||||
nassertr(_has_no_data_value, LPoint4f::zero());
|
||||
return _no_data_value;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,8 @@ class PNMImage;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PfmFile
|
||||
// Description : Defines a pfm file, a 2-d table of floating-point
|
||||
// numbers, either 3-component or 1-component.
|
||||
// numbers, either 3-component or 1-component, or with a
|
||||
// special extension, 4-component.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_GRUTIL PfmFile {
|
||||
PUBLISHED:
|
||||
@ -52,16 +53,19 @@ PUBLISHED:
|
||||
|
||||
INLINE int get_x_size() const;
|
||||
INLINE int get_y_size() const;
|
||||
INLINE PN_stdfloat get_scale() const;
|
||||
INLINE PN_float32 get_scale() const;
|
||||
INLINE int get_num_channels() const;
|
||||
|
||||
INLINE bool has_point(int x, int y) const;
|
||||
INLINE const LPoint3 &get_point(int x, int y) const;
|
||||
INLINE void set_point(int x, int y, const LVecBase3 &point);
|
||||
INLINE LPoint3 &modify_point(int x, int y);
|
||||
INLINE const LPoint3f &get_point(int x, int y) const;
|
||||
INLINE void set_point(int x, int y, const LVecBase3f &point);
|
||||
INLINE LPoint3f &modify_point(int x, int y);
|
||||
INLINE const LPoint4f &get_point4(int x, int y) const;
|
||||
INLINE void set_point4(int x, int y, const LVecBase4f &point);
|
||||
INLINE LPoint4f &modify_point4(int x, int y);
|
||||
|
||||
BLOCKING bool calc_average_point(LPoint3 &result, PN_stdfloat x, PN_stdfloat y, PN_stdfloat radius) const;
|
||||
BLOCKING bool calc_min_max(LVecBase3 &min_points, LVecBase3 &max_points) const;
|
||||
BLOCKING bool calc_average_point(LPoint3f &result, PN_float32 x, PN_float32 y, PN_float32 radius) const;
|
||||
BLOCKING bool calc_min_max(LVecBase3f &min_points, LVecBase3f &max_points) const;
|
||||
BLOCKING bool calc_autocrop(int &x_begin, int &x_end, int &y_begin, int &y_end) const;
|
||||
BLOCKING INLINE bool calc_autocrop(LVecBase4 &range) const;
|
||||
|
||||
@ -69,10 +73,11 @@ PUBLISHED:
|
||||
bool is_column_empty(int x, int y_begin, int y_end) const;
|
||||
|
||||
INLINE void set_zero_special(bool zero_special);
|
||||
INLINE void set_no_data_value(const LPoint3 &no_data_value);
|
||||
INLINE void set_no_data_chan4(bool chan4);
|
||||
void set_no_data_value(const LPoint4f &no_data_value);
|
||||
INLINE void clear_no_data_value();
|
||||
INLINE bool has_no_data_value() const;
|
||||
INLINE const LPoint3 &get_no_data_value() const;
|
||||
INLINE const LPoint4f &get_no_data_value() const;
|
||||
|
||||
BLOCKING void resize(int new_x_size, int new_y_size);
|
||||
BLOCKING void reverse_rows();
|
||||
@ -82,10 +87,10 @@ PUBLISHED:
|
||||
BLOCKING void merge(const PfmFile &other);
|
||||
BLOCKING void apply_crop(int x_begin, int x_end, int y_begin, int y_end);
|
||||
|
||||
BLOCKING PT(BoundingHexahedron) compute_planar_bounds(PN_stdfloat point_dist, PN_stdfloat sample_radius) const;
|
||||
BLOCKING PT(BoundingHexahedron) compute_planar_bounds(const LPoint2 ¢er, PN_stdfloat point_dist, PN_stdfloat sample_radius, bool points_only) const;
|
||||
void compute_sample_point(LPoint3 &result,
|
||||
PN_stdfloat x, PN_stdfloat y, PN_stdfloat sample_radius) const;
|
||||
BLOCKING PT(BoundingHexahedron) compute_planar_bounds(PN_float32 point_dist, PN_float32 sample_radius) const;
|
||||
BLOCKING PT(BoundingHexahedron) compute_planar_bounds(const LPoint2 ¢er, PN_float32 point_dist, PN_float32 sample_radius, bool points_only) const;
|
||||
void compute_sample_point(LPoint3f &result,
|
||||
PN_float32 x, PN_float32 y, PN_float32 sample_radius) const;
|
||||
|
||||
INLINE void set_vis_inverse(bool vis_inverse);
|
||||
INLINE bool get_vis_inverse() const;
|
||||
@ -107,37 +112,47 @@ PUBLISHED:
|
||||
private:
|
||||
void make_vis_mesh_geom(GeomNode *gnode, bool inverted) const;
|
||||
|
||||
void box_filter_region(LPoint3 &result,
|
||||
PN_stdfloat x0, PN_stdfloat y0, PN_stdfloat x1, PN_stdfloat y1) const;
|
||||
void box_filter_line(LPoint3 &result, PN_stdfloat &coverage,
|
||||
PN_stdfloat x0, int y, PN_stdfloat x1, PN_stdfloat y_contrib) const;
|
||||
void box_filter_point(LPoint3 &result, PN_stdfloat &coverage,
|
||||
int x, int y, PN_stdfloat x_contrib, PN_stdfloat y_contrib) const;
|
||||
void box_filter_region(LPoint4f &result,
|
||||
PN_float32 x0, PN_float32 y0, PN_float32 x1, PN_float32 y1) const;
|
||||
void box_filter_line(LPoint4f &result, PN_float32 &coverage,
|
||||
PN_float32 x0, int y, PN_float32 x1, PN_float32 y_contrib) const;
|
||||
void box_filter_point(LPoint4f &result, PN_float32 &coverage,
|
||||
int x, int y, PN_float32 x_contrib, PN_float32 y_contrib) const;
|
||||
|
||||
class MiniGridCell {
|
||||
public:
|
||||
MiniGridCell() : _ti(-1), _dist(-1) { }
|
||||
int _ti;
|
||||
MiniGridCell() : _sxi(-1), _syi(-1), _dist(-1) { }
|
||||
int _sxi, _syi;
|
||||
int _dist;
|
||||
};
|
||||
|
||||
void fill_mini_grid(MiniGridCell *mini_grid, int x_size, int y_size,
|
||||
int xi, int yi, int dist, int ti) const;
|
||||
int xi, int yi, int dist, int sxi, int syi) const;
|
||||
|
||||
static bool has_point_noop(const PfmFile *file, int x, int y);
|
||||
static bool has_point_1(const PfmFile *file, int x, int y);
|
||||
static bool has_point_3(const PfmFile *file, int x, int y);
|
||||
static bool has_point_4(const PfmFile *file, int x, int y);
|
||||
static bool has_point_chan4(const PfmFile *file, int x, int y);
|
||||
|
||||
private:
|
||||
typedef pvector<LPoint3> Table;
|
||||
typedef pvector<PN_float32> Table;
|
||||
Table _table;
|
||||
|
||||
int _x_size;
|
||||
int _y_size;
|
||||
PN_stdfloat _scale;
|
||||
PN_float32 _scale;
|
||||
int _num_channels;
|
||||
|
||||
bool _has_no_data_value;
|
||||
LPoint3 _no_data_value;
|
||||
LPoint4f _no_data_value;
|
||||
bool _vis_inverse;
|
||||
PT(InternalName) _flat_texcoord_name;
|
||||
bool _vis_2d;
|
||||
|
||||
typedef bool HasPointFunc(const PfmFile *file, int x, int y);
|
||||
HasPointFunc *_has_point;
|
||||
|
||||
};
|
||||
|
||||
#include "pfmFile.I"
|
||||
|
@ -95,8 +95,9 @@ has_magic_number() const {
|
||||
bool PNMFileTypePfm::
|
||||
matches_magic_number(const string &magic_number) const {
|
||||
return (magic_number.size() >= 2) &&
|
||||
magic_number[0] == 'P' &&
|
||||
(magic_number[1] == 'F' || magic_number[1] == 'f');
|
||||
(magic_number.substr(0, 2) == "PF" ||
|
||||
magic_number.substr(0, 2) == "Pf" ||
|
||||
magic_number.substr(0, 2) == "pf");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -164,8 +165,13 @@ read_data(xel *array, xelval *alpha) {
|
||||
|
||||
nassertr(_image.get_x_size() == get_x_size() &&
|
||||
_image.get_y_size() == get_y_size(), 0);
|
||||
memcpy(array, _image[0], get_x_size() * get_y_size() * sizeof(xel));
|
||||
nassertr(!has_alpha(), 0);
|
||||
|
||||
memcpy(array, _image.get_array(), get_x_size() * get_y_size() * sizeof(xel));
|
||||
|
||||
if (has_alpha()) {
|
||||
memcpy(alpha, _image.get_alpha_array(), get_x_size() * get_y_size() * sizeof(xelval));
|
||||
}
|
||||
|
||||
return get_y_size();
|
||||
}
|
||||
|
||||
@ -213,8 +219,10 @@ write_data(xel *array, xelval *alpha) {
|
||||
image.copy_header_from(*this);
|
||||
nassertr(image.get_x_size() == get_x_size() &&
|
||||
image.get_y_size() == get_y_size(), 0);
|
||||
memcpy(image[0], array, get_x_size() * get_y_size() * sizeof(xel));
|
||||
nassertr(!has_alpha(), 0);
|
||||
memcpy(image.get_array(), array, get_x_size() * get_y_size() * sizeof(xel));
|
||||
if (has_alpha()) {
|
||||
memcpy(image.get_alpha_array(), alpha, get_x_size() * get_y_size() * sizeof(xelval));
|
||||
}
|
||||
|
||||
PfmFile pfm;
|
||||
if (!pfm.load(image)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user