Browse Source

Add methods to efficiently access PfmFile data from Python

rdb 11 years ago
parent
commit
1b93b8fbb3

+ 2 - 0
makepanda/makepanda.py

@@ -3116,6 +3116,7 @@ if (not RUNTIME):
   TargetAdd('libp3pnmimage.in', opts=OPTS, input=IGATEFILES)
   TargetAdd('libp3pnmimage.in', opts=['IMOD:core', 'ILIB:libp3pnmimage', 'SRCDIR:panda/src/pnmimage'])
   TargetAdd('libp3pnmimage_igate.obj', input='libp3pnmimage.in', opts=["DEPENDENCYONLY"])
+  TargetAdd('p3pnmimage_pfmFile_ext.obj', opts=OPTS, input='pfmFile_ext.cxx')
 
 #
 # DIRECTORY: panda/src/nativenet/
@@ -3540,6 +3541,7 @@ if (not RUNTIME):
   TargetAdd('libpanda.dll', input='libp3dtool.dll')
 
   TargetAdd('libpanda.dll', input='p3putil_typedWritable_ext.obj')
+  TargetAdd('libpanda.dll', input='p3pnmimage_pfmFile_ext.obj')
   TargetAdd('libpanda.dll', input='p3gobj_geomVertexArrayData_ext.obj')
   TargetAdd('libpanda.dll', input='p3pgraph_nodePath_ext.obj')
   TargetAdd('libpanda.dll', input='p3pgraph_nodePathCollection_ext.obj')

+ 2 - 0
panda/src/pnmimage/Sources.pp

@@ -12,6 +12,7 @@
   #define SOURCES \
      config_pnmimage.h \
      pfmFile.I pfmFile.h \
+     pfmFile_ext.cxx pfmFile_ext.h \
      pnmbitio.h \
      pnmBrush.h pnmBrush.I \
      pnmFileType.h pnmFileTypeRegistry.h pnmImage.I  \
@@ -36,6 +37,7 @@
   #define INSTALL_HEADERS \
      config_pnmimage.h \
      pfmFile.I pfmFile.h \
+     pfmFile_ext.cxx pfmFile_ext.h \
      pnmBrush.h pnmBrush.I \
      pnmFileType.h pnmFileTypeRegistry.h pnmImage.I \
      pnmImage.h pnmImageHeader.I pnmImageHeader.h \

+ 4 - 1
panda/src/pnmimage/pfmFile.h

@@ -95,7 +95,7 @@ PUBLISHED:
   BLOCKING bool calc_autocrop(int &x_begin, int &x_end, int &y_begin, int &y_end) const;
   BLOCKING INLINE bool calc_autocrop(LVecBase4f &range) const;
   BLOCKING INLINE bool calc_autocrop(LVecBase4d &range) const;
- 
+
   bool is_row_empty(int y, int x_begin, int x_end) const;
   bool is_column_empty(int x, int y_begin, int y_end) const;
 
@@ -140,6 +140,9 @@ PUBLISHED:
 
   void output(ostream &out) const;
 
+  EXTENSION(PyObject *get_points() const);
+  EXTENSION(int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const);
+
 public:
   INLINE const vector_float &get_table() const;
   INLINE void swap_table(vector_float &table);

+ 132 - 0
panda/src/pnmimage/pfmFile_ext.cxx

