From 2506d5ceb23c9050810a74827f87ca24297b7499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Gr=C3=A9us?= Date: Fri, 8 Dec 2023 03:18:01 +0100 Subject: [PATCH] test: Added test for saving images feat: Added IllegalFormatError --- src/safeds/data/image/containers/_image.py | 2 +- src/safeds/exceptions/__init__.py | 2 + src/safeds/exceptions/_data.py | 7 +++ .../data/image/containers/test_image.py | 59 ++++++++++++++++++- 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/safeds/data/image/containers/_image.py b/src/safeds/data/image/containers/_image.py index 1e3ea8084..fbb54a49e 100644 --- a/src/safeds/data/image/containers/_image.py +++ b/src/safeds/data/image/containers/_image.py @@ -21,7 +21,7 @@ from torchvision.transforms.v2 import functional as func2 from torchvision.utils import save_image -from safeds.exceptions import ClosedBound, OutOfBoundsError +from safeds.exceptions import ClosedBound, OutOfBoundsError, IllegalFormatError class Image: diff --git a/src/safeds/exceptions/__init__.py b/src/safeds/exceptions/__init__.py index 352334cf5..fa930f62f 100644 --- a/src/safeds/exceptions/__init__.py +++ b/src/safeds/exceptions/__init__.py @@ -5,6 +5,7 @@ ColumnLengthMismatchError, ColumnSizeError, DuplicateColumnNameError, + IllegalFormatError, IllegalSchemaModificationError, IndexOutOfBoundsError, MissingValuesColumnError, @@ -38,6 +39,7 @@ "ColumnLengthMismatchError", "ColumnSizeError", "DuplicateColumnNameError", + "IllegalFormatError", "IllegalSchemaModificationError", "IndexOutOfBoundsError", "MissingValuesColumnError", diff --git a/src/safeds/exceptions/_data.py b/src/safeds/exceptions/_data.py index 700a7dbac..9b6904e51 100644 --- a/src/safeds/exceptions/_data.py +++ b/src/safeds/exceptions/_data.py @@ -148,3 +148,10 @@ class ColumnIsTargetError(IllegalSchemaModificationError): def __init__(self, column_name: str) -> None: super().__init__(f'Column "{column_name}" is the target column and cannot be removed.') + + +class IllegalFormatError(Exception): + """Exception raised when a format is not legal.""" + + def __init__(self, formats: list[str] | str) -> None: + super().__init__(f"This format is illegal. Use one of the following formats: {formats}") diff --git a/tests/safeds/data/image/containers/test_image.py b/tests/safeds/data/image/containers/test_image.py index c97ab4f9b..f0c00d527 100644 --- a/tests/safeds/data/image/containers/test_image.py +++ b/tests/safeds/data/image/containers/test_image.py @@ -1,10 +1,11 @@ from pathlib import Path +from tempfile import NamedTemporaryFile import pytest import torch from safeds.data.image.containers import Image from safeds.data.tabular.containers import Table -from safeds.exceptions import OutOfBoundsError +from safeds.exceptions import OutOfBoundsError, IllegalFormatError from syrupy import SnapshotAssertion from torch.types import Device @@ -69,7 +70,7 @@ class TestFromBytes: def test_should_write_and_load_bytes_jpeg(self, resource_path: str | Path, device: Device) -> None: _skip_if_device_not_available(device) image = Image.from_file(resolve_resource_path(resource_path), device) - image_copy = Image.from_bytes(image._repr_jpeg_(), device) + image_copy = Image.from_bytes(bytes(image._repr_jpeg_()), device) assert image == image_copy @pytest.mark.parametrize( @@ -123,6 +124,60 @@ def test_should_return_bytes(self, resource_path: str | Path, device: Device) -> assert isinstance(image._repr_png_(), bytes) +@pytest.mark.parametrize("device", _test_devices(), ids=_test_devices_ids()) +class TestToJpegFile: + @pytest.mark.parametrize( + "resource_path", + ["image/white_square.jpg", "image/white_square.png"], + ids=["white_square-jpg", "white_square-png"], + ) + def test_should_save_file(self, resource_path: str | Path, device: Device) -> None: + _skip_if_device_not_available(device) + image = Image.from_file(resolve_resource_path(resource_path), device) + with NamedTemporaryFile(suffix=".jpg") as tmp_jpeg_file: + tmp_jpeg_file.close() + with Path(tmp_jpeg_file.name).open("w", encoding="utf-8") as tmp_file: + image.to_jpeg_file(tmp_file.name) + with Path(tmp_jpeg_file.name).open("r", encoding="utf-8") as tmp_file: + image_r = Image.from_file(tmp_file.name) + assert image == image_r + + @pytest.mark.parametrize( + "resource_path", + [ + "image/plane.png", + "image/rgba.png", + ], + ids=["plane-png", "rgba-png"], + ) + def test_should_raise_if_image_has_alpha_channel(self, resource_path: str | Path, device: Device) -> None: + _skip_if_device_not_available(device) + image = Image.from_file(resolve_resource_path(resource_path), device) + with NamedTemporaryFile(suffix=".jpg") as tmp_jpeg_file: + tmp_jpeg_file.close() + with Path(tmp_jpeg_file.name).open("w", encoding="utf-8") as tmp_file, pytest.raises(IllegalFormatError, match=r"This format is illegal. Use one of the following formats: png"): + image.to_jpeg_file(tmp_file.name) + + +@pytest.mark.parametrize("device", _test_devices(), ids=_test_devices_ids()) +class TestToPngFile: + @pytest.mark.parametrize( + "resource_path", + ["image/plane.jpg", "image/plane.png", "image/rgba.png", "image/white_square.jpg", "image/white_square.png"], + ids=["plane-jpg", "plane-png", "rgba-png", "white_square-jpg", "white_square-png"], + ) + def test_should_save_file(self, resource_path: str | Path, device: Device) -> None: + _skip_if_device_not_available(device) + image = Image.from_file(resolve_resource_path(resource_path), device) + with NamedTemporaryFile(suffix=".png") as tmp_png_file: + tmp_png_file.close() + with Path(tmp_png_file.name).open("w", encoding="utf-8") as tmp_file: + image.to_png_file(tmp_file.name) + with Path(tmp_png_file.name).open("r", encoding="utf-8") as tmp_file: + image_r = Image.from_file(tmp_file.name) + assert image == image_r + + @pytest.mark.parametrize("device", _test_devices(), ids=_test_devices_ids()) class TestProperties: @pytest.mark.parametrize(