mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +03:00 
			
		
		
		
	find * -type f "-(" -name "*.bdf" -o -name "*.c" -o -name "*.h" -o -name "*.py" -o -name "*.rst" -o -name "*.txt" "-)" -exec sed -e "s/[[:space:]]*$//" -i {} \;
		
	
			
		
			
				
	
	
		
			398 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			398 lines
		
	
	
		
			9.6 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 "Imaging.h"
 | 
						|
 | 
						|
#ifdef WIN32
 | 
						|
#define WIN32_LEAN_AND_MEAN
 | 
						|
#undef INT8
 | 
						|
#undef UINT8
 | 
						|
#undef INT16
 | 
						|
#undef UINT16
 | 
						|
#undef INT32
 | 
						|
#undef INT64
 | 
						|
#undef UINT32
 | 
						|
#include "windows.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#include "py3.h"
 | 
						|
 | 
						|
/* compatibility wrappers (defined in _imaging.c) */
 | 
						|
extern int PyImaging_CheckBuffer(PyObject* buffer);
 | 
						|
extern int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view);
 | 
						|
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
/* Standard mapper */
 | 
						|
 | 
						|
typedef struct {
 | 
						|
    PyObject_HEAD
 | 
						|
    char* base;
 | 
						|
    int   size;
 | 
						|
    int   offset;
 | 
						|
#ifdef WIN32
 | 
						|
    HANDLE hFile;
 | 
						|
    HANDLE hMap;
 | 
						|
#endif
 | 
						|
} ImagingMapperObject;
 | 
						|
 | 
						|
static PyTypeObject ImagingMapperType;
 | 
						|
 | 
						|
ImagingMapperObject*
 | 
						|
