Merge pull request #3107 from radarhere/effects

Corrected undefined behaviour
This commit is contained in:
Hugo 2018-04-22 09:04:35 +03:00 committed by GitHub
commit ad36932ebb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 49 additions and 55 deletions

View File

@ -96,8 +96,6 @@
#undef VERBOSE #undef VERBOSE
#define CLIP(x) ((x) <= 0 ? 0 : (x) < 256 ? (x) : 255)
#define B16(p, i) ((((int)p[(i)]) << 8) + p[(i)+1]) #define B16(p, i) ((((int)p[(i)]) << 8) + p[(i)+1])
#define L16(p, i) ((((int)p[(i)+1]) << 8) + p[(i)]) #define L16(p, i) ((((int)p[(i)+1]) << 8) + p[(i)])
#define S16(v) ((v) < 32768 ? (v) : ((v) - 65536)) #define S16(v) ((v) < 32768 ? (v) : ((v) - 65536))
@ -409,7 +407,7 @@ getlist(PyObject* arg, Py_ssize_t* length, const char* wrong_length, int type)
switch (type) { switch (type) {
case TYPE_UINT8: case TYPE_UINT8:
itemp = PyInt_AsLong(op); itemp = PyInt_AsLong(op);
((UINT8*)list)[i] = CLIP(itemp); ((UINT8*)list)[i] = CLIP8(itemp);
break; break;
case TYPE_INT32: case TYPE_INT32:
itemp = PyInt_AsLong(op); itemp = PyInt_AsLong(op);
@ -529,7 +527,7 @@ getink(PyObject* color, Imaging im, char* ink)
return NULL; return NULL;
} }
} }
ink[0] = CLIP(r); ink[0] = CLIP8(r);
ink[1] = ink[2] = ink[3] = 0; ink[1] = ink[2] = ink[3] = 0;
} else { } else {
a = 255; a = 255;
@ -549,10 +547,10 @@ getink(PyObject* color, Imaging im, char* ink)
return NULL; return NULL;
} }
} }
ink[0] = CLIP(r); ink[0] = CLIP8(r);
ink[1] = CLIP(g); ink[1] = CLIP8(g);
ink[2] = CLIP(b); ink[2] = CLIP8(b);
ink[3] = CLIP(a); ink[3] = CLIP8(a);
} }
return ink; return ink;
case IMAGING_TYPE_INT32: case IMAGING_TYPE_INT32:
@ -1284,17 +1282,17 @@ _point(ImagingObject* self, PyObject* args)
im = ImagingPoint(self->image, mode, (void*) data); im = ImagingPoint(self->image, mode, (void*) data);
else if (mode && bands > 1) { else if (mode && bands > 1) {
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
lut[i*4] = CLIP(data[i]); lut[i*4] = CLIP8(data[i]);
lut[i*4+1] = CLIP(data[i+256]); lut[i*4+1] = CLIP8(data[i+256]);
lut[i*4+2] = CLIP(data[i+512]); lut[i*4+2] = CLIP8(data[i+512]);
if (n > 768) if (n > 768)
lut[i*4+3] = CLIP(data[i+768]); lut[i*4+3] = CLIP8(data[i+768]);
} }
im = ImagingPoint(self->image, mode, (void*) lut); im = ImagingPoint(self->image, mode, (void*) lut);
} else { } else {
/* map individual bands */ /* map individual bands */
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
lut[i] = CLIP(data[i]); lut[i] = CLIP8(data[i]);
im = ImagingPoint(self->image, mode, (void*) lut); im = ImagingPoint(self->image, mode, (void*) lut);
} }
free(data); free(data);
@ -1358,7 +1356,7 @@ _putdata(ImagingObject* self, PyObject* args)
else else
/* Scaled and clipped string data */ /* Scaled and clipped string data */
for (i = x = y = 0; i < n; i++) { for (i = x = y = 0; i < n; i++) {
image->image8[y][x] = CLIP((int) (p[i] * scale + offset)); image->image8[y][x] = CLIP8((int) (p[i] * scale + offset));
if (++x >= (int) image->xsize) if (++x >= (int) image->xsize)
x = 0, y++; x = 0, y++;
} }
@ -1372,7 +1370,7 @@ _putdata(ImagingObject* self, PyObject* args)
/* Clipped data */ /* Clipped data */
for (i = x = y = 0; i < n; i++) { for (i = x = y = 0; i < n; i++) {
op = PySequence_Fast_GET_ITEM(seq, i); op = PySequence_Fast_GET_ITEM(seq, i);
image->image8[y][x] = (UINT8) CLIP(PyInt_AsLong(op)); image->image8[y][x] = (UINT8) CLIP8(PyInt_AsLong(op));
if (++x >= (int) image->xsize){ if (++x >= (int) image->xsize){
x = 0, y++; x = 0, y++;
} }
@ -1382,7 +1380,7 @@ _putdata(ImagingObject* self, PyObject* args)
/* Scaled and clipped data */ /* Scaled and clipped data */
for (i = x = y = 0; i < n; i++) { for (i = x = y = 0; i < n; i++) {
PyObject *op = PySequence_Fast_GET_ITEM(seq, i); PyObject *op = PySequence_Fast_GET_ITEM(seq, i);
image->image8[y][x] = CLIP( image->image8[y][x] = CLIP8(
(int) (PyFloat_AsDouble(op) * scale + offset)); (int) (PyFloat_AsDouble(op) * scale + offset));
if (++x >= (int) image->xsize){ if (++x >= (int) image->xsize){
x = 0, y++; x = 0, y++;

View File

@ -19,9 +19,6 @@
#include "Imaging.h" #include "Imaging.h"
#define CLIP(x) ((x) <= 0 ? 0 : (x) < 256 ? (x) : 255)
Imaging Imaging
ImagingGetBand(Imaging imIn, int band) ImagingGetBand(Imaging imIn, int band)
{ {
@ -214,7 +211,7 @@ ImagingFillBand(Imaging imOut, int band, int color)
if (imOut->bands == 2 && band == 1) if (imOut->bands == 2 && band == 1)
band = 3; band = 3;
color = CLIP(color); color = CLIP8(color);
/* Insert color into image */ /* Insert color into image */
for (y = 0; y < imOut->ysize; y++) { for (y = 0; y < imOut->ysize; y++) {

View File

@ -38,7 +38,6 @@
#define MAX(a, b) (a)>(b) ? (a) : (b) #define MAX(a, b) (a)>(b) ? (a) : (b)
#define MIN(a, b) (a)<(b) ? (a) : (b) #define MIN(a, b) (a)<(b) ? (a) : (b)
#define CLIP(v) ((v) <= 0 ? 0 : (v) >= 255 ? 255 : (v))
#define CLIP16(v) ((v) <= -32768 ? -32768 : (v) >= 32767 ? 32767 : (v)) #define CLIP16(v) ((v) <= -32768 ? -32768 : (v) >= 32767 ? 32767 : (v))
/* ITU-R Recommendation 601-2 (assuming nonlinear RGB) */ /* ITU-R Recommendation 601-2 (assuming nonlinear RGB) */
@ -141,7 +140,7 @@ la2lA(UINT8* out, const UINT8* in, int xsize)
if (alpha == 255 || alpha == 0) { if (alpha == 255 || alpha == 0) {
pixel = in[0]; pixel = in[0];
} else { } else {
pixel = CLIP((255 * in[0]) / alpha); pixel = CLIP8((255 * in[0]) / alpha);
} }
*out++ = (UINT8) pixel; *out++ = (UINT8) pixel;
*out++ = (UINT8) pixel; *out++ = (UINT8) pixel;
@ -316,8 +315,8 @@ rgb2hsv(UINT8* out, const UINT8* in, int xsize)
// incorrect hue happens if h/6 is negative. // incorrect hue happens if h/6 is negative.
h = fmod((h/6.0 + 1.0), 1.0); h = fmod((h/6.0 + 1.0), 1.0);
uh = (UINT8)CLIP((int)(h*255.0)); uh = (UINT8)CLIP8((int)(h*255.0));
us = (UINT8)CLIP((int)(s*255.0)); us = (UINT8)CLIP8((int)(s*255.0));
*out++ = uh; *out++ = uh;
*out++ = us; *out++ = us;
@ -355,9 +354,9 @@ hsv2rgb(UINT8* out, const UINT8* in, int xsize)
p = round((float)v * (1.0-fs)); p = round((float)v * (1.0-fs));
q = round((float)v * (1.0-fs*f)); q = round((float)v * (1.0-fs*f));
t = round((float)v * (1.0-fs*(1.0-f))); t = round((float)v * (1.0-fs*(1.0-f)));
up = (UINT8)CLIP(p); up = (UINT8)CLIP8(p);
uq = (UINT8)CLIP(q); uq = (UINT8)CLIP8(q);
ut = (UINT8)CLIP(t); ut = (UINT8)CLIP8(t);
switch (i%6) { switch (i%6) {
case 0: case 0:
@ -466,9 +465,9 @@ rgba2rgbA(UINT8* out, const UINT8* in, int xsize)
*out++ = in[1]; *out++ = in[1];
*out++ = in[2]; *out++ = in[2];
} else { } else {
*out++ = CLIP((255 * in[0]) / alpha); *out++ = CLIP8((255 * in[0]) / alpha);
*out++ = CLIP((255 * in[1]) / alpha); *out++ = CLIP8((255 * in[1]) / alpha);
*out++ = CLIP((255 * in[2]) / alpha); *out++ = CLIP8((255 * in[2]) / alpha);
} }
*out++ = in[3]; *out++ = in[3];
} }
@ -537,9 +536,9 @@ cmyk2rgb(UINT8* out, const UINT8* in, int xsize)
int x, nk, tmp; int x, nk, tmp;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
nk = 255 - in[3]; nk = 255 - in[3];
out[0] = CLIP(nk - MULDIV255(in[0], nk, tmp)); out[0] = CLIP8(nk - MULDIV255(in[0], nk, tmp));
out[1] = CLIP(nk - MULDIV255(in[1], nk, tmp)); out[1] = CLIP8(nk - MULDIV255(in[1], nk, tmp));
out[2] = CLIP(nk - MULDIV255(in[2], nk, tmp)); out[2] = CLIP8(nk - MULDIV255(in[2], nk, tmp));
out[3] = 255; out[3] = 255;
out += 4; out += 4;
in += 4; in += 4;
@ -1132,9 +1131,9 @@ topalette(Imaging imOut, Imaging imIn, ImagingPalette inpalette, int dither)
int d2; int d2;
INT16* cache; INT16* cache;
r = CLIP(in[0] + (r + e[3+0])/16); r = CLIP8(in[0] + (r + e[3+0])/16);
g = CLIP(in[1] + (g + e[3+1])/16); g = CLIP8(in[1] + (g + e[3+1])/16);
b = CLIP(in[2] + (b + e[3+2])/16); b = CLIP8(in[2] + (b + e[3+2])/16);
/* get closest colour */ /* get closest colour */
cache = &ImagingPaletteCache(palette, r, g, b); cache = &ImagingPaletteCache(palette, r, g, b);
@ -1236,7 +1235,7 @@ tobilevel(Imaging imOut, Imaging imIn, int dither)
for (x = 0; x < imIn->xsize; x++) { for (x = 0; x < imIn->xsize; x++) {
/* pick closest colour */ /* pick closest colour */
l = CLIP(in[x] + (l + errors[x+1])/16); l = CLIP8(in[x] + (l + errors[x+1])/16);
out[x] = (l > 128) ? 255 : 0; out[x] = (l > 128) ? 255 : 0;
/* propagate errors */ /* propagate errors */
@ -1264,7 +1263,7 @@ tobilevel(Imaging imOut, Imaging imIn, int dither)
for (x = 0; x < imIn->xsize; x++, in += 4) { for (x = 0; x < imIn->xsize; x++, in += 4) {
/* pick closest colour */ /* pick closest colour */
l = CLIP(L(in)/1000 + (l + errors[x+1])/16); l = CLIP8(L(in)/1000 + (l + errors[x+1])/16);
out[x] = (l > 128) ? 255 : 0; out[x] = (l > 128) ? 255 : 0;
/* propagate errors */ /* propagate errors */

View File

@ -106,7 +106,7 @@ ImagingEffectNoise(int xsize, int ysize, float sigma)
this = factor * v1; this = factor * v1;
next = factor * v2; next = factor * v2;
} }
out[x] = (unsigned char) (128 + sigma * this); out[x] = CLIP8(128 + sigma * this);
} }
} }

View File

@ -30,6 +30,8 @@
(MULDIV255(in1, (255 - mask), tmp1) + in2) (MULDIV255(in1, (255 - mask), tmp1) + in2)
#define CLIP8(v) ((v) <= 0 ? 0 : (v) < 256 ? (v) : 255)
/* This is to work around a bug in GCC prior 4.9 in 64 bit mode. /* This is to work around a bug in GCC prior 4.9 in 64 bit mode.
GCC generates code with partial dependency which is 3 times slower. GCC generates code with partial dependency which is 3 times slower.
See: http://stackoverflow.com/a/26588074/253146 */ See: http://stackoverflow.com/a/26588074/253146 */

View File

@ -45,8 +45,6 @@
#define Y 2 #define Y 2
#define K 3 #define K 3
#define CLIP(x) ((x) <= 0 ? 0 : (x) < 256 ? (x) : 255)
/* byte-swapping macros */ /* byte-swapping macros */
#define C16N\ #define C16N\
@ -749,9 +747,9 @@ unpackRGBa16L(UINT8* _out, const UINT8* in, int pixels)
} else if (a == 255) { } else if (a == 255) {
out[i] = MAKE_UINT32(in[1], in[3], in[5], a); out[i] = MAKE_UINT32(in[1], in[3], in[5], a);
} else { } else {
out[i] = MAKE_UINT32(CLIP(in[1] * 255 / a), out[i] = MAKE_UINT32(CLIP8(in[1] * 255 / a),
CLIP(in[3] * 255 / a), CLIP8(in[3] * 255 / a),
CLIP(in[5] * 255 / a), a); CLIP8(in[5] * 255 / a), a);
} }
in += 8; in += 8;
} }
@ -770,9 +768,9 @@ unpackRGBa16B(UINT8* _out, const UINT8* in, int pixels)
} else if (a == 255) { } else if (a == 255) {
out[i] = MAKE_UINT32(in[0], in[2], in[4], a); out[i] = MAKE_UINT32(in[0], in[2], in[4], a);
} else { } else {
out[i] = MAKE_UINT32(CLIP(in[0] * 255 / a), out[i] = MAKE_UINT32(CLIP8(in[0] * 255 / a),
CLIP(in[2] * 255 / a), CLIP8(in[2] * 255 / a),
CLIP(in[4] * 255 / a), a); CLIP8(in[4] * 255 / a), a);
} }
in += 8; in += 8;
} }
@ -791,9 +789,9 @@ unpackRGBa(UINT8* _out, const UINT8* in, int pixels)
} else if (a == 255) { } else if (a == 255) {
out[i] = MAKE_UINT32(in[0], in[1], in[2], a); out[i] = MAKE_UINT32(in[0], in[1], in[2], a);
} else { } else {
out[i] = MAKE_UINT32(CLIP(in[0] * 255 / a), out[i] = MAKE_UINT32(CLIP8(in[0] * 255 / a),
CLIP(in[1] * 255 / a), CLIP8(in[1] * 255 / a),
CLIP(in[2] * 255 / a), a); CLIP8(in[2] * 255 / a), a);
} }
in += 4; in += 4;
} }
@ -812,9 +810,9 @@ unpackBGRa(UINT8* _out, const UINT8* in, int pixels)
} else if (a == 255) { } else if (a == 255) {
out[i] = MAKE_UINT32(in[2], in[1], in[0], a); out[i] = MAKE_UINT32(in[2], in[1], in[0], a);
} else { } else {
out[i] = MAKE_UINT32(CLIP(in[2] * 255 / a), out[i] = MAKE_UINT32(CLIP8(in[2] * 255 / a),
CLIP(in[1] * 255 / a), CLIP8(in[1] * 255 / a),
CLIP(in[0] * 255 / a), a); CLIP8(in[0] * 255 / a), a);
} }
in += 4; in += 4;
} }