mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-05 22:20:54 +03:00
python api for resources
This commit is contained in:
parent
53dde3b7f6
commit
af3dcf84af
|
@ -305,9 +305,9 @@ class CoreResampleAlphaCorrectTest(PillowTestCase):
|
||||||
class CoreResamplePassesTest(PillowTestCase):
|
class CoreResamplePassesTest(PillowTestCase):
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def count(self, diff):
|
def count(self, diff):
|
||||||
count = Image.core.getcount()
|
count = Image.core.get_stats()['new_count']
|
||||||
yield
|
yield
|
||||||
self.assertEqual(Image.core.getcount() - count, diff)
|
self.assertEqual(Image.core.get_stats()['new_count'] - count, diff)
|
||||||
|
|
||||||
def test_horizontal(self):
|
def test_horizontal(self):
|
||||||
im = hopper('L')
|
im = hopper('L')
|
||||||
|
|
186
_imaging.c
186
_imaging.c
|
@ -641,15 +641,6 @@ _new_block(PyObject* self, PyObject* args)
|
||||||
return PyImagingNew(ImagingNewBlock(mode, xsize, ysize));
|
return PyImagingNew(ImagingNewBlock(mode, xsize, ysize));
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
_getcount(PyObject* self, PyObject* args)
|
|
||||||
{
|
|
||||||
if (!PyArg_ParseTuple(args, ":getcount"))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return PyInt_FromLong(ImagingDefaultArena.stats_new_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
_linear_gradient(PyObject* self, PyObject* args)
|
_linear_gradient(PyObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
|
@ -3337,6 +3328,169 @@ static PyTypeObject PixelAccess_Type = {
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
_get_stats(PyObject* self, PyObject* args)
|
||||||
|
{
|
||||||
|
PyObject* d;
|
||||||
|
ImagingMemoryArena arena = &ImagingDefaultArena;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, ":get_stats"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
d = PyDict_New();
|
||||||
|
if ( ! d)
|
||||||
|
return NULL;
|
||||||
|
PyDict_SetItemString(d, "new_count",
|
||||||
|
PyInt_FromLong(arena->stats_new_count));
|
||||||
|
PyDict_SetItemString(d, "allocated_blocks",
|
||||||
|
PyInt_FromLong(arena->stats_allocated_blocks));
|
||||||
|
PyDict_SetItemString(d, "reused_blocks",
|
||||||
|
PyInt_FromLong(arena->stats_reused_blocks));
|
||||||
|
PyDict_SetItemString(d, "reallocated_blocks",
|
||||||
|
PyInt_FromLong(arena->stats_reallocated_blocks));
|
||||||
|
PyDict_SetItemString(d, "freed_blocks",
|
||||||
|
PyInt_FromLong(arena->stats_freed_blocks));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
_reset_stats(PyObject* self, PyObject* args)
|
||||||
|
{
|
||||||
|
ImagingMemoryArena arena = &ImagingDefaultArena;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, ":reset_stats"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
arena->stats_new_count = 0;
|
||||||
|
arena->stats_allocated_blocks = 0;
|
||||||
|
arena->stats_reused_blocks = 0;
|
||||||
|
arena->stats_reallocated_blocks = 0;
|
||||||
|
arena->stats_freed_blocks = 0;
|
||||||
|
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
_get_alignment(PyObject* self, PyObject* args)
|
||||||
|
{
|
||||||
|
if (!PyArg_ParseTuple(args, ":get_alignment"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return PyInt_FromLong(ImagingDefaultArena.alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
_get_block_size(PyObject* self, PyObject* args)
|
||||||
|
{
|
||||||
|
if (!PyArg_ParseTuple(args, ":get_block_size"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return PyInt_FromLong(ImagingDefaultArena.block_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
_get_blocks_max(PyObject* self, PyObject* args)
|
||||||
|
{
|
||||||
|
if (!PyArg_ParseTuple(args, ":get_blocks_max"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return PyInt_FromLong(ImagingDefaultArena.blocks_max);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
_get_blocks_free(PyObject* self, PyObject* args)
|
||||||
|
{
|
||||||
|
if (!PyArg_ParseTuple(args, ":get_blocks_free"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return PyInt_FromLong(ImagingDefaultArena.blocks_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
_set_alignment(PyObject* self, PyObject* args)
|
||||||
|
{
|
||||||
|
int alignment;
|
||||||
|
if (!PyArg_ParseTuple(args, "i:set_alignment", &alignment))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (alignment < 1 || alignment > 128) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "alignment should be from 1 to 128");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* Is power of two */
|
||||||
|
if (alignment & (alignment - 1)) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "alignment should be power of two");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImagingDefaultArena.alignment = alignment;
|
||||||
|
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
_set_block_size(PyObject* self, PyObject* args)
|
||||||
|
{
|
||||||
|
int block_size;
|
||||||
|
if (!PyArg_ParseTuple(args, "i:set_block_size", &block_size))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (block_size < 0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"block_size should be greater than 0");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block_size & 0xfff) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"block_size should be multiple of 4096");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImagingDefaultArena.block_size = block_size;
|
||||||
|
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
_set_blocks_max(PyObject* self, PyObject* args)
|
||||||
|
{
|
||||||
|
int blocks_max;
|
||||||
|
if (!PyArg_ParseTuple(args, "i:set_blocks_max", &blocks_max))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (blocks_max < 0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"blocks_max should be greater than 0");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! ImagingMemorySetBlocksMax(&ImagingDefaultArena, blocks_max)) {
|
||||||
|
ImagingError_MemoryError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
_clear_cache(PyObject* self, PyObject* args)
|
||||||
|
{
|
||||||
|
if (!PyArg_ParseTuple(args, ":_clear_cache"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ImagingMemoryClearCache(&ImagingDefaultArena);
|
||||||
|
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* FIXME: this is something of a mess. Should replace this with
|
/* FIXME: this is something of a mess. Should replace this with
|
||||||
pluggable codecs, but not before PIL 1.2 */
|
pluggable codecs, but not before PIL 1.2 */
|
||||||
|
|
||||||
|
@ -3400,8 +3554,6 @@ static PyMethodDef functions[] = {
|
||||||
{"new", (PyCFunction)_new, 1},
|
{"new", (PyCFunction)_new, 1},
|
||||||
{"merge", (PyCFunction)_merge, 1},
|
{"merge", (PyCFunction)_merge, 1},
|
||||||
|
|
||||||
{"getcount", (PyCFunction)_getcount, 1},
|
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
{"convert", (PyCFunction)_convert2, 1},
|
{"convert", (PyCFunction)_convert2, 1},
|
||||||
|
|
||||||
|
@ -3491,6 +3643,18 @@ static PyMethodDef functions[] = {
|
||||||
{"outline", (PyCFunction)PyOutline_Create, 1},
|
{"outline", (PyCFunction)PyOutline_Create, 1},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Resource management */
|
||||||
|
{"get_stats", (PyCFunction)_get_stats, 1},
|
||||||
|
{"reset_stats", (PyCFunction)_reset_stats, 1},
|
||||||
|
{"get_alignment", (PyCFunction)_get_alignment, 1},
|
||||||
|
{"get_block_size", (PyCFunction)_get_block_size, 1},
|
||||||
|
{"get_blocks_max", (PyCFunction)_get_blocks_max, 1},
|
||||||
|
{"get_blocks_free", (PyCFunction)_get_blocks_free, 1},
|
||||||
|
{"set_alignment", (PyCFunction)_set_alignment, 1},
|
||||||
|
{"set_block_size", (PyCFunction)_set_block_size, 1},
|
||||||
|
{"set_blocks_max", (PyCFunction)_set_blocks_max, 1},
|
||||||
|
{"clear_cache", (PyCFunction)_clear_cache, 1},
|
||||||
|
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -52,3 +52,6 @@ identified the format of the clipboard data.
|
||||||
|
|
||||||
The ``PIL.Image.core.copy`` and ``PIL.Image.Image.im.copy2`` methods
|
The ``PIL.Image.core.copy`` and ``PIL.Image.Image.im.copy2`` methods
|
||||||
have been removed.
|
have been removed.
|
||||||
|
|
||||||
|
The ``PIL.Image.core.getcount`` methods have been removed, use
|
||||||
|
``PIL.Image.core.get_stats()['new_count']`` property instead.
|
||||||
|
|
|
@ -160,10 +160,10 @@ typedef struct ImagingMemoryArena {
|
||||||
int blocks_free;
|
int blocks_free;
|
||||||
void **blocks;
|
void **blocks;
|
||||||
int stats_new_count;
|
int stats_new_count;
|
||||||
int stats_allocated_block;
|
int stats_allocated_blocks;
|
||||||
int stats_reused_block;
|
int stats_reused_blocks;
|
||||||
int stats_reallocated_block;
|
int stats_reallocated_blocks;
|
||||||
int stats_freed_block;
|
int stats_freed_blocks;
|
||||||
} *ImagingMemoryArena;
|
} *ImagingMemoryArena;
|
||||||
|
|
||||||
|
|
||||||
|
@ -171,6 +171,8 @@ typedef struct ImagingMemoryArena {
|
||||||
/* ------- */
|
/* ------- */
|
||||||
|
|
||||||
extern struct ImagingMemoryArena ImagingDefaultArena;
|
extern struct ImagingMemoryArena ImagingDefaultArena;
|
||||||
|
extern int ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max);
|
||||||
|
extern void ImagingMemoryClearCache(ImagingMemoryArena arena);
|
||||||
|
|
||||||
extern Imaging ImagingNew(const char* mode, int xsize, int ysize);
|
extern Imaging ImagingNew(const char* mode, int xsize, int ysize);
|
||||||
extern Imaging ImagingNewDirty(const char* mode, int xsize, int ysize);
|
extern Imaging ImagingNewDirty(const char* mode, int xsize, int ysize);
|
||||||
|
|
|
@ -273,24 +273,47 @@ struct ImagingMemoryArena ImagingDefaultArena = {
|
||||||
0, 0, 0, 0, 0 // Stats
|
0, 0, 0, 0, 0 // Stats
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
int
|
||||||
memory_set_blocks_max(ImagingMemoryArena arena, int blocks_max)
|
ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max)
|
||||||
{
|
{
|
||||||
|
void *p;
|
||||||
/* Free already cached blocks */
|
/* Free already cached blocks */
|
||||||
while (arena->blocks_free > blocks_max) {
|
while (arena->blocks_free > blocks_max) {
|
||||||
arena->blocks_free -= 1;
|
arena->blocks_free -= 1;
|
||||||
free(arena->blocks[arena->blocks_free]);
|
free(arena->blocks[arena->blocks_free]);
|
||||||
arena->stats_freed_block += 1;
|
arena->stats_freed_blocks += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
arena->blocks_max = blocks_max;
|
|
||||||
if (blocks_max == 0 && arena->blocks != NULL) {
|
if (blocks_max == 0 && arena->blocks != NULL) {
|
||||||
free(arena->blocks);
|
free(arena->blocks);
|
||||||
arena->blocks = NULL;
|
arena->blocks = NULL;
|
||||||
} else if (arena->blocks != NULL) {
|
} else if (arena->blocks != NULL) {
|
||||||
arena->blocks = realloc(arena->blocks, sizeof(void*) * blocks_max);
|
p = realloc(arena->blocks, sizeof(void*) * blocks_max);
|
||||||
|
if ( ! p) {
|
||||||
|
// Leave previous blocks_max value
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
arena->blocks = p;
|
||||||
} else {
|
} else {
|
||||||
arena->blocks = calloc(sizeof(void*), blocks_max);
|
arena->blocks = calloc(sizeof(void*), blocks_max);
|
||||||
|
if ( ! arena->blocks) {
|
||||||
|
// Fallback to 0
|
||||||
|
arena->blocks_max = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arena->blocks_max = blocks_max;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImagingMemoryClearCache(ImagingMemoryArena arena)
|
||||||
|
{
|
||||||
|
while (arena->blocks_free > 0) {
|
||||||
|
arena->blocks_free -= 1;
|
||||||
|
free(arena->blocks[arena->blocks_free]);
|
||||||
|
arena->stats_freed_blocks += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,12 +326,12 @@ memory_get_block(ImagingMemoryArena arena, int requested_size, int dirty)
|
||||||
block = realloc(arena->blocks[arena->blocks_free], requested_size);
|
block = realloc(arena->blocks[arena->blocks_free], requested_size);
|
||||||
if ( ! block) {
|
if ( ! block) {
|
||||||
free(arena->blocks[arena->blocks_free]);
|
free(arena->blocks[arena->blocks_free]);
|
||||||
arena->stats_freed_block += 1;
|
arena->stats_freed_blocks += 1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
arena->stats_reused_block += 1;
|
arena->stats_reused_blocks += 1;
|
||||||
if (block != arena->blocks[arena->blocks_free]) {
|
if (block != arena->blocks[arena->blocks_free]) {
|
||||||
arena->stats_reallocated_block += 1;
|
arena->stats_reallocated_blocks += 1;
|
||||||
}
|
}
|
||||||
if ( ! dirty) {
|
if ( ! dirty) {
|
||||||
memset(block, 0, requested_size);
|
memset(block, 0, requested_size);
|
||||||
|
@ -319,7 +342,7 @@ memory_get_block(ImagingMemoryArena arena, int requested_size, int dirty)
|
||||||
} else {
|
} else {
|
||||||
block = calloc(1, requested_size);
|
block = calloc(1, requested_size);
|
||||||
}
|
}
|
||||||
arena->stats_allocated_block += 1;
|
arena->stats_allocated_blocks += 1;
|
||||||
}
|
}
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
@ -332,7 +355,7 @@ memory_return_block(ImagingMemoryArena arena, void *block)
|
||||||
arena->blocks_free += 1;
|
arena->blocks_free += 1;
|
||||||
} else {
|
} else {
|
||||||
free(block);
|
free(block);
|
||||||
arena->stats_freed_block += 1;
|
arena->stats_freed_blocks += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user