Merge pull request #2676 from uploadcare/fast-split

Fast split()
This commit is contained in:
wiredfool 2017-08-16 16:10:33 +01:00 committed by GitHub
commit d3580451e2
4 changed files with 137 additions and 4 deletions

View File

@ -1958,9 +1958,7 @@ class Image(object):
if self.im.bands == 1: if self.im.bands == 1:
ims = [self.copy()] ims = [self.copy()]
else: else:
ims = [] ims = map(self._new, self.im.split())
for i in range(self.im.bands):
ims.append(self._new(self.im.getband(i)))
return tuple(ims) return tuple(ims)
def getchannel(self, channel): def getchannel(self, channel):

View File

@ -1888,6 +1888,32 @@ _putband(ImagingObject* self, PyObject* args)
return Py_None; return Py_None;
} }
static PyObject*
_split(ImagingObject* self, PyObject* args)
{
int fails = 0;
Py_ssize_t i;
PyObject* list;
PyObject* imaging_object;
Imaging bands[4] = {NULL, NULL, NULL, NULL};
if ( ! ImagingSplit(self->image, bands))
return NULL;
list = PyTuple_New(self->image->bands);
for (i = 0; i < self->image->bands; i++) {
imaging_object = PyImagingNew(bands[i]);
if ( ! imaging_object)
fails += 1;
PyTuple_SET_ITEM(list, i, imaging_object);
}
if (fails) {
Py_DECREF(list);
list = NULL;
}
return list;
}
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
#ifdef WITH_IMAGECHOPS #ifdef WITH_IMAGECHOPS
@ -2954,6 +2980,7 @@ static struct PyMethodDef methods[] = {
{"getband", (PyCFunction)_getband, 1}, {"getband", (PyCFunction)_getband, 1},
{"putband", (PyCFunction)_putband, 1}, {"putband", (PyCFunction)_putband, 1},
{"split", (PyCFunction)_split, 1},
{"fillband", (PyCFunction)_fillband, 1}, {"fillband", (PyCFunction)_fillband, 1},
{"setmode", (PyCFunction)im_setmode, 1}, {"setmode", (PyCFunction)im_setmode, 1},

View File

@ -22,6 +22,13 @@
#define CLIP(x) ((x) <= 0 ? 0 : (x) < 256 ? (x) : 255) #define CLIP(x) ((x) <= 0 ? 0 : (x) < 256 ? (x) : 255)
#ifdef WORDS_BIGENDIAN
#define MAKE_UINT32(u0, u1, u2, u3) (u3 | (u2<<8) | (u1<<16) | (u0<<24))
#else
#define MAKE_UINT32(u0, u1, u2, u3) (u0 | (u1<<8) | (u2<<16) | (u3<<24))
#endif
Imaging Imaging
ImagingGetBand(Imaging imIn, int band) ImagingGetBand(Imaging imIn, int band)
{ {
@ -51,7 +58,12 @@ ImagingGetBand(Imaging imIn, int band)
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
UINT8* in = (UINT8*) imIn->image[y] + band; UINT8* in = (UINT8*) imIn->image[y] + band;
UINT8* out = imOut->image8[y]; UINT8* out = imOut->image8[y];
for (x = 0; x < imIn->xsize; x++) { x = 0;
for (; x < imIn->xsize - 3; x += 4) {
*((UINT32*) (out + x)) = MAKE_UINT32(in[0], in[4], in[8], in[12]);
in += 16;
}
for (; x < imIn->xsize; x++) {
out[x] = *in; out[x] = *in;
in += 4; in += 4;
} }
@ -60,6 +72,101 @@ ImagingGetBand(Imaging imIn, int band)
return imOut; return imOut;
} }
int
ImagingSplit(Imaging imIn, Imaging bands[4])
{
int i, j, x, y;
/* Check arguments */
if (!imIn || imIn->type != IMAGING_TYPE_UINT8) {
(Imaging) ImagingError_ModeError();
return 0;
}
/* Shortcuts */
if (imIn->bands == 1) {
bands[0] = ImagingCopy(imIn);
return imIn->bands;
}
for (i = 0; i < imIn->bands; i++) {
bands[i] = ImagingNew("L", imIn->xsize, imIn->ysize);
if ( ! bands[i]) {
for (j = 0; j < i; ++j) {
ImagingDelete(bands[j]);
}
return 0;
}
}
/* Extract bands from image */
if (imIn->bands == 2) {
for (y = 0; y < imIn->ysize; y++) {
UINT8* in = (UINT8*) imIn->image[y];
UINT8* out0 = bands[0]->image8[y];
UINT8* out1 = bands[1]->image8[y];
x = 0;
for (; x < imIn->xsize - 3; x += 4) {
*((UINT32*) (out0 + x)) = MAKE_UINT32(in[0], in[4], in[8], in[12]);
*((UINT32*) (out1 + x)) = MAKE_UINT32(in[0+3], in[4+3], in[8+3], in[12+3]);
in += 16;
}
for (; x < imIn->xsize; x++) {
out0[x] = in[0];
out1[x] = in[3];
in += 4;
}
}
} else if (imIn->bands == 3) {
for (y = 0; y < imIn->ysize; y++) {
UINT8* in = (UINT8*) imIn->image[y];
UINT8* out0 = bands[0]->image8[y];
UINT8* out1 = bands[1]->image8[y];
UINT8* out2 = bands[2]->image8[y];
x = 0;
for (; x < imIn->xsize - 3; x += 4) {
*((UINT32*) (out0 + x)) = MAKE_UINT32(in[0], in[4], in[8], in[12]);
*((UINT32*) (out1 + x)) = MAKE_UINT32(in[0+1], in[4+1], in[8+1], in[12+1]);
*((UINT32*) (out2 + x)) = MAKE_UINT32(in[0+2], in[4+2], in[8+2], in[12+2]);
in += 16;
}
for (; x < imIn->xsize; x++) {
out0[x] = in[0];
out1[x] = in[1];
out2[x] = in[2];
in += 4;
}
}
} else {
for (y = 0; y < imIn->ysize; y++) {
UINT8* in = (UINT8*) imIn->image[y];
UINT8* out0 = bands[0]->image8[y];
UINT8* out1 = bands[1]->image8[y];
UINT8* out2 = bands[2]->image8[y];
UINT8* out3 = bands[3]->image8[y];
x = 0;
for (; x < imIn->xsize - 3; x += 4) {
*((UINT32*) (out0 + x)) = MAKE_UINT32(in[0], in[4], in[8], in[12]);
*((UINT32*) (out1 + x)) = MAKE_UINT32(in[0+1], in[4+1], in[8+1], in[12+1]);
*((UINT32*) (out2 + x)) = MAKE_UINT32(in[0+2], in[4+2], in[8+2], in[12+2]);
*((UINT32*) (out3 + x)) = MAKE_UINT32(in[0+3], in[4+3], in[8+3], in[12+3]);
in += 16;
}
for (; x < imIn->xsize; x++) {
out0[x] = in[0];
out1[x] = in[1];
out2[x] = in[2];
out3[x] = in[3];
in += 4;
}
}
}
return imIn->bands;
}
Imaging Imaging
ImagingPutBand(Imaging imOut, Imaging imIn, int band) ImagingPutBand(Imaging imOut, Imaging imIn, int band)
{ {

View File

@ -266,6 +266,7 @@ extern Imaging ImagingFlipTopBottom(Imaging imOut, Imaging imIn);
extern Imaging ImagingGaussianBlur(Imaging imOut, Imaging imIn, float radius, extern Imaging ImagingGaussianBlur(Imaging imOut, Imaging imIn, float radius,
int passes); int passes);
extern Imaging ImagingGetBand(Imaging im, int band); extern Imaging ImagingGetBand(Imaging im, int band);
extern int ImagingSplit(Imaging im, Imaging bands[4]);
extern int ImagingGetBBox(Imaging im, int bbox[4]); extern int ImagingGetBBox(Imaging im, int bbox[4]);
typedef struct { int x, y; INT32 count; INT32 pixel; } ImagingColorItem; typedef struct { int x, y; INT32 count; INT32 pixel; } ImagingColorItem;
extern ImagingColorItem* ImagingGetColors(Imaging im, int maxcolors, extern ImagingColorItem* ImagingGetColors(Imaging im, int maxcolors,