Skip to content

Commit

Permalink
Merge pull request #7849 from radarhere/png_i16
Browse files Browse the repository at this point in the history
  • Loading branch information
hugovk committed Mar 2, 2024
2 parents 2bd5426 + d6a3f89 commit dec3ef6
Show file tree
Hide file tree
Showing 18 changed files with 28 additions and 32 deletions.
Binary file removed Tests/images/16_bit_binary_pgm.png
Binary file not shown.
Binary file added Tests/images/16_bit_binary_pgm.tiff
Binary file not shown.
Binary file removed Tests/images/cmx3g8_wv_1998.260_0745_mcidas.png
Binary file not shown.
Binary file added Tests/images/cmx3g8_wv_1998.260_0745_mcidas.tiff
Binary file not shown.
Binary file modified Tests/images/hopper_emboss.bmp
Binary file not shown.
Binary file removed Tests/images/hopper_emboss_I.png
Binary file not shown.
Binary file modified Tests/images/hopper_emboss_more.bmp
Binary file not shown.
Binary file removed Tests/images/hopper_emboss_more_I.png
Binary file not shown.
Binary file removed Tests/images/imagedraw_rectangle_I.png
Binary file not shown.
Binary file added Tests/images/imagedraw_rectangle_I.tiff
Binary file not shown.
2 changes: 1 addition & 1 deletion Tests/test_file_mcidas.py
Expand Up @@ -19,7 +19,7 @@ def test_valid_file() -> None:
# https://ghrc.nsstc.nasa.gov/hydro/details/cmx3g8
# https://ghrc.nsstc.nasa.gov/pub/fieldCampaigns/camex3/cmx3g8/browse/
test_file = "Tests/images/cmx3g8_wv_1998.260_0745_mcidas.ara"
saved_file = "Tests/images/cmx3g8_wv_1998.260_0745_mcidas.png"
saved_file = "Tests/images/cmx3g8_wv_1998.260_0745_mcidas.tiff"

# Act
with Image.open(test_file) as im:
Expand Down
6 changes: 3 additions & 3 deletions Tests/test_file_png.py
Expand Up @@ -102,7 +102,7 @@ def test_sanity(self, tmp_path: Path) -> None:
im = hopper(mode)
im.save(test_file)
with Image.open(test_file) as reloaded:
if mode in ("I;16", "I;16B"):
if mode in ("I", "I;16B"):
reloaded = reloaded.convert(mode)
assert_image_equal(reloaded, im)

Expand Down Expand Up @@ -304,8 +304,8 @@ def test_save_p_transparent_black(self, tmp_path: Path) -> None:
assert im.getcolors() == [(100, (0, 0, 0, 0))]

def test_save_grayscale_transparency(self, tmp_path: Path) -> None:
for mode, num_transparent in {"1": 1994, "L": 559, "I": 559}.items():
in_file = "Tests/images/" + mode.lower() + "_trns.png"
for mode, num_transparent in {"1": 1994, "L": 559, "I;16": 559}.items():
in_file = "Tests/images/" + mode.split(";")[0].lower() + "_trns.png"
with Image.open(in_file) as im:
assert im.mode == mode
assert im.info["transparency"] == 255
Expand Down
2 changes: 1 addition & 1 deletion Tests/test_file_ppm.py
Expand Up @@ -88,7 +88,7 @@ def test_16bit_pgm() -> None:
assert im.size == (20, 100)
assert im.get_format_mimetype() == "image/x-portable-graymap"

assert_image_equal_tofile(im, "Tests/images/16_bit_binary_pgm.png")
assert_image_equal_tofile(im, "Tests/images/16_bit_binary_pgm.tiff")


def test_16bit_pgm_write(tmp_path: Path) -> None:
Expand Down
24 changes: 2 additions & 22 deletions Tests/test_image_filter.py
Expand Up @@ -148,9 +148,7 @@ def test_kernel_not_enough_coefficients() -> None:
@pytest.mark.parametrize("mode", ("L", "LA", "I", "RGB", "CMYK"))
def test_consistency_3x3(mode: str) -> None:
with Image.open("Tests/images/hopper.bmp") as source:
reference_name = "hopper_emboss"
reference_name += "_I.png" if mode == "I" else ".bmp"
with Image.open("Tests/images/" + reference_name) as reference:
with Image.open("Tests/images/hopper_emboss.bmp") as reference:
kernel = ImageFilter.Kernel(
(3, 3),
# fmt: off
Expand All @@ -160,23 +158,13 @@ def test_consistency_3x3(mode: str) -> None:
# fmt: on
0.3,
)
source = source.split() * 2
reference = reference.split() * 2

if mode == "I":
source = source[0].convert(mode)
else:
source = Image.merge(mode, source[: len(mode)])
reference = Image.merge(mode, reference[: len(mode)])
assert_image_equal(source.filter(kernel), reference)


