Skip to content

Commit

Permalink
Merge pull request #3225 from DerDakon/unaligned-access
Browse files Browse the repository at this point in the history
Use explicit memcpy() to avoid unaligned memory accesses
  • Loading branch information
hugovk committed Jul 1, 2019
2 parents 290cd17 + 7a4af2b commit 555e305
Show file tree
Hide file tree
Showing 15 changed files with 372 additions and 329 deletions.
31 changes: 20 additions & 11 deletions src/_imaging.c
Expand Up @@ -382,7 +382,8 @@ getlist(PyObject* arg, Py_ssize_t* length, const char* wrong_length, int type)
Py_ssize_t i, n;
int itemp;
double dtemp;
void* list;
FLOAT32 ftemp;
UINT8* list;
PyObject* seq;
PyObject* op;

Expand Down Expand Up @@ -416,19 +417,19 @@ getlist(PyObject* arg, Py_ssize_t* length, const char* wrong_length, int type)
switch (type) {
case TYPE_UINT8:
itemp = PyInt_AsLong(op);
((UINT8*)list)[i] = CLIP8(itemp);
list[i] = CLIP8(itemp);
break;
case TYPE_INT32:
itemp = PyInt_AsLong(op);
((INT32*)list)[i] = itemp;
memcpy(list + i * sizeof(INT32), &itemp, sizeof(itemp));
break;
case TYPE_FLOAT32:
dtemp = PyFloat_AsDouble(op);
((FLOAT32*)list)[i] = (FLOAT32) dtemp;
ftemp = (FLOAT32)PyFloat_AsDouble(op);
memcpy(list + i * sizeof(ftemp), &ftemp, sizeof(ftemp));
break;
case TYPE_DOUBLE:
dtemp = PyFloat_AsDouble(op);
((double*)list)[i] = (double) dtemp;
memcpy(list + i * sizeof(dtemp), &dtemp, sizeof(dtemp));
break;
}
}
Expand Down Expand Up @@ -532,6 +533,8 @@ getink(PyObject* color, Imaging im, char* ink)
to return it into a 32 bit C long
*/
PY_LONG_LONG r = 0;
FLOAT32 ftmp;
INT32 itmp;

/* fill ink buffer (four bytes) with something that can
be cast to either UINT8 or INT32 */
Expand Down Expand Up @@ -597,14 +600,16 @@ getink(PyObject* color, Imaging im, char* ink)
/* signed integer */
if (rIsInt != 1)
return NULL;
*(INT32*) ink = r;
itmp = r;
memcpy(ink, &itmp, sizeof(itmp));
return ink;
case IMAGING_TYPE_FLOAT32:
/* floating point */
f = PyFloat_AsDouble(color);
if (f == -1.0 && PyErr_Occurred())
return NULL;
*(FLOAT32*) ink = (FLOAT32) f;
ftmp = f;
memcpy(ink, &ftmp, sizeof(ftmp));
return ink;
case IMAGING_TYPE_SPECIAL:
if (strncmp(im->mode, "I;16", 4) == 0) {
Expand Down Expand Up @@ -799,15 +804,19 @@ _prepare_lut_table(PyObject* table, Py_ssize_t table_size)
}

