diff --git a/src/safeds/data/image/containers/_image.py b/src/safeds/data/image/containers/_image.py index ddfeec3e6..2d0d3fc17 100644 --- a/src/safeds/data/image/containers/_image.py +++ b/src/safeds/data/image/containers/_image.py @@ -12,6 +12,7 @@ from PIL.Image import open as open_image from safeds.data.image.typing import ImageFormat +from safeds.exceptions._data import WrongFileExtensionError class Image: @@ -416,3 +417,40 @@ def invert_colors(self) -> Image: new_image = Image(data, self._format) new_image._image = ImageOps.invert(new_image._image) return new_image + + def rotate_right(self) -> Image: + """ + Return the png-image clockwise rotated by 90 degrees. + + Returns + ------- + result : Image + The image clockwise rotated by 90 degrees. + """ + if self.format != ImageFormat.PNG: + raise WrongFileExtensionError("/image", ".png") + + imagecopy = copy.deepcopy(self) + imagecopy._image = imagecopy._image.rotate(270, expand=True) + return imagecopy + + def rotate_left(self) -> Image: + """ + Return the png-image counter-clockwise rotated by 90 degrees. + + Returns + ------- + result : Image + The image counter-clockwise rotated by 90 degrees. + + Raises + ------ + WrongFileExtensionError + If given a File that's not PNG. + """ + if self.format != ImageFormat.PNG: + raise WrongFileExtensionError("/image", ".png") + + imagecopy = copy.deepcopy(self) + imagecopy._image = imagecopy._image.rotate(90, expand=True) + return imagecopy diff --git a/tests/resources/image/snapshot_boxplot_left_rotation.png b/tests/resources/image/snapshot_boxplot_left_rotation.png new file mode 100644 index 000000000..600de1fee Binary files /dev/null and b/tests/resources/image/snapshot_boxplot_left_rotation.png differ diff --git a/tests/resources/image/snapshot_boxplot_right_rotation.png b/tests/resources/image/snapshot_boxplot_right_rotation.png new file mode 100644 index 000000000..f6c40de31 Binary files /dev/null and b/tests/resources/image/snapshot_boxplot_right_rotation.png differ diff --git a/tests/safeds/data/image/containers/test_image.py b/tests/safeds/data/image/containers/test_image.py index 29237dcd9..34da91c5a 100644 --- a/tests/safeds/data/image/containers/test_image.py +++ b/tests/safeds/data/image/containers/test_image.py @@ -5,6 +5,7 @@ from safeds.data.image.containers import Image from safeds.data.image.typing import ImageFormat from safeds.data.tabular.containers import Table +from safeds.exceptions._data import WrongFileExtensionError from tests.helpers import resolve_resource_path @@ -383,3 +384,41 @@ def test_should_not_sharpen(self) -> None: image = Image.from_png_file(resolve_resource_path("image/sharpen/to_sharpen.png")) image2 = image.sharpen(1) assert image == image2 + + +class TestRotate: + def test_should_return_clockwise_rotated_image( + self, + ) -> None: + image = Image.from_png_file(resolve_resource_path("image/snapshot_boxplot.png")) + image = image.rotate_right() + image2 = Image.from_png_file(resolve_resource_path("image/snapshot_boxplot_right_rotation.png")) + assert image == image2 + + def test_should_return_counter_clockwise_rotated_image( + self, + ) -> None: + image = Image.from_png_file(resolve_resource_path("image/snapshot_boxplot.png")) + image = image.rotate_left() + image2 = Image.from_png_file(resolve_resource_path("image/snapshot_boxplot_left_rotation.png")) + assert image == image2 + + def test_should_raise_if_not_png_right(self) -> None: + with pytest.raises( + WrongFileExtensionError, + match=( + "The file /image has a wrong file extension. Please provide a file with the following extension\\(s\\):" + " .png" + ), + ): + Image.from_jpeg_file(resolve_resource_path("image/white_square.jpg")).rotate_right() + + def test_should_raise_if_not_png_left(self) -> None: + with pytest.raises( + WrongFileExtensionError, + match=( + "The file /image has a wrong file extension. Please provide a file with the following extension\\(s\\):" + " .png" + ), + ): + Image.from_jpeg_file(resolve_resource_path("image/white_square.jpg")).rotate_left()