Add methods to efficiently access PfmFile data from Python

This commit is contained in:
rdb 2014-03-09 01:05:34 +00:00
parent ae4bddd7f7
commit 1b93b8fbb3
5 changed files with 184 additions and 1 deletions

View File

@ -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')

View File

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

View File

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

View File

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

View File

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