Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: flip images / eq method for image #360

Merged
merged 24 commits into from
Jun 16, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
efdc12c
eq method for image
patrikguempel Jun 16, 2023
6383af5
linter sugar
patrikguempel Jun 16, 2023
be7d617
linter sugar
patrikguempel Jun 16, 2023
f01d1e2
linter sugar
patrikguempel Jun 16, 2023
cc36b11
Merge remote-tracking branch 'origin/280-flip-image-horizontally-and-…
patrikguempel Jun 16, 2023
b7a1578
Merge remote-tracking branch 'origin/280-flip-image-horizontally-and-…
patrikguempel Jun 16, 2023
fbc456d
Merge remote-tracking branch 'origin/280-flip-image-horizontally-and-…
patrikguempel Jun 16, 2023
6579c23
Merge remote-tracking branch 'origin/280-flip-image-horizontally-and-…
patrikguempel Jun 16, 2023
e830d23
Merge remote-tracking branch 'origin/280-flip-image-horizontally-and-…
patrikguempel Jun 16, 2023
ac093dd
style: apply automated linter fixes
megalinter-bot Jun 16, 2023
0d63e3a
Merge remote-tracking branch 'origin/280-flip-image-horizontally-and-…
patrikguempel Jun 16, 2023
1fbff97
Merge remote-tracking branch 'origin/280-flip-image-horizontally-and-…
patrikguempel Jun 16, 2023
251b475
Update src/safeds/data/image/containers/_image.py
patrikguempel Jun 16, 2023
f02b133
Merge remote-tracking branch 'origin/280-flip-image-horizontally-and-…
patrikguempel Jun 16, 2023
147dbc0
Merge remote-tracking branch 'origin/280-flip-image-horizontally-and-…
patrikguempel Jun 16, 2023
e561554
Merge remote-tracking branch 'origin/280-flip-image-horizontally-and-…
patrikguempel Jun 16, 2023
04a16dc
added test, renamed methods
patrikguempel Jun 16, 2023
e172562
flip tests adjusted
daniaHu Jun 16, 2023
742193e
flip tests adjusted
daniaHu Jun 16, 2023
ed6a26c
flip tests adjusted
daniaHu Jun 16, 2023
303b978
Merge remote-tracking branch 'origin/280-flip-image-horizontally-and-…
patrikguempel Jun 16, 2023
a6b787a
Merge branch 'main' into 280-flip-image-horizontally-and-vertically
patrikguempel Jun 16, 2023
31770a7
style: apply automated linter fixes
megalinter-bot Jun 16, 2023
f2916be
Update tests/safeds/data/image/containers/test_image.py
patrikguempel Jun 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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_should_be_original(self) -> None:
patrikguempel marked this conversation as resolved.
Show resolved Hide resolved
image = Image.from_png_file(resolve_resource_path("image/original.png"))
image2 = image.flip_horizontally().flip_horizontally()
assert image == image2