Using OpenImageIO to quickly edit an EXR display window
At the office, I was being asked about how to use Nuke to do some image manipulation to resize an image and twizzle the display and data windows. We could, of course, do this in Nuke as a kind of general -purpose image processor but it can be a tad overkill when all you need to do is fix some metadata. Might I suggest OpenImageIO?
(This code sample is written in a bit of a conversational style, you can make this much, much, better, however this might be a lot easier to read. For context as well, this was inspired by a convo with Hugo Sutton at work the other day.)
Nuke Script & Support Files
There’s one nuke script, plus four EXRs to fetch:
- render_full.exr : our render with all the pixels
- render_corrected_nuke.exr : our render that we ran through nuke to reformat
- render_corrected_oiio.exr : our render corrected via OpenImageIO
- render_corrected_tool.exr : same same, just using Oiiotool
- some python scripts so don’t have to type as much stuff
- the .nknc script you can use to inspect it
Grab the lot here (2,457kb)
Essentially what we’re doing here is noticing that the pixels are all there, and they’re all what we want, but our display and data windows are the same. If we bring this into nuke on the B stream, then nuke will think we want to work at this resolution.
We can fix this in nuke, but honestly, all we’re doing is we’re tweaking some metadata (this applies to all metadata btw) so firing it up is probably gross overkill. You can do this in a more lightweight fashion.
Python and OpenImageIO
Let’s look at the target and the fix from nuke as our gold standard as it’s likely to be where we grab the image, manipulate it and make sure we’re happy with the results. I’ve used a reformat node - pretty standard.
Throw open a shell and give this a whirl to inspect things:
which should give you this:
You can see that the target image has a display window of 720p, and the data window is 1080p sized, but it’s shift/offset to the left and down. What we call 0 is just a reference point. We can redefine these, without touching any pixels - which we’ll see now:
oiiotool and well, OpenImageIO
Most likely, if you have got OpenImageIO, you’re going to have
as a ginsu knife of sorts. You can easily bolt this into a pipeline/subprocess
if you don’t have or want to fire up a python interpreter:
Or in english, dear
- Shift the origin left by 320 pixels, down by 180
- Make the ‘full’ size the 720p center zone
- Dump it out, thanks
Last, but not least, don’t overlook the fact that we’re preserving metadata using oiiotool and our python approach above. If you do it right (and by default, with oiiotool), you’re going to add a few extra fragments but you’re really, really, really, unlikely to clobber metadata. This is going to be important when you’re processing renders, you don’t want to wipe out critical info (like.. oh, a header for cryptomatte?)