diff options
Diffstat (limited to 'core/image.cpp')
| -rw-r--r-- | core/image.cpp | 92 | 
1 files changed, 78 insertions, 14 deletions
diff --git a/core/image.cpp b/core/image.cpp index 2ac8ffea56..51fbe75dec 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -366,6 +366,8 @@ int Image::get_mipmap_count() const {  template <uint32_t read_bytes, bool read_alpha, uint32_t write_bytes, bool write_alpha, bool read_gray, bool write_gray>  static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p_dst) { +	uint32_t max_bytes = MAX(read_bytes, write_bytes); +  	for (int y = 0; y < p_height; y++) {  		for (int x = 0; x < p_width; x++) { @@ -379,7 +381,8 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p  				rgba[1] = rofs[0];  				rgba[2] = rofs[0];  			} else { -				for (uint32_t i = 0; i < MAX(read_bytes, write_bytes); i++) { + +				for (uint32_t i = 0; i < max_bytes; i++) {  					rgba[i] = (i < read_bytes) ? rofs[i] : 0;  				} @@ -937,7 +940,7 @@ bool Image::_can_modify(Format p_format) const {  	return p_format <= FORMAT_RGBE9995;  } -template <int CC> +template <int CC, bool renormalize>  static void _generate_po2_mipmap(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_width, uint32_t p_height) {  	//fast power of 2 mipmap generation @@ -963,6 +966,19 @@ static void _generate_po2_mipmap(const uint8_t *p_src, uint8_t *p_dst, uint32_t  				dst_ptr[j] = val >> 2;  			} +			if (renormalize) { +				Vector3 n(dst_ptr[0] / 255.0, dst_ptr[1] / 255.0, dst_ptr[2] / 255.0); +				n *= 2.0; +				n -= Vector3(1, 1, 1); +				n.normalize(); +				n += Vector3(1, 1, 1); +				n *= 0.5; +				n *= 255; +				dst_ptr[0] = CLAMP(int(n.x), 0, 255); +				dst_ptr[1] = CLAMP(int(n.y), 0, 255); +				dst_ptr[2] = CLAMP(int(n.z), 0, 255); +			} +  			dst_ptr += CC;  			rup_ptr += CC * 2;  			rdown_ptr += CC * 2; @@ -1045,11 +1061,11 @@ void Image::shrink_x2() {  			switch (format) {  				case FORMAT_L8: -				case FORMAT_R8: _generate_po2_mipmap<1>(r.ptr(), w.ptr(), width, height); break; -				case FORMAT_LA8: _generate_po2_mipmap<2>(r.ptr(), w.ptr(), width, height); break; -				case FORMAT_RG8: _generate_po2_mipmap<2>(r.ptr(), w.ptr(), width, height); break; -				case FORMAT_RGB8: _generate_po2_mipmap<3>(r.ptr(), w.ptr(), width, height); break; -				case FORMAT_RGBA8: _generate_po2_mipmap<4>(r.ptr(), w.ptr(), width, height); break; +				case FORMAT_R8: _generate_po2_mipmap<1, false>(r.ptr(), w.ptr(), width, height); break; +				case FORMAT_LA8: _generate_po2_mipmap<2, false>(r.ptr(), w.ptr(), width, height); break; +				case FORMAT_RG8: _generate_po2_mipmap<2, false>(r.ptr(), w.ptr(), width, height); break; +				case FORMAT_RGB8: _generate_po2_mipmap<3, false>(r.ptr(), w.ptr(), width, height); break; +				case FORMAT_RGBA8: _generate_po2_mipmap<4, false>(r.ptr(), w.ptr(), width, height); break;  				default: {}  			}  		} @@ -1060,7 +1076,7 @@ void Image::shrink_x2() {  	}  } -Error Image::generate_mipmaps() { +Error Image::generate_mipmaps(bool p_renormalize) {  	if (!_can_modify(format)) {  		ERR_EXPLAIN("Cannot generate mipmaps in indexed, compressed or custom image formats."); @@ -1089,11 +1105,22 @@ Error Image::generate_mipmaps() {  		switch (format) {  			case FORMAT_L8: -			case FORMAT_R8: _generate_po2_mipmap<1>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; +			case FORMAT_R8: _generate_po2_mipmap<1, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;  			case FORMAT_LA8: -			case FORMAT_RG8: _generate_po2_mipmap<2>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; -			case FORMAT_RGB8: _generate_po2_mipmap<3>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; -			case FORMAT_RGBA8: _generate_po2_mipmap<4>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; +			case FORMAT_RG8: _generate_po2_mipmap<2, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; +			case FORMAT_RGB8: +				if (p_renormalize) +					_generate_po2_mipmap<3, true>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); +				else +					_generate_po2_mipmap<3, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); + +				break; +			case FORMAT_RGBA8: +				if (p_renormalize) +					_generate_po2_mipmap<4, true>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); +				else +					_generate_po2_mipmap<4, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); +				break;  			default: {}  		} @@ -1134,6 +1161,9 @@ PoolVector<uint8_t> Image::get_data() const {  void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format) { +	ERR_FAIL_INDEX(p_width - 1, MAX_WIDTH); +	ERR_FAIL_INDEX(p_height - 1, MAX_HEIGHT); +  	int mm = 0;  	int size = _get_dst_image_size(p_width, p_height, p_format, mm, p_use_mipmaps ? -1 : 0);  	data.resize(size); @@ -1598,6 +1628,12 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po  	ERR_FAIL_COND(format != p_src->format);  	Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(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.size.x <= 0 || clipped_src_rect.size.y <= 0)  		return; @@ -1646,6 +1682,12 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co  	ERR_FAIL_COND(format != p_src->format);  	Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(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.size.x <= 0 || clipped_src_rect.size.y <= 0)  		return; @@ -1697,6 +1739,12 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P  	ERR_FAIL_COND(format != p_src->format);  	Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(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.size.x <= 0 || clipped_src_rect.size.y <= 0)  		return; @@ -1745,6 +1793,12 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c  	ERR_FAIL_COND(format != p_src->format);  	Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(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.size.x <= 0 || clipped_src_rect.size.y <= 0)  		return; @@ -1880,6 +1934,10 @@ void Image::unlock() {  	write_lock = PoolVector<uint8_t>::Write();  } +Color Image::get_pixelv(const Point2 &p_src) const { +	return get_pixel(p_src.x, p_src.y); +} +  Color Image::get_pixel(int p_x, int p_y) const {  	uint8_t *ptr = write_lock.ptr(); @@ -2026,6 +2084,10 @@ Color Image::get_pixel(int p_x, int p_y) const {  	return Color();  } +void Image::set_pixelv(const Point2 &p_dst, const Color &p_color) { +	return set_pixel(p_dst.x, p_dst.y, p_color); +} +  void Image::set_pixel(int p_x, int p_y, const Color &p_color) {  	uint8_t *ptr = write_lock.ptr(); @@ -2217,7 +2279,7 @@ void Image::_bind_methods() {  	ClassDB::bind_method(D_METHOD("crop", "width", "height"), &Image::crop);  	ClassDB::bind_method(D_METHOD("flip_x"), &Image::flip_x);  	ClassDB::bind_method(D_METHOD("flip_y"), &Image::flip_y); -	ClassDB::bind_method(D_METHOD("generate_mipmaps"), &Image::generate_mipmaps); +	ClassDB::bind_method(D_METHOD("generate_mipmaps", "renormalize"), &Image::generate_mipmaps, DEFVAL(false));  	ClassDB::bind_method(D_METHOD("clear_mipmaps"), &Image::clear_mipmaps);  	ClassDB::bind_method(D_METHOD("create", "width", "height", "use_mipmaps", "format"), &Image::_create_empty); @@ -2257,8 +2319,10 @@ void Image::_bind_methods() {  	ClassDB::bind_method(D_METHOD("lock"), &Image::lock);  	ClassDB::bind_method(D_METHOD("unlock"), &Image::unlock); -	ClassDB::bind_method(D_METHOD("set_pixel", "x", "y", "color"), &Image::set_pixel); +	ClassDB::bind_method(D_METHOD("get_pixelv", "src"), &Image::get_pixelv);  	ClassDB::bind_method(D_METHOD("get_pixel", "x", "y"), &Image::get_pixel); +	ClassDB::bind_method(D_METHOD("set_pixelv", "dst", "color"), &Image::set_pixelv); +	ClassDB::bind_method(D_METHOD("set_pixel", "x", "y", "color"), &Image::set_pixel);  	ClassDB::bind_method(D_METHOD("load_png_from_buffer", "buffer"), &Image::load_png_from_buffer);  	ClassDB::bind_method(D_METHOD("load_jpg_from_buffer", "buffer"), &Image::load_jpg_from_buffer);  |