diff options
Diffstat (limited to 'core/io/image.cpp')
-rw-r--r-- | core/io/image.cpp | 140 |
1 files changed, 71 insertions, 69 deletions
diff --git a/core/io/image.cpp b/core/io/image.cpp index 5376b78a89..661a9f7177 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -378,25 +378,25 @@ Image::Image3DValidateError Image::validate_3d_image(Image::Format p_format, int String Image::get_3d_image_validation_error_text(Image3DValidateError p_error) { switch (p_error) { case VALIDATE_3D_OK: { - return TTR("Ok"); + return "Ok"; } break; case VALIDATE_3D_ERR_IMAGE_EMPTY: { - return TTR("Empty Image found"); + return "Empty Image found"; } break; case VALIDATE_3D_ERR_MISSING_IMAGES: { - return TTR("Missing Images"); + return "Missing Images"; } break; case VALIDATE_3D_ERR_EXTRA_IMAGES: { - return TTR("Too many Images"); + return "Too many Images"; } break; case VALIDATE_3D_ERR_IMAGE_SIZE_MISMATCH: { - return TTR("Image size mismatch"); + return "Image size mismatch"; } break; case VALIDATE_3D_ERR_IMAGE_FORMAT_MISMATCH: { - return TTR("Image format mismatch"); + return "Image format mismatch"; } break; case VALIDATE_3D_ERR_IMAGE_HAS_MIPMAPS: { - return TTR("Image has included mipmaps"); + return "Image has included mipmaps"; } break; } return String(); @@ -2442,6 +2442,39 @@ Ref<Image> Image::get_rect(const Rect2 &p_area) const { return img; } +void Image::_get_clipped_src_and_dest_rects(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest, Rect2i &r_clipped_src_rect, Rect2i &r_clipped_dest_rect) const { + r_clipped_dest_rect.position = p_dest; + r_clipped_src_rect = p_src_rect; + + if (r_clipped_src_rect.position.x < 0) { + r_clipped_dest_rect.position.x -= r_clipped_src_rect.position.x; + r_clipped_src_rect.size.x += r_clipped_src_rect.position.x; + r_clipped_src_rect.position.x = 0; + } + if (r_clipped_src_rect.position.y < 0) { + r_clipped_dest_rect.position.y -= r_clipped_src_rect.position.y; + r_clipped_src_rect.size.y += r_clipped_src_rect.position.y; + r_clipped_src_rect.position.y = 0; + } + + if (r_clipped_dest_rect.position.x < 0) { + r_clipped_src_rect.position.x -= r_clipped_dest_rect.position.x; + r_clipped_src_rect.size.x += r_clipped_dest_rect.position.x; + r_clipped_dest_rect.position.x = 0; + } + if (r_clipped_dest_rect.position.y < 0) { + r_clipped_src_rect.position.y -= r_clipped_dest_rect.position.y; + r_clipped_src_rect.size.y += r_clipped_dest_rect.position.y; + r_clipped_dest_rect.position.y = 0; + } + + r_clipped_src_rect.size.x = MAX(0, MIN(r_clipped_src_rect.size.x, MIN(p_src->width - r_clipped_src_rect.position.x, width - r_clipped_dest_rect.position.x))); + r_clipped_src_rect.size.y = MAX(0, MIN(r_clipped_src_rect.size.y, MIN(p_src->height - r_clipped_src_rect.position.y, height - r_clipped_dest_rect.position.y))); + + r_clipped_dest_rect.size.x = r_clipped_src_rect.size.x; + r_clipped_dest_rect.size.y = r_clipped_src_rect.size.y; +} + void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) { ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object."); int dsize = data.size(); @@ -2451,22 +2484,13 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po ERR_FAIL_COND(format != p_src->format); ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot blit_rect in compressed or custom image formats."); - Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect); - - if (p_dest.x < 0) { - clipped_src_rect.position.x = ABS(p_dest.x); - } - if (p_dest.y < 0) { - clipped_src_rect.position.y = ABS(p_dest.y); - } - - if (clipped_src_rect.has_no_area()) { + Rect2i src_rect; + Rect2i dest_rect; + _get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect); + if (src_rect.has_no_area() || dest_rect.has_no_area()) { return; } - Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); - Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); - uint8_t *wp = data.ptrw(); uint8_t *dst_data_ptr = wp; @@ -2477,8 +2501,8 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po for (int i = 0; i < dest_rect.size.y; i++) { for (int j = 0; j < dest_rect.size.x; j++) { - int src_x = clipped_src_rect.position.x + j; - int src_y = clipped_src_rect.position.y + i; + int src_x = src_rect.position.x + j; + int src_y = src_rect.position.y + i; int dst_x = dest_rect.position.x + j; int dst_y = dest_rect.position.y + i; @@ -2506,22 +2530,13 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co ERR_FAIL_COND_MSG(p_src->height != p_mask->height, "Source image height is different from mask height."); ERR_FAIL_COND(format != p_src->format); - Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect); - - if (p_dest.x < 0) { - clipped_src_rect.position.x = ABS(p_dest.x); - } - if (p_dest.y < 0) { - clipped_src_rect.position.y = ABS(p_dest.y); - } - - if (clipped_src_rect.has_no_area()) { + Rect2i src_rect; + Rect2i dest_rect; + _get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect); + if (src_rect.has_no_area() || dest_rect.has_no_area()) { return; } - Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); - Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); - uint8_t *wp = data.ptrw(); uint8_t *dst_data_ptr = wp; @@ -2534,8 +2549,8 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co for (int i = 0; i < dest_rect.size.y; i++) { for (int j = 0; j < dest_rect.size.x; j++) { - int src_x = clipped_src_rect.position.x + j; - int src_y = clipped_src_rect.position.y + i; + int src_x = src_rect.position.x + j; + int src_y = src_rect.position.y + i; if (msk->get_pixel(src_x, src_y).a != 0) { int dst_x = dest_rect.position.x + j; @@ -2560,28 +2575,19 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P ERR_FAIL_COND(srcdsize == 0); ERR_FAIL_COND(format != p_src->format); - Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect); - - if (p_dest.x < 0) { - clipped_src_rect.position.x = ABS(p_dest.x); - } - if (p_dest.y < 0) { - clipped_src_rect.position.y = ABS(p_dest.y); - } - - if (clipped_src_rect.has_no_area()) { + Rect2i src_rect; + Rect2i dest_rect; + _get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect); + if (src_rect.has_no_area() || dest_rect.has_no_area()) { return; } - Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); - Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); - Ref<Image> img = p_src; for (int i = 0; i < dest_rect.size.y; i++) { for (int j = 0; j < dest_rect.size.x; j++) { - int src_x = clipped_src_rect.position.x + j; - int src_y = clipped_src_rect.position.y + i; + int src_x = src_rect.position.x + j; + int src_y = src_rect.position.y + i; int dst_x = dest_rect.position.x + j; int dst_y = dest_rect.position.y + i; @@ -2609,29 +2615,20 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c ERR_FAIL_COND_MSG(p_src->height != p_mask->height, "Source image height is different from mask height."); ERR_FAIL_COND(format != p_src->format); - Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect); - - if (p_dest.x < 0) { - clipped_src_rect.position.x = ABS(p_dest.x); - } - if (p_dest.y < 0) { - clipped_src_rect.position.y = ABS(p_dest.y); - } - - if (clipped_src_rect.has_no_area()) { + Rect2i src_rect; + Rect2i dest_rect; + _get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect); + if (src_rect.has_no_area() || dest_rect.has_no_area()) { return; } - Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); - Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); - Ref<Image> img = p_src; Ref<Image> msk = p_mask; for (int i = 0; i < dest_rect.size.y; i++) { for (int j = 0; j < dest_rect.size.x; j++) { - int src_x = clipped_src_rect.position.x + j; - int src_y = clipped_src_rect.position.y + i; + int src_x = src_rect.position.x + j; + int src_y = src_rect.position.y + i; // If the mask's pixel is transparent then we skip it //Color c = msk->get_pixel(src_x, src_y); @@ -2726,6 +2723,7 @@ Vector<uint8_t> (*Image::png_packer)(const Ref<Image> &) = nullptr; Ref<Image> (*Image::png_unpacker)(const Vector<uint8_t> &) = nullptr; Vector<uint8_t> (*Image::basis_universal_packer)(const Ref<Image> &, Image::UsedChannels) = nullptr; Ref<Image> (*Image::basis_universal_unpacker)(const Vector<uint8_t> &) = nullptr; +Ref<Image> (*Image::basis_universal_unpacker_ptr)(const uint8_t *, int) = nullptr; void Image::_set_data(const Dictionary &p_data) { ERR_FAIL_COND(!p_data.has("width")); @@ -3008,7 +3006,7 @@ void Image::adjust_bcs(float p_brightness, float p_contrast, float p_saturation) } } -Image::UsedChannels Image::detect_used_channels(CompressSource p_source) { +Image::UsedChannels Image::detect_used_channels(CompressSource p_source) const { ERR_FAIL_COND_V(data.size() == 0, USED_CHANNELS_RGBA); ERR_FAIL_COND_V(is_compressed(), USED_CHANNELS_RGBA); bool r = false, g = false, b = false, a = false, c = false; @@ -3275,7 +3273,7 @@ Ref<Image> Image::rgbe_to_srgb() { for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { - new_image->set_pixel(col, row, get_pixel(col, row).to_srgb()); + new_image->set_pixel(col, row, get_pixel(col, row).linear_to_srgb()); } } @@ -3613,6 +3611,10 @@ Image::Image(const uint8_t *p_mem_png_jpg, int p_len) { if (is_empty() && _jpg_mem_loader_func) { copy_internals_from(_jpg_mem_loader_func(p_mem_png_jpg, p_len)); } + + if (is_empty() && _webp_mem_loader_func) { + copy_internals_from(_webp_mem_loader_func(p_mem_png_jpg, p_len)); + } } Ref<Resource> Image::duplicate(bool p_subresources) const { |