Pillow/Tests/test_image_convert.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

352 lines
8.7 KiB
Python
Raw Normal View History

from __future__ import annotations
2024-01-20 14:23:03 +03:00
2024-01-25 14:18:46 +03:00
from pathlib import Path
import pytest
from PIL import Image
2020-02-25 12:57:27 +03:00
from .helper import assert_image, assert_image_equal, assert_image_similar, hopper
2024-01-25 14:18:46 +03:00
def test_sanity() -> None:
def convert(im: Image.Image, mode: str) -> None:
2020-02-25 12:57:27 +03:00
out = im.convert(mode)
assert out.mode == mode
assert out.size == im.size
modes = (
"1",
"L",
"LA",
"P",
"PA",
"I",
"F",
"RGB",
"RGBA",
"RGBX",
"CMYK",
"YCbCr",
"HSV",
)
2022-04-10 19:52:38 +03:00
for input_mode in modes:
im = hopper(input_mode)
for output_mode in modes:
convert(im, output_mode)
2020-02-25 12:57:27 +03:00
# Check 0
2022-04-10 19:52:38 +03:00
im = Image.new(input_mode, (0, 0))
for output_mode in modes:
convert(im, output_mode)
2014-05-18 00:33:50 +04:00
2017-01-29 15:03:38 +03:00
2024-01-25 14:18:46 +03:00
def test_unsupported_conversion() -> None:
im = hopper()
with pytest.raises(ValueError):
im.convert("INVALID")
2024-01-25 14:18:46 +03:00
def test_default() -> None:
2020-02-25 12:57:27 +03:00
im = hopper("P")
assert im.mode == "P"
converted_im = im.convert()
assert_image(converted_im, "RGB", im.size)
converted_im = im.convert()
assert_image(converted_im, "RGB", im.size)
im.info["transparency"] = 0
converted_im = im.convert()
assert_image(converted_im, "RGBA", im.size)
2014-05-18 00:33:50 +04:00
2020-02-25 12:57:27 +03:00
# ref https://github.com/python-pillow/Pillow/issues/274
2014-05-18 00:33:50 +04:00
2014-05-17 20:08:08 +04:00
2024-01-25 14:18:46 +03:00
def _test_float_conversion(im: Image.Image) -> None:
2020-02-25 12:57:27 +03:00
orig = im.getpixel((5, 5))
converted = im.convert("F").getpixel((5, 5))
assert orig == converted
2014-05-18 00:33:50 +04:00
2024-01-25 14:18:46 +03:00
def test_8bit() -> None:
2020-02-25 12:57:27 +03:00
with Image.open("Tests/images/hopper.jpg") as im:
_test_float_conversion(im.convert("L"))
2014-03-26 08:42:04 +04:00
2014-05-17 20:08:08 +04:00
2024-01-25 14:18:46 +03:00
def test_16bit() -> None:
2020-02-25 12:57:27 +03:00
with Image.open("Tests/images/16bit.cropped.tif") as im:
_test_float_conversion(im)
2014-05-18 00:33:50 +04:00
2022-03-05 05:42:39 +03:00
for color in (65535, 65536):
im = Image.new("I", (1, 1), color)
im_i16 = im.convert("I;16")
assert im_i16.getpixel((0, 0)) == 65535
2014-03-26 10:33:49 +04:00
2024-01-25 14:18:46 +03:00
def test_16bit_workaround() -> None:
2020-02-25 12:57:27 +03:00
with Image.open("Tests/images/16bit.cropped.tif") as im:
_test_float_conversion(im.convert("I"))
2014-03-26 10:33:49 +04:00
2024-01-25 14:18:46 +03:00
def test_opaque() -> None:
alpha = hopper("P").convert("PA").getchannel("A")
solid = Image.new("L", (128, 128), 255)
assert_image_equal(alpha, solid)
2024-01-25 14:18:46 +03:00
def test_rgba_p() -> None:
2020-02-25 12:57:27 +03:00
im = hopper("RGBA")
im.putalpha(hopper("L"))
2014-05-17 20:08:08 +04:00
2020-02-25 12:57:27 +03:00
converted = im.convert("P")
comparable = converted.convert("RGBA")
2014-05-17 20:08:08 +04:00
2020-02-25 12:57:27 +03:00
assert_image_similar(im, comparable, 20)
2014-05-18 00:33:50 +04:00
2014-05-17 20:08:08 +04:00
2024-01-25 14:18:46 +03:00
def test_rgba() -> None:
2022-11-01 00:39:02 +03:00
with Image.open("Tests/images/transparent.png") as im:
assert im.mode == "RGBA"
assert_image_similar(im.convert("RGBa").convert("RGB"), im.convert("RGB"), 1.5)
2024-01-25 14:18:46 +03:00
def test_trns_p(tmp_path: Path) -> None:
2020-02-25 12:57:27 +03:00
im = hopper("P")
im.info["transparency"] = 0
2018-01-27 09:07:24 +03:00
2020-02-25 12:57:27 +03:00
f = str(tmp_path / "temp.png")
2014-05-17 20:08:08 +04:00
2020-02-25 12:57:27 +03:00
im_l = im.convert("L")
2023-07-17 16:04:43 +03:00
assert im_l.info["transparency"] == 0
2020-02-25 12:57:27 +03:00
im_l.save(f)
2014-05-17 20:08:08 +04:00
2020-02-25 12:57:27 +03:00
im_rgb = im.convert("RGB")
2023-07-17 16:04:43 +03:00
assert im_rgb.info["transparency"] == (0, 0, 0)
2020-02-25 12:57:27 +03:00
im_rgb.save(f)
2014-03-26 10:33:49 +04:00
2014-05-17 20:08:08 +04:00
2020-02-25 12:57:27 +03:00
# ref https://github.com/python-pillow/Pillow/issues/664
@pytest.mark.parametrize("mode", ("LA", "PA", "RGBA"))
2024-01-25 14:18:46 +03:00
def test_trns_p_transparency(mode: str) -> None:
2020-02-25 12:57:27 +03:00
# Arrange
im = hopper("P")
im.info["transparency"] = 128
# Act
converted_im = im.convert(mode)
2020-02-25 12:57:27 +03:00
# Assert
assert "transparency" not in converted_im.info
if mode == "PA":
assert converted_im.palette is not None
else:
# https://github.com/python-pillow/Pillow/issues/2702
assert converted_im.palette is None
2020-02-25 12:57:27 +03:00
2024-01-25 14:18:46 +03:00
def test_trns_l(tmp_path: Path) -> None:
2020-02-25 12:57:27 +03:00
im = hopper("L")
im.info["transparency"] = 128
f = str(tmp_path / "temp.png")
im_la = im.convert("LA")
assert "transparency" not in im_la.info
im_la.save(f)
2020-02-25 12:57:27 +03:00
im_rgb = im.convert("RGB")
assert im_rgb.info["transparency"] == (128, 128, 128) # undone
im_rgb.save(f)
im_p = im.convert("P")
assert "transparency" in im_p.info
im_p.save(f)
2022-01-15 01:02:31 +03:00
im_p = im.convert("P", palette=Image.Palette.ADAPTIVE)
2021-06-27 08:09:39 +03:00
assert "transparency" in im_p.info
2020-02-25 12:57:27 +03:00
im_p.save(f)
2024-01-25 14:18:46 +03:00
def test_trns_RGB(tmp_path: Path) -> None:
2020-02-25 12:57:27 +03:00
im = hopper("RGB")
im.info["transparency"] = im.getpixel((0, 0))
f = str(tmp_path / "temp.png")
im_l = im.convert("L")
assert im_l.info["transparency"] == im_l.getpixel((0, 0)) # undone
im_l.save(f)
im_la = im.convert("LA")
assert "transparency" not in im_la.info
im_la.save(f)
2024-03-26 11:57:17 +03:00
im_la = im.convert("La")
assert "transparency" not in im_la.info
assert im_la.getpixel((0, 0)) == (0, 0)
2020-02-25 12:57:27 +03:00
im_p = im.convert("P")
assert "transparency" in im_p.info
im_p.save(f)
2014-05-17 20:08:08 +04:00
2020-02-25 12:57:27 +03:00
im_rgba = im.convert("RGBA")
assert "transparency" not in im_rgba.info
im_rgba.save(f)
2024-03-21 08:25:40 +03:00
im_rgba = im.convert("RGBa")
assert "transparency" not in im_rgba.info
assert im_rgba.getpixel((0, 0)) == (0, 0, 0, 0)
2022-01-15 01:02:31 +03:00
im_p = pytest.warns(UserWarning, im.convert, "P", palette=Image.Palette.ADAPTIVE)
2020-02-25 12:57:27 +03:00
assert "transparency" not in im_p.info
im_p.save(f)
2021-06-27 09:33:47 +03:00
im = Image.new("RGB", (1, 1))
im.info["transparency"] = im.getpixel((0, 0))
2022-01-15 01:02:31 +03:00
im_p = im.convert("P", palette=Image.Palette.ADAPTIVE)
2021-06-27 09:33:47 +03:00
assert im_p.info["transparency"] == im_p.getpixel((0, 0))
im_p.save(f)
2020-02-25 12:57:27 +03:00
@pytest.mark.parametrize("convert_mode", ("L", "LA", "I"))
2024-01-25 14:18:46 +03:00
def test_l_macro_rounding(convert_mode: str) -> None:
for mode in ("P", "PA"):
im = Image.new(mode, (1, 1))
im.palette.getcolor((0, 1, 2))
converted_im = im.convert(convert_mode)
px = converted_im.load()
converted_color = px[0, 0]
if convert_mode == "LA":
converted_color = converted_color[0]
assert converted_color == 1
2024-01-25 14:18:46 +03:00
def test_gif_with_rgba_palette_to_p() -> None:
2020-02-25 12:57:27 +03:00
# See https://github.com/python-pillow/Pillow/issues/2433
with Image.open("Tests/images/hopper.gif") as im:
im.info["transparency"] = 255
im.load()
assert im.palette.mode == "RGB"
2019-06-13 18:54:24 +03:00
im_p = im.convert("P")
2014-03-26 10:33:49 +04:00
2020-02-25 12:57:27 +03:00
# Should not raise ValueError: unrecognized raw mode
im_p.load()
2014-05-17 20:08:08 +04:00
2024-01-25 14:18:46 +03:00
def test_p_la() -> None:
2020-02-25 12:57:27 +03:00
im = hopper("RGBA")
alpha = hopper("L")
im.putalpha(alpha)
2020-02-25 12:57:27 +03:00
comparable = im.convert("P").convert("LA").getchannel("A")
2020-02-25 12:57:27 +03:00
assert_image_similar(alpha, comparable, 5)
2024-01-25 14:18:46 +03:00
def test_p2pa_alpha() -> None:
2022-05-27 13:34:05 +03:00
with Image.open("Tests/images/tiny.png") as im:
assert im.mode == "P"
im_pa = im.convert("PA")
2022-05-28 02:24:42 +03:00
assert im_pa.mode == "PA"
2022-05-27 13:34:05 +03:00
2022-05-28 02:24:42 +03:00
im_a = im_pa.getchannel("A")
for x in range(4):
alpha = 255 if x > 1 else 0
for y in range(4):
assert im_a.getpixel((x, y)) == alpha
2022-05-27 13:34:05 +03:00
2024-01-25 14:18:46 +03:00
def test_p2pa_palette() -> None:
with Image.open("Tests/images/tiny.png") as im:
im_pa = im.convert("PA")
assert im_pa.getpalette() == im.getpalette()
2024-01-25 14:18:46 +03:00
def test_matrix_illegal_conversion() -> None:
2020-02-25 12:57:27 +03:00
# Arrange
im = hopper("CMYK")
# fmt: off
matrix = (
0.412453, 0.357580, 0.180423, 0,
0.212671, 0.715160, 0.072169, 0,
0.019334, 0.119193, 0.950227, 0)
# fmt: on
assert im.mode != "RGB"
2016-06-26 13:50:38 +03:00
2020-02-25 12:57:27 +03:00
# Act / Assert
with pytest.raises(ValueError):
im.convert(mode="CMYK", matrix=matrix)
2024-01-25 14:18:46 +03:00
def test_matrix_wrong_mode() -> None:
2020-02-25 12:57:27 +03:00
# Arrange
im = hopper("L")
# fmt: off
matrix = (
0.412453, 0.357580, 0.180423, 0,
0.212671, 0.715160, 0.072169, 0,
0.019334, 0.119193, 0.950227, 0)
# fmt: on
assert im.mode == "L"
2017-01-29 15:03:38 +03:00
2020-02-25 12:57:27 +03:00
# Act / Assert
with pytest.raises(ValueError):
im.convert(mode="L", matrix=matrix)
2017-01-29 15:03:38 +03:00
2020-02-25 12:57:27 +03:00
2022-08-23 14:41:32 +03:00
@pytest.mark.parametrize("mode", ("RGB", "L"))
2024-01-25 14:18:46 +03:00
def test_matrix_xyz(mode: str) -> None:
2022-08-23 14:41:32 +03:00
# Arrange
im = hopper("RGB")
im.info["transparency"] = (255, 0, 0)
# fmt: off
matrix = (
0.412453, 0.357580, 0.180423, 0,
0.212671, 0.715160, 0.072169, 0,
0.019334, 0.119193, 0.950227, 0)
# fmt: on
assert im.mode == "RGB"
# Act
# Convert an RGB image to the CIE XYZ colour space
converted_im = im.convert(mode=mode, matrix=matrix)
# Assert
assert converted_im.mode == mode
assert converted_im.size == im.size
with Image.open("Tests/images/hopper-XYZ.png") as target:
if converted_im.mode == "RGB":
assert_image_similar(converted_im, target, 3)
assert converted_im.info["transparency"] == (105, 54, 4)
else:
assert_image_similar(converted_im, target.getchannel(0), 1)
assert converted_im.info["transparency"] == 105
2020-02-25 12:57:27 +03:00
2024-01-25 14:18:46 +03:00
def test_matrix_identity() -> None:
2020-02-25 12:57:27 +03:00
# Arrange
im = hopper("RGB")
# fmt: off
identity_matrix = (
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0)
# fmt: on
assert im.mode == "RGB"
# Act
# Convert with an identity matrix
converted_im = im.convert(mode="RGB", matrix=identity_matrix)
# Assert
# No change
assert_image_equal(converted_im, im)