diff options
Diffstat (limited to 'core/image.cpp')
-rw-r--r-- | core/image.cpp | 96 |
1 files changed, 34 insertions, 62 deletions
diff --git a/core/image.cpp b/core/image.cpp index 10778eced6..900efb0eb0 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -83,6 +83,7 @@ const char *Image::format_names[Image::FORMAT_MAX] = { }; SavePNGFunc Image::save_png_func = NULL; +SaveEXRFunc Image::save_exr_func = NULL; void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel) { @@ -422,8 +423,7 @@ void Image::convert(Format p_new_format) { if (format > FORMAT_RGBE9995 || p_new_format > FORMAT_RGBE9995) { - ERR_EXPLAIN("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead."); - ERR_FAIL(); + ERR_FAIL_MSG("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead."); } else if (format > FORMAT_RGBA8 || p_new_format > FORMAT_RGBA8) { @@ -753,15 +753,14 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict for (int32_t buffer_x = 0; buffer_x < dst_width; buffer_x++) { - float src_real_x = buffer_x * x_scale; - int32_t src_x = src_real_x; - - int32_t start_x = MAX(0, src_x - half_kernel + 1); - int32_t end_x = MIN(src_width - 1, src_x + half_kernel); + // The corresponding point on the source image + float src_x = (buffer_x + 0.5f) * x_scale; // Offset by 0.5 so it uses the pixel's center + int32_t start_x = MAX(0, int32_t(src_x) - half_kernel + 1); + int32_t end_x = MIN(src_width - 1, int32_t(src_x) + half_kernel); // Create the kernel used by all the pixels of the column for (int32_t target_x = start_x; target_x <= end_x; target_x++) - kernel[target_x - start_x] = _lanczos((src_real_x - target_x) / scale_factor); + kernel[target_x - start_x] = _lanczos((target_x + 0.5f - src_x) / scale_factor); for (int32_t buffer_y = 0; buffer_y < src_height; buffer_y++) { @@ -804,14 +803,12 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict for (int32_t dst_y = 0; dst_y < dst_height; dst_y++) { - float buffer_real_y = dst_y * y_scale; - int32_t buffer_y = buffer_real_y; - - int32_t start_y = MAX(0, buffer_y - half_kernel + 1); - int32_t end_y = MIN(src_height - 1, buffer_y + half_kernel); + float buffer_y = (dst_y + 0.5f) * y_scale; + int32_t start_y = MAX(0, int32_t(buffer_y) - half_kernel + 1); + int32_t end_y = MIN(src_height - 1, int32_t(buffer_y) + half_kernel); for (int32_t target_y = start_y; target_y <= end_y; target_y++) - kernel[target_y - start_y] = _lanczos((buffer_real_y - target_y) / scale_factor); + kernel[target_y - start_y] = _lanczos((target_y + 0.5f - buffer_y) / scale_factor); for (int32_t dst_x = 0; dst_x < dst_width; dst_x++) { @@ -866,10 +863,7 @@ bool Image::is_size_po2() const { void Image::resize_to_po2(bool p_square) { - if (!_can_modify(format)) { - ERR_EXPLAIN("Cannot resize in indexed, compressed or custom image formats."); - ERR_FAIL(); - } + ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats."); int w = next_power_of_2(width); int h = next_power_of_2(height); @@ -885,15 +879,9 @@ void Image::resize_to_po2(bool p_square) { void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { - if (data.size() == 0) { - ERR_EXPLAIN("Cannot resize image before creating it, use create() or create_from_data() first."); - ERR_FAIL(); - } + ERR_FAIL_COND_MSG(data.size() == 0, "Cannot resize image before creating it, use create() or create_from_data() first."); - if (!_can_modify(format)) { - ERR_EXPLAIN("Cannot resize in indexed, compressed or custom image formats."); - ERR_FAIL(); - } + ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats."); bool mipmap_aware = p_interpolation == INTERPOLATE_TRILINEAR /* || p_interpolation == INTERPOLATE_TRICUBIC */; @@ -1106,10 +1094,8 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) { - if (!_can_modify(format)) { - ERR_EXPLAIN("Cannot crop in indexed, compressed or custom image formats."); - ERR_FAIL(); - } + ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot crop in compressed or custom image formats."); + ERR_FAIL_COND(p_x < 0); ERR_FAIL_COND(p_y < 0); ERR_FAIL_COND(p_width <= 0); @@ -1163,10 +1149,7 @@ void Image::crop(int p_width, int p_height) { void Image::flip_y() { - if (!_can_modify(format)) { - ERR_EXPLAIN("Cannot flip_y in indexed, compressed or custom image formats."); - ERR_FAIL(); - } + ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_y in compressed or custom image formats."); bool used_mipmaps = has_mipmaps(); if (used_mipmaps) { @@ -1199,10 +1182,7 @@ void Image::flip_y() { void Image::flip_x() { - if (!_can_modify(format)) { - ERR_EXPLAIN("Cannot flip_x in indexed, compressed or custom image formats."); - ERR_FAIL(); - } + ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_x in compressed or custom image formats."); bool used_mipmaps = has_mipmaps(); if (used_mipmaps) { @@ -1461,15 +1441,9 @@ void Image::normalize() { Error Image::generate_mipmaps(bool p_renormalize) { - if (!_can_modify(format)) { - ERR_EXPLAIN("Cannot generate mipmaps in indexed, compressed or custom image formats."); - ERR_FAIL_V(ERR_UNAVAILABLE); - } + ERR_FAIL_COND_V_MSG(!_can_modify(format), ERR_UNAVAILABLE, "Cannot generate mipmaps in compressed or custom image formats."); - if (width == 0 || height == 0) { - ERR_EXPLAIN("Cannot generate mipmaps with width or height equal to 0."); - ERR_FAIL_V(ERR_UNCONFIGURED); - } + ERR_FAIL_COND_V_MSG(width == 0 || height == 0, ERR_UNCONFIGURED, "Cannot generate mipmaps with width or height equal to 0."); int mmcount; @@ -1620,10 +1594,7 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma int mm; int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0); - if (size != p_data.size()) { - ERR_EXPLAIN("Expected data size of " + itos(size) + " bytes in Image::create(), got instead " + itos(p_data.size()) + " bytes."); - ERR_FAIL_COND(p_data.size() != size); - } + ERR_FAIL_COND_MSG(p_data.size() != size, "Expected data size of " + itos(size) + " bytes in Image::create(), got instead " + itos(p_data.size()) + " bytes."); height = p_height; width = p_width; @@ -1917,6 +1888,14 @@ Error Image::save_png(const String &p_path) const { return save_png_func(p_path, Ref<Image>((Image *)this)); } +Error Image::save_exr(const String &p_path, bool p_grayscale) const { + + if (save_exr_func == NULL) + return ERR_UNAVAILABLE; + + return save_exr_func(p_path, Ref<Image>((Image *)this), p_grayscale); +} + int Image::get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps) { int mm; @@ -2405,10 +2384,7 @@ Color Image::get_pixel(int p_x, int p_y) const { uint8_t *ptr = write_lock.ptr(); #ifdef DEBUG_ENABLED - if (!ptr) { - ERR_EXPLAIN("Image must be locked with 'lock()' before using get_pixel()"); - ERR_FAIL_V(Color()); - } + ERR_FAIL_COND_V_MSG(!ptr, Color(), "Image must be locked with 'lock()' before using get_pixel()."); ERR_FAIL_INDEX_V(p_x, width, Color()); ERR_FAIL_INDEX_V(p_y, height, Color()); @@ -2524,8 +2500,7 @@ Color Image::get_pixel(int p_x, int p_y) const { return Color::from_rgbe9995(((uint32_t *)ptr)[ofs]); } default: { - ERR_EXPLAIN("Can't get_pixel() on compressed image, sorry."); - ERR_FAIL_V(Color()); + ERR_FAIL_V_MSG(Color(), "Can't get_pixel() on compressed image, sorry."); } } } @@ -2538,10 +2513,7 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) { uint8_t *ptr = write_lock.ptr(); #ifdef DEBUG_ENABLED - if (!ptr) { - ERR_EXPLAIN("Image must be locked with 'lock()' before using set_pixel()"); - ERR_FAIL(); - } + ERR_FAIL_COND_MSG(!ptr, "Image must be locked with 'lock()' before using set_pixel()."); ERR_FAIL_INDEX(p_x, width); ERR_FAIL_INDEX(p_y, height); @@ -2653,8 +2625,7 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) { } break; default: { - ERR_EXPLAIN("Can't set_pixel() on compressed image, sorry."); - ERR_FAIL(); + ERR_FAIL_MSG("Can't set_pixel() on compressed image, sorry."); } } } @@ -2746,6 +2717,7 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("load", "path"), &Image::load); ClassDB::bind_method(D_METHOD("save_png", "path"), &Image::save_png); + ClassDB::bind_method(D_METHOD("save_exr", "path", "grayscale"), &Image::save_exr, DEFVAL(false)); ClassDB::bind_method(D_METHOD("detect_alpha"), &Image::detect_alpha); ClassDB::bind_method(D_METHOD("is_invisible"), &Image::is_invisible); |