Skip to content

fix(exr): handle multi-level hierarchical EXR channel names#232

Open
throb wants to merge 1 commit intoAcademySoftwareFoundation:mainfrom
throb:fix/exr-hierarchical-channels
Open

fix(exr): handle multi-level hierarchical EXR channel names#232
throb wants to merge 1 commit intoAcademySoftwareFoundation:mainfrom
throb:fix/exr-hierarchical-channels

Conversation

@throb
Copy link

@throb throb commented Mar 16, 2026

Summary

  • Fix "Unable to choose decoder routines" error when loading EXR files with hierarchical dot-separated channel names (e.g. Blender/Cycles multi-layer renders)
  • get_channel_names_by_layer() now splits on the last dot (rfind) instead of the first, so bg_wall.Combined.R produces layer bg_wall.Combined with channel R
  • Add defensive bounds checks to prevent array out-of-bounds reads in FrameBuffer setup

Problem

EXR files with hierarchical channel names like bg_wall.Combined.R, bg_wall.CryptoObject00.r, fg_rocks.Diffuse Direct.B caused the OpenEXR library to throw "Unable to choose decoder routines".

The root cause was that get_channel_names_by_layer() split on the first dot, creating layers with 30+ channels (e.g. all bg_wall.* channels grouped under bg_wall). The reader's pix_type array is fixed at 4 elements, so the FrameBuffer setup loop read past the array bounds, producing undefined pixel types that OpenEXR's exr_decoding_choose_default_routines() rejected.

Fix

  1. Layer grouping: Use rfind(".") instead of find(".") to split on the last dot. This produces proper sub-layers with 3-4 channels each (e.g. bg_wall.Combined → R,G,B,A)
  2. FrameBuffer safety: Add if (ii >= 4) return; guard in the FrameBuffer setup lambda
  3. Channel cap: Resize exr_channels_to_load to max 4 after assignment from the layer map

Test plan

  • Tested with 56-channel Blender/Cycles render EXR containing hierarchical AOV names across 2 render layers (16 sub-layers total)
  • Verified all 16 layers appear as separate streams in the AOV selector
  • Verified playback works without decoder errors
  • Verified simple RGBA EXRs (no dots in channel names) still work correctly

🤖 Generated with Claude Code

EXR files with hierarchical dot-separated channel names (e.g.
bg_wall.Combined.R, fg_rocks.Diffuse Direct.B) caused "Unable to
choose decoder routines" errors from OpenEXR.

Root cause: get_channel_names_by_layer() split channel names on the
first dot, grouping all sub-layers under a single parent layer. For
render outputs with many AOVs this created layers with 30+ channels,
but the reader's pix_type array and FrameBuffer setup only support 4
channels (RGBA). Reading past the array produced undefined pixel types
that OpenEXR's decoder rejected.

Fix:
- Split on the last dot (rfind) so "bg_wall.Combined.R" produces
  layer "bg_wall.Combined" with channel "R" instead of lumping all
  channels under "bg_wall"
- Add defensive bounds check in FrameBuffer setup loop (cap at 4)
- Cap exr_channels_to_load to 4 entries after assignment

Tested with 56-channel Blender/Cycles render EXRs containing
hierarchical AOV names across multiple render layers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant