mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-11-10 19:56:47 +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):
|
||||
@contextmanager
|
||||
def count(self, diff):
|
||||
count = Image.core.getcount()
|
||||
count = Image.core.get_stats()['new_count']
|
||||
yield
|
||||
self.assertEqual(Image.core.getcount() - count, diff)
|
||||
self.assertEqual(Image.core.get_stats()['new_count'] - count, diff)
|
||||
|
||||
def test_horizontal(self):
|
||||
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));
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_getcount(PyObject* self, PyObject* args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ":getcount"))
|
||||
return NULL;
|
||||
|
||||
return PyInt_FromLong(ImagingDefaultArena.stats_new_count);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_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
|
||||
pluggable codecs, but not before PIL 1.2 */
|
||||
|
||||
|
@ -3400,8 +3554,6 @@ static PyMethodDef functions[] = {
|
|||
{"new", (PyCFunction)_new, 1},
|
||||
{"merge", (PyCFunction)_merge, 1},
|
||||
|
||||
{"getcount", (PyCFunction)_getcount, 1},
|
||||
|
||||
/* Functions */
|
||||
{"convert", (PyCFunction)_convert2, 1},
|
||||
|
||||
|
@ -3491,6 +3643,18 @@ static PyMethodDef functions[] = {
|
|||
{"outline", (PyCFunction)PyOutline_Create, 1},
|
||||
#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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -52,3 +52,6 @@ identified the format of the clipboard data.
|
|||
|
||||
The ``PIL.Image.core.copy`` and ``PIL.Image.Image.im.copy2`` methods
|
||||
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;
|
||||
void **blocks;
|
||||
int stats_new_count;
|
||||
int stats_allocated_block;
|
||||
int stats_reused_block;
|
||||
int stats_reallocated_block;
|
||||
int stats_freed_block;
|
||||
int stats_allocated_blocks;
|
||||
int stats_reused_blocks;
|
||||
int stats_reallocated_blocks;
|
||||
int stats_freed_blocks;
|
||||
} *ImagingMemoryArena;
|
||||
|
||||
|
||||
|
@ -171,6 +171,8 @@ typedef struct ImagingMemoryArena {
|
|||
/* ------- */
|
||||
|
||||
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 ImagingNewDirty(const char* mode, int xsize, int ysize);
|
||||
|
|
|
@ -273,24 +273,47 @@ struct ImagingMemoryArena ImagingDefaultArena = {
|
|||
0, 0, 0, 0, 0 // Stats
|
||||
};
|
||||
|
||||
void
|
||||
memory_set_blocks_max(ImagingMemoryArena arena, int blocks_max)
|
||||
int
|
||||
ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max)
|
||||
{
|
||||
void *p;
|
||||
/* Free already cached blocks */
|
||||
while (arena->blocks_free > blocks_max) {
|
||||
arena->blocks_free -= 1;
|
||||
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) {
|
||||
free(arena->blocks);
|
||||
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 {
|
||||
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);
|
||||
if ( ! block) {
|
||||
free(arena->blocks[arena->blocks_free]);
|
||||
arena->stats_freed_block += 1;
|
||||
arena->stats_freed_blocks += 1;
|
||||
return NULL;
|
||||
}
|
||||
arena->stats_reused_block += 1;
|
||||
arena->stats_reused_blocks += 1;
|
||||
if (block != arena->blocks[arena->blocks_free]) {
|
||||
arena->stats_reallocated_block += 1;
|
||||
arena->stats_reallocated_blocks += 1;
|
||||
}
|
||||
if ( ! dirty) {
|
||||
memset(block, 0, requested_size);
|
||||
|
@ -319,7 +342,7 @@ memory_get_block(ImagingMemoryArena arena, int requested_size, int dirty)
|
|||
} else {
|
||||
block = calloc(1, requested_size);
|
||||
}
|
||||
arena->stats_allocated_block += 1;
|
||||
arena->stats_allocated_blocks += 1;
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
@ -332,7 +355,7 @@ memory_return_block(ImagingMemoryArena arena, void *block)
|
|||
arena->blocks_free += 1;
|
||||
} else {
|
||||
free(block);
|
||||
arena->stats_freed_block += 1;
|
||||
arena->stats_freed_blocks += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user