diff options
Diffstat (limited to 'core/io/image.cpp')
-rw-r--r-- | core/io/image.cpp | 55 |
1 files changed, 27 insertions, 28 deletions
diff --git a/core/io/image.cpp b/core/io/image.cpp index 2c74229125..3f34de132f 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -86,20 +86,14 @@ SaveEXRFunc Image::save_exr_func = nullptr; SavePNGBufferFunc Image::save_png_buffer_func = nullptr; -void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel) { - uint32_t ofs = (p_y * width + p_x) * p_pixelsize; - - for (uint32_t i = 0; i < p_pixelsize; i++) { - p_data[ofs + i] = p_pixel[i]; - } +void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixel_size, uint8_t *p_data, const uint8_t *p_pixel) { + uint32_t ofs = (p_y * width + p_x) * p_pixel_size; + memcpy(p_data + ofs, p_pixel, p_pixel_size); } -void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p_data, uint8_t *p_pixel) { - uint32_t ofs = (p_y * width + p_x) * p_pixelsize; - - for (uint32_t i = 0; i < p_pixelsize; i++) { - p_pixel[i] = p_data[ofs + i]; - } +void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixel_size, const uint8_t *p_data, uint8_t *p_pixel) { + uint32_t ofs = (p_y * width + p_x) * p_pixel_size; + memcpy(p_pixel, p_data + ofs, p_pixel_size); } int Image::get_format_pixel_size(Format p_format) { @@ -2697,6 +2691,19 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c } } +// Repeats `p_pixel` `p_count` times in consecutive memory. +// Results in the original pixel and `p_count - 1` subsequent copies of it. +void Image::_repeat_pixel_over_subsequent_memory(uint8_t *p_pixel, int p_pixel_size, int p_count) { + int offset = 1; + for (int stride = 1; offset + stride <= p_count; stride *= 2) { + memcpy(p_pixel + offset * p_pixel_size, p_pixel, stride * p_pixel_size); + offset += stride; + } + if (offset < p_count) { + memcpy(p_pixel + offset * p_pixel_size, p_pixel, (p_count - offset) * p_pixel_size); + } +} + void Image::fill(const Color &p_color) { ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot fill in compressed or custom image formats."); @@ -2707,15 +2714,7 @@ void Image::fill(const Color &p_color) { // Put first pixel with the format-aware API. _set_color_at_ofs(dst_data_ptr, 0, p_color); - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - uint8_t *dst = &dst_data_ptr[(y * width + x) * pixel_size]; - - for (int k = 0; k < pixel_size; k++) { - dst[k] = dst_data_ptr[k]; - } - } - } + _repeat_pixel_over_subsequent_memory(dst_data_ptr, pixel_size, width * height); } void Image::fill_rect(const Rect2 &p_rect, const Color &p_color) { @@ -2734,13 +2733,13 @@ void Image::fill_rect(const Rect2 &p_rect, const Color &p_color) { uint8_t *rect_first_pixel_ptr = &dst_data_ptr[(r.position.y * width + r.position.x) * pixel_size]; _set_color_at_ofs(rect_first_pixel_ptr, 0, p_color); - for (int y = r.position.y; y < r.position.y + r.size.y; y++) { - for (int x = r.position.x; x < r.position.x + r.size.x; x++) { - uint8_t *dst = &dst_data_ptr[(y * width + x) * pixel_size]; - - for (int k = 0; k < pixel_size; k++) { - dst[k] = rect_first_pixel_ptr[k]; - } + if (r.size.x == width) { + // No need to fill rows separately. + _repeat_pixel_over_subsequent_memory(rect_first_pixel_ptr, pixel_size, width * r.size.y); + } else { + _repeat_pixel_over_subsequent_memory(rect_first_pixel_ptr, pixel_size, r.size.x); + for (int y = 1; y < r.size.y; y++) { + memcpy(rect_first_pixel_ptr + y * width * pixel_size, rect_first_pixel_ptr, r.size.x * pixel_size); } } } |