Converting Linear EXR to sRGB JPEG with Python?

I’m writing a script right now to submit .exr’s to our studio’s Dailies folder. What would be great is if I could convert them to JPG’s during the process.

I’m using Python and I have the OpenEXR module. The only real example I can find close to what I want to do is here: http://excamera.com/articles/26/doc/intro.html#openexr-to-jpg

The problem with that example is that it doesn’t do any color space conversion, so the images always end up too dark. Even worse, that example normalizes the image rather than clipping the overbright values.

Does anyone know of a reliable method, using Python or a Command Line Utility, to properly convert a Linear EXR to an sRGB JPG?

There’s an example on this page, showing how to use OpenEXR and PIL (Python Imaging Library) together:
http://excamera.com/articles/26/doc/intro.html

Alternatively, have you tried ImageMagick? It has Python bindings and claims to support EXR.
http://www.imagemagick.org/

[QUOTE=Adam Pletcher;14262]There’s an example on this page, showing how to use OpenEXR and PIL (Python Imaging Library) together:
http://excamera.com/articles/26/doc/intro.html

Alternatively, have you tried ImageMagick? It has Python bindings and claims to support EXR.
http://www.imagemagick.org/[/QUOTE]

Yeah, I referenced that first example in my originial post. It is not the best example for a production pipeline as it normalizes the EXR data, rather than clamping it, and it doesn’t do any color space transformation.

I looked into ImageMagick but in order to support EXR you must compile the entire project from source alongside the ILM EXR source. Too much hassle for something that should be simple.

I wound up tearing apart the OpenEXR and PIL demo, rewriting it to support an sRGB transformation. This method isn’t super fast, but it works and provides a (near) perfect Linear -> sRGB transformation. Note - this code has not been optimized:

import OpenEXR
import Imath
import Image
import array
import sys

def ConvertEXRToJPG(exrfile, jpgfile):
	File = OpenEXR.InputFile(exrfile)
	PixType = Imath.PixelType(Imath.PixelType.FLOAT)
	DW = File.header()['dataWindow']
	Size = (DW.max.x - DW.min.x + 1, DW.max.y - DW.min.y + 1)

	RedStr = File.channel('R', PixType)
	GreenStr = File.channel('G', PixType)
	BlueStr = File.channel('B', PixType)

	Red = array.array('f', RedStr)
	Green = array.array('f', GreenStr)
	Blue = array.array('f', BlueStr)

	for I in range(len(Red)):
		Red[I] = EncodeToSRGB(Red[I])

	for I in range(len(Green)):
		Green[I] = EncodeToSRGB(Green[I])

	for I in range(len(Blue)):
		Blue[I] = EncodeToSRGB(Blue[I])

	rgbf = [Image.fromstring("F", Size, Red.tostring())]
	rgbf.append(Image.fromstring("F", Size, Green.tostring()))
	rgbf.append(Image.fromstring("F", Size, Blue.tostring()))

	rgb8 = [im.convert("L") for im in rgbf]
	Image.merge("RGB", rgb8).save(jpgfile, "JPEG", quality=95)
	

def EncodeToSRGB(v):
	if (v <= 0.0031308):
		return (v * 12.92) * 255.0
	else:
		return (1.055*(v**(1.0/2.4))-0.055) * 255.0