for (i = 0; i < table_size; i++) {
FLOAT16 htmp;
double dtmp;
switch (data_type) {
case TYPE_FLOAT16:
item = float16tofloat32(((FLOAT16*) table_data)[i]);
memcpy(&htmp, ((char*) table_data) + i * sizeof(htmp), sizeof(htmp));
item = float16tofloat32(htmp);
break;
case TYPE_FLOAT32:
item = ((FLOAT32*) table_data)[i];
memcpy(&item, ((char*) table_data) + i * sizeof(FLOAT32), sizeof(FLOAT32));
break;
case TYPE_DOUBLE:
item = ((double*) table_data)[i];
memcpy(&dtmp, ((char*) table_data) + i * sizeof(dtmp), sizeof(dtmp));
item = (FLOAT32) dtmp;
break;
}
/* Max value for INT16 */
Expand Down
43 changes: 17 additions & 26 deletions src/libImaging/Access.c
Expand Up @@ -94,54 +94,53 @@ static void
get_pixel_16L(Imaging im, int x, int y, void* color)
{
UINT8* in = (UINT8*) &im->image[y][x+x];
UINT16* out = color;
#ifdef WORDS_BIGENDIAN
out[0] = in[0] + (in[1]<<8);
UINT16 out = in[0] + (in[1]<<8);
memcpy(color, &out, sizeof(out));
#else
out[0] = *(UINT16*) in;
memcpy(color, in, sizeof(UINT16));
#endif
}

static void
get_pixel_16B(Imaging im, int x, int y, void* color)
{
UINT8* in = (UINT8*) &im->image[y][x+x];
UINT16* out = color;
#ifdef WORDS_BIGENDIAN
out[0] = *(UINT16*) in;
memcpy(color, in, sizeof(UINT16));
#else
out[0] = in[1] + (in[0]<<8);
UINT16 out = in[1] + (in[0]<<8);
memcpy(color, &out, sizeof(out));
#endif
}

static void
get_pixel_32(Imaging im, int x, int y, void* color)
{
INT32* out = color;
out[0] = im->image32[y][x];
memcpy(color, &im->image32[y][x], sizeof(INT32));
}

static void
get_pixel_32L(Imaging im, int x, int y, void* color)
{
UINT8* in = (UINT8*) &im->image[y][x*4];
INT32* out = color;
#ifdef WORDS_BIGENDIAN
out[0] = in[0] + (in[1]<<8) + (in[2]<<16) + (in[3]<<24);
INT32 out = in[0] + (in[1]<<8) + (in[2]<<16) + (in[3]<<24);
memcpy(color, &out, sizeof(out));
#else
out[0] = *(INT32*) in;
memcpy(color, in, sizeof(INT32));
#endif
}

static void
get_pixel_32B(Imaging im, int x, int y, void* color)
{
UINT8* in = (UINT8*) &im->image[y][x*4];
INT32* out = color;
#ifdef WORDS_BIGENDIAN
out[0] = *(INT32*) in;
memcpy(color, in, sizeof(INT32));
#else
out[0] = in[3] + (in[2]<<8) + (in[1]<<16) + (in[0]<<24);
INT32 out = in[3] + (in[2]<<8) + (in[1]<<16) + (in[0]<<24);
memcpy(color, &out, sizeof(out));
#endif
}

Expand All @@ -153,7 +152,7 @@ put_pixel(Imaging im, int x, int y, const void* color)
if (im->image8)
im->image8[y][x] = *((UINT8*) color);
else
im->image32[y][x] = *((INT32*) color);
memcpy(&im->image32[y][x], color, sizeof(INT32));
}

static void
Expand All @@ -165,10 +164,7 @@ put_pixel_8(Imaging im, int x, int y, const void* color)
static void
put_pixel_16L(Imaging im, int x, int y, const void* color)
{
const char* in = color;
UINT8* out = (UINT8*) &im->image8[y][x+x];
out[0] = in[0];
out[1] = in[1];
memcpy(&im->image8[y][x+x], color, 2);
}

static void
Expand All @@ -183,12 +179,7 @@ put_pixel_16B(Imaging im, int x, int y, const void* color)
static void
put_pixel_32L(Imaging im, int x, int y, const void* color)
{
const char* in = color;
UINT8* out = (UINT8*) &im->image8[y][x*4];
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
out[3] = in[3];
memcpy(&im->image8[y][x*4], color, 4);
}

static void
Expand All @@ -205,7 +196,7 @@ put_pixel_32B(Imaging im, int x, int y, const void* color)
static void
put_pixel_32(Imaging im, int x, int y, const void* color)
{
im->image32[y][x] = *((INT32*) color);
memcpy(&im->image32[y][x], color, sizeof(INT32));
}