PyImaging_MapperNew(const char* filename, int readonly)
 | 
						|
{
 | 
						|
    ImagingMapperObject *mapper;
 | 
						|
 | 
						|
    if (PyType_Ready(&ImagingMapperType) < 0)
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    mapper = PyObject_New(ImagingMapperObject, &ImagingMapperType);
 | 
						|
    if (mapper == NULL)
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    mapper->base = NULL;
 | 
						|
    mapper->size = mapper->offset = 0;
 | 
						|
 | 
						|
#ifdef WIN32
 | 
						|
    mapper->hFile = (HANDLE)-1;
 | 
						|
    mapper->hMap  = (HANDLE)-1;
 | 
						|
 | 
						|
    /* FIXME: currently supports readonly mappings only */
 | 
						|
    mapper->hFile = CreateFile(
 | 
						|
        filename,
 | 
						|
        GENERIC_READ,
 | 
						|
        FILE_SHARE_READ,
 | 
						|
        NULL, OPEN_EXISTING,
 | 
						|
        FILE_ATTRIBUTE_NORMAL,
 | 
						|
        NULL);
 | 
						|
    if (mapper->hFile == (HANDLE)-1) {
 | 
						|
        PyErr_SetString(PyExc_IOError, "cannot open file");
 | 
						|
        PyObject_Del(mapper);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    mapper->hMap = CreateFileMapping(
 | 
						|
        mapper->hFile, NULL,
 | 
						|
        PAGE_READONLY,
 | 
						|
        0, 0, NULL);
 | 
						|
    if (mapper->hMap == (HANDLE)-1) {
 | 
						|
	CloseHandle(mapper->hFile);
 | 
						|
        PyErr_SetString(PyExc_IOError, "cannot map file");
 | 
						|
        PyObject_Del(mapper);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    mapper->base = (char*) MapViewOfFile(
 | 
						|
        mapper->hMap,
 | 
						|
        FILE_MAP_READ,
 | 
						|
        0, 0, 0);
 | 
						|
 | 
						|
    mapper->size = GetFileSize(mapper->hFile, 0);
 | 
						|
#endif
 | 
						|
 | 
						|
    return mapper;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
mapping_dealloc(ImagingMapperObject* mapper)
 | 
						|
{
 | 
						|
#ifdef WIN32
 | 
						|
    if (mapper->base != 0)
 | 
						|
	UnmapViewOfFile(mapper->base);
 | 
						|
    if (mapper->hMap != (HANDLE)-1)
 | 
						|
	CloseHandle(mapper->hMap);
 | 
						|
    if (mapper->hFile != (HANDLE)-1)
 | 
						|
	CloseHandle(mapper->hFile);
 | 
						|
    mapper->base = 0;
 | 
						|
    mapper->hMap = mapper->hFile = (HANDLE)-1;
 | 
						|
#endif
 | 
						|
    PyObject_Del(mapper);
 | 
						|
}
 | 
						|
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
/* standard file operations */
 | 
						|
 | 
						|
static PyObject*
 | 
						|
mapping_read(ImagingMapperObject* mapper, PyObject* args)
 | 
						|
{
 | 
						|
    PyObject* buf;
 | 
						|
 | 
						|
    int size = -1;
 | 
						|
    if (!PyArg_ParseTuple(args, "|i", &size))
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    /* check size */
 | 
						|
    if (size < 0 || mapper->offset + size > mapper->size)
 | 
						|
        size = mapper->size - mapper->offset;
 | 
						|
    if (size < 0)
 | 
						|
        size = 0;
 | 
						|
 | 
						|
    buf = PyBytes_FromStringAndSize(NULL, size);
 | 
						|
    if (!buf)
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    if (size > 0) {
 | 
						|
        memcpy(PyBytes_AsString(buf), mapper->base + mapper->offset, size);
 | 
						|
        mapper->offset += size;
 | 
						|
    }
 | 
						|
 | 
						|
    return buf;
 | 
						|
}
 | 
						|
 | 
						|
static PyObject*
 | 
						|
mapping_seek(ImagingMapperObject* mapper, PyObject* args)
 | 
						|
{
 | 
						|
    int offset;
 | 
						|
    int whence = 0;
 | 
						|
    if (!PyArg_ParseTuple(args, "i|i", &offset, &whence))
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    switch (whence) {
 | 
						|
        case 0: /* SEEK_SET */
 | 
						|
            mapper->offset = offset;
 | 
						|
            break;
 | 
						|
        case 1: /* SEEK_CUR */
 | 
						|
            mapper->offset += offset;
 | 
						|
            break;
 | 
						|
        case 2: /* SEEK_END */
 | 
						|
            mapper->offset = mapper->size + offset;
 | 
						|
            break;
 | 
						|
        default:
 | 
						|
            /* FIXME: raise ValueError? */
 | 
						|
            break;
 | 
						|
    }
 | 
						|
 | 
						|
    Py_INCREF(Py_None);
 | 
						|
    return Py_None;
 | 
						|
}
 | 
						|
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
/* map entire image */
 | 
						|
 | 
						|
extern PyObject*PyImagingNew(Imaging im);
 | 
						|
 | 
						|
static void
 | 
						|
ImagingDestroyMap(Imaging im)
 | 
						|
{
 | 
						|
    return; /* nothing to do! */
 | 
						|
}
 | 
						|
 | 
						|
static PyObject*
 | 
						|
mapping_readimage(ImagingMapperObject* mapper, PyObject* args)
 | 
						|
{
 | 
						|
    int y, size;
 | 
						|
    Imaging im;
 | 
						|
 | 
						|
    char* mode;
 | 
						|
    int xsize;
 | 
						|
    int ysize;
 | 
						|
    int stride;
 | 
						|
    int orientation;
 | 
						|
    if (!PyArg_ParseTuple(args, "s(ii)ii", &mode, &xsize, &ysize,
 | 
						|
                          &stride, &orientation))
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    if (stride <= 0) {
 | 
						|
        /* FIXME: maybe we should call ImagingNewPrologue instead */
 | 
						|
        if (!strcmp(mode, "L") || !strcmp(mode, "P"))
 | 
						|
            stride = xsize;
 | 
						|
        else if (!strcmp(mode, "I;16") || !strcmp(mode, "I;16B"))
 | 
						|
            stride = xsize * 2;
 | 
						|
        else
 | 
						|
            stride = xsize * 4;
 | 
						|
    }
 | 
						|
 | 
						|
    size = ysize * stride;
 | 
						|
 | 
						|
    if (mapper->offset + size > mapper->size) {
 | 
						|
        PyErr_SetString(PyExc_IOError, "image file truncated");
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    im = ImagingNewPrologue(mode, xsize, ysize);
 | 
						|
    if (!im)
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    /* setup file pointers */
 | 
						|
    if (orientation > 0)
 | 
						|
        for (y = 0; y < ysize; y++)
 | 
						|
            im->image[y] = mapper->base + mapper->offset + y * stride;
 | 
						|
    else
 | 
						|
        for (y = 0; y < ysize; y++)
 | 
						|
            im->image[ysize-y-1] = mapper->base + mapper->offset + y * stride;
 | 
						|
 | 
						|
    im->destroy = ImagingDestroyMap;
 | 
						|
 | 
						|
    if (!ImagingNewEpilogue(im))
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    mapper->offset += size;
 | 
						|
 | 
						|
    return PyImagingNew(im);
 | 
						|
}
 | 
						|
 | 
						|
static struct PyMethodDef methods[] = {
 | 
						|
    /* standard file interface */
 | 
						|
    {"read", (PyCFunction)mapping_read, 1},
 | 
						|
    {"seek", (PyCFunction)mapping_seek, 1},
 | 
						|
    /* extensions */
 | 
						|
    {"readimage", (PyCFunction)mapping_readimage, 1},
 | 
						|
    {NULL, NULL} /* sentinel */
 | 
						|
};
 | 
						|
 | 
						|
static PyTypeObject ImagingMapperType = {
 | 
						|
	PyVarObject_HEAD_INIT(NULL, 0)
 | 
						|
	"ImagingMapper",		/*tp_name*/
 | 
						|
	sizeof(ImagingMapperObject),	/*tp_size*/
 | 
						|
	0,				/*tp_itemsize*/
 | 
						|
	/* methods */
 | 
						|
	(destructor)mapping_dealloc,	/*tp_dealloc*/
 | 
						|
	0,				/*tp_print*/
 | 
						|
    0,                          /*tp_getattr*/
 | 
						|
    0,                          /*tp_setattr*/
 | 
						|
    0,                          /*tp_compare*/
 | 
						|
    0,                          /*tp_repr*/
 | 
						|
    0,                          /*tp_as_number */
 | 
						|
    0,                          /*tp_as_sequence */
 | 
						|
    0,                          /*tp_as_mapping */
 | 
						|
    0,                          /*tp_hash*/
 | 
						|
    0,                          /*tp_call*/
 | 
						|
    0,                          /*tp_str*/
 | 
						|
    0,                          /*tp_getattro*/
 | 
						|
    0,                          /*tp_setattro*/
 | 
						|
    0,                          /*tp_as_buffer*/
 | 
						|
    Py_TPFLAGS_DEFAULT,         /*tp_flags*/
 | 
						|
    0,                          /*tp_doc*/
 | 
						|
    0,                          /*tp_traverse*/
 | 
						|
    0,                          /*tp_clear*/
 | 
						|
    0,                          /*tp_richcompare*/
 | 
						|
    0,                          /*tp_weaklistoffset*/
 | 
						|
    0,                          /*tp_iter*/
 | 
						|
    0,                          /*tp_iternext*/
 | 
						|
    methods,                    /*tp_methods*/
 | 
						|
    0,                          /*tp_members*/
 | 
						|
    0,                          /*tp_getset*/
 | 
						|
};
 | 
						|
 | 
						|
PyObject*
 | 
						|
PyImaging_Mapper(PyObject* self, PyObject* args)
 | 
						|
{
 | 
						|
    char* filename;
 | 
						|
    if (!PyArg_ParseTuple(args, "s", &filename))
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    return (PyObject*) PyImaging_MapperNew(filename, 1);
 | 
						|
}
 | 
						|
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
/* 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)
 | 
						|
{
 | 
						|
    int y, size;
 | 
						|
    Imaging im;
 | 
						|
 | 
						|
    PyObject* target;
 | 
						|
    Py_buffer view;
 | 
						|
    char* mode;
 | 
						|
    char* codec;
 | 
						|
    PyObject* bbox;
 | 
						|
    int offset;
 | 
						|
    int xsize, ysize;
 | 
						|
    int stride;
 | 
						|
    int ystep;
 | 
						|
 | 
						|
    if (!PyArg_ParseTuple(args, "O(ii)sOi(sii)", &target, &xsize, &ysize,
 | 
						|
                          &codec, &bbox, &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;
 | 
						|
    }
 | 
						|
 | 
						|
    size = ysize * stride;
 | 
						|
 | 
						|
    /* check buffer size */
 | 
						|
    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 > view.len) {
 | 
						|
        PyErr_SetString(PyExc_ValueError, "buffer is not large enough");
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    im = ImagingNewPrologueSubtype(
 | 
						|
        mode, xsize, ysize, sizeof(ImagingBufferInstance)
 | 
						|
        );
 | 
						|
    if (!im)
 | 
						|
        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;
 | 
						|
 | 
						|
    if (!ImagingNewEpilogue(im))
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    return PyImagingNew(im);
 | 
						|
}
 | 
						|
 |