Convert PyQt to PIL image
I have an image in a QImage and I want to process it in PIL before I display it. While the ImageQT class lets me convert a PIL Image to a QImage, there doesn't appear to anything to go from a开发者_Go百科 QImage to a PIL Image.
I convert it from QImage to PIL with this code:
img = QImage("/tmp/example.png")
buffer = QBuffer()
buffer.open(QIODevice.ReadWrite)
img.save(buffer, "PNG")
strio = cStringIO.StringIO()
strio.write(buffer.data())
buffer.close()
strio.seek(0)
pil_im = Image.open(strio)
I tried many combinations before getting it to work.
#Code for converting grayscale QImage to PIL image
from PyQt4 import QtGui, QtCore
qimage1 = QtGui.QImage("t1.png")
bytes=qimage1.bits().asstring(qimage1.numBytes())
from PIL import Image
pilimg = Image.frombuffer("L",(qimage1.width(),qimage1.height()),bytes,'raw', "L", 0, 1)
pilimg.show()
Another route would be:
- Load the image data into a numpy array (example code using PIL)
- Manipulate the image using numpy, scipy or scikits.image
- Load the data into a QImage (example: browse the scikits.image archive (linked in 1) and look on line 45 of qt_plugin.py -- sorry, stackoverflow doesn't allow me to post more links yet)
As Virgil mentions, the data must be 32-bit (or 4-byte) aligned, which means you need to remember to specify the strides in step 3 (as shown in the snippet).
from PyQt5 import QtGui
from PIL import Image
img = QtGui.QImage(width, height, QImage.Format_RGBA8888)
data = img.constBits().asstring(img.byteCount())
pilimg = Image.frombuffer('RGBA', (img.width(), img.height()), data, 'raw', 'RGBA', 0, 1)
from PyQt4 import QtGui
from PIL import Image
img = QtGui.QImage("greyScaleImage.png")
bytes = img.bits().asstring(img.numBytes())
pilimg = Image.frombuffer('L', (img.width(), img.height()), bytes, 'raw', 'L', 0, 1)
pilimg.show()
Thanks Eli Bendersky, your code was helpful.
You can convert a QImage into a Python string:
>>> image = QImage(256, 256, QImage.Format_ARGB32)
>>> bytes = image.bits().asstring(image.numBytes())
>>> len(bytes)
262144
Converting from this to PIL should be easy.
Here is an answer for those using PySide2 5.x
, the official python wrappings for qt. They should also work for PyQt 5.x
I also added to QImage
to numpy
that I've used in conjunction with this one. I prefer to use PIL
dependency, mainly because I don't have to track color channel changes.
from PySide2 import QtCore, QtGui
from PIL import Image
import io
def qimage_to_pimage(qimage: QtGui.QImage) -> Image:
"""
Convert qimage to PIL.Image
Code adapted from SO:
https://stackoverflow.com/a/1756587/7330813
"""
bio = io.BytesIO()
bfr = QtCore.QBuffer()
bfr.open(QtCore.QIODevice.ReadWrite)
qimage.save(bfr, 'PNG')
bytearr = bfr.data()
bio.write(bytearr.data())
bfr.close()
bio.seek(0)
img = Image.open(bio)
return img
Here is one to convert numpy.ndarray
to QImage
from PIL import Image, ImageQt
import numpy as np
def array_to_qimage(arr: np.ndarray):
"Convert numpy array to QImage"
img = Image.fromarray(arr)
return ImageQt.ImageQt(img)
精彩评论