简体   繁体   English

PIL 图像到 QPixmap 的转换问题

[英]PIL Image to QPixmap conversion issue

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.我正在尝试将 PIL.Image 转换为 QPixmap,以便我可以在 PyQT GUI 上使用 QgraphicsScene 进行显示。 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.我在 Windows 7 64 位上,使用 python 3.4 和 PyQt4 和枕头 3.1.0。 The results im getting can be seen below.我得到的结果如下所示。

Original picture原图

Picture displayed in GUI GUI中显示的图片

Thanks in advance :).提前致谢 :)。

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).在您的 PIL 图像中,最后一个波段是 alpha 通道,而在 Qt 图像中,alpha 通道是第一个(RGBA 与 ARGB)。 There may be ways of permuting the bands but the easiest way seems to use the ImageQt class.可能有排列波段的方法,但最简单的方法似乎是使用 ImageQt 类。

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

I dont know why, but ImageQt crashed in my system Win10, Python3, Qt5.我不知道为什么,但 ImageQt 在我的系统 Win10、Python3、Qt5 中崩溃了。 So i went to an other direction and tried a solution found on github.所以我去了另一个方向并尝试了在 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我对此的解决方案是,将 RGB 图片分离为每种颜色并将其组装为 BGR 或 BGRA,然后再将其转换为 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

I've tested RGB, and PIL saves data with the qt format Format_RGB888 :我已经测试过 RGB,PIL 使用 qt 格式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 :我还没有测试过,但我假设对于 RGBA 它将是等效格式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)

This maybe usefull这可能有用

Creates an ImageQt object from a PIL Image object.从 PIL Image 对象创建一个 ImageQt 对象。 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.该类是 QtGui.QImage 的子类,这意味着您可以将生成的对象直接传递给 PyQt4/5 API 函数和方法。 This operation is currently supported for mode 1, L, P, RGB, and RGBA images.此操作目前支持模式 1、L、P、RGB 和 RGBA 图像。 To handle other modes, you need to convert the image first.要处理其他模式,您需要先转换图像。

https://pillow.readthedocs.io/en/stable/reference/ImageQt.html https://pillow.readthedocs.io/en/stable/reference/ImageQt.html

@titusjan's answer didn't work for me. @titusjan 的回答对我不起作用。 Both @Michael and @Jordan have solutions that worked. @Michael 和 @Jordan 都有有效的解决方案。 A simpler version of @Michael's is just to redefine how the bytes are written for the image. @Michael's 的一个更简单的版本就是重新定义如何为图像写入字节。 So this works for me:所以这对我有用:

im2 = im.convert("RGBA")
data = im2.tobytes("raw", "BGRA")
qim = QtGui.QImage(data, im.width, im.height, QtGui.QImage.Format_ARGB32)
pixmap = QtGui.QPixmap.fromImage(qim)

The only difference is that I swapped the order for the encoding, eg to 'BGRA' instead of 'RGBA'.唯一的区别是我交换了编码的顺序,例如“BGRA”而不是“RGBA”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM