mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-14 19:36:38 +03:00
limit allocated memory to lines_per_block * linesize size
allocate block for wider lines
This commit is contained in:
parent
d4a1f7a01a
commit
f2123b4222
|
@ -265,30 +265,34 @@ ImagingDelete(Imaging im)
|
||||||
/* Allocate image as an array of line buffers. */
|
/* Allocate image as an array of line buffers. */
|
||||||
|
|
||||||
#define MEMORY_BLOCK_SIZE (1024*1024)
|
#define MEMORY_BLOCK_SIZE (1024*1024)
|
||||||
#define MEMORY_MAX_BLOCKS 0
|
#define MEMORY_CACHE_BLOCKS 0
|
||||||
#define MEMORY_ALIGN_LINES 64
|
#define MEMORY_ALIGN_LINES 1
|
||||||
|
|
||||||
void **_blocks = NULL;
|
void **_blocks = NULL;
|
||||||
int _blocks_free = 0;
|
int _blocks_free = 0;
|
||||||
|
|
||||||
void *
|
void *
|
||||||
_get_block(int dirty)
|
_get_block(int requested_size, int dirty)
|
||||||
{
|
{
|
||||||
void *block;
|
void *block;
|
||||||
if ( ! _blocks) {
|
if ( ! _blocks) {
|
||||||
_blocks = calloc(sizeof(void*), MEMORY_MAX_BLOCKS);
|
_blocks = calloc(sizeof(void*), MEMORY_CACHE_BLOCKS);
|
||||||
}
|
}
|
||||||
if (_blocks_free > 0) {
|
if (_blocks_free > 0) {
|
||||||
_blocks_free -= 1;
|
_blocks_free -= 1;
|
||||||
block = _blocks[_blocks_free];
|
block = realloc(_blocks[_blocks_free], requested_size);
|
||||||
|
if ( ! block) {
|
||||||
|
free(_blocks[_blocks_free]);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if ( ! dirty) {
|
if ( ! dirty) {
|
||||||
memset(block, 0, MEMORY_BLOCK_SIZE);
|
memset(block, 0, requested_size);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
block = malloc(MEMORY_BLOCK_SIZE);
|
block = malloc(requested_size);
|
||||||
} else {
|
} else {
|
||||||
block = calloc(1, MEMORY_BLOCK_SIZE);
|
block = calloc(1, requested_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return block;
|
return block;
|
||||||
|
@ -297,7 +301,7 @@ _get_block(int dirty)
|
||||||
void
|
void
|
||||||
_return_block(void *block)
|
_return_block(void *block)
|
||||||
{
|
{
|
||||||
if (_blocks_free < MEMORY_MAX_BLOCKS) {
|
if (_blocks_free < MEMORY_CACHE_BLOCKS) {
|
||||||
_blocks[_blocks_free] = block;
|
_blocks[_blocks_free] = block;
|
||||||
_blocks_free += 1;
|
_blocks_free += 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -325,11 +329,14 @@ ImagingAllocateArray(Imaging im, int dirty)
|
||||||
{
|
{
|
||||||
int y, line_in_block, current_block;
|
int y, line_in_block, current_block;
|
||||||
char* p;
|
char* p;
|
||||||
int lines_pre_block, blocks_count, linesize;
|
int linesize, lines_per_block, blocks_count;
|
||||||
|
|
||||||
|
linesize = (im->linesize + MEMORY_ALIGN_LINES - 1) & -MEMORY_ALIGN_LINES;
|
||||||
|
lines_per_block = MEMORY_BLOCK_SIZE / linesize;
|
||||||
|
if (lines_per_block <= 0)
|
||||||
|
lines_per_block = 1;
|
||||||
|
blocks_count = (im->ysize + lines_per_block - 1) / lines_per_block;
|
||||||
|
|
||||||
linesize = ((im->linesize - 1) / MEMORY_ALIGN_LINES + 1) * MEMORY_ALIGN_LINES;
|
|
||||||
lines_pre_block = MEMORY_BLOCK_SIZE / linesize;
|
|
||||||
blocks_count = (im->ysize + lines_pre_block - 1) / lines_pre_block;
|
|
||||||
|
|
||||||
/* One extra ponter is always NULL */
|
/* One extra ponter is always NULL */
|
||||||
im->blocks = (char **)calloc(sizeof(char *), blocks_count + 1);
|
im->blocks = (char **)calloc(sizeof(char *), blocks_count + 1);
|
||||||
|
@ -340,17 +347,18 @@ ImagingAllocateArray(Imaging im, int dirty)
|
||||||
/* Allocate image as an array of lines */
|
/* Allocate image as an array of lines */
|
||||||
for (y = 0, line_in_block = 0, current_block = 0; y < im->ysize; y++) {
|
for (y = 0, line_in_block = 0, current_block = 0; y < im->ysize; y++) {
|
||||||
if (line_in_block == 0) {
|
if (line_in_block == 0) {
|
||||||
p = (char *)_get_block(dirty);
|
p = (char *)_get_block(lines_per_block * linesize, dirty);
|
||||||
if ( ! p) {
|
if ( ! p) {
|
||||||
ImagingDestroyArray(im);
|
ImagingDestroyArray(im);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
im->blocks[current_block] = p;
|
im->blocks[current_block] = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
im->image[y] = p + linesize * line_in_block;
|
im->image[y] = p + linesize * line_in_block;
|
||||||
|
|
||||||
line_in_block += 1;
|
line_in_block += 1;
|
||||||
if (line_in_block >= lines_pre_block) {
|
if (line_in_block >= lines_per_block) {
|
||||||
/* Reset counter and start new block */
|
/* Reset counter and start new block */
|
||||||
line_in_block = 0;
|
line_in_block = 0;
|
||||||
current_block += 1;
|
current_block += 1;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user