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 QImage to a PIL Image.
Asked
Active
Viewed 7,859 times
11
6 Answers
13
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.

skuda
- 1,068
- 1
- 6
- 10
-
1This also works in Python3, just change "cStringIO.StringIO" to "io.BytesIO". – mzuther Oct 17 '14 at 14:35
-
for PySide2 `5.x`, `buffer.data()` returns a `QByteArray`. If you call `data()` on the `QByteArray` it should give you what you want. Be careful about color channels though if you are using `numpy`. – Kaan E. Apr 30 '19 at 00:51
2
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).

iacopo
- 663
- 1
- 7
- 22

Stefan van der Walt
- 7,165
- 1
- 32
- 41
-
Can you add the other link yet? (Back when I had that problem, I just posted another answer to hold the second link ;-) – SamB Nov 27 '10 at 23:46
-
Sure, here it is: https://github.com/stefanv/scikits.image/blob/master/scikits/image/io/_plugins/qt_plugin.py#L45 – Stefan van der Walt Jan 10 '11 at 11:59
2
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.

Oleh Prypin
- 33,184
- 10
- 89
- 99

Chenna V
- 10,185
- 11
- 77
- 104
-
You forgot to add four spaces before each line of code (and put only one newline between lines). – SamB Nov 27 '10 at 23:50
2
#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()

Chenna V
- 10,185
- 11
- 77
- 104
0
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.

Eli Bendersky
- 263,248
- 89
- 350
- 412
-
I dont think that direct image data are compatible between QImage and PIL images. What I found out after some messing around (it bit me): Qt aligns all its lines on 32bit, which means that if the number of bytes per line for image is not divisible by 4, there's going to be crap inserted in the data. Maybe there's even more gotchas... – Virgil Dupras Nov 16 '09 at 14:54
0
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)

Kaan E.
- 515
- 4
- 16