2
0
Эх сурвалжийг харах

PfmFile::set_no_data_nan() and related methods

David Rose 12 жил өмнө
parent
commit
a38de91fbd

+ 8 - 9
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
 //       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
-//               channel indicates valid data.
+//               it is false, all points are valid.
 //
 //
 //               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();

+ 217 - 1
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
 //     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;
+}

+ 14 - 2
panda/src/pnmimage/pfmFile.h

@@ -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 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 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;

+ 3 - 1
panda/src/pnmimage/pnm-image-filter-sparse-core.cxx

@@ -94,7 +94,9 @@ 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++) {
-      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);
+      }
     }
     }
   }
   }
 
 

+ 8 - 8
panda/src/pnmimage/pnm-image-filter.cxx

@@ -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 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"
 #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 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"
 #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 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"
 #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 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"
 #include "pnm-image-filter-sparse-core.cxx"
 #undef SETVAL
 #undef SETVAL
 #undef GETVAL
 #undef GETVAL