@pytest.mark.parametrize("mode", ("L", "LA", "I", "RGB", "CMYK"))
def test_consistency_5x5(mode: str) -> None:
with Image.open("Tests/images/hopper.bmp") as source:
reference_name = "hopper_emboss_more"
reference_name += "_I.png" if mode == "I" else ".bmp"
with Image.open("Tests/images/" + reference_name) as reference:
with Image.open("Tests/images/hopper_emboss_more.bmp") as reference:
kernel = ImageFilter.Kernel(
(5, 5),
# fmt: off
Expand All @@ -188,14 +176,6 @@ def test_consistency_5x5(mode: str) -> None:
# fmt: on
0.3,
)
source = source.split() * 2
reference = reference.split() * 2

if mode == "I":
source = source[0].convert(mode)
else:
source = Image.merge(mode, source[: len(mode)])
reference = Image.merge(mode, reference[: len(mode)])
assert_image_equal(source.filter(kernel), reference)


Expand Down
2 changes: 1 addition & 1 deletion Tests/test_imagedraw.py
Expand Up @@ -753,7 +753,7 @@ def test_rectangle_I16(bbox: Coords) -> None:
draw.rectangle(bbox, outline=0xFFFF)

# Assert
assert_image_equal_tofile(im.convert("I"), "Tests/images/imagedraw_rectangle_I.png")
assert_image_equal_tofile(im, "Tests/images/imagedraw_rectangle_I.tiff")


@pytest.mark.parametrize("bbox", BBOX)
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/Image.py
Expand Up @@ -978,7 +978,7 @@ def convert_transparency(m, v):
delete_trns = False
# transparency handling
if has_transparency:
if (self.mode in ("1", "L", "I") and mode in ("LA", "RGBA")) or (
if (self.mode in ("1", "L", "I", "I;16") and mode in ("LA", "RGBA")) or (
self.mode == "RGB" and mode == "RGBA"
):
# Use transparent conversion to promote from transparent
Expand Down
6 changes: 3 additions & 3 deletions src/PIL/PngImagePlugin.py
Expand Up @@ -62,7 +62,7 @@
(2, 0): ("L", "L;2"),
(4, 0): ("L", "L;4"),
(8, 0): ("L", "L"),
(16, 0): ("I", "I;16B"),
(16, 0): ("I;16", "I;16B"),
# Truecolour
(8, 2): ("RGB", "RGB"),
(16, 2): ("RGB", "RGB;16B"),
Expand Down Expand Up @@ -467,7 +467,7 @@ def chunk_tRNS(self, pos, length):
# otherwise, we have a byte string with one alpha value
# for each palette entry
self.im_info["transparency"] = s
elif self.im_mode in ("1", "L", "I"):
elif self.im_mode in ("1", "L", "I;16"):
self.im_info["transparency"] = i16(s)
elif self.im_mode == "RGB":
self.im_info["transparency"] = i16(s), i16(s, 2), i16(s, 4)
Expand Down Expand Up @@ -1356,7 +1356,7 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False):
transparency = max(0, min(255, transparency))
alpha = b"\xFF" * transparency + b"\0"
chunk(fp, b"tRNS", alpha[:alpha_bytes])
elif im.mode in ("1", "L", "I"):
elif im.mode in ("1", "L", "I", "I;16"):
transparency = max(0, min(65535, transparency))
chunk(fp, b"tRNS", o16(transparency))
elif im.mode == "RGB":
Expand Down
16 changes: 16 additions & 0 deletions src/libImaging/Convert.c
Expand Up @@ -878,6 +878,18 @@ I16B_L(UINT8 *out, const UINT8 *in, int xsize) {
}
}

static void
I16_RGB(UINT8 *out, const UINT8 *in, int xsize) {
int x;
for (x = 0; x < xsize; x++, in += 2) {
UINT8 v = in[1] == 0 ? in[0] : 255;
*out++ = v;
*out++ = v;
*out++ = v;
*out++ = 255;
}
}

static struct {
const char *from;
const char *to;
Expand Down Expand Up @@ -978,6 +990,7 @@ static struct {

{"I", "I;16", I_I16L},
{"I;16", "I", I16L_I},
{"I;16", "RGB", I16_RGB},
{"L", "I;16", L_I16L},
{"I;16", "L", I16L_L},

Expand Down Expand Up @@ -1678,6 +1691,7 @@ ImagingConvertTransparent(Imaging imIn, const char *mode, int r, int g, int b) {
convert = rgb2rgba;
} else if ((strcmp(imIn->mode, "1") == 0 ||
strcmp(imIn->mode, "I") == 0 ||
strcmp(imIn->mode, "I;16") == 0 ||
strcmp(imIn->mode, "L") == 0
) && (
strcmp(mode, "RGBA") == 0 ||
Expand All @@ -1687,6 +1701,8 @@ ImagingConvertTransparent(Imaging imIn, const char *mode, int r, int g, int b) {
convert = bit2rgb;
} else if (strcmp(imIn->mode, "I") == 0) {
convert = i2rgb;
} else if (strcmp(imIn->mode, "I;16") == 0) {
convert = I16_RGB;
} else {
convert = l2rgb;
}
Expand Down

0 comments on commit dec3ef6

Please sign in to comment.