diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2017-12-05 22:50:09 +0100 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2017-12-05 22:50:17 +0100 |
commit | 7d9f14e9e49547fdfca67687b7ddee2c25dbcd9b (patch) | |
tree | 9b9110851e2bac8c33b76c5697c9b0ed5d24657b /modules | |
parent | 0036019e67ef1074a61552b4072dec16b2666992 (diff) |
TinyEXR: Fix EXR header when parsing pixels encoded as HALF
Also free the header and image properly after usage.
Fixes #13490.
Diffstat (limited to 'modules')
-rw-r--r-- | modules/tinyexr/image_loader_tinyexr.cpp | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp index 49a4db237a..c88662454c 100644 --- a/modules/tinyexr/image_loader_tinyexr.cpp +++ b/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; } |