Skip to content

Commit

Permalink
feat: flip images / eq method for image (#360)
Browse files Browse the repository at this point in the history
flip images

Closes #280.

###Summary of Changes
Images can now be flipped both horizontally and vertically.
Image now has an eq method 

Co-authored-by: daniaHu <129186516+daniaHu@users.noreply.github.com>

---------

Co-authored-by: megalinter-bot <129584137+megalinter-bot@users.noreply.github.com>
Co-authored-by: Alex Senger <91055000+alex-senger@users.noreply.github.com>
Co-authored-by: daniaHu <s5dahuss@uni-bonn.de>
Co-authored-by: Alexander <47296670+Marsmaennchen221@users.noreply.github.com>
  • Loading branch information
5 people authored Jun 16, 2023
1 parent d9ebdc1 commit 54f4ae1
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 2 deletions.
50 changes: 48 additions & 2 deletions src/safeds/data/image/containers/_image.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from __future__ import annotations

import copy
import io
from pathlib import Path
from typing import BinaryIO
from typing import Any, BinaryIO

import PIL
from PIL.Image import Image as PillowImage
from PIL.Image import open as open_image

Expand Down Expand Up @@ -138,6 +140,24 @@ def to_png_file(self, path: str | Path) -> None:
# IPython integration
# ------------------------------------------------------------------------------------------------------------------

def __eq__(self, other: Any) -> bool:
"""
Compare two images.
Parameters
----------
other: The image to compare to.
Returns
-------
equals : bool
Whether the two images contain equal pixel data.
"""
if not isinstance(other, Image):
return NotImplemented
return self._image.tobytes() == other._image.tobytes()

def _repr_jpeg_(self) -> bytes | None:
"""
Return a JPEG image as bytes.
Expand Down Expand Up @@ -182,7 +202,7 @@ def _repr_png_(self) -> bytes | None:

def resize(self, new_width: int, new_height: int) -> Image:
"""
Return the resized image.
Return an image that has been resized to a given size.
Returns
-------
Expand All @@ -200,3 +220,29 @@ def resize(self, new_width: int, new_height: int) -> Image:
new_image = Image(data, self._format)
new_image._image = new_image._image.resize((new_width, new_height))
return new_image

def flip_vertically(self) -> Image:
"""
Flip the image vertically (horizontal axis, flips up-down and vice versa).
Returns
-------
result : Image
The flipped image.
"""
imagecopy = copy.deepcopy(self)
imagecopy._image = self._image.transpose(PIL.Image.FLIP_TOP_BOTTOM)
return imagecopy

def flip_horizontally(self) -> Image:
"""
Flip the image horizontally (vertical axis, flips left-right and vice versa).
Returns
-------
result : Image
The flipped image.
"""
imagecopy = copy.deepcopy(self)
imagecopy._image = self._image.transpose(PIL.Image.FLIP_LEFT_RIGHT)
return imagecopy
Binary file added tests/resources/image/copy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/resources/image/flip_horizontally.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/resources/image/flip_vertically.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/resources/image/original.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions tests/safeds/data/image/containers/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pytest
from safeds.data.image.containers import Image
from safeds.data.image.typing import ImageFormat
from safeds.data.tabular.containers import Table

from tests.helpers import resolve_resource_path

Expand Down Expand Up @@ -203,3 +204,46 @@ def test_should_return_resized_image(
new_size: tuple[int, int],
) -> None:
assert image.resize(new_width, new_height)._image.size == new_size


class TestEQ:
def test_should_be_equal(self) -> None:
image = Image.from_png_file(resolve_resource_path("image/original.png"))
image2 = Image.from_png_file(resolve_resource_path("image/copy.png"))
assert image == image2

def test_should_not_be_equal(self) -> None:
image = Image.from_png_file(resolve_resource_path("image/original.png"))
image2 = Image.from_png_file(resolve_resource_path("image/white_square.png"))
assert image != image2

def test_should_raise(self) -> None:
image = Image.from_png_file(resolve_resource_path("image/original.png"))
other = Table()
assert (image.__eq__(other)) is NotImplemented


class TestFlipVertically:
def test_should_flip_vertically(self) -> None:
image = Image.from_png_file(resolve_resource_path("image/original.png"))
image = image.flip_vertically()
image2 = Image.from_png_file(resolve_resource_path("image/flip_vertically.png"))
assert image == image2

def test_should_be_original(self) -> None:
image = Image.from_png_file(resolve_resource_path("image/original.png"))
image2 = image.flip_vertically().flip_vertically()
assert image == image2


class TestFlipHorizontally:
def test_should_flip_horizontally(self) -> None:
image = Image.from_png_file(resolve_resource_path("image/original.png"))
image = image.flip_horizontally()
image2 = Image.from_png_file(resolve_resource_path("image/flip_horizontally.png"))
assert image == image2

def test_should_be_original(self) -> None:
image = Image.from_png_file(resolve_resource_path("image/original.png"))
image2 = image.flip_horizontally().flip_horizontally()
assert image == image2

0 comments on commit 54f4ae1

Please sign in to comment.