trinkner trinkner - 14 days ago 7
Python Question

Python: convert QT QIcon into jpeg?

I'm writing a photo-organizing app that uses a QListWidget to display the filename and thumbnail of photo files. I use the QIcon property of the QListWidget's QItem to display a thumbnail of the image. Users can edit EXIF data and the photos' filename, and then save the data to the image files. Jpgs may not already have thumbnails ebedded in them, so my app lets the user embed newly generated thumbnails into the jpg files.

I'd like to retrieve the QIcon image and save it in the EXIF section of the original photo file's metadata. To do that, I need to convert the QIcon image to jpeg bytes. I've read the QIcon documentation, but can't find a way to get jpeg byles from a QIcon object.

I'm using Python 3 and piexif to write the EXIF data to the file. I'm using PILLOW to create jpeg thumbnails when populating the QListWidget. I could use PILLOW to create thumbnails upon saving, but since thumbnails already exist in the QIcon, it would be more efficient to use the QIcon image.

Here's the essence of my code so far. Obviously, it doesn't work, because QIcon is a QIcon object, not jpeg bytes.

fileName
is a variable that contains a full valid path to the image file.
lstPhotos
is a QListWidget.

I'd greatly appreciate any advice!

for i in lstPhotos:
exif_dict["thumbnail"] = i.icon()
exif_bytes = piexif.dump(exif_dict)
piexif.insert(exif_bytes, fileName)


Thanks to @Ekhumoro for help! The following code WORKS:

def ConvertIconToJpeg(self, icon, size=None, fmt='JPG'):
if size is None:
size = icon.availableSizes()[0]
pixmap = icon.pixmap(size)
array = QtCore.QByteArray()
buffer = QtCore.QBuffer(array)
buffer.open(QtCore.QIODevice.WriteOnly)
pixmap.save(buffer, fmt)
buffer.close()
return array.data()'


and then followed later in a routine in the same class:

for i in lstPhotos.items():
thisThumbnail = exif_dict.pop("thumbnail")
if thisThumbnail is None:
thisThumbnail = self.ConvertIconToJpeg(i.icon())
exif_dict["thumbnail"] = thisThumbnail
exif_bytes = piexif.dump(exif_dict)
piexif.insert(exif_bytes, fileName)`

Answer

You need to get the pixmap from the icon (which can have more than one), and then save that into a buffer with the required format:

def convert_icon(icon, size=None, fmt='JPG'):
    if size is None:
        size = icon.availableSizes()[0]
    pixmap = icon.pixmap(size)
    array = QtCore.QByteArray()
    buffer = QtCore.QBuffer(array)
    buffer.open(QtCore.QIODevice.WriteOnly)
    pixmap.save(buffer, fmt)
    buffer.close()
    return array.data()

The function should be used like this:

thumbnail = convert_icon(icon)
exif = piexif.load(path)
exif['thumbnail'] = thumbnail
data = piexif.dump(exif)
piexif.insert(data, path)