|
From: | Aaron Carlisle |
Subject: | Re: [Openexr-devel] Merging Multi Channel Layers |
Date: | Wed, 9 Dec 2015 17:32:28 +0000 |
It's a little weird to explain, but basically the EXR renders used to render out into the alpha channel (since it was only black and white). This is fine since now you can just dump the rgb channels and everything is great, the problem now is that due to
recent updates there is data being rendered in the rgb channels instead of the alpha channel (alpha is empty) and in some cases those channels contain different data (other than 1 or 0). What we did was merge the rgb data for a specific layer into one channel
(as if all the data was stored in the alpha again) and then gave that channel a custom name "matte". So (customLayer.blue, customLayer.green, customLayer.red) become (matte.customLayer). On the compositing side, when they open up the EXR in nuke all the channels
that use to be there (customLayer.blue...) are all replaced with just one channel (matte.customLayer). That new channel contains all the pixel data that was stored in the old channels. So essentially, three channels become one. Basically, we're turning it
into an alpha or an even better way to think about it is illumanence.
The issue is this conversion takes way to long in Python and C++ has been a bit harder to figure out. I'm not sure how to do the same conversion in C++. With Python it was basically just a series of collecting the rgb channels for each layer, grabbing the
pixelData for those layers, using array.array to convert it into a string set then assigning a new layer/channel to that collection of data and re-storing that back into the header of the file and writing out the new pixels.
here's the python code #!/usr/bin/python
import OpenEXR
import re
import os
import array
import Imath
import time
CHANNEL_MATCH = re.compile('([a-z0-9_]+)\.([rdgrnblue]+)', re.I)
ALPHA_MATCH = re.compile('([a-z0-9_]+)\.([a]+)', re.I)
HALF = Imath.Channel(Imath.PixelType(Imath.PixelType.HALF))
def matte_pass_channel_cleanup(exr_file = '/path/to/exr/image.exr'):
start = time.time()
if os.path.exists(exr_file) and OpenEXR.isOpenExrFile(exr_file):
channels_to_merge = defaultdict(list)
base_channels = []
# Read the file and header
handle = OpenEXR.InputFile(exr_file)
header = handle.header()
# Get the channels (is a dict)
channels = header['channels']
header['channels'] = {}
new_channels = {}
for channel_name, channel_data in channels.iteritems():
match = CHANNEL_MATCH.match(channel_name)
if match:
layer, channel = match.groups()
channels_to_merge[layer].append(channel)
elif not ALPHA_MATCH.match(channel_name):
base_channels.append(channel_name)
for layer in base_channels:
all_pixels = array.array( 'f', handle.channel(layer, Imath.PixelType(Imath.PixelType.HALF))).tolist()
new_channels[layer] = array.array('f', all_pixels).tostring()
print layer
for layer, data in channels_to_merge.iteritems():
new_pixels = []
# naming
try:
new_layer_name = layer.split('_')[1]
except:
new_layer_name = layer
new_pixels = array.array('f', handle.channel('{0}.{1}'.format(layer, data[0])))
new_channels['matte.{0}'.format(new_layer_name)] = array.array(
'f', new_pixels).tostring()
header['channels'] = dict([(c, HALF) for c in new_channels.keys()])
out = OpenEXR.OutputFile('/path/to/exr/image.exr', header)
out.writePixels(new_channels)
if __name__ == "__main__":
matte_pass_channel_cleanup()
Thanks! -Aaron From: Ari Rubenstein <address@hidden>
Sent: Wednesday, December 9, 2015 7:31 AM To: Aaron Carlisle Cc: address@hidden; Ari Rubenstein Subject: Re: [Openexr-devel] Merging Multi Channel Layers
Aaron,
I'm not a programmer, but coming at it from the end user of exr multi-channel files in compositing ... I'm curious how you'd intend to merge the 4-part channel down into 1 and how the end user would be able to split out individual channels within Nuke ? Compositors access the individual channels for all sorts purposes in editing and look development. not sure why the exr's would be black and white except that when you view individual channels (R G B) separately they do appear greyscale. -- Ari Rubenstein Lead Compositor www.blueskystudios.com
From: "Aaron Carlisle" <address@hidden>
To: address@hidden Sent: Tuesday, December 8, 2015 5:34:05 PM Subject: [Openexr-devel] Merging Multi Channel Layers Hi! Not sure if this is the right place to reach out, but I'm trying to take an EXR image and merge the channels in each layer down to one. Currently there are multiple channels for one layer (test.alpha, test.red, test.green, test.blue) but the EXR's that are being rendered out are black and white and all the pixel data is being stored in the RGB channels. In nuke there are channel limits and we're trying not to reach that (we have ran into that issue in the past). I was able to accomplish this in Python, so that when the script is ran it takes the EXR and basically sums up all the pixel data for each of the RGB channels in the layer into one, then writes it back out with a custom name (matte.whateverTheLayerWasCalled). This works great accept it's incredibly slow. So, I'm porting it to C++ but I'm struggling a little bit on the best way to handle this. I was wondering if anyone could help provide a generic example solution or maybe some tips. All the best! -Aaron If you'd like to see the Python/C++ code just let me know. _______________________________________________ Openexr-devel mailing list address@hidden https://lists.nongnu.org/mailman/listinfo/openexr-devel |
[Prev in Thread] | Current Thread | [Next in Thread] |