mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-25 05:01:26 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			149 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			149 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 (isModeI16(mode)) {
 | |
|             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->read_only = view.readonly;
 | |
|     im->destroy = mapping_destroy_buffer;
 | |
| 
 | |
|     Py_INCREF(target);
 | |
|     ((ImagingBufferInstance *)im)->target = target;
 | |
|     ((ImagingBufferInstance *)im)->view = view;
 | |
| 
 | |
|     return PyImagingNew(im);
 | |
| }
 |