mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-11-11 04:07:21 +03:00
make coefficients ints
This commit is contained in:
parent
342e6f213b
commit
e13297b396
|
@ -38,8 +38,6 @@ static inline float lanczos_filter(float x)
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
static struct filter LANCZOS = { lanczos_filter, 3.0 };
|
||||
|
||||
static inline float bilinear_filter(float x)
|
||||
{
|
||||
if (x < 0.0)
|
||||
|
@ -49,8 +47,6 @@ static inline float bilinear_filter(float x)
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
static struct filter BILINEAR = { bilinear_filter, 1.0 };
|
||||
|
||||
static inline float bicubic_filter(float x)
|
||||
{
|
||||
/* https://en.wikipedia.org/wiki/Bicubic_interpolation#Bicubic_convolution_algorithm */
|
||||
|
@ -65,45 +61,41 @@ static inline float bicubic_filter(float x)
|
|||
#undef a
|
||||
}
|
||||
|
||||
static struct filter LANCZOS = { lanczos_filter, 3.0 };
|
||||
static struct filter BILINEAR = { bilinear_filter, 1.0 };
|
||||
static struct filter BICUBIC = { bicubic_filter, 2.0 };
|
||||
|
||||
|
||||
static inline UINT8 clip8(float in)
|
||||
|
||||
/* 8 bits for result. Filter can have negative areas.
|
||||
In one cases the sum of the coefficients will be negative,
|
||||
in the other it will be more than 1.0. That is why we need
|
||||
two extra bits for overflow and int type. */
|
||||
#define PRECISION_BITS (32 - 8 - 2)
|
||||
|
||||
|
||||
static inline UINT8 clip8(int in)
|
||||
{
|
||||
int out = (int) in;
|
||||
if (out >= 255)
|
||||
if (in >= (1 << PRECISION_BITS << 8))
|
||||
return 255;
|
||||
if (out <= 0)
|
||||
if (in <= 0)
|
||||
return 0;
|
||||
return (UINT8) out;
|
||||
return (UINT8) (in >> PRECISION_BITS);
|
||||
}
|
||||
|
||||
|
||||
/* This is work around bug in GCC prior 4.9 in 64-bit mode.
|
||||
GCC generates code with partial dependency which 3 times slower.
|
||||
See: http://stackoverflow.com/a/26588074/253146 */
|
||||
#if defined(__x86_64__) && defined(__SSE__) && ! defined(__NO_INLINE__) && \
|
||||
! defined(__clang__) && defined(GCC_VERSION) && (GCC_VERSION < 40900)
|
||||
static float __attribute__((always_inline)) i2f(int v) {
|
||||
float x;
|
||||
__asm__("xorps %0, %0; cvtsi2ss %1, %0" : "=X"(x) : "r"(v) );
|
||||
return x;
|
||||
}
|
||||
#else
|
||||
static float inline i2f(int v) { return (float) v; }
|
||||
#endif
|
||||
|
||||
|
||||
Imaging
|
||||
ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
||||
{
|
||||
ImagingSectionCookie cookie;
|
||||
Imaging imOut;
|
||||
float support, scale, filterscale;
|
||||
float center, ww, ss, ss0, ss1, ss2, ss3;
|
||||
float center, ww, ss;
|
||||
int ss0, ss1, ss2, ss3;
|
||||
int xx, yy, x, kmax, xmin, xmax;
|
||||
int *xbounds;
|
||||
float *k, *kk, *kw;
|
||||
int *k, *kk;
|
||||
float *kw;
|
||||
|
||||
/* prepare for horizontal stretch */
|
||||
filterscale = scale = (float) imIn->xsize / xsize;
|
||||
|
@ -118,7 +110,7 @@ ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
|||
kmax = (int) ceil(support) * 2 + 1;
|
||||
|
||||
// check for overflow
|
||||
if (xsize > SIZE_MAX / (kmax * sizeof(float)))
|
||||
if (xsize > SIZE_MAX / (kmax * sizeof(int)))
|
||||
return (Imaging) ImagingError_MemoryError();
|
||||
|
||||
// sizeof(int) should be greater than 0 as well
|
||||
|
@ -126,7 +118,7 @@ ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
|||
return (Imaging) ImagingError_MemoryError();
|
||||
|
||||
/* coefficient buffer */
|
||||
kk = malloc(xsize * kmax * sizeof(float));
|
||||
kk = malloc(xsize * kmax * sizeof(int));
|
||||
if ( ! kk)
|
||||
return (Imaging) ImagingError_MemoryError();
|
||||
|
||||
|
@ -162,7 +154,7 @@ ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
|||
k = &kk[xx * kmax];
|
||||
for (x = 0; x < xmax - xmin; x++) {
|
||||
if (ww != 0.0)
|
||||
k[x] = kw[x] / ww;
|
||||
k[x] = (int) floor(0.5 + kw[x] / ww * (1 << PRECISION_BITS));
|
||||
}
|
||||
xbounds[xx * 2 + 0] = xmin;
|
||||
xbounds[xx * 2 + 1] = xmax;
|
||||
|
@ -186,10 +178,10 @@ ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
|||
xmin = xbounds[xx * 2 + 0];
|
||||
xmax = xbounds[xx * 2 + 1];
|
||||
k = &kk[xx * kmax];
|
||||
ss = 0.5;
|
||||
ss0 = 0;
|
||||
for (x = xmin; x < xmax; x++)
|
||||
ss += i2f(imIn->image8[yy][x]) * k[x - xmin];
|
||||
imOut->image8[yy][xx] = clip8(ss);
|
||||
ss0 += ((UINT8) imIn->image8[yy][x]) * k[x - xmin];
|
||||
imOut->image8[yy][xx] = clip8(ss0);
|
||||
}
|
||||
} else {
|
||||
switch(imIn->type) {
|
||||
|
@ -200,10 +192,10 @@ ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
|||
xmin = xbounds[xx * 2 + 0];
|
||||
xmax = xbounds[xx * 2 + 1];
|
||||
k = &kk[xx * kmax];
|
||||
ss0 = ss1 = 0.5;
|
||||
ss0 = ss1 = 0;
|
||||
for (x = xmin; x < xmax; x++) {
|
||||
ss0 += i2f((UINT8) imIn->image[yy][x*4 + 0]) * k[x - xmin];
|
||||
ss1 += i2f((UINT8) imIn->image[yy][x*4 + 3]) * k[x - xmin];
|
||||
ss0 += ((UINT8) imIn->image[yy][x*4 + 0]) * k[x - xmin];
|
||||
ss1 += ((UINT8) imIn->image[yy][x*4 + 3]) * k[x - xmin];
|
||||
}
|
||||
imOut->image[yy][xx*4 + 0] = clip8(ss0);
|
||||
imOut->image[yy][xx*4 + 3] = clip8(ss1);
|
||||
|
@ -213,11 +205,11 @@ ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
|||
xmin = xbounds[xx * 2 + 0];
|
||||
xmax = xbounds[xx * 2 + 1];
|
||||
k = &kk[xx * kmax];
|
||||
ss0 = ss1 = ss2 = 0.5;
|
||||
ss0 = ss1 = ss2 = 0;
|
||||
for (x = xmin; x < xmax; x++) {
|
||||
ss0 += i2f((UINT8) imIn->image[yy][x*4 + 0]) * k[x - xmin];
|
||||
ss1 += i2f((UINT8) imIn->image[yy][x*4 + 1]) * k[x - xmin];
|
||||
ss2 += i2f((UINT8) imIn->image[yy][x*4 + 2]) * k[x - xmin];
|
||||
ss0 += ((UINT8) imIn->image[yy][x*4 + 0]) * k[x - xmin];
|
||||
ss1 += ((UINT8) imIn->image[yy][x*4 + 1]) * k[x - xmin];
|
||||
ss2 += ((UINT8) imIn->image[yy][x*4 + 2]) * k[x - xmin];
|
||||
}
|
||||
imOut->image[yy][xx*4 + 0] = clip8(ss0);
|
||||
imOut->image[yy][xx*4 + 1] = clip8(ss1);
|
||||
|
@ -228,12 +220,12 @@ ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
|||
xmin = xbounds[xx * 2 + 0];
|
||||
xmax = xbounds[xx * 2 + 1];
|
||||
k = &kk[xx * kmax];
|
||||
ss0 = ss1 = ss2 = ss3 = 0.5;
|
||||
ss0 = ss1 = ss2 = ss3 = 0;
|
||||
for (x = xmin; x < xmax; x++) {
|
||||
ss0 += i2f((UINT8) imIn->image[yy][x*4 + 0]) * k[x - xmin];
|
||||
ss1 += i2f((UINT8) imIn->image[yy][x*4 + 1]) * k[x - xmin];
|
||||
ss2 += i2f((UINT8) imIn->image[yy][x*4 + 2]) * k[x - xmin];
|
||||
ss3 += i2f((UINT8) imIn->image[yy][x*4 + 3]) * k[x - xmin];
|
||||
ss0 += ((UINT8) imIn->image[yy][x*4 + 0]) * k[x - xmin];
|
||||
ss1 += ((UINT8) imIn->image[yy][x*4 + 1]) * k[x - xmin];
|
||||
ss2 += ((UINT8) imIn->image[yy][x*4 + 2]) * k[x - xmin];
|
||||
ss3 += ((UINT8) imIn->image[yy][x*4 + 3]) * k[x - xmin];
|
||||
}
|
||||
imOut->image[yy][xx*4 + 0] = clip8(ss0);
|
||||
imOut->image[yy][xx*4 + 1] = clip8(ss1);
|
||||
|
@ -250,7 +242,7 @@ ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
|||
k = &kk[xx * kmax];
|
||||
ss = 0.0;
|
||||
for (x = xmin; x < xmax; x++)
|
||||
ss += i2f(IMAGING_PIXEL_I(imIn, x, yy)) * k[x - xmin];
|
||||
ss += (IMAGING_PIXEL_I(imIn, x, yy)) * k[x - xmin];
|
||||
IMAGING_PIXEL_I(imOut, xx, yy) = (int) ss;
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue
Block a user