@@ -0,0 +1,132 @@
+// Filename: pfmFile_ext.I
+// Created by:  rdb (26Feb14)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pfmFile_ext.h"
+
+#ifdef HAVE_PYTHON
+
+#ifndef CPPPARSER
+IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint2f;
+IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3f;
+IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint4f;
+#endif
+
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::get_points
+//       Access: Published
+//  Description: Returns a list of all of the points.
+////////////////////////////////////////////////////////////////////
+PyObject *Extension<PfmFile>::
+get_points() const {
+  int num_points = _this->get_x_size() * _this->get_y_size();
+  PyObject *list = PyList_New(num_points);
+  const vector_float &table = _this->get_table();
+
+  switch (_this->get_num_channels()) {
+  case 1:
+    for (int i = 0; i < num_points; ++i) {
+      PyList_SET_ITEM(list, i, PyFloat_FromDouble(table[i]));
+    }
+    break;
+
+  case 2:
+    for (int i = 0; i < num_points; ++i) {
+      LPoint2f *point = (LPoint2f *) &(table[i * 2]);
+      PyObject *item = DTool_CreatePyInstance((void *)point, Dtool_LPoint2f, false, true);
+      PyList_SET_ITEM(list, i, item);
+    }
+    break;
+
+  case 3:
+    for (int i = 0; i < num_points; ++i) {
+      LPoint3f *point = (LPoint3f *) &(table[i * 3]);
+      PyObject *item = DTool_CreatePyInstance((void *)point, Dtool_LPoint3f, false, true);
+      PyList_SET_ITEM(list, i, item);
+    }
+    break;
+
+  case 4:
+    for (int i = 0; i < num_points; ++i) {
+      LPoint4f *point = (LPoint4f *) &(table[i * 4]);
+      PyObject *item = DTool_CreatePyInstance((void *)point, Dtool_LPoint4f, false, true);
+      PyList_SET_ITEM(list, i, item);
+    }
+    break;
+
+  default:
+    Py_DECREF(list);
+    Py_INCREF(Py_None);
+    return Py_None;
+  }
+
+  return list;
+}
+
+#if PY_VERSION_HEX >= 0x02060000
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::__getbuffer__
+//       Access: Published
+//  Description: This is a very low-level function that returns a
+//               read-only multiview into the internal table of
+//               floating-point numbers.  Use this method at your own
+//               risk.
+////////////////////////////////////////////////////////////////////
+int Extension<PfmFile>::
+__getbuffer__(PyObject *self, Py_buffer *view, int flags) const {
+
+  if ((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) {
+      PyErr_SetString(PyExc_BufferError,
+                      "Object is not writable.");
+      return -1;
+  }
+
+  // Since we have absolutely no guarantees about the lifetime
+  // of this object or the continued validity of the data pointer,
+  // we should arguably make a copy of the data.  However, since
+  // the whole point of this method is to provide fast access to
+  // the underlying data, perhaps we can trust the user to handle
+  // the copy operation himself if he needs to.
+  const vector_float &table = _this->get_table();
+  int channels = _this->get_num_channels();
+  int num_pixels = _this->get_x_size() * _this->get_y_size();
+
+  if (self != NULL) {
+    Py_INCREF(self);
+  }
+  view->obj = self;
+  view->buf = (void *) &(table[0]);
+  view->len = 4 * table.size();
+  view->readonly = 1;
+  view->itemsize = 4;
+  view->format = NULL;
+  if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
+    view->format = (char *) "f";
+  }
+  view->ndim = 2;
+  view->shape = NULL;
+  if ((flags & PyBUF_ND) == PyBUF_ND) {
+    // If you're leaking and you know it, clap your hands!
+    view->shape = new Py_ssize_t[2];
+    view->shape[0] = num_pixels;
+    view->shape[1] = channels;
+  }
+  view->strides = NULL;
+  view->suboffsets = NULL;
+
+  return 0;
+}
+
+#endif  // PY_VERSION_HEX >= 0x02060000
+
+#endif  // HAVE_PYTHON

+ 44 - 0
panda/src/pnmimage/pfmFile_ext.h

@@ -0,0 +1,44 @@
+// Filename: pfmFile_ext.h
+// Created by:  rdb (26Feb14)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef PFMFILE_EXT_H
+#define PFMFILE_EXT_H
+
+#include "dtoolbase.h"
+
+#ifdef HAVE_PYTHON
+
+#include "extension.h"
+#include "pfmFile.h"
+#include "py_panda.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Extension<PfmFile>
+// Description : This class defines the extension methods for
+//               PfmFile, which are called instead of
+//               any C++ methods with the same prototype.
+////////////////////////////////////////////////////////////////////
+template<>
+class Extension<PfmFile> : public ExtensionBase<PfmFile> {
+public:
+  PyObject *get_points() const;
+
+#if PY_VERSION_HEX >= 0x02060000
+  int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const;
+#endif
+};
+
+#endif  // HAVE_PYTHON
+
+#endif  // PFMFILE_EXT_H