Merge pull request #448 from wiredfool/2gigapix-redux

2gigapix redux
This commit is contained in:
Alex Clark ☺ 2013-12-28 06:06:42 -08:00
commit 243160ee78
3 changed files with 95 additions and 58 deletions

View File

@ -0,0 +1,37 @@
from tester import *
# This test is not run automatically.
#
# It requires > 2gb memory for the >2 gigapixel image generated in the
# second test. Running this automatically would amount to a denial of
# service on our testing infrastructure. I expect this test to fail
# on any 32 bit machine, as well as any smallish things (like
# raspberrypis).
from PIL import Image
try:
import numpy as np
except:
skip()
ydim = 32769
xdim = 48000
f = tempfile('temp.png')
def _write_png(xdim,ydim):
dtype = np.uint8
a = np.zeros((xdim, ydim), dtype=dtype)
im = Image.fromarray(a, 'L')
im.save(f)
success()
def test_large():
""" succeeded prepatch"""
_write_png(xdim,ydim)
def test_2gpx():
"""failed prepatch"""
_write_png(xdim,xdim)

View File

@ -54,7 +54,7 @@ ImagingNewPrologueSubtype(const char *mode, unsigned xsize, unsigned ysize,
im = (Imaging) calloc(1, size);
if (!im)
return (Imaging) ImagingError_MemoryError();
return (Imaging) ImagingError_MemoryError();
/* Setup image descriptor */
im->xsize = xsize;
@ -106,7 +106,7 @@ ImagingNewPrologueSubtype(const char *mode, unsigned xsize, unsigned ysize,
im->type = IMAGING_TYPE_INT32;
} else if (strcmp(mode, "I;16") == 0 || strcmp(mode, "I;16L") == 0 \
|| strcmp(mode, "I;16B") == 0 || strcmp(mode, "I;16N") == 0) {
|| strcmp(mode, "I;16B") == 0 || strcmp(mode, "I;16N") == 0) {
/* EXPERIMENTAL */
/* 16-bit raw integer images */
im->bands = 1;
@ -203,8 +203,8 @@ ImagingNewPrologueSubtype(const char *mode, unsigned xsize, unsigned ysize,
ImagingSectionLeave(&cookie);
if (!im->image) {
free(im);
return (Imaging) ImagingError_MemoryError();
free(im);
return (Imaging) ImagingError_MemoryError();
}
ImagingNewCount++;
@ -227,16 +227,16 @@ ImagingNewEpilogue(Imaging im)
assume that it couldn't allocate the required amount of
memory. */
if (!im->destroy)
return (Imaging) ImagingError_MemoryError();
return (Imaging) ImagingError_MemoryError();
/* Initialize alias pointers to pixel data. */
switch (im->pixelsize) {
case 1: case 2: case 3:
im->image8 = (UINT8 **) im->image;
break;
im->image8 = (UINT8 **) im->image;
break;
case 4:
im->image32 = (INT32 **) im->image;
break;
im->image32 = (INT32 **) im->image;
break;
}
return im;
@ -246,16 +246,16 @@ void
ImagingDelete(Imaging im)
{
if (!im)
return;
return;
if (im->palette)
ImagingPaletteDelete(im->palette);
ImagingPaletteDelete(im->palette);
if (im->destroy)
im->destroy(im);
im->destroy(im);
if (im->image)
free(im->image);
free(im->image);
free(im);
}
@ -271,9 +271,9 @@ ImagingDestroyArray(Imaging im)
int y;
if (im->image)
for (y = 0; y < im->ysize; y++)
if (im->image[y])
free(im->image[y]);
for (y = 0; y < im->ysize; y++)
if (im->image[y])
free(im->image[y]);
}
Imaging
@ -287,24 +287,24 @@ ImagingNewArray(const char *mode, int xsize, int ysize)
im = ImagingNewPrologue(mode, xsize, ysize);
if (!im)
return NULL;
return NULL;
ImagingSectionEnter(&cookie);
/* Allocate image as an array of lines */
for (y = 0; y < im->ysize; y++) {
p = (char *) malloc(im->linesize);
if (!p) {
ImagingDestroyArray(im);
break;
}
p = (char *) malloc(im->linesize);
if (!p) {
ImagingDestroyArray(im);
break;
}
im->image[y] = p;
}
ImagingSectionLeave(&cookie);
if (y == im->ysize)
im->destroy = ImagingDestroyArray;
im->destroy = ImagingDestroyArray;
return ImagingNewEpilogue(im);
}
@ -318,22 +318,22 @@ static void
ImagingDestroyBlock(Imaging im)
{
if (im->block)
free(im->block);
free(im->block);
}
Imaging
ImagingNewBlock(const char *mode, int xsize, int ysize)
{
Imaging im;
int y, i;
int bytes;
Py_ssize_t y, i;
Py_ssize_t bytes;
im = ImagingNewPrologue(mode, xsize, ysize);
if (!im)
return NULL;
return NULL;
/* Use a single block */
bytes = im->ysize * im->linesize;
bytes = (Py_ssize_t) im->ysize * im->linesize;
if (bytes <= 0)
/* some platforms return NULL for malloc(0); this fix
prevents MemoryError on zero-sized images on such
@ -344,12 +344,12 @@ ImagingNewBlock(const char *mode, int xsize, int ysize)
if (im->block) {
memset(im->block, 0, bytes);
for (y = i = 0; y < im->ysize; y++) {
im->image[y] = im->block + i;
i += im->linesize;
}
for (y = i = 0; y < im->ysize; y++) {
im->image[y] = im->block + i;
i += im->linesize;
}
im->destroy = ImagingDestroyBlock;
im->destroy = ImagingDestroyBlock;
}
@ -360,9 +360,9 @@ ImagingNewBlock(const char *mode, int xsize, int ysize)
* Create a new, internally allocated, image.
*/
#if defined(IMAGING_SMALL_MODEL)
#define THRESHOLD 16384L
#define THRESHOLD 16384L
#else
#define THRESHOLD (2048*2048*4L)
#define THRESHOLD (2048*2048*4L)
#endif
Imaging
@ -418,6 +418,6 @@ ImagingCopyInfo(Imaging destination, Imaging source)
if (source->palette) {
if (destination->palette)
ImagingPaletteDelete(destination->palette);
destination->palette = ImagingPaletteDuplicate(source->palette);
destination->palette = ImagingPaletteDuplicate(source->palette);
}
}

44
map.c
View File

@ -66,7 +66,7 @@ PyImaging_MapperNew(const char* filename, int readonly)
mapper = PyObject_New(ImagingMapperObject, &ImagingMapperType);
if (mapper == NULL)
return NULL;
return NULL;
mapper->base = NULL;
mapper->size = mapper->offset = 0;
@ -94,7 +94,7 @@ PyImaging_MapperNew(const char* filename, int readonly)
PAGE_READONLY,
0, 0, NULL);
if (mapper->hMap == (HANDLE)-1) {
CloseHandle(mapper->hFile);
CloseHandle(mapper->hFile);
PyErr_SetString(PyExc_IOError, "cannot map file");
PyObject_Del(mapper);
return NULL;
@ -116,11 +116,11 @@ mapping_dealloc(ImagingMapperObject* mapper)
{
#ifdef WIN32
if (mapper->base != 0)
UnmapViewOfFile(mapper->base);
UnmapViewOfFile(mapper->base);
if (mapper->hMap != (HANDLE)-1)
CloseHandle(mapper->hMap);
CloseHandle(mapper->hMap);
if (mapper->hFile != (HANDLE)-1)
CloseHandle(mapper->hFile);
CloseHandle(mapper->hFile);
mapper->base = 0;
mapper->hMap = mapper->hFile = (HANDLE)-1;
#endif
@ -137,7 +137,7 @@ mapping_read(ImagingMapperObject* mapper, PyObject* args)
int size = -1;
if (!PyArg_ParseTuple(args, "|i", &size))
return NULL;
return NULL;
/* check size */
if (size < 0 || mapper->offset + size > mapper->size)
@ -147,7 +147,7 @@ mapping_read(ImagingMapperObject* mapper, PyObject* args)
buf = PyBytes_FromStringAndSize(NULL, size);
if (!buf)
return NULL;
return NULL;
if (size > 0) {
memcpy(PyBytes_AsString(buf), mapper->base + mapper->offset, size);
@ -163,7 +163,7 @@ mapping_seek(ImagingMapperObject* mapper, PyObject* args)
int offset;
int whence = 0;
if (!PyArg_ParseTuple(args, "i|i", &offset, &whence))
return NULL;
return NULL;
switch (whence) {
case 0: /* SEEK_SET */
@ -208,7 +208,7 @@ mapping_readimage(ImagingMapperObject* mapper, PyObject* args)
int orientation;
if (!PyArg_ParseTuple(args, "s(ii)ii", &mode, &xsize, &ysize,
&stride, &orientation))
return NULL;
return NULL;
if (stride <= 0) {
/* FIXME: maybe we should call ImagingNewPrologue instead */
@ -259,13 +259,13 @@ static struct PyMethodDef methods[] = {
};
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*/
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*/
@ -297,7 +297,7 @@ PyImaging_Mapper(PyObject* self, PyObject* args)
{
char* filename;
if (!PyArg_ParseTuple(args, "s", &filename))
return NULL;
return NULL;
return (PyObject*) PyImaging_MapperNew(filename, 1);
}
@ -323,7 +323,7 @@ mapping_destroy_buffer(Imaging im)
PyObject*
PyImaging_MapBuffer(PyObject* self, PyObject* args)
{
int y, size;
Py_ssize_t y, size;
Imaging im;
PyObject* target;
@ -331,14 +331,14 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
char* mode;
char* codec;
PyObject* bbox;
int offset;
Py_ssize_t offset;
int xsize, ysize;
int stride;
int ystep;
if (!PyArg_ParseTuple(args, "O(ii)sOi(sii)", &target, &xsize, &ysize,
if (!PyArg_ParseTuple(args, "O(ii)sOn(sii)", &target, &xsize, &ysize,
&codec, &bbox, &offset, &mode, &stride, &ystep))
return NULL;
return NULL;
if (!PyImaging_CheckBuffer(target)) {
PyErr_SetString(PyExc_TypeError, "expected string or buffer");
@ -354,7 +354,7 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
stride = xsize * 4;
}
size = ysize * stride;
size = (Py_ssize_t) ysize * stride;
/* check buffer size */
if (PyImaging_GetBuffer(target, &view) < 0)