首页 > 解决方案 > 如何避免(PIL)imageQt 的奇怪行为?

问题描述

我使用 PIL 进行图像镶嵌,并希望使用QGraphicsView查看结果。为此,我对QtImageViewer进行了子类化。相关方法有

def setImage(self, image):
    """ Set the scene's current image pixmap to the input QImage or QPixmap.
    Raises a RuntimeError if the input image has type other than QImage or QPixmap.
    :type image: QImage | QPixmap
    """
#    image.save("r:/test.png")
    if isinstance(image, QPixmap):
        pixmap = image
    elif isinstance(image, QImage):
        pixmap = QPixmap.fromImage(image)
    else:
        raise RuntimeError("ImageViewer.setImage: Argument must be a QImage or QPixmap.")

    if self.hasImage():
        self._pixmapHandle.setPixmap(pixmap)
    else:
        self._pixmapHandle = self.scene.addPixmap(pixmap)
    self.setSceneRect(QRectF(pixmap.rect()))  # Set scene size to image size.
    self.updateViewer()

我从它的子类中调用的内容如下:

    def redraw(self):
        img = Image.new("RGB", (self.width(), self.height()), "gray")
        if self._source is not None:
            self._source.paintMap(img)
        img.save("r:/debug.png")
#         self.setImage(QImage("r:\debug.png"))
        self.setImage(ImageQt(img))

在这两个片段中都有几行测试代码,将图像内容保存到临时文件中。当我保存 PIL 图像(img.save("r:/debug.png") )并从该文件创建QImage ( self.setImage(QImage("r:\debug.png")))时,图像是正确显示。

问题

期望的结果: 在此处输入图像描述

结果我正常运行: 在此处输入图像描述

现在可以观察到三种情况:

  1. 只需运行代码(没有测试代码):显示了一个图形,但显然它是一块随机存储器,虽然看起来总是一样的。
  2. 调试代码,在setImage ()中停止,保存传入的图像:保存的文件和显示的图像都是正确的。
  3. 调试或运行image.save("r:/test.png") uncommented行:然后 python 崩溃。

所以,我认为ImageQt中有些东西已经腐烂,最终可能会得到纠正。奇怪的行为让人想起Nick Morgan 讨论的问题,但只是将imageQt包装在另一个QImage中并不会改变这种情况。哦,是的,我在 Windows 下运行。

此外:与PIL Image 到 QPixmap 的转换问题没有任何联系,因为该问题与颜色通道的顺序有关,与 imageQt 中的虚假内存指针无关。

问题

标签: pythonpyqtpython-imaging-libraryqimage

解决方案


Padraic Cunningham解决了将Pillow (PIL) 中的 python 崩溃到 QImage 转换的问题 -> python.exe 已停止工作并提供了解决方法。然而,在他的示例代码中,色带混淆了。Jordanpil-image to qpixmap conversion issue中回答了这个问题。所以最后,这个改编解决了我的问题:

def redraw(self):
    img = Image.new("RGB", (self.width(), self.height()), "gray")
    if self._source is not None:
        self._source.paintMap(img)
    data = img.convert("RGB").tostring("raw", "RGB")
    qimg = QImage(data, img.size[0], img.size[1], QImage.Format_RGB888)
    self.setImage(qimg)

推荐阅读