PIL Image to QPixmap conversion issue

2019-02-26 03:11发布

问题:

I've been struggling with this challenge for the best of today, I've managed to get a good point using previous posts and other resources.

I'm trying to convert a PIL.Image to a QPixmap so that I can display using a QgraphicsScene on my PyQT GUI. However when the picture is displayed the colours have changed?? Has anyone ever experienced this issue?

The code I use for this is as below.

self.graphicsScene.clear()
im = Image.open('Penguins.jpg')
im = im.convert("RGBA")
data = im.tobytes("raw","RGBA")
qim = QtGui.QImage(data, im.size[0], im.size[1], QtGui.QImage.Format_ARGB32)
pix = QtGui.QPixmap.fromImage(qim)
self.graphicsScene.addPixmap(pix)
self.graphicsView.fitInView(QtCore.QRectF(0,0,im.size[0], im.size[1]), QtCore.Qt.KeepAspectRatio)
self.graphicsScene.update()

Im on windows 7 64bit, using python 3.4 with PyQt4 and pillow 3.1.0. The results im getting can be seen below.

Original picture

Picture displayed in GUI

Thanks in advance :).

回答1:

In your PIL image the last band is the alpha channel, whereas in the Qt image the alpha channels is the first (RGBA vs. ARGB). There may be ways of permuting the bands but the easiest way seems to use the ImageQt class.

from PIL.ImageQt import ImageQt
qim = ImageQt(im)
pix = QtGui.QPixmap.fromImage(qim)


回答2:

This maybe usefull

Creates an ImageQt object from a PIL Image object. This class is a subclass of QtGui.QImage, which means that you can pass the resulting objects directly to PyQt4/5 API functions and methods. This operation is currently supported for mode 1, L, P, RGB, and RGBA images. To handle other modes, you need to convert the image first.

http://pillow.readthedocs.io/en/3.1.x/reference/ImageQt.html



回答3:

I've tested RGB, and PIL saves data with the qt format Format_RGB888:

im = im.convert("RGB")
data = im.tobytes("raw","RGB")
qim = QtGui.QImage(data, im.size[0], im.size[1], QtGui.QImage.Format_RGB888)

I haven't tested it, but I assume for that RGBA it will be the equivalent format Format_RGBA8888:

im = im.convert("RGBA")
data = im.tobytes("raw","RGBA")
qim = QtGui.QImage(data, im.size[0], im.size[1], QtGui.QImage.Format_RGBA8888)


回答4:

I dont know why, but ImageQt crashed in my system Win10, Python3, Qt5. So i went to an other direction and tried a solution found on github. This code doesnt crash, but gives a effect shown in first post.

My solution for this is, to separate the RGB pic to each color and assemble it as BGR or BGRA before converting it to a Pixmap

    def pil2pixmap(self, im):

    if im.mode == "RGB":
        r, g, b = im.split()
        im = Image.merge("RGB", (b, g, r))
    elif  im.mode == "RGBA":
        r, g, b, a = im.split()
        im = Image.merge("RGBA", (b, g, r, a))
    elif im.mode == "L":
        im = im.convert("RGBA")
    # Bild in RGBA konvertieren, falls nicht bereits passiert
    im2 = im.convert("RGBA")
    data = im2.tobytes("raw", "RGBA")
    qim = QtGui.QImage(data, im.size[0], im.size[1], QtGui.QImage.Format_ARGB32)
    pixmap = QtGui.QPixmap.fromImage(qim)
    return pixmap