mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-27 10:26:19 +03:00
147 lines
3.5 KiB
C
147 lines
3.5 KiB
C
/*
|
|
* The Python Imaging Library.
|
|
*
|
|
* standard memory mapping interface for the Imaging library
|
|
*
|
|
* history:
|
|
* 1998-03-05 fl added Win32 read mapping
|
|
* 1999-02-06 fl added "I;16" support
|
|
* 2003-04-21 fl added PyImaging_MapBuffer primitive
|
|
*
|
|
* Copyright (c) 1998-2003 by Secret Labs AB.
|
|
* Copyright (c) 2003 by Fredrik Lundh.
|
|
*
|
|
* See the README file for information on usage and redistribution.
|
|
*/
|
|
|
|
/*
|
|
* FIXME: should move the memory mapping primitives into libImaging!
|
|
*/
|
|
|
|
#include "Python.h"
|
|
|
|
#include "libImaging/Imaging.h"
|
|
|
|
/* compatibility wrappers (defined in _imaging.c) */
|
|
extern int
|
|
PyImaging_CheckBuffer(PyObject *buffer);
|
|
extern int
|
|
PyImaging_GetBuffer(PyObject *buffer, Py_buffer *view);
|
|
|
|
extern PyObject *
|
|
PyImagingNew(Imaging im);
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Buffer mapper */
|
|
|
|
typedef struct ImagingBufferInstance {
|
|
struct ImagingMemoryInstance im;
|
|
PyObject *target;
|
|
Py_buffer view;
|
|
} ImagingBufferInstance;
|
|
|
|
static void
|
|
mapping_destroy_buffer(Imaging im) {
|
|
ImagingBufferInstance *buffer = (ImagingBufferInstance *)im;
|
|
|
|
PyBuffer_Release(&buffer->view);
|
|
Py_XDECREF(buffer->target);
|
|
}
|
|
|
|
PyObject *
|
|
PyImaging_MapBuffer(PyObject *self, PyObject *args) {
|
|
Py_ssize_t y, size;
|
|
Imaging im;
|
|
|
|
PyObject *target;
|
|
Py_buffer view;
|
|
char *mode;
|
|
char *codec;
|
|
Py_ssize_t offset;
|
|
int xsize, ysize;
|
|
int stride;
|
|
int ystep;
|
|
|
|
if (!PyArg_ParseTuple(
|
|
args,
|
|
"O(ii)sn(sii)",
|
|
&target,
|
|
&xsize,
|
|
&ysize,
|
|
&codec,
|
|
&offset,
|
|
&mode,
|
|
&stride,
|
|
&ystep)) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!PyImaging_CheckBuffer(target)) {
|
|
PyErr_SetString(PyExc_TypeError, "expected string or buffer");
|
|
return NULL;
|
|
}
|
|
|
|
if (stride <= 0) {
|
|
if (!strcmp(mode, "L") || !strcmp(mode, "P")) {
|
|
stride = xsize;
|
|
} else if (!strncmp(mode, "I;16", 4)) {
|
|
stride = xsize * 2;
|
|
} else {
|
|
stride = xsize * 4;
|
|
}
|
|
}
|
|
|
|
if (stride > 0 && ysize > PY_SSIZE_T_MAX / stride) {
|
|
PyErr_SetString(PyExc_MemoryError, "Integer overflow in ysize");
|
|
return NULL;
|
|
}
|
|
|
|
size = (Py_ssize_t)ysize * stride;
|
|
|
|
if (offset > PY_SSIZE_T_MAX - size) {
|
|
PyErr_SetString(PyExc_MemoryError, "Integer overflow in offset");
|
|
return NULL;
|
|
}
|
|
|
|
/* check buffer size */
|
|
if (PyImaging_GetBuffer(target, &view) < 0) {
|
|
return NULL;
|
|
}
|
|
|
|
if (view.len < 0) {
|
|
PyErr_SetString(PyExc_ValueError, "buffer has negative size");
|
|
PyBuffer_Release(&view);
|
|
return NULL;
|
|
}
|
|
if (offset + size > view.len) {
|
|
PyErr_SetString(PyExc_ValueError, "buffer is not large enough");
|
|
PyBuffer_Release(&view);
|
|
return NULL;
|
|
}
|
|
|
|
im = ImagingNewPrologueSubtype(mode, xsize, ysize, sizeof(ImagingBufferInstance));
|
|
if (!im) {
|
|
PyBuffer_Release(&view);
|
|
return NULL;
|
|
}
|
|
|
|
/* setup file pointers */
|
|
if (ystep > 0) {
|
|
for (y = 0; y < ysize; y++) {
|
|
im->image[y] = (char *)view.buf + offset + y * stride;
|
|
}
|
|
} else {
|
|
for (y = 0; y < ysize; y++) {
|
|
im->image[ysize - y - 1] = (char *)view.buf + offset + y * stride;
|
|
}
|
|
}
|
|
|
|
im->destroy = mapping_destroy_buffer;
|
|
|
|
Py_INCREF(target);
|
|
((ImagingBufferInstance *)im)->target = target;
|
|
((ImagingBufferInstance *)im)->view = view;
|
|
|
|
return PyImagingNew(im);
|
|
}
|