Explorar el Código

TinyEXR: Fix EXR header when parsing pixels encoded as HALF

Also free the header and image properly after usage.
Fixes #13490.
Rémi Verschelde hace 7 años
padre
commit
7d9f14e9e4
Se han modificado 1 ficheros con 20 adiciones y 5 borrados
  1. 20 5
      modules/tinyexr/image_loader_tinyexr.cpp

+ 20 - 5
modules/tinyexr/image_loader_tinyexr.cpp

@@ -47,6 +47,11 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
 
 	f->close();
 
+	// Re-implementation of tinyexr's LoadEXRFromMemory using Godot types to store the Image data
+	// and Godot's error codes.
+	// When debugging after updating the thirdparty library, check that we're still in sync with
+	// their API usage in LoadEXRFromMemory.
+
 	EXRVersion exr_version;
 	EXRImage exr_image;
 	EXRHeader exr_header;
@@ -68,6 +73,13 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
 		return ERR_FILE_CORRUPT;
 	}
 
+	// Read HALF channel as FLOAT. (GH-13490)
+	for (int i = 0; i < exr_header.num_channels; i++) {
+		if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
+			exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
+		}
+	}
+
 	InitEXRImage(&exr_image);
 	ret = LoadEXRImageFromMemory(&exr_image, &exr_header, w.ptr(), src_image_len, &err);
 	if (ret != TINYEXR_SUCCESS) {
@@ -95,23 +107,25 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
 	}
 
 	if (idxR == -1) {
-		ERR_PRINT("R channel not found");
+		ERR_PRINT("TinyEXR: R channel not found.");
 		// @todo { free exr_image }
 		return ERR_FILE_CORRUPT;
 	}
 
 	if (idxG == -1) {
-		ERR_PRINT("G channel not found\n")
+		ERR_PRINT("TinyEXR: G channel not found.")
 		// @todo { free exr_image }
 		return ERR_FILE_CORRUPT;
 	}
 
 	if (idxB == -1) {
-		ERR_PRINT("B channel not found\n")
+		ERR_PRINT("TinyEXR: B channel not found.")
 		// @todo { free exr_image }
 		return ERR_FILE_CORRUPT;
 	}
 
+	// EXR image data loaded, now parse it into Godot-friendly image data
+
 	PoolVector<uint8_t> imgdata;
 	Image::Format format;
 
@@ -126,7 +140,6 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
 	}
 
 	{
-
 		PoolVector<uint8_t>::Write wd = imgdata.write();
 		uint16_t *iw = (uint16_t *)wd.ptr();
 
@@ -151,11 +164,13 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
 		}
 	}
 
-	print_line("EXR w: " + itos(exr_image.width) + " h:" + itos(exr_image.height) + " format " + Image::get_format_name(format));
 	p_image->create(exr_image.width, exr_image.height, false, format, imgdata);
 
 	w = PoolVector<uint8_t>::Write();
 
+	FreeEXRHeader(&exr_header);
+	FreeEXRImage(&exr_image);
+
 	return OK;
 }