在 QMovie 中加载动画 gif 数据
Loading animated gif data in QMovie
我是 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。
有什么想法吗?
谢谢!
这看起来像是一个 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())
看来 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)
我是 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。
有什么想法吗?
谢谢!
这看起来像是一个 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())
看来 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)