Merge pull request #2654 from python-pillow/storage-cleanup

Storage cleanup
This commit is contained in:
wiredfool 2017-08-16 12:00:32 +01:00 committed by GitHub
commit e7aa155b72
4 changed files with 86 additions and 86 deletions

View File

@ -7,6 +7,25 @@ import sys
class TestImage(PillowTestCase): class TestImage(PillowTestCase):
def test_image_modes_success(self):
for mode in [
'1', 'P', 'PA',
'L', 'LA', 'La',
'F', 'I', 'I;16', 'I;16L', 'I;16B', 'I;16N',
'RGB', 'RGBX', 'RGBA', 'RGBa',
'CMYK', 'YCbCr', 'LAB', 'HSV',
]:
Image.new(mode, (1, 1))
def test_image_modes_fail(self):
for mode in [
'', 'bad', 'very very long',
'BGR;15', 'BGR;16', 'BGR;24', 'BGR;32'
]:
with self.assertRaises(ValueError) as e:
Image.new(mode, (1, 1));
self.assertEqual(str(e.exception), 'unrecognized image mode')
def test_sanity(self): def test_sanity(self):
im = Image.new("L", (100, 100)) im = Image.new("L", (100, 100))

View File

@ -163,7 +163,6 @@ extern Imaging ImagingNew2(const char* mode, Imaging imOut, Imaging imIn);
extern void ImagingDelete(Imaging im); extern void ImagingDelete(Imaging im);
extern Imaging ImagingNewBlock(const char* mode, int xsize, int ysize); extern Imaging ImagingNewBlock(const char* mode, int xsize, int ysize);
extern Imaging ImagingNewArray(const char* mode, int xsize, int ysize);
extern Imaging ImagingNewMap(const char* filename, int readonly, extern Imaging ImagingNewMap(const char* filename, int readonly,
const char* mode, int xsize, int ysize); const char* mode, int xsize, int ysize);
@ -172,7 +171,6 @@ extern Imaging ImagingNewPrologue(const char *mode,
extern Imaging ImagingNewPrologueSubtype(const char *mode, extern Imaging ImagingNewPrologueSubtype(const char *mode,
int xsize, int ysize, int xsize, int ysize,
int structure_size); int structure_size);
extern Imaging ImagingNewEpilogue(Imaging im);
extern void ImagingCopyInfo(Imaging destination, Imaging source); extern void ImagingCopyInfo(Imaging destination, Imaging source);

View File

@ -46,21 +46,20 @@ int ImagingNewCount = 0;
*/ */
Imaging Imaging
ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
int size)
{ {
Imaging im; Imaging im;
ImagingSectionCookie cookie;
im = (Imaging) calloc(1, size);
if (!im)
return (Imaging) ImagingError_MemoryError();
/* linesize overflow check, roughly the current largest space req'd */ /* linesize overflow check, roughly the current largest space req'd */
if (xsize > (INT_MAX / 4) - 1) { if (xsize > (INT_MAX / 4) - 1) {
return (Imaging) ImagingError_MemoryError(); return (Imaging) ImagingError_MemoryError();
} }
im = (Imaging) calloc(1, size);
if (!im) {
return (Imaging) ImagingError_MemoryError();
}
/* Setup image descriptor */ /* Setup image descriptor */
im->xsize = xsize; im->xsize = xsize;
im->ysize = ysize; im->ysize = ysize;
@ -206,47 +205,21 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize,
} else { } else {
free(im); free(im);
return (Imaging) ImagingError_ValueError("unrecognized mode"); return (Imaging) ImagingError_ValueError("unrecognized image mode");
} }
/* Setup image descriptor */ /* Setup image descriptor */
strcpy(im->mode, mode); strcpy(im->mode, mode);
ImagingSectionEnter(&cookie);
/* Pointer array (allocate at least one line, to avoid MemoryError /* Pointer array (allocate at least one line, to avoid MemoryError
exceptions on platforms where calloc(0, x) returns NULL) */ exceptions on platforms where calloc(0, x) returns NULL) */
im->image = (char **) calloc((ysize > 0) ? ysize : 1, sizeof(void *)); im->image = (char **) calloc((ysize > 0) ? ysize : 1, sizeof(void *));
ImagingSectionLeave(&cookie); if ( ! im->image) {
if (!im->image) {
free(im); free(im);
return (Imaging) ImagingError_MemoryError(); return (Imaging) ImagingError_MemoryError();
} }
ImagingNewCount++;
return im;
}
Imaging
ImagingNewPrologue(const char *mode, int xsize, int ysize)
{
return ImagingNewPrologueSubtype(
mode, xsize, ysize, sizeof(struct ImagingMemoryInstance)
);
}
Imaging
ImagingNewEpilogue(Imaging im)
{
/* If the raster data allocator didn't setup a destructor,
assume that it couldn't allocate the required amount of
memory. */
if (!im->destroy)
return (Imaging) ImagingError_MemoryError();
/* Initialize alias pointers to pixel data. */ /* Initialize alias pointers to pixel data. */
switch (im->pixelsize) { switch (im->pixelsize) {
case 1: case 2: case 3: case 1: case 2: case 3:
@ -257,9 +230,18 @@ ImagingNewEpilogue(Imaging im)
break; break;
} }
ImagingNewCount++;
return im; return im;
} }
Imaging
ImagingNewPrologue(const char *mode, int xsize, int ysize)
{
return ImagingNewPrologueSubtype(
mode, xsize, ysize, sizeof(struct ImagingMemoryInstance));
}
void void
ImagingDelete(Imaging im) ImagingDelete(Imaging im)
{ {
@ -295,18 +277,13 @@ ImagingDestroyArray(Imaging im)
} }
Imaging Imaging
ImagingNewArray(const char *mode, int xsize, int ysize) ImagingAllocateArray(Imaging im)
{ {
Imaging im;
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
int y; int y;
char* p; char* p;
im = ImagingNewPrologue(mode, xsize, ysize);
if (!im)
return NULL;
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
/* Allocate image as an array of lines */ /* Allocate image as an array of lines */
@ -322,10 +299,13 @@ ImagingNewArray(const char *mode, int xsize, int ysize)
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
if (y == im->ysize) if (y != im->ysize) {
return (Imaging) ImagingError_MemoryError();
}
im->destroy = ImagingDestroyArray; im->destroy = ImagingDestroyArray;
return ImagingNewEpilogue(im); return im;
} }
@ -341,15 +321,10 @@ ImagingDestroyBlock(Imaging im)
} }
Imaging Imaging
ImagingNewBlock(const char *mode, int xsize, int ysize) ImagingAllocateBlock(Imaging im)
{ {
Imaging im;
Py_ssize_t y, i; Py_ssize_t y, i;
im = ImagingNewPrologue(mode, xsize, ysize);
if (!im)
return NULL;
/* We shouldn't overflow, since the threshold defined /* We shouldn't overflow, since the threshold defined
below says that we're only going to allocate max 4M below says that we're only going to allocate max 4M
here before going to the array allocator. Check anyway. here before going to the array allocator. Check anyway.
@ -357,7 +332,7 @@ ImagingNewBlock(const char *mode, int xsize, int ysize)
if (im->linesize && if (im->linesize &&
im->ysize > INT_MAX / im->linesize) { im->ysize > INT_MAX / im->linesize) {
/* punt if we're going to overflow */ /* punt if we're going to overflow */
return NULL; return (Imaging) ImagingError_MemoryError();
} }
if (im->ysize * im->linesize <= 0) { if (im->ysize * im->linesize <= 0) {
@ -370,7 +345,10 @@ ImagingNewBlock(const char *mode, int xsize, int ysize)
im->block = (char *) calloc(im->ysize, im->linesize); im->block = (char *) calloc(im->ysize, im->linesize);
} }
if (im->block) { if ( ! im->block) {
return (Imaging) ImagingError_MemoryError();
}
for (y = i = 0; y < im->ysize; y++) { for (y = i = 0; y < im->ysize; y++) {
im->image[y] = im->block + i; im->image[y] = im->block + i;
i += im->linesize; i += im->linesize;
@ -378,9 +356,7 @@ ImagingNewBlock(const char *mode, int xsize, int ysize)
im->destroy = ImagingDestroyBlock; im->destroy = ImagingDestroyBlock;
} return im;
return ImagingNewEpilogue(im);
} }
/* -------------------------------------------------------------------- /* --------------------------------------------------------------------
@ -395,33 +371,47 @@ ImagingNewBlock(const char *mode, int xsize, int ysize)
Imaging Imaging
ImagingNew(const char* mode, int xsize, int ysize) ImagingNew(const char* mode, int xsize, int ysize)
{ {
int bytes;
Imaging im; Imaging im;
if (strcmp(mode, "") == 0)
return (Imaging) ImagingError_ValueError("empty mode");
if (strlen(mode) == 1) {
if (mode[0] == 'F' || mode[0] == 'I')
bytes = 4;
else
bytes = 1;
} else
bytes = strlen(mode); /* close enough */
if (xsize < 0 || ysize < 0) { if (xsize < 0 || ysize < 0) {
return (Imaging) ImagingError_ValueError("bad image size"); return (Imaging) ImagingError_ValueError("bad image size");
} }
if ((int64_t) xsize * (int64_t) ysize <= THRESHOLD / bytes) { im = ImagingNewPrologue(mode, xsize, ysize);
im = ImagingNewBlock(mode, xsize, ysize); if ( ! im)
if (im) return NULL;
if (im->ysize && im->linesize <= THRESHOLD / im->ysize) {
if (ImagingAllocateBlock(im)) {
return im; return im;
}
/* assume memory error; try allocating in array mode instead */ /* assume memory error; try allocating in array mode instead */
ImagingError_Clear(); ImagingError_Clear();
} }
return ImagingNewArray(mode, xsize, ysize); if (ImagingAllocateArray(im)) {
return im;
}
ImagingDelete(im);
return NULL;
}
Imaging
ImagingNewBlock(const char* mode, int xsize, int ysize)
{
Imaging im;
im = ImagingNewPrologue(mode, xsize, ysize);
if ( ! im)
return NULL;
if (ImagingAllocateBlock(im)) {
return im;
}
ImagingDelete(im);
return NULL;
} }
Imaging Imaging

9
map.c
View File

@ -229,9 +229,6 @@ mapping_readimage(ImagingMapperObject* mapper, PyObject* args)
im->destroy = ImagingDestroyMap; im->destroy = ImagingDestroyMap;
if (!ImagingNewEpilogue(im))
return NULL;
mapper->offset += size; mapper->offset += size;
return PyImagingNew(im); return PyImagingNew(im);
@ -368,8 +365,7 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
} }
im = ImagingNewPrologueSubtype( im = ImagingNewPrologueSubtype(
mode, xsize, ysize, sizeof(ImagingBufferInstance) mode, xsize, ysize, sizeof(ImagingBufferInstance));
);
if (!im) if (!im)
return NULL; return NULL;
@ -387,9 +383,6 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
((ImagingBufferInstance*) im)->target = target; ((ImagingBufferInstance*) im)->target = target;
((ImagingBufferInstance*) im)->view = view; ((ImagingBufferInstance*) im)->view = view;
if (!ImagingNewEpilogue(im))
return NULL;
return PyImagingNew(im); return PyImagingNew(im);
} }