From 95dcd22b461d0f15b99bfb5290ff0141ae2fe687 Mon Sep 17 00:00:00 2001 From: "dumitru.stama" Date: Wed, 14 Jun 2017 00:55:52 -0700 Subject: [PATCH] Added a new 'blend_rect' method acting as 'blit_rect' with alpha-blending --- core/image.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++ core/image.h | 1 + core/variant_call.cpp | 2 ++ doc/base/classes.xml | 11 +++++++++++ 4 files changed, 60 insertions(+) diff --git a/core/image.cpp b/core/image.cpp index df29879f163..56f09d8f8c1 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -2217,6 +2217,52 @@ void Image::blit_rect(const Image &p_src, const Rect2 &p_src_rect, const Point2 } } +void Image::blend_rect(const Image &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) { + + int dsize = data.size(); + int srcdsize = p_src.data.size(); + int dst_data_size = data.size(); + ERR_FAIL_COND(dsize == 0); + ERR_FAIL_COND(srcdsize == 0); + ERR_FAIL_COND(dst_data_size == 0); + + Rect2 rrect = Rect2(0, 0, p_src.width, p_src.height).clip(p_src_rect); + + DVector::Write wp = data.write(); + unsigned char *dst_data_ptr = wp.ptr(); + + DVector::Read rp = p_src.data.read(); + const unsigned char *src_data_ptr = rp.ptr(); + + if (format == FORMAT_INDEXED || format == FORMAT_INDEXED || p_src.format == FORMAT_INDEXED || p_src.format == FORMAT_INDEXED_ALPHA) { + + return; + + } else { + + for (int i = 0; i < rrect.size.y; i++) { + + if (i + p_dest.y < 0 || i + p_dest.y >= height) + continue; + for (int j = 0; j < rrect.size.x; j++) { + + if (j + p_dest.x < 0 || j + p_dest.x >= width) + continue; + + BColor src = p_src._get_pixel(rrect.pos.x + j, rrect.pos.y + i, src_data_ptr, srcdsize); + BColor dst = _get_pixel(p_dest.x + j, p_dest.y + i, dst_data_ptr, dst_data_size); + float ba = (float) dst.a / 255.0; + float fa = (float) src.a / 255.0; + dst.r = (uint8_t) (fa*src.r + ba*(1.0 - fa) * dst.r); + dst.g = (uint8_t) (fa*src.g + ba*(1.0 - fa) * dst.g); + dst.b = (uint8_t) (fa*src.b + ba*(1.0 - fa) * dst.b); + dst.a = (uint8_t) (255.0 * (fa + ba * (1.0 - fa))); + _put_pixel(p_dest.x + j, p_dest.y + i, dst, dst_data_ptr); + } + } + } +} + Image (*Image::_png_mem_loader_func)(const uint8_t *, int) = NULL; Image (*Image::_jpg_mem_loader_func)(const uint8_t *, int) = NULL; diff --git a/core/image.h b/core/image.h index e727b004eb1..4156d6a6ac5 100644 --- a/core/image.h +++ b/core/image.h @@ -351,6 +351,7 @@ public: void normalmap_to_xy(); void blit_rect(const Image &p_src, const Rect2 &p_src_rect, const Point2 &p_dest); + void blend_rect(const Image &p_src, const Rect2 &p_src_rect, const Point2 &p_dest); void brush_transfer(const Image &p_src, const Image &p_brush, const Point2 &p_dest); Image brushed(const Image &p_src, const Image &p_brush, const Point2 &p_dest) const; diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 01a3b4a1b03..878bd55dcac 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -619,6 +619,7 @@ struct _VariantCall { VCALL_PTR3R(Image, resized); VCALL_PTR0R(Image, get_data); VCALL_PTR3(Image, blit_rect); + VCALL_PTR3(Image, blend_rect); VCALL_PTR1R(Image, converted); VCALL_PTR0(Image, fix_alpha_edges); @@ -1467,6 +1468,7 @@ void register_variant_methods() { ADDFUNC3(IMAGE, IMAGE, Image, resized, INT, "x", INT, "y", INT, "interpolation", varray(((int)Image::INTERPOLATE_BILINEAR))); ADDFUNC0(IMAGE, RAW_ARRAY, Image, get_data, varray()); ADDFUNC3(IMAGE, NIL, Image, blit_rect, IMAGE, "src", RECT2, "src_rect", VECTOR2, "dest", varray(0)); + ADDFUNC3(IMAGE, NIL, Image, blend_rect, IMAGE, "src", RECT2, "src_rect", VECTOR2, "dest", varray(0)); ADDFUNC1(IMAGE, IMAGE, Image, converted, INT, "format", varray(0)); ADDFUNC0(IMAGE, NIL, Image, fix_alpha_edges, varray()); diff --git a/doc/base/classes.xml b/doc/base/classes.xml index c8c09e82a9e..33d476b64f0 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -15855,6 +15855,17 @@ Create an empty image of a specific size and format. + + + + + + + + + Alpha-blends a "src_rect" [Rect2] from "src" [Image] to this [Image] on coordinates "dest". + +