PfmFile::set_no_data_nan() and related methods

This commit is contained in:
David Rose 2013-05-03 18:05:05 +00:00
parent 1885ccdb97
commit a38de91fbd
5 changed files with 250 additions and 21 deletions

View File

@ -59,13 +59,13 @@ has_point(int x, int y) const {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: PfmFile::get_component // Function: PfmFile::get_channel
// Access: Published // 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. // indicated point.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE PN_float32 PfmFile:: 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 && nassertr(x >= 0 && x < _x_size &&
y >= 0 && y < _y_size && y >= 0 && y < _y_size &&
c >= 0 && c < _num_channels, 0.0f); 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 // 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. // indicated point.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void PfmFile:: 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 && nassertv(x >= 0 && x < _x_size &&
y >= 0 && y < _y_size && y >= 0 && y < _y_size &&
c >= 0 && c < _num_channels); 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, // Description: Sets the no_data_chan4 flag. When this flag is true,
// and the pfm file has 4 channels, then a negative // and the pfm file has 4 channels, then a negative
// value in the fourth channel indicates no data. When // value in the fourth channel indicates no data. When
// it is false, a zero or positive value in the fourth // it is false, all points are valid.
// channel indicates valid data.
// //
// This is a special case of set_no_data_value(). // This is a special case of set_no_data_value().
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -479,7 +478,7 @@ INLINE void PfmFile::
set_no_data_chan4(bool chan4) { set_no_data_chan4(bool chan4) {
if (chan4 && _num_channels == 4) { if (chan4 && _num_channels == 4) {
_has_no_data_value = true; _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; _has_point = has_point_chan4;
} else { } else {
clear_no_data_value(); clear_no_data_value();

View File

@ -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 // Function: PfmFile::calc_average_point
// Access: Published // Access: Published
@ -792,6 +881,48 @@ is_column_empty(int x, int y_begin, int y_end) const {
return true; 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 // Function: PfmFile::set_no_data_value
// Access: Published // Access: Published
@ -806,6 +937,9 @@ set_no_data_value(const LPoint4f &no_data_value) {
case 1: case 1:
_has_point = has_point_1; _has_point = has_point_1;
break; break;
case 2:
_has_point = has_point_2;
break;
case 3: case 3:
_has_point = has_point_3; _has_point = has_point_3;
break; break;
@ -838,6 +972,9 @@ resize(int new_x_size, int new_y_size) {
PfmFile result; PfmFile result;
result.clear(new_x_size, new_y_size, _num_channels); result.clear(new_x_size, new_y_size, _num_channels);
if (_has_no_data_value) {
result.fill(_no_data_value);
}
if (pfm_resize_gaussian) { if (pfm_resize_gaussian) {
result.gaussian_filter_from(pfm_resize_radius, *this); 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 yi = 0; yi < _y_size; ++yi) {
for (int xi = 0; xi < _x_size; ++xi) { 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; 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 // Function: PfmFile::has_point_3
// Access: Private, Static // Access: Private, Static
@ -2055,3 +2207,67 @@ has_point_chan4(const PfmFile *self, int x, int y) {
} }
return false; 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;
}

View File

@ -57,8 +57,8 @@ PUBLISHED:
INLINE void set_scale(PN_float32 scale); INLINE void set_scale(PN_float32 scale);
INLINE bool has_point(int x, int y) const; INLINE bool has_point(int x, int y) const;
INLINE PN_float32 get_component(int x, int y, int c) const; INLINE PN_float32 get_channel(int x, int y, int c) const;
INLINE void set_component(int x, int y, int c, PN_float32 value); INLINE void set_channel(int x, int y, int c, PN_float32 value);
INLINE PN_float32 get_point1(int x, int y) const; INLINE PN_float32 get_point1(int x, int y) const;
INLINE void set_point1(int x, int y, PN_float32 point); INLINE void set_point1(int x, int y, PN_float32 point);
INLINE const LPoint2f &get_point2(int x, int y) const; 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 LPoint2f &value);
INLINE void fill(const LPoint3f &value); INLINE void fill(const LPoint3f &value);
void fill(const LPoint4f &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_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; 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_zero_special(bool zero_special);
INLINE void set_no_data_chan4(bool chan4); 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); void set_no_data_value(const LPoint4f &no_data_value);
INLINE void set_no_data_value(const LPoint4d &no_data_value); INLINE void set_no_data_value(const LPoint4d &no_data_value);
INLINE void clear_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_noop(const PfmFile *file, int x, int y);
static bool has_point_1(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_3(const PfmFile *file, int x, int y);
static bool has_point_4(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_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: private:
typedef vector_float Table; typedef vector_float Table;

View File

@ -94,9 +94,11 @@ FUNCTION_NAME(IMAGETYPE &dest, const IMAGETYPE &source,
filter, filter_width); filter, filter_width);
for (b = 0; b < dest.BSIZE(); b++) { for (b = 0; b < dest.BSIZE(); b++) {
if (temp_dest_weight[b] != 0) {
dest.SETVAL(a, b, channel, (double)temp_dest[b]/(double)source_max); dest.SETVAL(a, b, channel, (double)temp_dest[b]/(double)source_max);
} }
} }
}
PANDA_FREE_ARRAY(temp_dest); PANDA_FREE_ARRAY(temp_dest);
PANDA_FREE_ARRAY(temp_dest_weight); PANDA_FREE_ARRAY(temp_dest_weight);

View File

@ -555,8 +555,8 @@ gaussian_filter_from(double width, const PNMImage &copy) {
#define IMAGETYPE PfmFile #define IMAGETYPE PfmFile
#define ASIZE get_x_size #define ASIZE get_x_size
#define BSIZE get_y_size #define BSIZE get_y_size
#define GETVAL(a, b, channel) get_component(a, b, channel) #define GETVAL(a, b, channel) get_channel(a, b, channel)
#define SETVAL(a, b, channel, v) set_component(a, b, channel, v) #define SETVAL(a, b, channel, v) set_channel(a, b, channel, v)
#include "pnm-image-filter-core.cxx" #include "pnm-image-filter-core.cxx"
#undef SETVAL #undef SETVAL
#undef GETVAL #undef GETVAL
@ -569,8 +569,8 @@ gaussian_filter_from(double width, const PNMImage &copy) {
#define IMAGETYPE PfmFile #define IMAGETYPE PfmFile
#define ASIZE get_y_size #define ASIZE get_y_size
#define BSIZE get_x_size #define BSIZE get_x_size
#define GETVAL(a, b, channel) get_component(b, a, channel) #define GETVAL(a, b, channel) get_channel(b, a, channel)
#define SETVAL(a, b, channel, v) set_component(b, a, channel, v) #define SETVAL(a, b, channel, v) set_channel(b, a, channel, v)
#include "pnm-image-filter-core.cxx" #include "pnm-image-filter-core.cxx"
#undef SETVAL #undef SETVAL
#undef GETVAL #undef GETVAL
@ -585,8 +585,8 @@ gaussian_filter_from(double width, const PNMImage &copy) {
#define ASIZE get_x_size #define ASIZE get_x_size
#define BSIZE get_y_size #define BSIZE get_y_size
#define HASVAL(a, b) has_point(a, b) #define HASVAL(a, b) has_point(a, b)
#define GETVAL(a, b, channel) get_component(a, b, channel) #define GETVAL(a, b, channel) get_channel(a, b, channel)
#define SETVAL(a, b, channel, v) set_component(a, b, channel, v) #define SETVAL(a, b, channel, v) set_channel(a, b, channel, v)
#include "pnm-image-filter-sparse-core.cxx" #include "pnm-image-filter-sparse-core.cxx"
#undef SETVAL #undef SETVAL
#undef GETVAL #undef GETVAL
@ -601,8 +601,8 @@ gaussian_filter_from(double width, const PNMImage &copy) {
#define ASIZE get_y_size #define ASIZE get_y_size
#define BSIZE get_x_size #define BSIZE get_x_size
#define HASVAL(a, b) has_point(b, a) #define HASVAL(a, b) has_point(b, a)
#define GETVAL(a, b, channel) get_component(b, a, channel) #define GETVAL(a, b, channel) get_channel(b, a, channel)
#define SETVAL(a, b, channel, v) set_component(b, a, channel, v) #define SETVAL(a, b, channel, v) set_channel(b, a, channel, v)
#include "pnm-image-filter-sparse-core.cxx" #include "pnm-image-filter-sparse-core.cxx"
#undef SETVAL #undef SETVAL
#undef GETVAL #undef GETVAL