|
|
@ -5,12 +5,35 @@ |
|
|
|
#pragma warning(push) |
|
|
|
#pragma warning(push) |
|
|
|
#pragma warning(disable:5033) // 'register' is no longer a supported storage class
|
|
|
|
#pragma warning(disable:5033) // 'register' is no longer a supported storage class
|
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// #define CVPY_DYNAMIC_INIT
|
|
|
|
|
|
|
|
// #define Py_DEBUG
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(CVPY_DYNAMIC_INIT) && !defined(Py_DEBUG) |
|
|
|
|
|
|
|
# define Py_LIMITED_API 0x03030000 |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#include <math.h> |
|
|
|
#include <math.h> |
|
|
|
#include <Python.h> |
|
|
|
#include <Python.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION < 3 |
|
|
|
|
|
|
|
#undef CVPY_DYNAMIC_INIT |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if defined(_MSC_VER) && (_MSC_VER > 1800) |
|
|
|
#if defined(_MSC_VER) && (_MSC_VER > 1800) |
|
|
|
#pragma warning(pop) |
|
|
|
#pragma warning(pop) |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define MODULESTR "cv2" |
|
|
|
|
|
|
|
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION |
|
|
|
|
|
|
|
#include <numpy/ndarrayobject.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "pyopencv_generated_include.h" |
|
|
|
|
|
|
|
#include "opencv2/core/types_c.h" |
|
|
|
|
|
|
|
#include "opencv2/opencv_modules.hpp" |
|
|
|
|
|
|
|
#include "pycompat.hpp" |
|
|
|
|
|
|
|
#include <map> |
|
|
|
|
|
|
|
|
|
|
|
template<typename T, class TEnable = void> // TEnable is used for SFINAE checks
|
|
|
|
template<typename T, class TEnable = void> // TEnable is used for SFINAE checks
|
|
|
|
struct PyOpenCV_Converter |
|
|
|
struct PyOpenCV_Converter |
|
|
|
{ |
|
|
|
{ |
|
|
@ -24,95 +47,6 @@ bool pyopencv_to(PyObject* obj, T& p, const char* name = "<unknown>") { return P |
|
|
|
template<typename T> static |
|
|
|
template<typename T> static |
|
|
|
PyObject* pyopencv_from(const T& src) { return PyOpenCV_Converter<T>::from(src); } |
|
|
|
PyObject* pyopencv_from(const T& src) { return PyOpenCV_Converter<T>::from(src); } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CV_PY_FN_WITH_KW_(fn, flags) (PyCFunction)(void*)(PyCFunctionWithKeywords)(fn), (flags) | METH_VARARGS | METH_KEYWORDS |
|
|
|
|
|
|
|
#define CV_PY_FN_NOARGS_(fn, flags) (PyCFunction)(fn), (flags) | METH_NOARGS |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CV_PY_FN_WITH_KW(fn) CV_PY_FN_WITH_KW_(fn, 0) |
|
|
|
|
|
|
|
#define CV_PY_FN_NOARGS(fn) CV_PY_FN_NOARGS_(fn, 0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define MODULESTR "cv2" |
|
|
|
|
|
|
|
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION |
|
|
|
|
|
|
|
#include <numpy/ndarrayobject.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3 |
|
|
|
|
|
|
|
# define CV_PYTHON_TYPE_HEAD_INIT() PyVarObject_HEAD_INIT(&PyType_Type, 0) |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
# define CV_PYTHON_TYPE_HEAD_INIT() PyObject_HEAD_INIT(&PyType_Type) 0, |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CV_PY_TO_CLASS(TYPE) \ |
|
|
|
|
|
|
|
template<> \
|
|
|
|
|
|
|
|
bool pyopencv_to(PyObject* dst, TYPE& src, const char* name) \
|
|
|
|
|
|
|
|
{ \
|
|
|
|
|
|
|
|
if (!dst || dst == Py_None) \
|
|
|
|
|
|
|
|
return true; \
|
|
|
|
|
|
|
|
Ptr<TYPE> ptr; \
|
|
|
|
|
|
|
|
\
|
|
|
|
|
|
|
|
if (!pyopencv_to(dst, ptr, name)) return false; \
|
|
|
|
|
|
|
|
src = *ptr; \
|
|
|
|
|
|
|
|
return true; \
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CV_PY_FROM_CLASS(TYPE) \ |
|
|
|
|
|
|
|
template<> \
|
|
|
|
|
|
|
|
PyObject* pyopencv_from(const TYPE& src) \
|
|
|
|
|
|
|
|
{ \
|
|
|
|
|
|
|
|
Ptr<TYPE> ptr(new TYPE()); \
|
|
|
|
|
|
|
|
\
|
|
|
|
|
|
|
|
*ptr = src; \
|
|
|
|
|
|
|
|
return pyopencv_from(ptr); \
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CV_PY_TO_CLASS_PTR(TYPE) \ |
|
|
|
|
|
|
|
template<> \
|
|
|
|
|
|
|
|
bool pyopencv_to(PyObject* dst, TYPE*& src, const char* name) \
|
|
|
|
|
|
|
|
{ \
|
|
|
|
|
|
|
|
if (!dst || dst == Py_None) \
|
|
|
|
|
|
|
|
return true; \
|
|
|
|
|
|
|
|
Ptr<TYPE> ptr; \
|
|
|
|
|
|
|
|
\
|
|
|
|
|
|
|
|
if (!pyopencv_to(dst, ptr, name)) return false; \
|
|
|
|
|
|
|
|
src = ptr; \
|
|
|
|
|
|
|
|
return true; \
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CV_PY_FROM_CLASS_PTR(TYPE) \ |
|
|
|
|
|
|
|
static PyObject* pyopencv_from(TYPE*& src) \
|
|
|
|
|
|
|
|
{ \
|
|
|
|
|
|
|
|
return pyopencv_from(Ptr<TYPE>(src)); \
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CV_PY_TO_ENUM(TYPE) \ |
|
|
|
|
|
|
|
template<> \
|
|
|
|
|
|
|
|
bool pyopencv_to(PyObject* dst, TYPE& src, const char* name) \
|
|
|
|
|
|
|
|
{ \
|
|
|
|
|
|
|
|
if (!dst || dst == Py_None) \
|
|
|
|
|
|
|
|
return true; \
|
|
|
|
|
|
|
|
int underlying = 0; \
|
|
|
|
|
|
|
|
\
|
|
|
|
|
|
|
|
if (!pyopencv_to(dst, underlying, name)) return false; \
|
|
|
|
|
|
|
|
src = static_cast<TYPE>(underlying); \
|
|
|
|
|
|
|
|
return true; \
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CV_PY_FROM_ENUM(TYPE) \ |
|
|
|
|
|
|
|
template<> \
|
|
|
|
|
|
|
|
PyObject* pyopencv_from(const TYPE& src) \
|
|
|
|
|
|
|
|
{ \
|
|
|
|
|
|
|
|
return pyopencv_from(static_cast<int>(src)); \
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "pyopencv_generated_include.h" |
|
|
|
|
|
|
|
#include "opencv2/core/types_c.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "opencv2/opencv_modules.hpp" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "pycompat.hpp" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <map> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject* opencv_error = NULL; |
|
|
|
static PyObject* opencv_error = NULL; |
|
|
|
|
|
|
|
|
|
|
|
static int failmsg(const char *fmt, ...) |
|
|
|
static int failmsg(const char *fmt, ...) |
|
|
@ -337,7 +271,7 @@ static bool pyopencv_to(PyObject* o, Mat& m, const ArgInfo info) |
|
|
|
m = Mat(sz, 1, CV_64F); |
|
|
|
m = Mat(sz, 1, CV_64F); |
|
|
|
for( i = 0; i < sz; i++ ) |
|
|
|
for( i = 0; i < sz; i++ ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
PyObject* oi = PyTuple_GET_ITEM(o, i); |
|
|
|
PyObject* oi = PyTuple_GetItem(o, i); |
|
|
|
if( PyInt_Check(oi) ) |
|
|
|
if( PyInt_Check(oi) ) |
|
|
|
m.at<double>(i) = (double)PyInt_AsLong(oi); |
|
|
|
m.at<double>(i) = (double)PyInt_AsLong(oi); |
|
|
|
else if( PyFloat_Check(oi) ) |
|
|
|
else if( PyFloat_Check(oi) ) |
|
|
@ -571,21 +505,26 @@ static PyObject* pyopencv_from(void*& ptr) |
|
|
|
return PyLong_FromVoidPtr(ptr); |
|
|
|
return PyLong_FromVoidPtr(ptr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct SafeSeqItem |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
PyObject * item; |
|
|
|
|
|
|
|
SafeSeqItem(PyObject *obj, size_t idx) { item = PySequence_GetItem(obj, idx); } |
|
|
|
|
|
|
|
~SafeSeqItem() { Py_XDECREF(item); } |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static bool pyopencv_to(PyObject *o, Scalar& s, const ArgInfo info) |
|
|
|
static bool pyopencv_to(PyObject *o, Scalar& s, const ArgInfo info) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if(!o || o == Py_None) |
|
|
|
if(!o || o == Py_None) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
if (PySequence_Check(o)) { |
|
|
|
if (PySequence_Check(o)) { |
|
|
|
PyObject *fi = PySequence_Fast(o, info.name); |
|
|
|
if (4 < PySequence_Size(o)) |
|
|
|
if (fi == NULL) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
if (4 < PySequence_Fast_GET_SIZE(fi)) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
failmsg("Scalar value for argument '%s' is longer than 4", info.name); |
|
|
|
failmsg("Scalar value for argument '%s' is longer than 4", info.name); |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(fi); i++) { |
|
|
|
for (Py_ssize_t i = 0; i < PySequence_Size(o); i++) { |
|
|
|
PyObject *item = PySequence_Fast_GET_ITEM(fi, i); |
|
|
|
SafeSeqItem item_wrap(o, i); |
|
|
|
|
|
|
|
PyObject *item = item_wrap.item; |
|
|
|
if (PyFloat_Check(item) || PyInt_Check(item)) { |
|
|
|
if (PyFloat_Check(item) || PyInt_Check(item)) { |
|
|
|
s[(int)i] = PyFloat_AsDouble(item); |
|
|
|
s[(int)i] = PyFloat_AsDouble(item); |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -593,7 +532,6 @@ static bool pyopencv_to(PyObject *o, Scalar& s, const ArgInfo info) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
Py_DECREF(fi); |
|
|
|
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if (PyFloat_Check(o) || PyInt_Check(o)) { |
|
|
|
if (PyFloat_Check(o) || PyInt_Check(o)) { |
|
|
|
s[0] = PyFloat_AsDouble(o); |
|
|
|
s[0] = PyFloat_AsDouble(o); |
|
|
@ -741,16 +679,18 @@ PyObject* pyopencv_from(const String& value) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<> |
|
|
|
template<> |
|
|
|
bool pyopencv_to(PyObject* obj, String& value, const char* name) |
|
|
|
bool pyopencv_to(PyObject* obj, String &value, const char* name) |
|
|
|
{ |
|
|
|
{ |
|
|
|
CV_UNUSED(name); |
|
|
|
CV_UNUSED(name); |
|
|
|
if(!obj || obj == Py_None) |
|
|
|
if(!obj || obj == Py_None) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
const char* str = PyString_AsString(obj); |
|
|
|
std::string str; |
|
|
|
if(!str) |
|
|
|
if (getUnicodeString(obj, str)) |
|
|
|
return false; |
|
|
|
{ |
|
|
|
value = String(str); |
|
|
|
value = str; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<> |
|
|
|
template<> |
|
|
@ -821,36 +761,31 @@ bool pyopencv_to(PyObject* obj, Range& r, const char* name) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
while (PySequence_Check(obj)) |
|
|
|
while (PySequence_Check(obj)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
PyObject *fi = PySequence_Fast(obj, name); |
|
|
|
if (2 != PySequence_Size(obj)) |
|
|
|
if (fi == NULL) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
if (2 != PySequence_Fast_GET_SIZE(fi)) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
failmsg("Range value for argument '%s' is longer than 2", name); |
|
|
|
failmsg("Range value for argument '%s' is longer than 2", name); |
|
|
|
Py_DECREF(fi); |
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
{ |
|
|
|
{ |
|
|
|
PyObject *item = PySequence_Fast_GET_ITEM(fi, 0); |
|
|
|
SafeSeqItem item_wrap(obj, 0); |
|
|
|
|
|
|
|
PyObject *item = item_wrap.item; |
|
|
|
if (PyInt_Check(item)) { |
|
|
|
if (PyInt_Check(item)) { |
|
|
|
r.start = (int)PyInt_AsLong(item); |
|
|
|
r.start = (int)PyInt_AsLong(item); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
failmsg("Range.start value for argument '%s' is not integer", name); |
|
|
|
failmsg("Range.start value for argument '%s' is not integer", name); |
|
|
|
Py_DECREF(fi); |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
{ |
|
|
|
{ |
|
|
|
PyObject *item = PySequence_Fast_GET_ITEM(fi, 1); |
|
|
|
SafeSeqItem item_wrap(obj, 1); |
|
|
|
|
|
|
|
PyObject *item = item_wrap.item; |
|
|
|
if (PyInt_Check(item)) { |
|
|
|
if (PyInt_Check(item)) { |
|
|
|
r.end = (int)PyInt_AsLong(item); |
|
|
|
r.end = (int)PyInt_AsLong(item); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
failmsg("Range.end value for argument '%s' is not integer", name); |
|
|
|
failmsg("Range.end value for argument '%s' is not integer", name); |
|
|
|
Py_DECREF(fi); |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
Py_DECREF(fi); |
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
if(PyObject_Size(obj) == 0) |
|
|
|
if(PyObject_Size(obj) == 0) |
|
|
@ -873,11 +808,10 @@ bool pyopencv_to(PyObject* obj, Point& p, const char* name) |
|
|
|
CV_UNUSED(name); |
|
|
|
CV_UNUSED(name); |
|
|
|
if(!obj || obj == Py_None) |
|
|
|
if(!obj || obj == Py_None) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
if(!!PyComplex_CheckExact(obj)) |
|
|
|
if(PyComplex_Check(obj)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Py_complex c = PyComplex_AsCComplex(obj); |
|
|
|
p.x = saturate_cast<int>(PyComplex_RealAsDouble(obj)); |
|
|
|
p.x = saturate_cast<int>(c.real); |
|
|
|
p.y = saturate_cast<int>(PyComplex_ImagAsDouble(obj)); |
|
|
|
p.y = saturate_cast<int>(c.imag); |
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
return PyArg_ParseTuple(obj, "ii", &p.x, &p.y) > 0; |
|
|
|
return PyArg_ParseTuple(obj, "ii", &p.x, &p.y) > 0; |
|
|
@ -889,11 +823,10 @@ bool pyopencv_to(PyObject* obj, Point2f& p, const char* name) |
|
|
|
CV_UNUSED(name); |
|
|
|
CV_UNUSED(name); |
|
|
|
if(!obj || obj == Py_None) |
|
|
|
if(!obj || obj == Py_None) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
if(!!PyComplex_CheckExact(obj)) |
|
|
|
if (PyComplex_Check(obj)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Py_complex c = PyComplex_AsCComplex(obj); |
|
|
|
p.x = saturate_cast<float>(PyComplex_RealAsDouble(obj)); |
|
|
|
p.x = saturate_cast<float>(c.real); |
|
|
|
p.y = saturate_cast<float>(PyComplex_ImagAsDouble(obj)); |
|
|
|
p.y = saturate_cast<float>(c.imag); |
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
return PyArg_ParseTuple(obj, "ff", &p.x, &p.y) > 0; |
|
|
|
return PyArg_ParseTuple(obj, "ff", &p.x, &p.y) > 0; |
|
|
@ -905,11 +838,10 @@ bool pyopencv_to(PyObject* obj, Point2d& p, const char* name) |
|
|
|
CV_UNUSED(name); |
|
|
|
CV_UNUSED(name); |
|
|
|
if(!obj || obj == Py_None) |
|
|
|
if(!obj || obj == Py_None) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
if(!!PyComplex_CheckExact(obj)) |
|
|
|
if(PyComplex_Check(obj)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Py_complex c = PyComplex_AsCComplex(obj); |
|
|
|
p.x = PyComplex_RealAsDouble(obj); |
|
|
|
p.x = saturate_cast<double>(c.real); |
|
|
|
p.y = PyComplex_ImagAsDouble(obj); |
|
|
|
p.y = saturate_cast<double>(c.imag); |
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
return PyArg_ParseTuple(obj, "dd", &p.x, &p.y) > 0; |
|
|
|
return PyArg_ParseTuple(obj, "dd", &p.x, &p.y) > 0; |
|
|
@ -1136,9 +1068,41 @@ PyObject* pyopencv_from(const Point3d& p) |
|
|
|
|
|
|
|
|
|
|
|
template<typename _Tp> struct pyopencvVecConverter |
|
|
|
template<typename _Tp> struct pyopencvVecConverter |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
typedef typename DataType<_Tp>::channel_type _Cp; |
|
|
|
|
|
|
|
static inline bool copyOneItem(PyObject *obj, size_t start, int channels, _Cp * data) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for(size_t j = 0; (int)j < channels; j++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
SafeSeqItem sub_item_wrap(obj, start + j); |
|
|
|
|
|
|
|
PyObject* item_ij = sub_item_wrap.item; |
|
|
|
|
|
|
|
if( PyInt_Check(item_ij)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int v = (int)PyInt_AsLong(item_ij); |
|
|
|
|
|
|
|
if( v == -1 && PyErr_Occurred() ) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
data[j] = saturate_cast<_Cp>(v); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if( PyLong_Check(item_ij)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int v = (int)PyLong_AsLong(item_ij); |
|
|
|
|
|
|
|
if( v == -1 && PyErr_Occurred() ) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
data[j] = saturate_cast<_Cp>(v); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if( PyFloat_Check(item_ij)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
double v = PyFloat_AsDouble(item_ij); |
|
|
|
|
|
|
|
if( PyErr_Occurred() ) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
data[j] = saturate_cast<_Cp>(v); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
static bool to(PyObject* obj, std::vector<_Tp>& value, const ArgInfo info) |
|
|
|
static bool to(PyObject* obj, std::vector<_Tp>& value, const ArgInfo info) |
|
|
|
{ |
|
|
|
{ |
|
|
|
typedef typename DataType<_Tp>::channel_type _Cp; |
|
|
|
|
|
|
|
if(!obj || obj == Py_None) |
|
|
|
if(!obj || obj == Py_None) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
if (PyArray_Check(obj)) |
|
|
|
if (PyArray_Check(obj)) |
|
|
@ -1146,34 +1110,26 @@ template<typename _Tp> struct pyopencvVecConverter |
|
|
|
Mat m; |
|
|
|
Mat m; |
|
|
|
pyopencv_to(obj, m, info); |
|
|
|
pyopencv_to(obj, m, info); |
|
|
|
m.copyTo(value); |
|
|
|
m.copyTo(value); |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
if (!PySequence_Check(obj)) |
|
|
|
else if (PySequence_Check(obj)) |
|
|
|
return false; |
|
|
|
{ |
|
|
|
PyObject *seq = PySequence_Fast(obj, info.name); |
|
|
|
const int type = traits::Type<_Tp>::value; |
|
|
|
if (seq == NULL) |
|
|
|
const int depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type); |
|
|
|
return false; |
|
|
|
size_t i, n = PySequence_Size(obj); |
|
|
|
int i, j, n = (int)PySequence_Fast_GET_SIZE(seq); |
|
|
|
|
|
|
|
value.resize(n); |
|
|
|
value.resize(n); |
|
|
|
|
|
|
|
for (i = 0; i < n; i++ ) |
|
|
|
int type = traits::Type<_Tp>::value; |
|
|
|
|
|
|
|
int depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type); |
|
|
|
|
|
|
|
PyObject** items = PySequence_Fast_ITEMS(seq); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( i = 0; i < n; i++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
PyObject* item = items[i]; |
|
|
|
SafeSeqItem item_wrap(obj, i); |
|
|
|
PyObject* seq_i = 0; |
|
|
|
PyObject* item = item_wrap.item; |
|
|
|
PyObject** items_i = &item; |
|
|
|
|
|
|
|
_Cp* data = (_Cp*)&value[i]; |
|
|
|
_Cp* data = (_Cp*)&value[i]; |
|
|
|
|
|
|
|
|
|
|
|
if( channels == 2 && PyComplex_CheckExact(item) ) |
|
|
|
if( channels == 2 && PyComplex_Check(item) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Py_complex c = PyComplex_AsCComplex(obj); |
|
|
|
data[0] = saturate_cast<_Cp>(PyComplex_RealAsDouble(item)); |
|
|
|
data[0] = saturate_cast<_Cp>(c.real); |
|
|
|
data[1] = saturate_cast<_Cp>(PyComplex_ImagAsDouble(item)); |
|
|
|
data[1] = saturate_cast<_Cp>(c.imag); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
if( channels > 1 ) |
|
|
|
else if( channels > 1 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if( PyArray_Check(item)) |
|
|
|
if( PyArray_Check(item)) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1187,52 +1143,31 @@ template<typename _Tp> struct pyopencvVecConverter |
|
|
|
src.convertTo(dst, type); |
|
|
|
src.convertTo(dst, type); |
|
|
|
if( dst.data != (uchar*)data ) |
|
|
|
if( dst.data != (uchar*)data ) |
|
|
|
break; |
|
|
|
break; |
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else if (PySequence_Check(item)) |
|
|
|
seq_i = PySequence_Fast(item, info.name); |
|
|
|
|
|
|
|
if( !seq_i || (int)PySequence_Fast_GET_SIZE(seq_i) != channels ) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
Py_XDECREF(seq_i); |
|
|
|
if (!copyOneItem(item, 0, channels, data)) |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
items_i = PySequence_Fast_ITEMS(seq_i); |
|
|
|
else |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( j = 0; j < channels; j++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
PyObject* item_ij = items_i[j]; |
|
|
|
|
|
|
|
if( PyInt_Check(item_ij)) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
int v = (int)PyInt_AsLong(item_ij); |
|
|
|
|
|
|
|
if( v == -1 && PyErr_Occurred() ) |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
data[j] = saturate_cast<_Cp>(v); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
else if( PyLong_Check(item_ij)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int v = (int)PyLong_AsLong(item_ij); |
|
|
|
|
|
|
|
if( v == -1 && PyErr_Occurred() ) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
data[j] = saturate_cast<_Cp>(v); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
else if( PyFloat_Check(item_ij)) |
|
|
|
else if (channels == 1) |
|
|
|
{ |
|
|
|
{ |
|
|
|
double v = PyFloat_AsDouble(item_ij); |
|
|
|
if (!copyOneItem(obj, i, channels, data)) |
|
|
|
if( PyErr_Occurred() ) |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
data[j] = saturate_cast<_Cp>(v); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
Py_XDECREF(seq_i); |
|
|
|
|
|
|
|
if( j < channels ) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
Py_DECREF(seq); |
|
|
|
|
|
|
|
return i == n; |
|
|
|
return i == n; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static PyObject* from(const std::vector<_Tp>& value) |
|
|
|
static PyObject* from(const std::vector<_Tp>& value) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1263,22 +1198,15 @@ template<typename _Tp> static inline bool pyopencv_to_generic_vec(PyObject* obj, |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
if (!PySequence_Check(obj)) |
|
|
|
if (!PySequence_Check(obj)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
PyObject *seq = PySequence_Fast(obj, info.name); |
|
|
|
size_t n = PySequence_Size(obj); |
|
|
|
if (seq == NULL) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
int i, n = (int)PySequence_Fast_GET_SIZE(seq); |
|
|
|
|
|
|
|
value.resize(n); |
|
|
|
value.resize(n); |
|
|
|
|
|
|
|
for(size_t i = 0; i < n; i++ ) |
|
|
|
PyObject** items = PySequence_Fast_ITEMS(seq); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( i = 0; i < n; i++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
PyObject* item = items[i]; |
|
|
|
SafeSeqItem item_wrap(obj, i); |
|
|
|
if(!pyopencv_to(item, value[i], info)) |
|
|
|
if(!pyopencv_to(item_wrap.item, value[i], info)) |
|
|
|
break; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
Py_DECREF(seq); |
|
|
|
return true; |
|
|
|
return i == n; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<typename _Tp> static inline PyObject* pyopencv_from_generic_vec(const std::vector<_Tp>& value) |
|
|
|
template<typename _Tp> static inline PyObject* pyopencv_from_generic_vec(const std::vector<_Tp>& value) |
|
|
@ -1290,7 +1218,7 @@ template<typename _Tp> static inline PyObject* pyopencv_from_generic_vec(const s |
|
|
|
PyObject* item = pyopencv_from(value[i]); |
|
|
|
PyObject* item = pyopencv_from(value[i]); |
|
|
|
if(!item) |
|
|
|
if(!item) |
|
|
|
break; |
|
|
|
break; |
|
|
|
PyList_SET_ITEM(seq, i, item); |
|
|
|
PyList_SetItem(seq, i, item); |
|
|
|
} |
|
|
|
} |
|
|
|
if( i < n ) |
|
|
|
if( i < n ) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1669,31 +1597,37 @@ static PyObject *pycvCreateButton(PyObject*, PyObject *args, PyObject *kw) |
|
|
|
|
|
|
|
|
|
|
|
static int convert_to_char(PyObject *o, char *dst, const char *name = "no_name") |
|
|
|
static int convert_to_char(PyObject *o, char *dst, const char *name = "no_name") |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (PyString_Check(o) && PyString_Size(o) == 1) { |
|
|
|
std::string str; |
|
|
|
*dst = PyString_AsString(o)[0]; |
|
|
|
if (getUnicodeString(o, str)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
*dst = str[0]; |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
|
} else { |
|
|
|
} |
|
|
|
(*dst) = 0; |
|
|
|
(*dst) = 0; |
|
|
|
return failmsg("Expected single character string for argument '%s'", name); |
|
|
|
return failmsg("Expected single character string for argument '%s'", name); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3 |
|
|
|
|
|
|
|
#define MKTYPE2(NAME) pyopencv_##NAME##_specials(); if (!to_ok(&pyopencv_##NAME##_Type)) return NULL; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
#define MKTYPE2(NAME) pyopencv_##NAME##_specials(); if (!to_ok(&pyopencv_##NAME##_Type)) return |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __GNUC__ |
|
|
|
#ifdef __GNUC__ |
|
|
|
# pragma GCC diagnostic ignored "-Wunused-parameter" |
|
|
|
# pragma GCC diagnostic ignored "-Wunused-parameter" |
|
|
|
# pragma GCC diagnostic ignored "-Wmissing-field-initializers" |
|
|
|
# pragma GCC diagnostic ignored "-Wmissing-field-initializers" |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "pyopencv_generated_enums.h" |
|
|
|
#include "pyopencv_generated_enums.h" |
|
|
|
#include "pyopencv_custom_headers.h" |
|
|
|
#include "pyopencv_custom_headers.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef CVPY_DYNAMIC_INIT |
|
|
|
|
|
|
|
#define CVPY_TYPE(NAME, STORAGE, SNAME, _1, _2) CVPY_TYPE_DECLARE_DYNAMIC(NAME, STORAGE, SNAME) |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
#define CVPY_TYPE(NAME, STORAGE, SNAME, _1, _2) CVPY_TYPE_DECLARE(NAME, STORAGE, SNAME) |
|
|
|
|
|
|
|
#endif |
|
|
|
#include "pyopencv_generated_types.h" |
|
|
|
#include "pyopencv_generated_types.h" |
|
|
|
|
|
|
|
#undef CVPY_TYPE |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "pyopencv_generated_types_content.h" |
|
|
|
#include "pyopencv_generated_funcs.h" |
|
|
|
#include "pyopencv_generated_funcs.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static PyMethodDef special_methods[] = { |
|
|
|
static PyMethodDef special_methods[] = { |
|
|
|
{"redirectError", CV_PY_FN_WITH_KW(pycvRedirectError), "redirectError(onError) -> None"}, |
|
|
|
{"redirectError", CV_PY_FN_WITH_KW(pycvRedirectError), "redirectError(onError) -> None"}, |
|
|
|
#ifdef HAVE_OPENCV_HIGHGUI |
|
|
|
#ifdef HAVE_OPENCV_HIGHGUI |
|
|
@ -1758,53 +1692,28 @@ static void init_submodule(PyObject * root, const char * name, PyMethodDef * met |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#include "pyopencv_generated_ns_reg.h" |
|
|
|
#include "pyopencv_generated_modules_content.h" |
|
|
|
|
|
|
|
|
|
|
|
static int to_ok(PyTypeObject *to) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
to->tp_alloc = PyType_GenericAlloc; |
|
|
|
|
|
|
|
to->tp_new = PyType_GenericNew; |
|
|
|
|
|
|
|
to->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; |
|
|
|
|
|
|
|
return (PyType_Ready(to) == 0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(__GNUC__) |
|
|
|
|
|
|
|
#pragma GCC visibility push(default) |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3 |
|
|
|
|
|
|
|
PyMODINIT_FUNC PyInit_cv2(); |
|
|
|
|
|
|
|
static struct PyModuleDef cv2_moduledef = |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
PyModuleDef_HEAD_INIT, |
|
|
|
|
|
|
|
MODULESTR, |
|
|
|
|
|
|
|
"Python wrapper for OpenCV.", |
|
|
|
|
|
|
|
-1, /* size of per-interpreter state of the module,
|
|
|
|
|
|
|
|
or -1 if the module keeps state in global variables. */ |
|
|
|
|
|
|
|
special_methods |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PyObject* PyInit_cv2() |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
PyMODINIT_FUNC initcv2(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void initcv2() |
|
|
|
static bool init_body(PyObject * m) |
|
|
|
#endif |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
import_array(); |
|
|
|
#define CVPY_MODULE(NAMESTR, NAME) \ |
|
|
|
|
|
|
|
init_submodule(m, MODULESTR NAMESTR, methods_##NAME, consts_##NAME) |
|
|
|
|
|
|
|
#include "pyopencv_generated_modules.h" |
|
|
|
|
|
|
|
#undef CVPY_MODULE |
|
|
|
|
|
|
|
|
|
|
|
#include "pyopencv_generated_type_reg.h" |
|
|
|
#ifdef CVPY_DYNAMIC_INIT |
|
|
|
|
|
|
|
#define CVPY_TYPE(NAME, _1, _2, BASE, CONSTRUCTOR) CVPY_TYPE_INIT_DYNAMIC(NAME, return false, BASE, CONSTRUCTOR) |
|
|
|
#if PY_MAJOR_VERSION >= 3 |
|
|
|
PyObject * pyopencv_NoBase_TypePtr = NULL; |
|
|
|
PyObject* m = PyModule_Create(&cv2_moduledef); |
|
|
|
|
|
|
|
#else |
|
|
|
#else |
|
|
|
PyObject* m = Py_InitModule(MODULESTR, special_methods); |
|
|
|
#define CVPY_TYPE(NAME, _1, _2, BASE, CONSTRUCTOR) CVPY_TYPE_INIT_STATIC(NAME, return false, BASE, CONSTRUCTOR) |
|
|
|
|
|
|
|
PyTypeObject * pyopencv_NoBase_TypePtr = NULL; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
init_submodules(m); // from "pyopencv_generated_ns_reg.h"
|
|
|
|
#include "pyopencv_generated_types.h" |
|
|
|
|
|
|
|
#undef CVPY_TYPE |
|
|
|
|
|
|
|
|
|
|
|
PyObject* d = PyModule_GetDict(m); |
|
|
|
PyObject* d = PyModule_GetDict(m); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PyDict_SetItemString(d, "__version__", PyString_FromString(CV_VERSION)); |
|
|
|
PyDict_SetItemString(d, "__version__", PyString_FromString(CV_VERSION)); |
|
|
|
|
|
|
|
|
|
|
|
PyObject *opencv_error_dict = PyDict_New(); |
|
|
|
PyObject *opencv_error_dict = PyDict_New(); |
|
|
@ -1818,22 +1727,8 @@ void initcv2() |
|
|
|
Py_DECREF(opencv_error_dict); |
|
|
|
Py_DECREF(opencv_error_dict); |
|
|
|
PyDict_SetItemString(d, "error", opencv_error); |
|
|
|
PyDict_SetItemString(d, "error", opencv_error); |
|
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3 |
|
|
|
|
|
|
|
#define PUBLISH_OBJECT(name, type) Py_INCREF(&type);\ |
|
|
|
|
|
|
|
PyModule_AddObject(m, name, (PyObject *)&type); |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
// Unrolled Py_INCREF(&type) without (PyObject*) cast
|
|
|
|
|
|
|
|
// due to "warning: dereferencing type-punned pointer will break strict-aliasing rules"
|
|
|
|
|
|
|
|
#define PUBLISH_OBJECT(name, type) _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA (&type)->ob_refcnt++;\ |
|
|
|
|
|
|
|
PyModule_AddObject(m, name, (PyObject *)&type); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "pyopencv_generated_type_publish.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define PUBLISH(I) PyDict_SetItemString(d, #I, PyInt_FromLong(I)) |
|
|
|
#define PUBLISH(I) PyDict_SetItemString(d, #I, PyInt_FromLong(I)) |
|
|
|
//#define PUBLISHU(I) PyDict_SetItemString(d, #I, PyLong_FromUnsignedLong(I))
|
|
|
|
|
|
|
|
#define PUBLISH2(I, value) PyDict_SetItemString(d, #I, PyLong_FromLong(value)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PUBLISH(CV_8U); |
|
|
|
PUBLISH(CV_8U); |
|
|
|
PUBLISH(CV_8UC1); |
|
|
|
PUBLISH(CV_8UC1); |
|
|
|
PUBLISH(CV_8UC2); |
|
|
|
PUBLISH(CV_8UC2); |
|
|
@ -1869,8 +1764,46 @@ void initcv2() |
|
|
|
PUBLISH(CV_64FC2); |
|
|
|
PUBLISH(CV_64FC2); |
|
|
|
PUBLISH(CV_64FC3); |
|
|
|
PUBLISH(CV_64FC3); |
|
|
|
PUBLISH(CV_64FC4); |
|
|
|
PUBLISH(CV_64FC4); |
|
|
|
|
|
|
|
#undef PUBLISH |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(__GNUC__) |
|
|
|
|
|
|
|
#pragma GCC visibility push(default) |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3 |
|
|
|
#if PY_MAJOR_VERSION >= 3 |
|
|
|
|
|
|
|
// === Python 3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct PyModuleDef cv2_moduledef = |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
PyModuleDef_HEAD_INIT, |
|
|
|
|
|
|
|
MODULESTR, |
|
|
|
|
|
|
|
"Python wrapper for OpenCV.", |
|
|
|
|
|
|
|
-1, /* size of per-interpreter state of the module,
|
|
|
|
|
|
|
|
or -1 if the module keeps state in global variables. */ |
|
|
|
|
|
|
|
special_methods |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PyMODINIT_FUNC PyInit_cv2(); |
|
|
|
|
|
|
|
PyObject* PyInit_cv2() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
import_array(); // from numpy
|
|
|
|
|
|
|
|
PyObject* m = PyModule_Create(&cv2_moduledef); |
|
|
|
|
|
|
|
if (!init_body(m)) |
|
|
|
|
|
|
|
return NULL; |
|
|
|
return m; |
|
|
|
return m; |
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
// === Python 2
|
|
|
|
|
|
|
|
PyMODINIT_FUNC initcv2(); |
|
|
|
|
|
|
|
void initcv2() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
import_array(); // from numpy
|
|
|
|
|
|
|
|
PyObject* m = Py_InitModule(MODULESTR, special_methods); |
|
|
|
|
|
|
|
init_body(m); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif |
|
|
|