From 662dc95a505b935c4644f4d737a0ab1b4a191cf0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 22 Sep 2025 13:10:39 +0200 Subject: [PATCH] OpenEXR: Support reading multipart files with full channel names The reading code currently assumes that the part name may be for example "ViewLayer.Combined" and then the channel within the part may be "R". For example Houdini writes files like this. However according to the docs the part name should be ignored and the channel name in each part should be complete like "ViewLayer.Combined.R". https://openexr.com/en/latest/MultiViewOpenEXR.html To support both cases we now only prepend the part name if it's not already there. Pull Request: https://projects.blender.org/blender/blender/pulls/146650 --- .../imbuf/intern/openexr/openexr_api.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 5ebf3f35983..d193b8d7cf4 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1598,15 +1598,23 @@ static std::vector exr_channels_in_multi_part_file( for (int p = 0; p < file.parts(); p++) { const ChannelList &c = file.header(p).channels(); - std::string part_view; + blender::StringRef part_view; if (file.header(p).hasView()) { part_view = file.header(p).view(); } - std::string part_name; + blender::StringRef part_name; if (file.header(p).hasName()) { part_name = file.header(p).name(); } + /* Strip part suffix from name. */ + if (part_name.endswith("." + part_view)) { + part_name = part_name.drop_known_suffix("." + part_view); + } + else if (part_name.endswith("-" + part_view)) { + part_name = part_name.drop_known_suffix("-" + part_view); + } + for (ChannelList::ConstIterator i = c.begin(); i != c.end(); i++) { MultiViewChannelName m; m.name = std::string(i.name()); @@ -1620,8 +1628,9 @@ static std::vector exr_channels_in_multi_part_file( m.view = part_view; } - /* Prepend part name as potential layer or pass name. */ - if (!part_name.empty()) { + /* Prepend part name as potential layer or pass name. According to OpenEXR docs + * this should not be needed, but Houdini writes files like this. */ + if (!part_name.is_empty() && !blender::StringRef(m.name).startswith(part_name + ".")) { m.name = part_name + "." + m.name; }