浏览代码

Image: Improve `is_invisible` function

BlueCube3310 4 月之前
父节点
当前提交
dd47d9173e
共有 1 个文件被更改,包括 50 次插入22 次删除
  1. 50 22
      core/io/image.cpp

+ 50 - 22
core/io/image.cpp

@@ -2438,47 +2438,75 @@ void Image::initialize_data(const char **p_xpm) {
 	}
 
 bool Image::is_invisible() const {
-	if (format == FORMAT_L8 || format == FORMAT_RGB8 || format == FORMAT_RG8) {
-		return false;
-	}
-
-	int64_t len = data.size();
+	int w, h;
+	int64_t len;
+	_get_mipmap_offset_and_size(1, len, w, h);
 
 	if (len == 0) {
 		return true;
 	}
 
-	int w, h;
-	_get_mipmap_offset_and_size(1, len, w, h);
-
-	const uint8_t *r = data.ptr();
-	const unsigned char *data_ptr = r;
-
-	bool detected = false;
-
 	switch (format) {
 		case FORMAT_LA8: {
-			for (int i = 0; i < (len >> 1); i++) {
-				DETECT_NON_ALPHA(data_ptr[(i << 1) + 1]);
-			}
+			const int pixel_count = len / 2;
+			const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
 
+			for (int i = 0; i < pixel_count; i++) {
+				if ((pixeldata[i] & 0xFF00) != 0) {
+					return false;
+				}
+			}
 		} break;
 		case FORMAT_RGBA8: {
-			for (int i = 0; i < (len >> 2); i++) {
-				DETECT_NON_ALPHA(data_ptr[(i << 2) + 3])
+			const int pixel_count = len / 4;
+			const uint32_t *pixeldata = reinterpret_cast<const uint32_t *>(data.ptr());
+
+			for (int i = 0; i < pixel_count; i++) {
+				if ((pixeldata[i] & 0xFF000000) != 0) {
+					return false;
+				}
 			}
+		} break;
+		case FORMAT_RGBA4444: {
+			const int pixel_count = len / 2;
+			const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
 
+			for (int i = 0; i < pixel_count; i++) {
+				if ((pixeldata[i] & 0x000F) != 0) {
+					return false;
+				}
+			}
 		} break;
+		case FORMAT_RGBAH: {
+			// The alpha mask accounts for the sign bit.
+			const int pixel_count = len / 4;
+			const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
 
-		case FORMAT_DXT3:
-		case FORMAT_DXT5: {
-			detected = true;
+			for (int i = 0; i < pixel_count; i += 4) {
+				if ((pixeldata[i + 3] & 0x7FFF) != 0) {
+					return false;
+				}
+			}
+		} break;
+		case FORMAT_RGBAF: {
+			// The alpha mask accounts for the sign bit.
+			const int pixel_count = len / 4;
+			const uint32_t *pixeldata = reinterpret_cast<const uint32_t *>(data.ptr());
+
+			for (int i = 0; i < pixel_count; i += 4) {
+				if ((pixeldata[i + 3] & 0x7FFFFFFF) != 0) {
+					return false;
+				}
+			}
 		} break;
 		default: {
+			// Formats that are compressed or don't support alpha channels are presumed to be visible.
+			return false;
 		}
 	}
 
-	return !detected;
+	// Every pixel has been checked, the image is invisible.
+	return true;
 }
 
 Image::AlphaMode Image::detect_alpha() const {