I am developing an Image viewer.
My main goal is to make something able to easily load .EXR files along with all other main formats.
I based it around :
- PySide2 (Qt) for the UI.
- OpenImageIO for .exr files (and some others) loading. I built a custom python module based around OpenImageIO (made with C++ and PyBind11)
On the c++ side, the output is pretty straight forward, my custom module return a simple struct
( nicely 'converted' into python by pybind11) :
struct img_data
{
bool is_valid;
int width;
int height;
int nchannels;
std::vector<unsigned char> pixels;
};
It's less straightforward when in python:
# get image_data from custom module
image_data = custom_exr_loader.load_image(image_path)
# convert pixels to a numpy array
np_array = np.uint8(image_data.pixels)
np_array.shape = (image_data.height, image_data.width, image_data.nchannels)
# convert to a PIL Image
pil_image = Image.fromarray(np_array).convert("RGBA")
# convert to a QImage
image_qt : ImageQt = ImageQt(pil_image)
# and finally convert to a QPixmap for final consumption ...
pixmap = QPixmap.fromImage(image_qt, Qt.ImageConversionFlag.ColorOnly)
Performance is pretty bad. Especially when caching a whole directory of big EXRs
I bet there is a better way to do this ...
Of course the idea is to offload some of the work from python to C++ land. But I'm not sure how.
I tried using QImage.fromData()
method, but I never got a working result.
It requires a QByteArray
as a param.
How should I format pixels data in c++ to be able to use QImage.fromData()
from UI code ?