Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 13e4704

Browse files
committed
_image.cpp: speed up image_frombyte; patch by C. Gohlke
Non-contiguous arrays, such as those resulting from pan and zoom, are handled efficiently without additional copying. This noticeably speeds up zoom and pan on large images. svn path=/trunk/matplotlib/; revision=8966
1 parent fb0a4cf commit 13e4704

1 file changed

Lines changed: 65 additions & 14 deletions

File tree

src/_image.cpp

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,7 +1085,7 @@ _image_module::frombyte(const Py::Tuple& args)
10851085
Py::Object x = args[0];
10861086
int isoutput = Py::Int(args[1]);
10871087

1088-
PyArrayObject *A = (PyArrayObject *) PyArray_ContiguousFromObject(x.ptr(), PyArray_UBYTE, 3, 3);
1088+
PyArrayObject *A = (PyArrayObject *) PyArray_FromObject(x.ptr(), PyArray_UBYTE, 3, 3);
10891089
if (A == NULL)
10901090
{
10911091
throw Py::ValueError("Array must have 3 dimensions");
@@ -1104,35 +1104,86 @@ _image_module::frombyte(const Py::Tuple& args)
11041104

11051105
agg::int8u *arrbuf;
11061106
agg::int8u *buffer;
1107+
agg::int8u *dstbuf;
11071108

11081109
arrbuf = reinterpret_cast<agg::int8u *>(A->data);
11091110

11101111
size_t NUMBYTES(imo->colsIn * imo->rowsIn * imo->BPP);
1111-
buffer = new agg::int8u[NUMBYTES];
1112+
buffer = dstbuf = new agg::int8u[NUMBYTES];
11121113

11131114
if (buffer == NULL) //todo: also handle allocation throw
11141115
{
11151116
throw Py::MemoryError("_image_module::frombyte could not allocate memory");
11161117
}
11171118

1118-
const size_t N = imo->rowsIn * imo->colsIn * imo->BPP;
1119-
size_t i = 0;
1120-
if (A->dimensions[2] == 4)
1119+
if PyArray_ISCONTIGUOUS(A)
11211120
{
1122-
memmove(buffer, arrbuf, N);
1121+
if (A->dimensions[2] == 4)
1122+
{
1123+
memmove(dstbuf, arrbuf, imo->rowsIn * imo->colsIn * 4);
1124+
}
1125+
else
1126+
{
1127+
size_t i = imo->rowsIn * imo->colsIn;
1128+
while (i--)
1129+
{
1130+
*dstbuf++ = *arrbuf++;
1131+
*dstbuf++ = *arrbuf++;
1132+
*dstbuf++ = *arrbuf++;
1133+
*dstbuf++ = 255;
1134+
}
1135+
}
1136+
}
1137+
else if ((A->strides[1] == 4) && (A->strides[2] == 1))
1138+
{
1139+
const size_t N = imo->colsIn * 4;
1140+
const size_t stride = A->strides[0];
1141+
for (size_t rownum = 0; rownum < imo->rowsIn; rownum++)
1142+
{
1143+
memmove(dstbuf, arrbuf, N);
1144+
arrbuf += stride;
1145+
dstbuf += N;
1146+
}
1147+
}
1148+
else if ((A->strides[1] == 3) && (A->strides[2] == 1))
1149+
{
1150+
const size_t stride = A->strides[0] - imo->colsIn * 3;
1151+
for (size_t rownum = 0; rownum < imo->rowsIn; rownum++)
1152+
{
1153+
for (size_t colnum = 0; colnum < imo->colsIn; colnum++)
1154+
{
1155+
*dstbuf++ = *arrbuf++;
1156+
*dstbuf++ = *arrbuf++;
1157+
*dstbuf++ = *arrbuf++;
1158+
*dstbuf++ = 255;
1159+
}
1160+
arrbuf += stride;
1161+
}
11231162
}
11241163
else
11251164
{
1126-
while (i < N)
1165+
PyArrayIterObject *iter;
1166+
iter = (PyArrayIterObject *)PyArray_IterNew((PyObject *)A);
1167+
if (A->dimensions[2] == 4)
1168+
{
1169+
while (iter->index < iter->size) {
1170+
*dstbuf++ = *((unsigned char *)iter->dataptr);
1171+
PyArray_ITER_NEXT(iter);
1172+
}
1173+
}
1174+
else
11271175
{
1128-
memmove(buffer, arrbuf, 3);
1129-
buffer += 3;
1130-
arrbuf += 3;
1131-
*buffer++ = 255;
1132-
i += 4;
1176+
while (iter->index < iter->size) {
1177+
*dstbuf++ = *((unsigned char *)iter->dataptr);
1178+
PyArray_ITER_NEXT(iter);
1179+
*dstbuf++ = *((unsigned char *)iter->dataptr);
1180+
PyArray_ITER_NEXT(iter);
1181+
*dstbuf++ = *((unsigned char *)iter->dataptr);
1182+
PyArray_ITER_NEXT(iter);
1183+
*dstbuf++ = 255;
1184+
}
11331185
}
1134-
buffer -= N;
1135-
arrbuf -= imo->rowsIn * imo->colsIn;
1186+
Py_DECREF(iter);
11361187
}
11371188

11381189
if (isoutput)

0 commit comments

Comments
 (0)