Exr files into pyqt interface

Hi,

Having python 2.7, PIL, openEXR and pyQt, what would be the best way to show an exr file into a pyqt interface ?
Basically, converting an exr file into Qimage or QPixmap

Any idea would help, really beginner with openEXR API

I think the basics will look like this, but I haven’t implemented it myself.

OpenExr (or one of the others) -> Load image into buffer -> Your code copies/converts image from 32 bit float channels (i assume) to 8 bit -> PyQt QPixmap or Canvas object, etc. -> PyQt UI

I would start by creating a sample UI with that can display an image that is supported by the QPixmap image loaders, then figure out how to update the image data in code (IE make it all blue, etc.). Then figure out how to load an exr image into a runtime object (I have no experience here), and then write the conversion code that massages the exr data into PyQt data.

You might also check and see if any of those packages provide a PyQt imageloader, which would make this really easy, but I would doubt it.

Yes this basiccally what I have done. I manage to open the exr, convert it to jpeg, save it to file then load it to qimage. But this isn’t and don’t manage to pass the jpg to qimage, which is embarrassing. Then I will have to set the gamma but seems relatively easy.
I was thinking lot of people here would do this regulary. Will post something if I get it clean.

I would not suggest saving a temporary file. That can get messy. I guess doing the conversion at runtime would be a better way. I have no real experience in that area, but the python OpenEXR bindings have examples for differrent kinds of conversions to other runtime formats (e.g. PIL or numpy) and it should be possible to do that for Qt image objects.

Regards,
Thorsten

P.S. this might have some pointers

http://skilldrick.co.uk/2010/03/pyqt-pil-and-windows/

Yes I want to avoid writing temp file, that’s what I say it’s not clean actually. I ever convert tga from pil to qt, so if I can find example to convert exr to pil image, it will be ok.
I am in hollidays for ten days and then will be hurry in production, but will work all this and let you know what I find. I think I will write a module to handle all this easily once solutions are found.

Writing temp files is not a big deal- I wouldn’t design software to do it as a first resort, and I probably wouldn’t release software into the wild that did tons of temp file writing, but we are forced to write temporary files constantly and it has never been a big deal. In fact you’d be amazed how much middleware creates temp files, often hard-coded temp files so that you can’t even run multiple versions at the same time! (I’m looking at you, granny preprocessor!). In fact I care more about the slowness of writing to disk than the cleanliness issue, as long as you use ‘best temp directory practices’.

You can just make sure your files are cleaned up (again, not necessary for inhouse software, but nice for sure), you aren’t hard-coding the temp files (ie, call mkstemp instead of gettempdir() + ‘\myfile.foo’), and you can even hide them under some temp dir to make it easier to clean up in the end (mkdtemp with hard-coded filenames, or mkstemp(dir=os.path.join(gettempdir(), ‘mymodulescratch’)) to get a random file in a hard-coded folder.

I don’t see a problem with temp files in general. But you should not create a temp file to read an image file in my eyes.

Ok dudes, sorry I’ve sort it for some times but didn’t post the result.
Here is a file explaining how to do it, as simple as possible.
Get gamma correction works but is lot slower. Maybe an alternative is to do gamma correction later on the pil image, if someone know how to do it, feel free to post it.


#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
based on python 2.7 amd64, PyQt4
needed modules : PIL, openEXR

put an exr file in same path as this script and enter exr name below
gammaCorrected 0 takes exrToJpg function, 1 takes exrToJpgGamma function (lot slower !)
"""
import sys, array
from PyQt4 import QtGui, QtCore

from PIL.ImageQt import ImageQt as PilImageQt
import OpenEXR, Imath, Image

exrPath = "Seq_0144.exr"
gammaCorrected = 0

class exr(QtGui.QWidget):
    def __init__(self):
        super(exr, self).__init__()
        self.resize(600, 300)
        self.setWindowTitle('EXR QT')

        self.layout = QtGui.QGridLayout()
        self.setLayout(self.layout)

        self.show()
        self.showEXR()
    #
    def showEXR(self):
        width = 280
        height = 160

        if gammaCorrected == 1:
            imageq = PilImageQt(exrToJpgGamma(exrPath))
        else:
            imageq = PilImageQt(exrToJpg(exrPath))
        qimage = QtGui.QImage(imageq)
        pixmap = QtGui.QPixmap.fromImage(qimage)
        ScaledPixmap = pixmap.scaled(width, height, QtCore.Qt.KeepAspectRatio, QtCore.Qt.FastTransformation)

        label = QtGui.QLabel("bibi", self)
        label.setPixmap(ScaledPixmap)
        self.layout.addWidget(label, 0, 0)
    #
#
def exrToJpg(exrfile):
    file = OpenEXR.InputFile(exrfile)
    pt = Imath.PixelType(Imath.PixelType.FLOAT)
    dw = file.header()['dataWindow']
    size = (dw.max.x - dw.min.x + 1, dw.max.y - dw.min.y + 1)

    rgbf = [Image.fromstring("F", size, file.channel(c, pt)) for c in "RGB"]

    extrema = [im.getextrema() for im in rgbf]
    darkest = min([lo for (lo,hi) in extrema])
    lighest = max([hi for (lo,hi) in extrema])
    scale = 255 / (lighest - darkest)
    def normalize_0_255(v):
         return (v * scale) + darkest
    rgb8 = [im.point(normalize_0_255).convert("L") for im in rgbf]
    myjpg = Image.merge("RGB", rgb8)
    return myjpg
#
def exrToJpgGamma(exrfile):
    file = OpenEXR.InputFile(exrfile)
    pt = 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', pt)
    GreenStr = file.channel('G', pt)
    BlueStr = file.channel('B', pt)

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

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

    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]
    myqimage = Image.merge("RGB", rgb8)
    return myqimage
#
def main():
    app = QtGui.QApplication(sys.argv)
    win = exr()
    sys.exit(app.exec_())
#
if __name__ == '__main__':
    main()

Post any optimization you would fine :wink: