【问题标题】:Loading animated gif data in QMovie在 QMovie 中加载动画 gif 数据
【发布时间】:2015-06-17 15:03:10
【问题描述】:

我对 Qt(特别是 PySide)非常陌生,我正在尝试编写一个脚本,将动画 gif 从文件加载到 QByteArray 中,然后加载到 QMovie 中。从文件转到 QByteArray 的原因是因为我无法将该 gif 文件保存在内存中。我希望能够以这样一种方式存储动画 gif,以便稍后将其写入 JSON 文件(因此是 QByteArray)。我尝试使用来自 here 的 ekhumoro 的回答,虽然没有出现错误,但动画 gif 也没有出现。 (那里可能有东西,但我什么也没看到。)简而言之,我的代码如下所示:

data = open("img.gif", "rb").read()
self.bArray = QtCore.QByteArray(data)
self.bBuffer = QtCore.QBuffer(self.bArray)
self.bBuffer.open(QtCore.QIODevice.ReadOnly)
self.movie = QtGui.QMovie(self.bBuffer, 'GIF')
self.movieLabel.setMovie(self.movie) # a QLabel
self.movie.start()

我想稍后将self.bArray 的内容存储到 JSON 文件中。

当我为 QMovie 构造函数提供文件路径时,我可以看到动画 gif,但是我将无法将 gif 的内容保存到 JSON 文件。

我想知道数据是否未正确读取或未正确传递给 QMovie。

有什么想法吗?

谢谢!

【问题讨论】:

  • 只是为了确保在创建ByteArray和Buffer时没有恶作剧:你能把缓冲的数据写出来,结果还是同样的动画gif吗?另外,您打算如何将 gif 编码为 JSON?二进制数据编码并不完全是 JSON 的强项(并且非标准化)
  • @deets。 base64 似乎是最明显的解决方案。
  • 我没有检查 ByteArray 和 Buffer 但我看不出为什么数据会被损坏。另外,根据下面的 ekhumoro 的建议,我可以让第一帧出现,所以看起来没问题。是的,我正计划使用 base64。

标签: json qt pyside animated-gif


【解决方案1】:

这看起来像一个 PySide 错误,因为相同的代码在 PyQt 中运行良好。

错误似乎在QMovie 构造函数中,它不会从传递给它的设备中读取任何内容。一种解决方法是显式设置设备,如下所示:

import sys
from PySide import QtCore, QtGui
# from PyQt4 import QtCore, QtGui

app = QtGui.QApplication(sys.argv)

data = open('anim.gif', 'rb').read()
a = QtCore.QByteArray(data)
b = QtCore.QBuffer(a)

print('open: %s' % b.open(QtCore.QIODevice.ReadOnly))

m = QtGui.QMovie()
m.setFormat('GIF')
m.setDevice(b)

print('valid: %s' % m.isValid())

w = QtGui.QLabel()
w.setMovie(m)
m.start()

w.resize(500, 500)
w.show()
app.exec_()

print('pos: %s' % b.pos())

【讨论】:

  • 谢谢,至少能够让第一帧出现。我当前的代码与 m.jumpToFrame(0) 一样,它显示了第一帧。但是任何尝试执行 m.start() 或 m.jumpToNextFrame() 都会导致我的应用程序崩溃。 (对编辑感到抱歉 - 不小心按了 Enter。)
  • @Yuuki。我在我的答案中添加了一个完整的、可运行的示例。这对我来说对 pyside 和 pyqt 都很好。请确认它是否适合您。如果是这样,那就回答了你原来的问题。对于您的其他问题,请开始一个新问题,并包含一个可运行的示例脚本来演示该问题。 (PS:我怀疑问题的原因是您没有保留对其中一个对象的引用)。
  • 是的,这确实有效。我认为新问题可能与我的 Pillow 安装如何与我的应用程序交互有关。我会在那里再挖一点。但除此之外,非常感谢!
  • 我的崩溃了,但注意到 ekhumoro 的评论以保留对其中一个对象的引用。这样做后,它修复了它。认为这对于遇到类似问题的任何人来说都是一件好事!
【解决方案2】:

ekhumoro 的解决方案似乎是针对 PyQt4 的,并且 gif 将在第一帧冻结。

我只想分享能够在 Python3 和 PyQt5 上工作的代码,并读取一个包含 base64 编码的 .gif 文件的 .py 文件,以便它甚至可以通过 pyinstaller 将图像打包成一个 .exe 文件。

这是代码,干杯!

from PyQt5 import QtWidgets
from PyQt5 import QtGui
from PyQt5 import QtCore

import base64

def cv2ImageToBase64String(variableName, imagePath, outputPath):
    """
    Parameters: imagePath [str]  -> path of image including file extension
                outputPath [str] -> path of .py file including file extension
    """    
    # read image as binary
    with open(imagePath, "rb") as image:
        data = image.read()

    # turn binary data into string by base64
    base64Image = base64.b64encode(data)

    # save it in a .py file with a variable called "image"
    with open(outputPath, "a") as f:
        f.write(f"{variableName}={base64Image}\n")


class Main(QtWidgets.QDialog):
    def __init__(self, dataInByte):
        # inherit and init QDialog
        super().__init__()

        # layout setting
        layout = QtWidgets.QVBoxLayout()
        label  = QtWidgets.QLabel()
        self.setLayout(layout)
        layout.addWidget(label)
        
        # decode and transform the data type
        rawData = base64.b64decode(dataInByte.decode())
        data    = QtCore.QByteArray(rawData)
        buffer  = QtCore.QBuffer(data)

        # it seems like a bug here that it shows nothing since we put buffer into QMovie like the example below
        # example: movie = QtGui.QMovie(buffer)
        movie = QtGui.QMovie()
        movie.setDevice(buffer)
        
        # start movie
        label.setMovie(movie)
        movie.start()
        self.exec_()

if __name__ == "__main__":
    # step 1: encode your gif by base64
    cv2ImageToBase64String(variableName="dataInByte", imagePath = "./src/Assets/loading.gif", outputPath = "./encodedGif.py")

    # step 2: load your gif from .py file
    from encodedGif import dataInByte

    # step 3: start the app
    app = QtWidgets.QApplication([])
    main = Main(dataInByte = dataInByte)

【讨论】:

    猜你喜欢
    • 2010-12-03
    • 1970-01-01
    • 2015-01-28
    • 2013-08-04
    • 1970-01-01
    • 2016-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多