AWS Thinkbox Discussion Forums

multi layer EXR

Looking at the channel names in these two files, I don’t think it would be good to remove the channel number… Draft-Test-01-__1_0017.exr has two layers that would simply be called “Object Select” without the layer number.

Looking at the UV-Figure-Test-01__1_0033.exr image, there’s two channels, “A” and “#0009#Alpha.Y”, that appear to contain the same data, and none of the other layers have alpha channels. Would you expect each of the output layers to have the ‘A’ channel? No alpha? (Or the other alpha channel? I don’t know if they’re always the same or not.)

Did you want anything done with the layers that end with “.Y”? (Layer 9 has both Alpha.Y and Z-Depth.Y)

I’ve attached a sample script that extracts the layers as images. As I’ve currently written it, the only output images that have alpha channels are the ones that have an alpha channel explicitly in that layer. Let me know if this does what you were looking for, or if you were expecting something a bit different.

[code]# Sample Draft script: Layer Extraction

Extract the layers from a (sequence of) multi-layer exr(s) and save them as separate images.

This script assumes that all images in the sequence have the same layers as the first.

import Draft
import sys # To access commmand line arguments. Deadline sends script parameters as command line arguments.
from DraftParamParser import * # Functions to process command line arguments for Draft.

The argument name/types we’re expecting from the command line arguments or Deadline.

expectedTypes = dict()
expectedTypes[ ‘inFile’ ] = ‘’
expectedTypes[ ‘outFile’ ] = ‘’
#expectedTypes[ ‘frameList’ ] = ‘’ # ****** uncomment this line if you want the parameter to be mandatory rather than optional

Parse the command line arguments.

params = ParseCommandLine( expectedTypes, sys.argv ) # params now contains a dictionary of the parameters initialized to values from the command line arguments.
inFilePattern = params[‘inFile’] # The pattern that the input files follow, for example frame_name_###.ext, where ### represents a three digit frame number.
outFilePattern = params[‘outFile’]

frames = [ None ]
currFile = None
if ‘frameList’ in params:
frames = FrameRangeToFrames( params[‘frameList’] ) # Get a list of the individual frames we are to process
currFile = ReplaceFilenameHashesWithNumber( inFilePattern, frames[0] )
else:
currFile = inFilePattern # Only one file to process, name same as pattern
frame = Draft.Image.ReadFromFile( currFile )
unprocChannels = frame.GetChannelNames()

Create a dictionary of layers, with the layer name as the key, and the value is the list of channels.

channelMap = { ‘red’: ‘R’, ‘green’: ‘G’, ‘blue’: ‘B’, ‘alpha’: ‘A’, ‘r’: ‘R’, ‘g’: ‘G’, ‘b’: ‘B’, ‘a’: ‘A’ }
layers = {}
for uc in unprocChannels:
if string.rfind( uc, ‘.’ ) >= 0:
( layer, channel ) = string.rsplit( uc, ‘.’, 1 )
else:
( layer, channel ) = ( None, uc )
if channel.lower() in channelMap:
if layer in layers:
layers[ layer ].append( channel )
else:
layers[ layer ] = [ channel ]
else:
print "Ignoring the following layer.channel: “, uc, " (channel not recognized as RGBA)”

Process each of the frames in the list of frames (including the first, which hasn’t yet been processed).

progressCounter = 0;
for currFrame in frames:
# Read in the frame.
if currFrame is not None:
currFile = ReplaceFilenameHashesWithNumber( inFilePattern, currFrame )
frame = Draft.Image.ReadFromFile( currFile )

# Extract the layers from the image, saving each as a separate image.
for ( layer, channels ) in layers.items():
	prefix = ''
	if layer is not None:
		prefix = layer + '.'
	channelList = [ prefix + channel for channel in channels ]
	imgLayer = Draft.Image.CreateImage( frame.width, frame.height, channelList )
	imgLayer.Copy( frame, channels = channelList )
	
	# Rename the channels to RGB(A).
	for channel in channels:
		if prefix + channel != channelMap[ channel.lower() ]:
			imgLayer.RenameChannel( prefix + channel, channelMap[ channel.lower() ] )
	
	# Write the layer as an image, adding the layer name to the filename.
	currOutFile = None
	if currFrame is not None:
		currOutFile = ReplaceFilenameHashesWithNumber( outFilePattern, currFrame )
	else:
		currOutFile = outFilePattern
	if layer is not None:
		if string.rfind( currOutFile, '_' ) >= 0:
			( first, second ) = string.rsplit( currOutFile, '_', 1 )
			currOutFile = first + '_' + layer + '_' + second
		else:
			( root, ext ) = os.path.splitext( currOutFile )
			currOutFile = root + '_' + layer + ext
	imgLayer.WriteToFile( currOutFile )

progressCounter = progressCounter + 1
progress = progressCounter * 100 / len( frames )
print( "Progress: %i%%" % progress )[/code]

convert_exr_layers_to_images.zip (1.57 KB)

Hi Andrea!
I know this was 5 years ago, but still is gold to me!
I am trying to apply this script to extract EXR layers from a single image (not animation) to .png images but I can’t make it work (I am very new to python).
I use the script with the submitter from Monitor (as a Draft Template).

First I had “out of index error” but I commented the loop involved:

# if 'frameList' in params:
	# frames = FrameRangeToFrames( params['frameList'] )	# Get a list of the individual frames we are to process
	# currFile = ReplaceFilenameHashesWithNumber( inFilePattern, frames[0] )
# else:
currFile = inFilePattern	# Only one file to process, name same as pattern
frame = Draft.Image.ReadFromFile( currFile )
unprocChannels = frame.GetChannelNames()

Now I got the following error:
RuntimeError: The provided filename “Z:\07 artist folders\Alo\2\Draft\Test_Glare.mov” cannot have a movie-type extension, please use the Draft.VideoEncoder class instead.

Is the script expecting to deliver a video file? How can I change the output format from .mov to .png?

This topic is very old. Is there already an implemented way to convert multi-layer EXR file to .PNGs?

Thank you very much for your help. Please let me know if there is any other data I can provide to help.

Best,
Alo

Privacy | Site terms | Cookie preferences