void
Expand Down
30 changes: 20 additions & 10 deletions src/libImaging/Bands.c
Expand Up @@ -50,7 +50,8 @@ ImagingGetBand(Imaging imIn, int band)
UINT8* out = imOut->image8[y];
x = 0;
for (; x < imIn->xsize - 3; x += 4) {
*((UINT32*) (out + x)) = MAKE_UINT32(in[0], in[4], in[8], in[12]);
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
memcpy(out + x, &v, sizeof(v));
in += 16;
}
for (; x < imIn->xsize; x++) {
Expand Down Expand Up @@ -98,8 +99,10 @@ ImagingSplit(Imaging imIn, Imaging bands[4])
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]);
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
memcpy(out0 + x, &v, sizeof(v));
v = MAKE_UINT32(in[0+3], in[4+3], in[8+3], in[12+3]);
memcpy(out1 + x, &v, sizeof(v));
in += 16;
}
for (; x < imIn->xsize; x++) {
Expand All @@ -116,9 +119,12 @@ ImagingSplit(Imaging imIn, Imaging bands[4])
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]);
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
memcpy(out0 + x, &v, sizeof(v));
v = MAKE_UINT32(in[0+1], in[4+1], in[8+1], in[12+1]);
memcpy(out1 + x, &v, sizeof(v));
v = MAKE_UINT32(in[0+2], in[4+2], in[8+2], in[12+2]);
memcpy(out2 + x, &v, sizeof(v));
in += 16;
}
for (; x < imIn->xsize; x++) {
Expand All @@ -137,10 +143,14 @@ ImagingSplit(Imaging imIn, Imaging bands[4])
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]);
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
memcpy(out0 + x, &v, sizeof(v));
v = MAKE_UINT32(in[0+1], in[4+1], in[8+1], in[12+1]);
memcpy(out1 + x, &v, sizeof(v));
v = MAKE_UINT32(in[0+2], in[4+2], in[8+2], in[12+2]);
memcpy(out2 + x, &v, sizeof(v));
v = MAKE_UINT32(in[0+3], in[4+3], in[8+3], in[12+3]);
memcpy(out3 + x, &v, sizeof(v));
in += 16;
}
for (; x < imIn->xsize; x++) {
Expand Down
10 changes: 7 additions & 3 deletions src/libImaging/ColorLUT.c
Expand Up @@ -105,7 +105,7 @@ ImagingColorLUT3D_linear(Imaging imOut, Imaging imIn, int table_channels,
ImagingSectionEnter(&cookie);
for (y = 0; y < imOut->ysize; y++) {
UINT8* rowIn = (UINT8 *)imIn->image[y];
UINT32* rowOut = (UINT32 *)imOut->image[y];
char* rowOut = (char *)imOut->image[y];
for (x = 0; x < imOut->xsize; x++) {
UINT32 index1D = rowIn[x*4 + 0] * scale1D;
UINT32 index2D = rowIn[x*4 + 1] * scale2D;
Expand All @@ -120,6 +120,7 @@ ImagingColorLUT3D_linear(Imaging imOut, Imaging imIn, int table_channels,
INT16 leftleft[4], leftright[4], rightleft[4], rightright[4];

if (table_channels == 3) {
UINT32 v;
interpolate3(leftleft, &table[idx + 0], &table[idx + 3], shift1D);
interpolate3(leftright, &table[idx + size1D*3],
&table[idx + size1D*3 + 3], shift1D);
Expand All @@ -133,12 +134,14 @@ ImagingColorLUT3D_linear(Imaging imOut, Imaging imIn, int table_channels,

interpolate3(result, left, right, shift3D);

rowOut[x] = MAKE_UINT32(
v = MAKE_UINT32(
clip8(result[0]), clip8(result[1]),
clip8(result[2]), rowIn[x*4 + 3]);
memcpy(rowOut + x * sizeof(v), &v, sizeof(v));
}

if (table_channels == 4) {
UINT32 v;
interpolate4(leftleft, &table[idx + 0], &table[idx + 4], shift1D);
interpolate4(leftright, &table[idx + size1D*4],
&table[idx + size1D*4 + 4], shift1D);
Expand All @@ -152,9 +155,10 @@ ImagingColorLUT3D_linear(Imaging imOut, Imaging imIn, int table_channels,

interpolate4(result, left, right, shift3D);

rowOut[x] = MAKE_UINT32(
v = MAKE_UINT32(
clip8(result[0]), clip8(result[1]),
clip8(result[2]), clip8(result[3]));
memcpy(rowOut + x * sizeof(v), &v, sizeof(v));
}
}
}
Expand Down

0 comments on commit 555e305

Please sign in to comment.