From a38de91fbde946af9682dc42b6d21ee20dbc869a Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 3 May 2013 18:05:05 +0000 Subject: [PATCH] PfmFile::set_no_data_nan() and related methods --- panda/src/pnmimage/pfmFile.I | 17 +- panda/src/pnmimage/pfmFile.cxx | 218 +++++++++++++++++- panda/src/pnmimage/pfmFile.h | 16 +- .../pnmimage/pnm-image-filter-sparse-core.cxx | 4 +- panda/src/pnmimage/pnm-image-filter.cxx | 16 +- 5 files changed, 250 insertions(+), 21 deletions(-) diff --git a/panda/src/pnmimage/pfmFile.I b/panda/src/pnmimage/pfmFile.I index 18a6f39a68..d53bd44523 100644 --- a/panda/src/pnmimage/pfmFile.I +++ b/panda/src/pnmimage/pfmFile.I @@ -59,13 +59,13 @@ has_point(int x, int y) const { } //////////////////////////////////////////////////////////////////// -// Function: PfmFile::get_component +// Function: PfmFile::get_channel // Access: Published -// Description: Returns the cth component of the point value at the +// Description: Returns the cth channel of the point value at the // indicated point. //////////////////////////////////////////////////////////////////// INLINE PN_float32 PfmFile:: -get_component(int x, int y, int c) const { +get_channel(int x, int y, int c) const { nassertr(x >= 0 && x < _x_size && y >= 0 && y < _y_size && c >= 0 && c < _num_channels, 0.0f); @@ -73,13 +73,13 @@ get_component(int x, int y, int c) const { } //////////////////////////////////////////////////////////////////// -// Function: PfmFile::set_component +// Function: PfmFile::set_channel // Access: Published -// Description: Replaces the cth component of the point value at the +// Description: Replaces the cth channel of the point value at the // indicated point. //////////////////////////////////////////////////////////////////// INLINE void PfmFile:: -set_component(int x, int y, int c, PN_float32 value) { +set_channel(int x, int y, int c, PN_float32 value) { nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size && c >= 0 && c < _num_channels); @@ -470,8 +470,7 @@ set_zero_special(bool zero_special) { // 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. +// it is false, all points are valid. // // This is a special case of set_no_data_value(). //////////////////////////////////////////////////////////////////// @@ -479,7 +478,7 @@ INLINE void PfmFile:: set_no_data_chan4(bool chan4) { if (chan4 && _num_channels == 4) { _has_no_data_value = true; - _no_data_value = LPoint4f::zero(); + _no_data_value.set(0.0, 0.0, 0.0, -1.0); _has_point = has_point_chan4; } else { clear_no_data_value(); diff --git a/panda/src/pnmimage/pfmFile.cxx b/panda/src/pnmimage/pfmFile.cxx index 9bb5cc0cc9..45587b1ff9 100644 --- a/panda/src/pnmimage/pfmFile.cxx +++ b/panda/src/pnmimage/pfmFile.cxx @@ -520,6 +520,95 @@ fill(const LPoint4f &value) { } } +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::fill_nan +// Access: Published +// Description: Fills the table with all NaN. +//////////////////////////////////////////////////////////////////// +void PfmFile:: +fill_nan() { + PN_float32 nan = make_nan((PN_float32)0.0); + LPoint4f nan4(nan, nan, nan, nan); + fill(nan4); +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::fill_no_data_value +// Access: Published +// Description: Fills the table with the current no_data value, so +// that the table is empty. +//////////////////////////////////////////////////////////////////// +void PfmFile:: +fill_no_data_value() { + fill(_no_data_value); +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::fill_channel +// Access: Published +// Description: Fills the indicated channel with all of the same +// value, leaving the other channels unchanged. +//////////////////////////////////////////////////////////////////// +void PfmFile:: +fill_channel(int channel, PN_float32 value) { + nassertv(channel >= 0 && channel < _num_channels); + + for (int yi = 0; yi < _y_size; ++yi) { + for (int xi = 0; xi < _x_size; ++xi) { + _table[(yi * _x_size + xi) * _num_channels + channel] = value; + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::fill_channel_nan +// Access: Published +// Description: Fills the indicated channel with NaN, leaving the +// other channels unchanged. +//////////////////////////////////////////////////////////////////// +void PfmFile:: +fill_channel_nan(int channel) { + PN_float32 nan = make_nan((PN_float32)0.0); + fill_channel(channel, nan); +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::fill_channel_masked +// Access: Published +// Description: Fills the indicated channel with all of the same +// value, but only where the table already has a data +// point. Leaves empty points unchanged. +//////////////////////////////////////////////////////////////////// +void PfmFile:: +fill_channel_masked(int channel, PN_float32 value) { + nassertv(channel >= 0 && channel < _num_channels); + + if (!_has_no_data_value) { + fill_channel(channel, value); + } else { + for (int yi = 0; yi < _y_size; ++yi) { + for (int xi = 0; xi < _x_size; ++xi) { + if (has_point(xi, yi)) { + _table[(yi * _x_size + xi) * _num_channels + channel] = value; + } + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::fill_channel_masked_nan +// Access: Published +// Description: Fills the indicated channel with NaN, but only where +// the table already has a data point. Leaves empty +// points unchanged. +//////////////////////////////////////////////////////////////////// +void PfmFile:: +fill_channel_masked_nan(int channel) { + PN_float32 nan = make_nan((PN_float32)0.0); + fill_channel_masked(channel, nan); +} + //////////////////////////////////////////////////////////////////// // Function: PfmFile::calc_average_point // Access: Published @@ -792,6 +881,48 @@ is_column_empty(int x, int y_begin, int y_end) const { return true; } +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::set_no_data_nan +// Access: Published +// Description: Sets the no_data_nan flag. When num_channels is +// nonzero, then a NaN value in any of the first +// num_channels channels indicates no data for that +// point. If num_channels is zero, then all points are +// valid. +// +// This is a special case of set_no_data_value(). +//////////////////////////////////////////////////////////////////// +void PfmFile:: +set_no_data_nan(int num_channels) { + if (num_channels > 0) { + num_channels = min(num_channels, _num_channels); + _has_no_data_value = true; + _no_data_value = LPoint4f::zero(); + PN_float32 nan = make_nan((PN_float32)0.0); + for (int i = 0; i < num_channels; ++i) { + _no_data_value[i] = nan; + } + switch (num_channels) { + case 1: + _has_point = has_point_nan_1; + break; + case 2: + _has_point = has_point_nan_2; + break; + case 3: + _has_point = has_point_nan_3; + break; + case 4: + _has_point = has_point_nan_4; + break; + default: + nassertv(false); + } + } else { + clear_no_data_value(); + } +} + //////////////////////////////////////////////////////////////////// // Function: PfmFile::set_no_data_value // Access: Published @@ -806,6 +937,9 @@ set_no_data_value(const LPoint4f &no_data_value) { case 1: _has_point = has_point_1; break; + case 2: + _has_point = has_point_2; + break; case 3: _has_point = has_point_3; break; @@ -838,6 +972,9 @@ resize(int new_x_size, int new_y_size) { PfmFile result; result.clear(new_x_size, new_y_size, _num_channels); + if (_has_no_data_value) { + result.fill(_no_data_value); + } if (pfm_resize_gaussian) { result.gaussian_filter_from(pfm_resize_radius, *this); @@ -1284,7 +1421,7 @@ copy_channel(int to_channel, const PfmFile &other, int from_channel) { for (int yi = 0; yi < _y_size; ++yi) { for (int xi = 0; xi < _x_size; ++xi) { - set_component(xi, yi, to_channel, other.get_component(xi, yi, from_channel)); + set_channel(xi, yi, to_channel, other.get_channel(xi, yi, from_channel)); } } } @@ -2010,6 +2147,21 @@ has_point_1(const PfmFile *self, int x, int y) { return false; } +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_point_2 +// Access: Private, Static +// Description: The implementation of has_point() for 2-component +// files with a no_data_value. +//////////////////////////////////////////////////////////////////// +bool PfmFile:: +has_point_2(const PfmFile *self, int x, int y) { + if ((x >= 0 && x < self->_x_size) && + (y >= 0 && y < self->_y_size)) { + return *(LPoint2f *)&self->_table[(y * self->_x_size + x) * 2] != *(LPoint2f *)&self->_no_data_value; + } + return false; +} + //////////////////////////////////////////////////////////////////// // Function: PfmFile::has_point_3 // Access: Private, Static @@ -2055,3 +2207,67 @@ has_point_chan4(const PfmFile *self, int x, int y) { } return false; } + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_point_nan_1 +// Access: Private, Static +// Description: The implementation of has_point() for +// files with set_no_data_nan() in effect. This means +// that the data is valid iff no components involve NaN. +//////////////////////////////////////////////////////////////////// +bool PfmFile:: +has_point_nan_1(const PfmFile *self, int x, int y) { + if ((x >= 0 && x < self->_x_size) && + (y >= 0 && y < self->_y_size)) { + return !cnan(self->_table[(y * self->_x_size + x) * self->_num_channels]); + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_point_nan_2 +// Access: Private, Static +// Description: The implementation of has_point() for +// files with set_no_data_nan() in effect. This means +// that the data is valid iff no components involve NaN. +//////////////////////////////////////////////////////////////////// +bool PfmFile:: +has_point_nan_2(const PfmFile *self, int x, int y) { + if ((x >= 0 && x < self->_x_size) && + (y >= 0 && y < self->_y_size)) { + return !((LVecBase2f *)&self->_table[(y * self->_x_size + x) * self->_num_channels])->is_nan(); + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_point_nan_3 +// Access: Private, Static +// Description: The implementation of has_point() for +// files with set_no_data_nan() in effect. This means +// that the data is valid iff no components involve NaN. +//////////////////////////////////////////////////////////////////// +bool PfmFile:: +has_point_nan_3(const PfmFile *self, int x, int y) { + if ((x >= 0 && x < self->_x_size) && + (y >= 0 && y < self->_y_size)) { + return !((LVecBase3f *)&self->_table[(y * self->_x_size + x) * self->_num_channels])->is_nan(); + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_point_nan_4 +// Access: Private, Static +// Description: The implementation of has_point() for +// files with set_no_data_nan() in effect. This means +// that the data is valid iff no components involve NaN. +//////////////////////////////////////////////////////////////////// +bool PfmFile:: +has_point_nan_4(const PfmFile *self, int x, int y) { + if ((x >= 0 && x < self->_x_size) && + (y >= 0 && y < self->_y_size)) { + return !((LVecBase4f *)&self->_table[(y * self->_x_size + x) * self->_num_channels])->is_nan(); + } + return false; +} diff --git a/panda/src/pnmimage/pfmFile.h b/panda/src/pnmimage/pfmFile.h index 7bc4a442ab..1559fe4dec 100644 --- a/panda/src/pnmimage/pfmFile.h +++ b/panda/src/pnmimage/pfmFile.h @@ -57,8 +57,8 @@ PUBLISHED: INLINE void set_scale(PN_float32 scale); INLINE bool has_point(int x, int y) const; - INLINE PN_float32 get_component(int x, int y, int c) const; - INLINE void set_component(int x, int y, int c, PN_float32 value); + INLINE PN_float32 get_channel(int x, int y, int c) const; + INLINE void set_channel(int x, int y, int c, PN_float32 value); INLINE PN_float32 get_point1(int x, int y) const; INLINE void set_point1(int x, int y, PN_float32 point); INLINE const LPoint2f &get_point2(int x, int y) const; @@ -82,6 +82,12 @@ PUBLISHED: INLINE void fill(const LPoint2f &value); INLINE void fill(const LPoint3f &value); void fill(const LPoint4f &value); + void fill_nan(); + void fill_no_data_value(); + void fill_channel(int channel, PN_float32 value); + void fill_channel_nan(int channel); + void fill_channel_masked(int channel, PN_float32 value); + void fill_channel_masked_nan(int channel); BLOCKING bool calc_average_point(LPoint3f &result, PN_float32 x, PN_float32 y, PN_float32 radius) const; BLOCKING bool calc_bilinear_point(LPoint3f &result, PN_float32 x, PN_float32 y) const; @@ -95,6 +101,7 @@ PUBLISHED: INLINE void set_zero_special(bool zero_special); INLINE void set_no_data_chan4(bool chan4); + void set_no_data_nan(int num_channels); void set_no_data_value(const LPoint4f &no_data_value); INLINE void set_no_data_value(const LPoint4d &no_data_value); INLINE void clear_no_data_value(); @@ -169,9 +176,14 @@ private: 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_2(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); + static bool has_point_nan_1(const PfmFile *file, int x, int y); + static bool has_point_nan_2(const PfmFile *file, int x, int y); + static bool has_point_nan_3(const PfmFile *file, int x, int y); + static bool has_point_nan_4(const PfmFile *file, int x, int y); private: typedef vector_float Table; diff --git a/panda/src/pnmimage/pnm-image-filter-sparse-core.cxx b/panda/src/pnmimage/pnm-image-filter-sparse-core.cxx index bed23f3e2a..9201ca9ee7 100755 --- a/panda/src/pnmimage/pnm-image-filter-sparse-core.cxx +++ b/panda/src/pnmimage/pnm-image-filter-sparse-core.cxx @@ -94,7 +94,9 @@ FUNCTION_NAME(IMAGETYPE &dest, const IMAGETYPE &source, filter, filter_width); for (b = 0; b < dest.BSIZE(); b++) { - dest.SETVAL(a, b, channel, (double)temp_dest[b]/(double)source_max); + if (temp_dest_weight[b] != 0) { + dest.SETVAL(a, b, channel, (double)temp_dest[b]/(double)source_max); + } } } diff --git a/panda/src/pnmimage/pnm-image-filter.cxx b/panda/src/pnmimage/pnm-image-filter.cxx index 491e6fafc1..a4b8ad61ea 100644 --- a/panda/src/pnmimage/pnm-image-filter.cxx +++ b/panda/src/pnmimage/pnm-image-filter.cxx @@ -555,8 +555,8 @@ gaussian_filter_from(double width, const PNMImage ©) { #define IMAGETYPE PfmFile #define ASIZE get_x_size #define BSIZE get_y_size -#define GETVAL(a, b, channel) get_component(a, b, channel) -#define SETVAL(a, b, channel, v) set_component(a, b, channel, v) +#define GETVAL(a, b, channel) get_channel(a, b, channel) +#define SETVAL(a, b, channel, v) set_channel(a, b, channel, v) #include "pnm-image-filter-core.cxx" #undef SETVAL #undef GETVAL @@ -569,8 +569,8 @@ gaussian_filter_from(double width, const PNMImage ©) { #define IMAGETYPE PfmFile #define ASIZE get_y_size #define BSIZE get_x_size -#define GETVAL(a, b, channel) get_component(b, a, channel) -#define SETVAL(a, b, channel, v) set_component(b, a, channel, v) +#define GETVAL(a, b, channel) get_channel(b, a, channel) +#define SETVAL(a, b, channel, v) set_channel(b, a, channel, v) #include "pnm-image-filter-core.cxx" #undef SETVAL #undef GETVAL @@ -585,8 +585,8 @@ gaussian_filter_from(double width, const PNMImage ©) { #define ASIZE get_x_size #define BSIZE get_y_size #define HASVAL(a, b) has_point(a, b) -#define GETVAL(a, b, channel) get_component(a, b, channel) -#define SETVAL(a, b, channel, v) set_component(a, b, channel, v) +#define GETVAL(a, b, channel) get_channel(a, b, channel) +#define SETVAL(a, b, channel, v) set_channel(a, b, channel, v) #include "pnm-image-filter-sparse-core.cxx" #undef SETVAL #undef GETVAL @@ -601,8 +601,8 @@ gaussian_filter_from(double width, const PNMImage ©) { #define ASIZE get_y_size #define BSIZE get_x_size #define HASVAL(a, b) has_point(b, a) -#define GETVAL(a, b, channel) get_component(b, a, channel) -#define SETVAL(a, b, channel, v) set_component(b, a, channel, v) +#define GETVAL(a, b, channel) get_channel(b, a, channel) +#define SETVAL(a, b, channel, v) set_channel(b, a, channel, v) #include "pnm-image-filter-sparse-core.cxx" #undef SETVAL #undef GETVAL