diff --git a/core/image.cpp b/core/image.cpp index b0e25db309c..827618020a6 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -2263,6 +2263,81 @@ void Image::blend_rect(const Image &p_src, const Rect2 &p_src_rect, const Point2 } } +void Image::blend_rect_mask(const Image &p_src, const Image &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest) { + + int dsize = data.size(); + int srcdsize = p_src.data.size(); + int maskdsize = p_mask.data.size(); + int dst_data_size = data.size(); + ERR_FAIL_COND(dsize == 0); + ERR_FAIL_COND(srcdsize == 0); + ERR_FAIL_COND(maskdsize == 0); + ERR_FAIL_COND(dst_data_size == 0); + ERR_FAIL_COND(p_src.width != p_mask.width); + ERR_FAIL_COND(p_src.height != p_mask.height); + + 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(); + + DVector::Read mrp = p_mask.data.read(); + const unsigned char *mask_data_ptr = mrp.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 msk = p_mask._get_pixel(rrect.pos.x + j, rrect.pos.y + i, mask_data_ptr, maskdsize); + if (msk.a != 0) { + 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); + } + } + } + } +} + +void Image::fill(const Color &p_color) { + int dsize = data.size(); + ERR_FAIL_COND(dsize == 0); + + DVector::Write wp = data.write(); + unsigned char *dst_data_ptr = wp.ptr(); + + BColor c = BColor(p_color.r*255, p_color.g*255, p_color.b*255, p_color.a*255); + + for (int i = 0; i < height; i++) { + + for (int j = 0; j < width; j++) { + + _put_pixel(j, i, c, 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 4156d6a6ac5..484e44a1a63 100644 --- a/core/image.h +++ b/core/image.h @@ -352,6 +352,10 @@ public: 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 blend_rect_mask(const Image &p_src, const Image &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest); + + void fill(const Color &p_color); + 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 353ceb70353..748a1f1a8d8 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -622,6 +622,8 @@ struct _VariantCall { VCALL_PTR0R(Image, get_data); VCALL_PTR3(Image, blit_rect); VCALL_PTR3(Image, blend_rect); + VCALL_PTR4(Image, blend_rect_mask); + VCALL_PTR1(Image, fill); VCALL_PTR1R(Image, converted); VCALL_PTR0(Image, fix_alpha_edges); @@ -1473,6 +1475,8 @@ void register_variant_methods() { 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)); + ADDFUNC4(IMAGE, NIL, Image, blend_rect_mask, IMAGE, "src", IMAGE, "mask", RECT2, "src_rect", VECTOR2, "dest", varray(0)); + ADDFUNC1(IMAGE, NIL, Image, fill, COLOR, "color", 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 33d476b64f0..1cbae37837c 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -1,5 +1,5 @@ - + Built-in GDScript functions. @@ -15866,6 +15866,19 @@ Alpha-blends a "src_rect" [Rect2] from "src" [Image] to this [Image] on coordinates "dest". + + + + + + + + + + + Alpha-blends a "src_rect" [Rect2] from "src" [Image] to this [Image] using a "mask" [Image] on coordinates "dest". Alpha channels are required for both "src" and "mask", dest pixels and src pixels will blend if the corresponding mask pixel's alpha value is not 0. "src" [Image] and "mask" [Image] *must* have the same size (width and height) but they can have different formats + + @@ -15933,6 +15946,13 @@ Return whether this [Image] is empty(no data). + + + + + Fills an [Image] with a specified [Color] + +