mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-12 18:26:17 +03:00
py3k: Use new buffer protocol
Other ports have taken advantage of the fact that Python 3 has wrappers for the old buffer protocol, but there's a significant disadvantage: you can't let the buffered object know when you're done with it. Since Python 2.6 supports the new protocol, we just go ahead and move to it.
This commit is contained in:
parent
9519013466
commit
804095ecb3
64
_imaging.c
64
_imaging.c
|
@ -103,19 +103,6 @@
|
||||||
#define L16(p, i) ((((int)p[(i)+1]) << 8) + p[(i)])
|
#define L16(p, i) ((((int)p[(i)+1]) << 8) + p[(i)])
|
||||||
#define S16(v) ((v) < 32768 ? (v) : ((v) - 65536))
|
#define S16(v) ((v) < 32768 ? (v) : ((v) - 65536))
|
||||||
|
|
||||||
#if PY_VERSION_HEX < 0x01060000
|
|
||||||
#define PyObject_New PyObject_NEW
|
|
||||||
#define PyObject_Del PyMem_DEL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PY_VERSION_HEX < 0x02050000
|
|
||||||
#define Py_ssize_t int
|
|
||||||
#define ssizeargfunc intargfunc
|
|
||||||
#define ssizessizeargfunc intintargfunc
|
|
||||||
#define ssizeobjargproc intobjargproc
|
|
||||||
#define ssizessizeobjargproc intintobjargproc
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* OBJECT ADMINISTRATION */
|
/* OBJECT ADMINISTRATION */
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
@ -243,43 +230,38 @@ void ImagingSectionLeave(ImagingSectionCookie* cookie)
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* Python compatibility API */
|
/* Python compatibility API */
|
||||||
|
|
||||||
#if PY_VERSION_HEX < 0x02020000
|
|
||||||
|
|
||||||
int PyImaging_CheckBuffer(PyObject *buffer)
|
|
||||||
{
|
|
||||||
PyBufferProcs *procs = buffer->ob_type->tp_as_buffer;
|
|
||||||
if (procs && procs->bf_getreadbuffer && procs->bf_getsegcount &&
|
|
||||||
procs->bf_getsegcount(buffer, NULL) == 1)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PyImaging_ReadBuffer(PyObject* buffer, const void** ptr)
|
|
||||||
{
|
|
||||||
PyBufferProcs *procs = buffer->ob_type->tp_as_buffer;
|
|
||||||
return procs->bf_getreadbuffer(buffer, 0, ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
int PyImaging_CheckBuffer(PyObject* buffer)
|
int PyImaging_CheckBuffer(PyObject* buffer)
|
||||||
{
|
{
|
||||||
return PyObject_CheckReadBuffer(buffer);
|
#if PY_VERSION_HEX >= 0x03000000
|
||||||
|
return PyObject_CheckBuffer(buffer);
|
||||||
|
#else
|
||||||
|
return PyObject_CheckBuffer(buffer) || PyObject_CheckReadBuffer(buffer);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int PyImaging_ReadBuffer(PyObject* buffer, const void** ptr)
|
int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view)
|
||||||
{
|
{
|
||||||
/* must call check_buffer first! */
|
/* must call check_buffer first! */
|
||||||
#if PY_VERSION_HEX < 0x02050000
|
#if PY_VERSION_HEX >= 0x03000000
|
||||||
int n = 0;
|
return PyObject_GetBuffer(buffer, view, PyBUF_SIMPLE);
|
||||||
#else
|
#else
|
||||||
Py_ssize_t n = 0;
|
/* Use new buffer protocol if available
|
||||||
#endif
|
(mmap doesn't support this in 2.7, go figure) */
|
||||||
PyObject_AsReadBuffer(buffer, ptr, &n);
|
if (PyObject_CheckBuffer(buffer)) {
|
||||||
return (int) n;
|
return PyObject_GetBuffer(buffer, view, PyBUF_SIMPLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pretend we support the new protocol; PyBuffer_Release happily ignores
|
||||||
|
calling bf_releasebuffer on objects that don't support it */
|
||||||
|
*view = (Py_buffer) {0};
|
||||||
|
view->readonly = 1;
|
||||||
|
|
||||||
|
Py_INCREF(buffer);
|
||||||
|
view->obj = buffer;
|
||||||
|
|
||||||
|
return PyObject_AsReadBuffer(buffer, (void *) &view->buf, &view->len);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* EXCEPTION REROUTING */
|
/* EXCEPTION REROUTING */
|
||||||
|
|
20
map.c
20
map.c
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
/* compatibility wrappers (defined in _imaging.c) */
|
/* compatibility wrappers (defined in _imaging.c) */
|
||||||
extern int PyImaging_CheckBuffer(PyObject* buffer);
|
extern int PyImaging_CheckBuffer(PyObject* buffer);
|
||||||
extern int PyImaging_ReadBuffer(PyObject* buffer, const void** ptr);
|
extern int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* Standard mapper */
|
/* Standard mapper */
|
||||||
|
@ -311,6 +311,7 @@ PyImaging_Mapper(PyObject* self, PyObject* args)
|
||||||
typedef struct ImagingBufferInstance {
|
typedef struct ImagingBufferInstance {
|
||||||
struct ImagingMemoryInstance im;
|
struct ImagingMemoryInstance im;
|
||||||
PyObject* target;
|
PyObject* target;
|
||||||
|
Py_buffer view;
|
||||||
} ImagingBufferInstance;
|
} ImagingBufferInstance;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -318,6 +319,7 @@ mapping_destroy_buffer(Imaging im)
|
||||||
{
|
{
|
||||||
ImagingBufferInstance* buffer = (ImagingBufferInstance*) im;
|
ImagingBufferInstance* buffer = (ImagingBufferInstance*) im;
|
||||||
|
|
||||||
|
PyBuffer_Release(&buffer->view);
|
||||||
Py_XDECREF(buffer->target);
|
Py_XDECREF(buffer->target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,10 +328,9 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
int y, size;
|
int y, size;
|
||||||
Imaging im;
|
Imaging im;
|
||||||
char* ptr;
|
|
||||||
int bytes;
|
|
||||||
|
|
||||||
PyObject* target;
|
PyObject* target;
|
||||||
|
Py_buffer view;
|
||||||
char* mode;
|
char* mode;
|
||||||
char* codec;
|
char* codec;
|
||||||
PyObject* bbox;
|
PyObject* bbox;
|
||||||
|
@ -359,12 +360,14 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
|
||||||
size = ysize * stride;
|
size = ysize * stride;
|
||||||
|
|
||||||
/* check buffer size */
|
/* check buffer size */
|
||||||
bytes = PyImaging_ReadBuffer(target, (const void**) &ptr);
|
if (PyImaging_GetBuffer(target, &view) < 0)
|
||||||
if (bytes < 0) {
|
return NULL;
|
||||||
|
|
||||||
|
if (view.len < 0) {
|
||||||
PyErr_SetString(PyExc_ValueError, "buffer has negative size");
|
PyErr_SetString(PyExc_ValueError, "buffer has negative size");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (offset + size > bytes) {
|
if (offset + size > view.len) {
|
||||||
PyErr_SetString(PyExc_ValueError, "buffer is not large enough");
|
PyErr_SetString(PyExc_ValueError, "buffer is not large enough");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -378,15 +381,16 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
|
||||||
/* setup file pointers */
|
/* setup file pointers */
|
||||||
if (ystep > 0)
|
if (ystep > 0)
|
||||||
for (y = 0; y < ysize; y++)
|
for (y = 0; y < ysize; y++)
|
||||||
im->image[y] = ptr + offset + y * stride;
|
im->image[y] = view.buf + offset + y * stride;
|
||||||
else
|
else
|
||||||
for (y = 0; y < ysize; y++)
|
for (y = 0; y < ysize; y++)
|
||||||
im->image[ysize-y-1] = ptr + offset + y * stride;
|
im->image[ysize-y-1] = view.buf + offset + y * stride;
|
||||||
|
|
||||||
im->destroy = mapping_destroy_buffer;
|
im->destroy = mapping_destroy_buffer;
|
||||||
|
|
||||||
Py_INCREF(target);
|
Py_INCREF(target);
|
||||||
((ImagingBufferInstance*) im)->target = target;
|
((ImagingBufferInstance*) im)->target = target;
|
||||||
|
((ImagingBufferInstance*) im)->view = view;
|
||||||
|
|
||||||
if (!ImagingNewEpilogue(im))
|
if (!ImagingNewEpilogue(im))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
26
path.c
26
path.c
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
/* compatibility wrappers (defined in _imaging.c) */
|
/* compatibility wrappers (defined in _imaging.c) */
|
||||||
extern int PyImaging_CheckBuffer(PyObject* buffer);
|
extern int PyImaging_CheckBuffer(PyObject* buffer);
|
||||||
extern int PyImaging_ReadBuffer(PyObject* buffer, const void** ptr);
|
extern int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* Class */
|
/* Class */
|
||||||
|
@ -134,16 +134,20 @@ PyPath_Flatten(PyObject* data, double **pxy)
|
||||||
|
|
||||||
if (PyImaging_CheckBuffer(data)) {
|
if (PyImaging_CheckBuffer(data)) {
|
||||||
/* Assume the buffer contains floats */
|
/* Assume the buffer contains floats */
|
||||||
float* ptr;
|
Py_buffer buffer;
|
||||||
int n = PyImaging_ReadBuffer(data, (const void**) &ptr);
|
if (PyImaging_GetBuffer(data, &buffer) == 0) {
|
||||||
n /= 2 * sizeof(float);
|
int n = buffer.len / (2 * sizeof(float));
|
||||||
xy = alloc_array(n);
|
float *ptr = (float*) buffer.buf;
|
||||||
if (!xy)
|
xy = alloc_array(n);
|
||||||
return -1;
|
if (!xy)
|
||||||
for (i = 0; i < n+n; i++)
|
return -1;
|
||||||
xy[i] = ptr[i];
|
for (i = 0; i < n+n; i++)
|
||||||
*pxy = xy;
|
xy[i] = ptr[i];
|
||||||
return n;
|
*pxy = xy;
|
||||||
|
PyBuffer_Release(&buffer);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
PyErr_Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PySequence_Check(data)) {
|
if (!PySequence_Check(data)) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user