如何避免(PIL)imageQt 的奇怪行为?

how to avoid (PIL) imageQt's bizarre behaviour?

我用 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") 未注释:然后 python 崩溃。

因此,我认为 ImageQt 中的某些内容已经烂掉,最终可能会得到纠正。奇怪的行为提醒了问题 Nick Morgan discusses,但只是将 imageQt 包裹在另一个 QImage 中并不能使情况变得更好。哦,是的,我在 Windows 下 运行ning。

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

问题

Padraic Cunningham 解决了 Pillow (PIL) to QImage conversion -> python.exe has stopped working and offered a work-around. However, in his example code the colour bands get mixed up. That issue is answered by Jordan in pil-image to qpixmap conversion issue 中崩溃 python 的问题。所以最后,这个改编解决了我的问题:

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)