From 86afe2136c823fc69497a1b374cf78461ede6bce Mon Sep 17 00:00:00 2001 From: Anton Soloviev Date: Mon, 12 Oct 2026 03:16:11 -0700 Subject: [PATCH] Refresh image dimensions after quarter-turn rotations --- CHANGELOG.md | 1 + tcod/image.py | 1 + tests/test_image.py | 27 +++++++++++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 tests/test_image.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 10c9a855..b8281650 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](https://semver.org/) since version ### Fixed +- `tcod.image.Image.rotate90` updates the width and height of rectangular images, keeping NumPy array conversions consistent with the rotated pixels. - Adding a root to an already resolved `tcod.path.Pathfinder` resets its predecessor only when its value improves the current distance. This prevents cyclic paths while preserving routes to cheaper roots. - Lazy pathfinder queries reconsider previously visited goals after adding a root or lowering a root's distance. diff --git a/tcod/image.py b/tcod/image.py index 0f154450..f1ccf451 100644 --- a/tcod/image.py +++ b/tcod/image.py @@ -110,6 +110,7 @@ def rotate90(self, rotations: int = 1) -> None: rotations (int): Number of 90 degree clockwise rotations. """ lib.TCOD_image_rotate90(self.image_c, rotations) + self.width, self.height = self._get_size() def vflip(self) -> None: """Vertically flip this Image.""" diff --git a/tests/test_image.py b/tests/test_image.py new file mode 100644 index 00000000..ebae367b --- /dev/null +++ b/tests/test_image.py @@ -0,0 +1,27 @@ +"""Tests for the image object and its NumPy interface.""" + +import numpy as np +import pytest + +import tcod.image + + +@pytest.mark.parametrize("shape", [(4, 6), (6, 4), (4, 4)]) +@pytest.mark.parametrize("rotations", [-5, -2, -1, 0, 1, 2, 3, 4, 5]) +def test_rotate90_dimensions(shape: tuple[int, int], rotations: int) -> None: + pixels = np.arange(shape[0] * shape[1] * 3, dtype=np.uint8).reshape(*shape, 3) + image = tcod.image.Image.from_array(pixels) + image.rotate90(rotations) + expected = np.rot90(pixels, -rotations) + assert (image.height, image.width) == expected.shape[:2] + np.testing.assert_array_equal(np.asarray(image), expected) + + +def test_rotate90_sequence() -> None: + pixels = np.arange(4 * 6 * 3, dtype=np.uint8).reshape(4, 6, 3) + image = tcod.image.Image.from_array(pixels) + for _ in range(4): + image.rotate90() + pixels = np.rot90(pixels, -1) + assert (image.height, image.width) == pixels.shape[:2] + np.testing.assert_array_equal(np.asarray(image), pixels)