diff options
author | RĂ©mi Verschelde <remi@verschelde.fr> | 2022-07-19 15:21:16 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-19 15:21:16 +0200 |
commit | eea14a0edc3f2a8ab4a91d1e142d48a5348584bb (patch) | |
tree | 1df5ccb333af741bdba800ca0cb80b0eec91648e /core | |
parent | 8351d75b7f8322fda894c151db7c91106425c098 (diff) | |
parent | 7e66903d5610ea5c72852d11b29c3f1a31a5aa00 (diff) |
Merge pull request #63005 from Chaosus/image_rotate
Implement `rotate_90/rotate_180` functions to `Image`
Diffstat (limited to 'core')
-rw-r--r-- | core/io/image.cpp | 105 | ||||
-rw-r--r-- | core/io/image.h | 3 |
2 files changed, 108 insertions, 0 deletions
diff --git a/core/io/image.cpp b/core/io/image.cpp index 8d15ede1e9..0f20aabd7e 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -1339,6 +1339,108 @@ void Image::crop(int p_width, int p_height) { crop_from_point(0, 0, p_width, p_height); } +void Image::rotate_90(ClockDirection p_direction) { + ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats."); + ERR_FAIL_COND_MSG(width <= 1, "The Image width specified (" + itos(width) + " pixels) must be greater than 1 pixels."); + ERR_FAIL_COND_MSG(height <= 1, "The Image height specified (" + itos(height) + " pixels) must be greater than 1 pixels."); + + int saved_width = height; + int saved_height = width; + + if (width != height) { + int n = MAX(width, height); + resize(n, n, INTERPOLATE_NEAREST); + } + + bool used_mipmaps = has_mipmaps(); + if (used_mipmaps) { + clear_mipmaps(); + } + + { + uint8_t *w = data.ptrw(); + uint8_t src[16]; + uint8_t dst[16]; + uint32_t pixel_size = get_format_pixel_size(format); + + // Flip. + + if (p_direction == CLOCKWISE) { + for (int y = 0; y < height / 2; y++) { + for (int x = 0; x < width; x++) { + _get_pixelb(x, y, pixel_size, w, src); + _get_pixelb(x, height - y - 1, pixel_size, w, dst); + + _put_pixelb(x, height - y - 1, pixel_size, w, src); + _put_pixelb(x, y, pixel_size, w, dst); + } + } + } else { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width / 2; x++) { + _get_pixelb(x, y, pixel_size, w, src); + _get_pixelb(width - x - 1, y, pixel_size, w, dst); + + _put_pixelb(width - x - 1, y, pixel_size, w, src); + _put_pixelb(x, y, pixel_size, w, dst); + } + } + } + + // Transpose. + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + if (x < y) { + _get_pixelb(x, y, pixel_size, w, src); + _get_pixelb(y, x, pixel_size, w, dst); + + _put_pixelb(y, x, pixel_size, w, src); + _put_pixelb(x, y, pixel_size, w, dst); + } + } + } + } + + if (saved_width != saved_height) { + resize(saved_width, saved_height, INTERPOLATE_NEAREST); + } else if (used_mipmaps) { + generate_mipmaps(); + } +} + +void Image::rotate_180() { + ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats."); + ERR_FAIL_COND_MSG(width <= 1, "The Image width specified (" + itos(width) + " pixels) must be greater than 1 pixels."); + ERR_FAIL_COND_MSG(height <= 1, "The Image height specified (" + itos(height) + " pixels) must be greater than 1 pixels."); + + bool used_mipmaps = has_mipmaps(); + if (used_mipmaps) { + clear_mipmaps(); + } + + { + uint8_t *w = data.ptrw(); + uint8_t src[16]; + uint8_t dst[16]; + uint32_t pixel_size = get_format_pixel_size(format); + + for (int y = 0; y < height / 2; y++) { + for (int x = 0; x < width; x++) { + _get_pixelb(x, y, pixel_size, w, src); + _get_pixelb(width - x - 1, height - y - 1, pixel_size, w, dst); + + _put_pixelb(width - x - 1, height - y - 1, pixel_size, w, src); + _put_pixelb(x, y, pixel_size, w, dst); + } + } + } + + if (used_mipmaps) { + generate_mipmaps(); + } +} + void Image::flip_y() { ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_y in compressed or custom image formats."); @@ -3217,6 +3319,9 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("decompress"), &Image::decompress); ClassDB::bind_method(D_METHOD("is_compressed"), &Image::is_compressed); + ClassDB::bind_method(D_METHOD("rotate_90", "direction"), &Image::rotate_90); + ClassDB::bind_method(D_METHOD("rotate_180"), &Image::rotate_180); + ClassDB::bind_method(D_METHOD("fix_alpha_edges"), &Image::fix_alpha_edges); ClassDB::bind_method(D_METHOD("premultiply_alpha"), &Image::premultiply_alpha); ClassDB::bind_method(D_METHOD("srgb_to_linear"), &Image::srgb_to_linear); diff --git a/core/io/image.h b/core/io/image.h index b926ed69ef..46820a4c08 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -254,6 +254,9 @@ public: void crop_from_point(int p_x, int p_y, int p_width, int p_height); void crop(int p_width, int p_height); + void rotate_90(ClockDirection p_direction); + void rotate_180(); + void flip_x(); void flip_y(); |