Support all resampling filters when resizing I;16* images

This commit is contained in:
Andrew Murray 2024-09-28 14:27:40 +10:00
parent 86b42a95d8
commit 04a00d273c
3 changed files with 99 additions and 11 deletions

View File

@ -44,9 +44,19 @@ class TestImagingCoreResize:
self.resize(hopper("1"), (15, 12), Image.Resampling.BILINEAR) self.resize(hopper("1"), (15, 12), Image.Resampling.BILINEAR)
with pytest.raises(ValueError): with pytest.raises(ValueError):
self.resize(hopper("P"), (15, 12), Image.Resampling.BILINEAR) self.resize(hopper("P"), (15, 12), Image.Resampling.BILINEAR)
with pytest.raises(ValueError): for mode in [
self.resize(hopper("I;16"), (15, 12), Image.Resampling.BILINEAR) "L",
for mode in ["L", "I", "F", "RGB", "RGBA", "CMYK", "YCbCr"]: "I",
"I;16",
"I;16L",
"I;16B",
"I;16N",
"F",
"RGB",
"RGBA",
"CMYK",
"YCbCr",
]:
im = hopper(mode) im = hopper(mode)
r = self.resize(im, (15, 12), Image.Resampling.BILINEAR) r = self.resize(im, (15, 12), Image.Resampling.BILINEAR)
assert r.mode == mode assert r.mode == mode

View File

@ -1579,16 +1579,12 @@ _putdata(ImagingObject *self, PyObject *args) {
int bigendian = 0; int bigendian = 0;
if (image->type == IMAGING_TYPE_SPECIAL) { if (image->type == IMAGING_TYPE_SPECIAL) {
// I;16* // I;16*
if (strcmp(image->mode, "I;16N") == 0) { if (strcmp(image->mode, "I;16B") == 0
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
bigendian = 1; || strcmp(image->mode, "I;16N") == 0
#else
bigendian = 0;
#endif #endif
} else if (strcmp(image->mode, "I;16B") == 0) { ) {
bigendian = 1; bigendian = 1;
} else {
bigendian = 0;
} }
} }
for (i = x = y = 0; i < n; i++) { for (i = x = y = 0; i < n; i++) {

View File

@ -460,6 +460,83 @@ ImagingResampleVertical_8bpc(
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
} }
void
ImagingResampleHorizontal_16bpc(
Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *kk
) {
ImagingSectionCookie cookie;
double ss;
int xx, yy, x, xmin, xmax, ss_int;
double *k;
int bigendian = 0;
if (strcmp(imIn->mode, "I;16N") == 0
#ifdef WORDS_BIGENDIAN
|| strcmp(imIn->mode, "I;16B") == 0
#endif
) {
bigendian = 1;
}
ImagingSectionEnter(&cookie);
for (yy = 0; yy < imOut->ysize; yy++) {
for (xx = 0; xx < imOut->xsize; xx++) {
xmin = bounds[xx * 2 + 0];
xmax = bounds[xx * 2 + 1];
k = &kk[xx * ksize];
ss = 0.0;
for (x = 0; x < xmax; x++) {
ss += (imIn->image8[yy + offset][(x + xmin) * 2 + (bigendian ? 1 : 0)] +
(imIn->image8[yy + offset][(x + xmin) * 2 + (bigendian ? 0 : 1)]
<< 8)) *
k[x];
}
ss_int = ROUND_UP(ss);
imOut->image8[yy][xx * 2 + (bigendian ? 1 : 0)] = CLIP8(ss_int % 256);
imOut->image8[yy][xx * 2 + (bigendian ? 0 : 1)] = CLIP8(ss_int >> 8);
}
}
ImagingSectionLeave(&cookie);
}
void
ImagingResampleVertical_16bpc(
Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *kk
) {
ImagingSectionCookie cookie;
double ss;
int xx, yy, y, ymin, ymax, ss_int;
double *k;
int bigendian = 0;
if (strcmp(imIn->mode, "I;16N") == 0
#ifdef WORDS_BIGENDIAN
|| strcmp(imIn->mode, "I;16B") == 0
#endif
) {
bigendian = 1;
}
ImagingSectionEnter(&cookie);
for (yy = 0; yy < imOut->ysize; yy++) {
ymin = bounds[yy * 2 + 0];
ymax = bounds[yy * 2 + 1];
k = &kk[yy * ksize];
for (xx = 0; xx < imOut->xsize; xx++) {
ss = 0.0;
for (y = 0; y < ymax; y++) {
ss += (imIn->image8[y + ymin][xx * 2 + (bigendian ? 1 : 0)] +
(imIn->image8[y + ymin][xx * 2 + (bigendian ? 0 : 1)] << 8)) *
k[y];
}
ss_int = ROUND_UP(ss);
imOut->image8[yy][xx * 2 + (bigendian ? 1 : 0)] = CLIP8(ss_int % 256);
imOut->image8[yy][xx * 2 + (bigendian ? 0 : 1)] = CLIP8(ss_int >> 8);
}
}
ImagingSectionLeave(&cookie);
}
void void
ImagingResampleHorizontal_32bpc( ImagingResampleHorizontal_32bpc(
Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *kk Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *kk
@ -574,7 +651,12 @@ ImagingResample(Imaging imIn, int xsize, int ysize, int filter, float box[4]) {
} }
if (imIn->type == IMAGING_TYPE_SPECIAL) { if (imIn->type == IMAGING_TYPE_SPECIAL) {
if (strncmp(imIn->mode, "I;16", 4) == 0) {
ResampleHorizontal = ImagingResampleHorizontal_16bpc;
ResampleVertical = ImagingResampleVertical_16bpc;
} else {
return (Imaging)ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
}
} else if (imIn->image8) { } else if (imIn->image8) {
ResampleHorizontal = ImagingResampleHorizontal_8bpc; ResampleHorizontal = ImagingResampleHorizontal_8bpc;
ResampleVertical = ImagingResampleVertical_8bpc; ResampleVertical = ImagingResampleVertical_8bpc;