mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 17:36:18 +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 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 */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -243,43 +230,38 @@ void ImagingSectionLeave(ImagingSectionCookie* cookie)
|
|||
/* -------------------------------------------------------------------- */
|
||||
/* 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)
|
||||
{
|
||||
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! */
|
||||
#if PY_VERSION_HEX < 0x02050000
|
||||
int n = 0;
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
return PyObject_GetBuffer(buffer, view, PyBUF_SIMPLE);
|
||||
#else
|
||||
Py_ssize_t n = 0;
|
||||
#endif
|
||||
PyObject_AsReadBuffer(buffer, ptr, &n);
|
||||
return (int) n;
|
||||
}
|
||||
/* Use new buffer protocol if available
|
||||
(mmap doesn't support this in 2.7, go figure) */
|
||||
if (PyObject_CheckBuffer(buffer)) {
|
||||
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
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* EXCEPTION REROUTING */
|
||||
|
|
20
map.c
20
map.c
|
@ -41,7 +41,7 @@
|
|||
|
||||
/* compatibility wrappers (defined in _imaging.c) */
|
||||
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 */
|
||||
|
@ -311,6 +311,7 @@ PyImaging_Mapper(PyObject* self, PyObject* args)
|
|||
typedef struct ImagingBufferInstance {
|
||||
struct ImagingMemoryInstance im;
|
||||
PyObject* target;
|
||||
Py_buffer view;
|
||||
} ImagingBufferInstance;
|
||||
|
||||
static void
|
||||
|
@ -318,6 +319,7 @@ mapping_destroy_buffer(Imaging im)
|
|||
{
|
||||
ImagingBufferInstance* buffer = (ImagingBufferInstance*) im;
|
||||
|
||||
PyBuffer_Release(&buffer->view);
|
||||
Py_XDECREF(buffer->target);
|
||||
}
|
||||
|
||||
|
@ -326,10 +328,9 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
|
|||
{
|
||||
int y, size;
|
||||
Imaging im;
|
||||
char* ptr;
|
||||
int bytes;
|
||||
|
||||
PyObject* target;
|
||||
Py_buffer view;
|
||||
char* mode;
|
||||
char* codec;
|
||||
PyObject* bbox;
|
||||
|
@ -359,12 +360,14 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
|
|||
size = ysize * stride;
|
||||
|
||||
/* check buffer size */
|
||||
bytes = PyImaging_ReadBuffer(target, (const void**) &ptr);
|
||||
if (bytes < 0) {
|
||||
if (PyImaging_GetBuffer(target, &view) < 0)
|
||||
return NULL;
|
||||
|
||||
if (view.len < 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "buffer has negative size");
|
||||
return NULL;
|
||||
}
|
||||
if (offset + size > bytes) {
|
||||
if (offset + size > view.len) {
|
||||
PyErr_SetString(PyExc_ValueError, "buffer is not large enough");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -378,15 +381,16 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
|
|||
/* setup file pointers */
|
||||
if (ystep > 0)
|
||||
for (y = 0; y < ysize; y++)
|
||||
im->image[y] = ptr + offset + y * stride;
|
||||
im->image[y] = view.buf + offset + y * stride;
|
||||
else
|
||||
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;
|
||||
|
||||
Py_INCREF(target);
|
||||
((ImagingBufferInstance*) im)->target = target;
|
||||
((ImagingBufferInstance*) im)->view = view;
|
||||
|
||||
if (!ImagingNewEpilogue(im))
|
||||
return NULL;
|
||||
|
|
26
path.c
26
path.c
|
@ -46,7 +46,7 @@
|
|||
|
||||
/* compatibility wrappers (defined in _imaging.c) */
|
||||
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 */
|
||||
|
@ -134,16 +134,20 @@ PyPath_Flatten(PyObject* data, double **pxy)
|
|||
|
||||
if (PyImaging_CheckBuffer(data)) {
|
||||
/* Assume the buffer contains floats */
|
||||
float* ptr;
|
||||
int n = PyImaging_ReadBuffer(data, (const void**) &ptr);
|
||||
n /= 2 * sizeof(float);
|
||||
xy = alloc_array(n);
|
||||
if (!xy)
|
||||
return -1;
|
||||
for (i = 0; i < n+n; i++)
|
||||
xy[i] = ptr[i];
|
||||
*pxy = xy;
|
||||
return n;
|
||||
Py_buffer buffer;
|
||||
if (PyImaging_GetBuffer(data, &buffer) == 0) {
|
||||
int n = buffer.len / (2 * sizeof(float));
|
||||
float *ptr = (float*) buffer.buf;
|
||||
xy = alloc_array(n);
|
||||
if (!xy)
|
||||
return -1;
|
||||
for (i = 0; i < n+n; i++)
|
||||
xy[i] = ptr[i];
|
||||
*pxy = xy;
|
||||
PyBuffer_Release(&buffer);
|
||||
return n;
|
||||
}
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
if (!PySequence_Check(data)) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user