mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-07-03 19:33:07 +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;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct filter LANCZOS = { lanczos_filter, 3.0 };
|
|
||||||
|
|
||||||
static inline float bilinear_filter(float x)
|
static inline float bilinear_filter(float x)
|
||||||
{
|
{
|
||||||
if (x < 0.0)
|
if (x < 0.0)
|
||||||
|
@ -49,8 +47,6 @@ static inline float bilinear_filter(float x)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct filter BILINEAR = { bilinear_filter, 1.0 };
|
|
||||||
|
|
||||||
static inline float bicubic_filter(float x)
|
static inline float bicubic_filter(float x)
|
||||||
{
|
{
|
||||||
/* https://en.wikipedia.org/wiki/Bicubic_interpolation#Bicubic_convolution_algorithm */
|
/* https://en.wikipedia.org/wiki/Bicubic_interpolation#Bicubic_convolution_algorithm */
|
||||||
|
@ -65,45 +61,41 @@ static inline float bicubic_filter(float x)
|
||||||
#undef a
|
#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 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 (in >= (1 << PRECISION_BITS << 8))
|
||||||
if (out >= 255)
|
|
||||||
return 255;
|
return 255;
|
||||||
if (out <= 0)
|
if (in <= 0)
|
||||||
return 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
|
Imaging
|
||||||
ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
||||||
{
|
{
|
||||||
ImagingSectionCookie cookie;
|
ImagingSectionCookie cookie;
|
||||||
Imaging imOut;
|
Imaging imOut;
|
||||||
float support, scale, filterscale;
|
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 xx, yy, x, kmax, xmin, xmax;
|
||||||
int *xbounds;
|
int *xbounds;
|
||||||
float *k, *kk, *kw;
|
int *k, *kk;
|
||||||
|
float *kw;
|
||||||
|
|
||||||
/* prepare for horizontal stretch */
|
/* prepare for horizontal stretch */
|
||||||
filterscale = scale = (float) imIn->xsize / xsize;
|
filterscale = scale = (float) imIn->xsize / xsize;
|
||||||
|
@ -118,7 +110,7 @@ ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
||||||
kmax = (int) ceil(support) * 2 + 1;
|
kmax = (int) ceil(support) * 2 + 1;
|
||||||
|
|
||||||
// check for overflow
|
// check for overflow
|
||||||
if (xsize > SIZE_MAX / (kmax * sizeof(float)))
|
if (xsize > SIZE_MAX / (kmax * sizeof(int)))
|
||||||
return (Imaging) ImagingError_MemoryError();
|
return (Imaging) ImagingError_MemoryError();
|
||||||
|
|
||||||
// sizeof(int) should be greater than 0 as well
|
// 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();
|
return (Imaging) ImagingError_MemoryError();
|
||||||
|
|
||||||
/* coefficient buffer */
|
/* coefficient buffer */
|
||||||
kk = malloc(xsize * kmax * sizeof(float));
|
kk = malloc(xsize * kmax * sizeof(int));
|
||||||
if ( ! kk)
|
if ( ! kk)
|
||||||
return (Imaging) ImagingError_MemoryError();
|
return (Imaging) ImagingError_MemoryError();
|
||||||
|
|
||||||
|
@ -162,7 +154,7 @@ ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
||||||
k = &kk[xx * kmax];
|
k = &kk[xx * kmax];
|
||||||
for (x = 0; x < xmax - xmin; x++) {
|
for (x = 0; x < xmax - xmin; x++) {
|
||||||
if (ww != 0.0)
|
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 + 0] = xmin;
|
||||||
xbounds[xx * 2 + 1] = xmax;
|
xbounds[xx * 2 + 1] = xmax;
|
||||||
|
@ -186,10 +178,10 @@ ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
||||||
xmin = xbounds[xx * 2 + 0];
|
xmin = xbounds[xx * 2 + 0];
|
||||||
xmax = xbounds[xx * 2 + 1];
|
xmax = xbounds[xx * 2 + 1];
|
||||||
k = &kk[xx * kmax];
|
k = &kk[xx * kmax];
|
||||||
ss = 0.5;
|
ss0 = 0;
|
||||||
for (x = xmin; x < xmax; x++)
|
for (x = xmin; x < xmax; x++)
|
||||||
ss += i2f(imIn->image8[yy][x]) * k[x - xmin];
|
ss0 += ((UINT8) imIn->image8[yy][x]) * k[x - xmin];
|
||||||
imOut->image8[yy][xx] = clip8(ss);
|
imOut->image8[yy][xx] = clip8(ss0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch(imIn->type) {
|
switch(imIn->type) {
|
||||||
|
@ -200,10 +192,10 @@ ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
||||||
xmin = xbounds[xx * 2 + 0];
|
xmin = xbounds[xx * 2 + 0];
|
||||||
xmax = xbounds[xx * 2 + 1];
|
xmax = xbounds[xx * 2 + 1];
|
||||||
k = &kk[xx * kmax];
|
k = &kk[xx * kmax];
|
||||||
ss0 = ss1 = 0.5;
|
ss0 = ss1 = 0;
|
||||||
for (x = xmin; x < xmax; x++) {
|
for (x = xmin; x < xmax; x++) {
|
||||||
ss0 += i2f((UINT8) imIn->image[yy][x*4 + 0]) * k[x - xmin];
|
ss0 += ((UINT8) imIn->image[yy][x*4 + 0]) * k[x - xmin];
|
||||||
ss1 += i2f((UINT8) imIn->image[yy][x*4 + 3]) * 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 + 0] = clip8(ss0);
|
||||||
imOut->image[yy][xx*4 + 3] = clip8(ss1);
|
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];
|
xmin = xbounds[xx * 2 + 0];
|
||||||
xmax = xbounds[xx * 2 + 1];
|
xmax = xbounds[xx * 2 + 1];
|
||||||
k = &kk[xx * kmax];
|
k = &kk[xx * kmax];
|
||||||
ss0 = ss1 = ss2 = 0.5;
|
ss0 = ss1 = ss2 = 0;
|
||||||
for (x = xmin; x < xmax; x++) {
|
for (x = xmin; x < xmax; x++) {
|
||||||
ss0 += i2f((UINT8) imIn->image[yy][x*4 + 0]) * k[x - xmin];
|
ss0 += ((UINT8) imIn->image[yy][x*4 + 0]) * k[x - xmin];
|
||||||
ss1 += i2f((UINT8) imIn->image[yy][x*4 + 1]) * k[x - xmin];
|
ss1 += ((UINT8) imIn->image[yy][x*4 + 1]) * k[x - xmin];
|
||||||
ss2 += i2f((UINT8) imIn->image[yy][x*4 + 2]) * 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 + 0] = clip8(ss0);
|
||||||
imOut->image[yy][xx*4 + 1] = clip8(ss1);
|
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];
|
xmin = xbounds[xx * 2 + 0];
|
||||||
xmax = xbounds[xx * 2 + 1];
|
xmax = xbounds[xx * 2 + 1];
|
||||||
k = &kk[xx * kmax];
|
k = &kk[xx * kmax];
|
||||||
ss0 = ss1 = ss2 = ss3 = 0.5;
|
ss0 = ss1 = ss2 = ss3 = 0;
|
||||||
for (x = xmin; x < xmax; x++) {
|
for (x = xmin; x < xmax; x++) {
|
||||||
ss0 += i2f((UINT8) imIn->image[yy][x*4 + 0]) * k[x - xmin];
|
ss0 += ((UINT8) imIn->image[yy][x*4 + 0]) * k[x - xmin];
|
||||||
ss1 += i2f((UINT8) imIn->image[yy][x*4 + 1]) * k[x - xmin];
|
ss1 += ((UINT8) imIn->image[yy][x*4 + 1]) * k[x - xmin];
|
||||||
ss2 += i2f((UINT8) imIn->image[yy][x*4 + 2]) * k[x - xmin];
|
ss2 += ((UINT8) imIn->image[yy][x*4 + 2]) * k[x - xmin];
|
||||||
ss3 += i2f((UINT8) imIn->image[yy][x*4 + 3]) * 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 + 0] = clip8(ss0);
|
||||||
imOut->image[yy][xx*4 + 1] = clip8(ss1);
|
imOut->image[yy][xx*4 + 1] = clip8(ss1);
|
||||||
|
@ -250,7 +242,7 @@ ImagingResampleHorizontal(Imaging imIn, int xsize, struct filter *filterp)
|
||||||
k = &kk[xx * kmax];
|
k = &kk[xx * kmax];
|
||||||
ss = 0.0;
|
ss = 0.0;
|
||||||
for (x = xmin; x < xmax; x++)
|
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;
|
IMAGING_PIXEL_I(imOut, xx, yy) = (int) ss;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user