Skip to content

Commit 04a00d2

Browse files
committed
Support all resampling filters when resizing I;16* images
1 parent 86b42a9 commit 04a00d2

File tree

3 files changed

+99
-11
lines changed

3 files changed

+99
-11
lines changed

Tests/test_image_resize.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,19 @@ def test_convolution_modes(self) -> None:
4444
self.resize(hopper("1"), (15, 12), Image.Resampling.BILINEAR)
4545
with pytest.raises(ValueError):
4646
self.resize(hopper("P"), (15, 12), Image.Resampling.BILINEAR)
47-
with pytest.raises(ValueError):
48-
self.resize(hopper("I;16"), (15, 12), Image.Resampling.BILINEAR)
49-
for mode in ["L", "I", "F", "RGB", "RGBA", "CMYK", "YCbCr"]:
47+
for mode in [
48+
"L",
49+
"I",
50+
"I;16",
51+
"I;16L",
52+
"I;16B",
53+
"I;16N",
54+
"F",
55+
"RGB",
56+
"RGBA",
57+
"CMYK",
58+
"YCbCr",
59+
]:
5060
im = hopper(mode)
5161
r = self.resize(im, (15, 12), Image.Resampling.BILINEAR)
5262
assert r.mode == mode

src/_imaging.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,16 +1579,12 @@ _putdata(ImagingObject *self, PyObject *args) {
15791579
int bigendian = 0;
15801580
if (image->type == IMAGING_TYPE_SPECIAL) {
15811581
// I;16*
1582-
if (strcmp(image->mode, "I;16N") == 0) {
1582+
if (strcmp(image->mode, "I;16B") == 0
15831583
#ifdef WORDS_BIGENDIAN
1584-
bigendian = 1;
1585-
#else
1586-
bigendian = 0;
1584+
|| strcmp(image->mode, "I;16N") == 0
15871585
#endif
1588-
} else if (strcmp(image->mode, "I;16B") == 0) {
1586+
) {
15891587
bigendian = 1;
1590-
} else {
1591-
bigendian = 0;
15921588
}
15931589
}
15941590
for (i = x = y = 0; i < n; i++) {

src/libImaging/Resample.c

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,83 @@ ImagingResampleVertical_8bpc(
460460
ImagingSectionLeave(&cookie);
461461
}
462462

463+
void
464+
ImagingResampleHorizontal_16bpc(
465+
Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *kk
466+
) {
467+
ImagingSectionCookie cookie;
468+
double ss;
469+
int xx, yy, x, xmin, xmax, ss_int;
470+
double *k;
471+
472+
int bigendian = 0;
473+
if (strcmp(imIn->mode, "I;16N") == 0
474+
#ifdef WORDS_BIGENDIAN
475+
|| strcmp(imIn->mode, "I;16B") == 0
476+
#endif
477+
) {
478+
bigendian = 1;
479+
}
480+
481+
ImagingSectionEnter(&cookie);
482+
for (yy = 0; yy < imOut->ysize; yy++) {
483+
for (xx = 0; xx < imOut->xsize; xx++) {
484+
xmin = bounds[xx * 2 + 0];
485+
xmax = bounds[xx * 2 + 1];
486+
k = &kk[xx * ksize];
487+
ss = 0.0;
488+
for (x = 0; x < xmax; x++) {
489+
ss += (imIn->image8[yy + offset][(x + xmin) * 2 + (bigendian ? 1 : 0)] +
490+
(imIn->image8[yy + offset][(x + xmin) * 2 + (bigendian ? 0 : 1)]
491+
<< 8)) *
492+
k[x];
493+
}
494+
ss_int = ROUND_UP(ss);
495+
imOut->image8[yy][xx * 2 + (bigendian ? 1 : 0)] = CLIP8(ss_int % 256);
496+
imOut->image8[yy][xx * 2 + (bigendian ? 0 : 1)] = CLIP8(ss_int >> 8);
497+
}
498+
}
499+
ImagingSectionLeave(&cookie);
500+
}
501+
502+
void
503+
ImagingResampleVertical_16bpc(
504+
Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *kk
505+
) {
506+
ImagingSectionCookie cookie;
507+
double ss;
508+
int xx, yy, y, ymin, ymax, ss_int;
509+
double *k;
510+
511+
int bigendian = 0;
512+
if (strcmp(imIn->mode, "I;16N") == 0
513+
#ifdef WORDS_BIGENDIAN
514+
|| strcmp(imIn->mode, "I;16B") == 0
515+
#endif
516+
) {
517+
bigendian = 1;
518+
}
519+
520+
ImagingSectionEnter(&cookie);
521+
for (yy = 0; yy < imOut->ysize; yy++) {
522+
ymin = bounds[yy * 2 + 0];
523+
ymax = bounds[yy * 2 + 1];
524+
k = &kk[yy * ksize];
525+
for (xx = 0; xx < imOut->xsize; xx++) {
526+
ss = 0.0;
527+
for (y = 0; y < ymax; y++) {
528+
ss += (imIn->image8[y + ymin][xx * 2 + (bigendian ? 1 : 0)] +
529+
(imIn->image8[y + ymin][xx * 2 + (bigendian ? 0 : 1)] << 8)) *
530+
k[y];
531+
}
532+
ss_int = ROUND_UP(ss);
533+
imOut->image8[yy][xx * 2 + (bigendian ? 1 : 0)] = CLIP8(ss_int % 256);
534+
imOut->image8[yy][xx * 2 + (bigendian ? 0 : 1)] = CLIP8(ss_int >> 8);
535+
}
536+
}
537+
ImagingSectionLeave(&cookie);
538+
}
539+
463540
void
464541
ImagingResampleHorizontal_32bpc(
465542
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]) {
574651
}
575652

576653
if (imIn->type == IMAGING_TYPE_SPECIAL) {
577-
return (Imaging)ImagingError_ModeError();
654+
if (strncmp(imIn->mode, "I;16", 4) == 0) {
655+
ResampleHorizontal = ImagingResampleHorizontal_16bpc;
656+
ResampleVertical = ImagingResampleVertical_16bpc;
657+
} else {
658+
return (Imaging)ImagingError_ModeError();
659+
}
578660
} else if (imIn->image8) {
579661
ResampleHorizontal = ImagingResampleHorizontal_8bpc;
580662
ResampleVertical = ImagingResampleVertical_8bpc;

0 commit comments

Comments
 (0)