Pillow/src/map.c

147 lines
3.5 KiB
C
Raw Permalink Normal View History

2010-07-31 06:52:47 +04:00
/*
* 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"
2010-07-31 06:52:47 +04:00
/* compatibility wrappers (defined in _imaging.c) */
2021-01-03 06:17:51 +03:00
extern int
PyImaging_CheckBuffer(PyObject *buffer);
extern int
PyImaging_GetBuffer(PyObject *buffer, Py_buffer *view);
2010-07-31 06:52:47 +04:00
2021-01-03 06:17:51 +03:00
extern PyObject *
PyImagingNew(Imaging im);
2010-07-31 06:52:47 +04:00
/* -------------------------------------------------------------------- */
/* Buffer mapper */
typedef struct ImagingBufferInstance {
struct ImagingMemoryInstance im;
2021-01-03 06:17:51 +03:00
PyObject *target;
Py_buffer view;
2010-07-31 06:52:47 +04:00
} ImagingBufferInstance;
static void
2021-01-03 06:17:51 +03:00
mapping_destroy_buffer(Imaging im) {
ImagingBufferInstance *buffer = (ImagingBufferInstance *)im;
PyBuffer_Release(&buffer->view);
2010-07-31 06:52:47 +04:00
Py_XDECREF(buffer->target);
}
2021-01-03 06:17:51 +03:00
PyObject *
PyImaging_MapBuffer(PyObject *self, PyObject *args) {
2013-12-14 03:13:19 +04:00
Py_ssize_t y, size;
2010-07-31 06:52:47 +04:00
Imaging im;
2021-01-03 06:17:51 +03:00
PyObject *target;
Py_buffer view;
2021-01-03 06:17:51 +03:00
char *mode;
char *codec;
2013-12-14 03:13:19 +04:00
Py_ssize_t offset;
2010-07-31 06:52:47 +04:00
int xsize, ysize;
int stride;
int ystep;
2021-01-03 06:17:51 +03:00
if (!PyArg_ParseTuple(
args,
"O(ii)sn(sii)",
&target,
&xsize,
&ysize,
&codec,
&offset,
&mode,
&stride,
&ystep)) {
return NULL;
2020-05-10 12:56:36 +03:00
}
2010-07-31 06:52:47 +04:00
if (!PyImaging_CheckBuffer(target)) {
PyErr_SetString(PyExc_TypeError, "expected string or buffer");
return NULL;
}
if (stride <= 0) {
2020-05-10 12:56:36 +03:00
if (!strcmp(mode, "L") || !strcmp(mode, "P")) {
2010-07-31 06:52:47 +04:00
stride = xsize;
2020-05-10 12:56:36 +03:00
} else if (!strncmp(mode, "I;16", 4)) {
2010-07-31 06:52:47 +04:00
stride = xsize * 2;
2020-05-10 12:56:36 +03:00
} else {
2010-07-31 06:52:47 +04:00
stride = xsize * 4;
2020-05-10 12:56:36 +03:00
}
2010-07-31 06:52:47 +04:00
}
if (stride > 0 && ysize > PY_SSIZE_T_MAX / stride) {
2016-09-29 17:05:00 +03:00
PyErr_SetString(PyExc_MemoryError, "Integer overflow in ysize");
return NULL;
}
2021-01-03 06:17:51 +03:00
size = (Py_ssize_t)ysize * stride;
2016-09-29 17:05:00 +03:00
if (offset > PY_SSIZE_T_MAX - size) {
2016-09-29 17:05:00 +03:00
PyErr_SetString(PyExc_MemoryError, "Integer overflow in offset");
return NULL;
2017-02-22 09:28:20 +03:00
}
2010-07-31 06:52:47 +04:00
/* check buffer size */
2020-05-10 12:56:36 +03:00
if (PyImaging_GetBuffer(target, &view) < 0) {
return NULL;
2020-05-10 12:56:36 +03:00
}
if (view.len < 0) {
2010-07-31 06:52:47 +04:00
PyErr_SetString(PyExc_ValueError, "buffer has negative size");
PyBuffer_Release(&view);
2010-07-31 06:52:47 +04:00
return NULL;
}
if (offset + size > view.len) {
2010-07-31 06:52:47 +04:00
PyErr_SetString(PyExc_ValueError, "buffer is not large enough");
PyBuffer_Release(&view);
2010-07-31 06:52:47 +04:00
return NULL;
}
2021-01-03 06:17:51 +03:00
im = ImagingNewPrologueSubtype(mode, xsize, ysize, sizeof(ImagingBufferInstance));
if (!im) {
PyBuffer_Release(&view);
2010-07-31 06:52:47 +04:00
return NULL;
}
2010-07-31 06:52:47 +04:00
/* setup file pointers */
2020-05-10 12:56:36 +03:00
if (ystep > 0) {
for (y = 0; y < ysize; y++) {
2021-01-03 06:17:51 +03:00
im->image[y] = (char *)view.buf + offset + y * stride;
2020-05-10 12:56:36 +03:00
}
} else {
for (y = 0; y < ysize; y++) {
2021-01-03 06:17:51 +03:00
im->image[ysize - y - 1] = (char *)view.buf + offset + y * stride;
2020-05-10 12:56:36 +03:00
}
}
2010-07-31 06:52:47 +04:00
im->destroy = mapping_destroy_buffer;
Py_INCREF(target);
2021-01-03 06:17:51 +03:00
((ImagingBufferInstance *)im)->target = target;
((ImagingBufferInstance *)im)->view = view;
2010-07-31 06:52:47 +04:00
return PyImagingNew(im);
}