From 0a3c852e1b549a9f72a4f14762dece2d84375e24 Mon Sep 17 00:00:00 2001 From: Alexander Date: Fri, 15 Sep 2017 17:34:13 +0300 Subject: [PATCH] work in ImagingAllocateArray with blocks --- libImaging/Imaging.h | 3 +- libImaging/Storage.c | 94 +++++++++++++++++++++++++++++++++----------- 2 files changed, 73 insertions(+), 24 deletions(-) diff --git a/libImaging/Imaging.h b/libImaging/Imaging.h index a48d373ee..d5b2a2a9d 100644 --- a/libImaging/Imaging.h +++ b/libImaging/Imaging.h @@ -94,7 +94,8 @@ struct ImagingMemoryInstance { /* Internals */ char **image; /* Actual raster data. */ - char *block; /* Set if data is allocated in a single block. */ + char *block; /* Set if data is allocated in a single block. */ + char **blocks; /* Memory blocks for pixel storage */ int pixelsize; /* Size of a pixel, in bytes (1, 2 or 4) */ int linesize; /* Size of a line, in bytes (xsize * pixelsize) */ diff --git a/libImaging/Storage.c b/libImaging/Storage.c index 0b5e742de..382877399 100644 --- a/libImaging/Storage.c +++ b/libImaging/Storage.c @@ -264,43 +264,91 @@ ImagingDelete(Imaging im) /* ------------------ */ /* Allocate image as an array of line buffers. */ +#define MEMORY_BLOCK_SIZE (1024*1024) +#define MEMORY_BLOCKS_COUNT 128 + +void **_blocks = NULL; +int _blocks_free = 0; + +void * +_get_block(int dirty) +{ + void *block; + if ( ! _blocks) { + _blocks = calloc(sizeof(void*), MEMORY_BLOCKS_COUNT); + } + if (_blocks_free > 0) { + _blocks_free -= 1; + block = _blocks[_blocks_free]; + if ( ! dirty) { + memset(block, 0, MEMORY_BLOCK_SIZE); + } + } else { + if (dirty) { + block = malloc(MEMORY_BLOCK_SIZE); + } else { + block = calloc(1, MEMORY_BLOCK_SIZE); + } + } + return block; +} + +void +_return_block(void *block) +{ + free(block); +} + + static void ImagingDestroyArray(Imaging im) { - int y; + int y = 0; - if (im->image) - for (y = 0; y < im->ysize; y++) - if (im->image[y]) - free(im->image[y]); + if (im->blocks) { + while (im->blocks[y]) { + _return_block(im->blocks[y]); + y ++; + } + free(im->blocks); + } } Imaging ImagingAllocateArray(Imaging im, int dirty) { - ImagingSectionCookie cookie; - - int y; + int y, line_in_block, current_block; char* p; + int lines_pre_block, blocks_count; - ImagingSectionEnter(&cookie); + lines_pre_block = MEMORY_BLOCK_SIZE / im->linesize; + blocks_count = (im->ysize + lines_pre_block - 1) / lines_pre_block; - /* Allocate image as an array of lines */ - for (y = 0; y < im->ysize; y++) { - /* malloc check linesize checked in prologue */ - if (dirty) { - p = (char *) malloc(im->linesize); - } else { - p = (char *) calloc(1, im->linesize); - } - if (!p) { - ImagingDestroyArray(im); - break; - } - im->image[y] = p; + /* One extra ponter is always NULL */ + im->blocks = (char **)calloc(sizeof(char *), blocks_count + 1); + if ( ! im->blocks) { + return (Imaging) ImagingError_MemoryError(); } - ImagingSectionLeave(&cookie); + /* Allocate image as an array of lines */ + for (y = 0, line_in_block = 0, current_block = 0; y < im->ysize; y++) { + if (line_in_block == 0) { + p = (char *)_get_block(dirty); + if ( ! p) { + ImagingDestroyArray(im); + break; + } + im->blocks[current_block] = p; + } + im->image[y] = p + im->linesize * line_in_block; + + line_in_block += 1; + if (line_in_block >= lines_pre_block) { + /* Reset counter and start new block */ + line_in_block = 0; + current_block += 1; + } + } if (y != im->ysize) { return (Imaging) ImagingError_MemoryError();