PDA

View Full Version : PyQt code to draw image from raw data?



StevenB
31st July 2010, 04:24
I'm trying to write PyQt code equivalent to the following C++ code, but I'm stuck. I'm relatively new to Python, and I'm having a hard time following the PyQt documentation for QImage (http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qimage.html).
I can create the GUI parts, but how do I set up the raw data and call the QImage constructor?



int main(int argc, char* argv[])
{
// Create the Qt application and GUI components
QApplication app(argc, argv);
QMainWindow win;
QGraphicsScene canvas;
QGraphicsView view(&canvas, &win);

unsigned char* imageData = new unsigned char[324];

// Generate some image data
for(int i = 0; i < 324; i++)
{
imageData[i] = i % 250;
}

// Create the colormap for the indexed image
QVector<QRgb> colormap;
for(int i = 0; i < 255; i++)
{
colormap.append(qRgb(i, i, i));
}

QImage img(imageData, 18, 18, QImage::Format_Indexed8); // Create the image
img.setColorTable(colormap); // Set up the colormap
QPixmap pix = QPixmap::fromImage(img); // Convert it to a pixmap so we can display it
canvas.addPixmap(pix); // Add the pixmap to the graphics canvas

win.show();
app.exec();
}


Here's the Python code I've got so far:


from PyQt4.QtGui import *
from os import sys

app = QApplication(sys.argv)

# Create the window and the graphics view
win = QMainWindow()
canvas = QGraphicsScene()
view = QGraphicsView(canvas, win)
view.resize(200, 200)

# Create the image data - How?
# Create the QImage - How?

# Create the colormap

pixmap = QPixmap.fromImage(img)

# Add the image to the canvas
canvas.addPixmap(pixmap)

win.show()
sys.exit(app.exec_())

MTK358
1st August 2010, 13:51
Something like this, maybe?

imageData = []

for i in range(0, 324):
imageData[i] = i % 250

colormap = []

for i in range(0, 255):
colormap.append(qRgb(i, i, i))

img = QImage(imageData, 18, 18, Format_Indexed8)
img.setColorTable(colormap);

StevenB
2nd August 2010, 02:57
Unfortunately, it doesn't seem to be that easy.

When I run the line img = QImage(imageData, 10, 10, QImage.Format_Indexed8), I get a bunch of errors saying that the arguments provided don't match any overloaded constructor:

QImage(sip.voidptr, int, int, QImage.Format): argument 1 has unexpected type 'list'
QImage(str, int, int, int, QImage.Format): argument 1 has unexpected type 'list'
QImage(sip.voidptr, int, int, int, QImage.Format): argument 1 has unexpected type 'list'
etc.


I think I need to do something with a "sip.voidptr", but it appears that's essentially just a C++ interface, and not something I can really work with in Python - is that correct?

MTK358
8th August 2010, 17:37
I think I need to do something with a "sip.voidptr", but it appears that's essentially just a C++ interface, and not something I can really work with in Python - is that correct?

I don't know much about bindings, maybe someone else can help.

chenna
31st August 2010, 01:02
Okay, firstly where are you getting this image data from? Is it a SWIGPy object?
I had the same problem a couple of days where I had a python binding for my camera driver library and the only way of getting image data was an unsigned char*. Which obviously cannot be understood by python because SWIG did the binding.
So when I access my unsigned char* image data directly in python here's what I get:
<Swig Object of type 'unsigned char *' at 0xb77b0bd8>
Anyways i wrote a small interface code to convert any unsigned char* image data to PIL image. which you can convert to QImage using ImageQt
Here's the link to the code
http://www.optionsbender.com/technologybending/python/unsignedcharimagedatatopilimage
and a similar post
http://stackoverflow.com/questions/3586003/unsigned-char-image-to-python

dbzhang800
31st August 2010, 06:09
I found a solution:


#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import sys
import ctypes
from PyQt4 import QtGui, QtCore
import sip

'''
2009-2010 dbzhang800@gmail.com
'''

class Window(QtGui.QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.label = QtGui.QLabel(self)
self.label.setMinimumSize(512, 512)
self.comboBox = QtGui.QComboBox(self)
self.comboBox.addItems(["Image.{}".format(i) for i in range(2)])
vbox = QtGui.QVBoxLayout(self)
vbox.addWidget(self.label)
vbox.addWidget(self.comboBox)
self.initImages()
self.comboBox.currentIndexChanged.connect(self.onC urrentIndexChanged)

def onCurrentIndexChanged(self, index):
self.label.setPixmap(QtGui.QPixmap.fromImage(self. images[index]))

def initImages(self):
self.images = []
self.colorTable = [QtGui.qRgb(i, i, i) for i in range(256)]
self.createImage0()
self.createImage1()
self.label.setPixmap(QtGui.QPixmap.fromImage(self. images[0]))

def createImage0(self):
'''Create an QImage object, the copy data from other buffer to the image buffer.
'''
image = QtGui.QImage(512, 512, QtGui.QImage.Format_Indexed8)
image.setColorTable(self.colorTable)
buff = ctypes.create_string_buffer('\xFF'*512*16, 512*16)
buff2 = ctypes.create_string_buffer('\x1f'*512*32, 512*32)
img_ptr = image.bits()
ctypes.memmove(int(img_ptr), buff, buff._length_)
ctypes.memmove(int(img_ptr)+buff._length_, buff2, buff2._length_)
ctypes.memmove(int(img_ptr)+buff._length_+buff2._l ength_, buff, buff._length_)
self.images.append(image)

def createImage1(self):
'''we already have a buffer, create an QImage object using the buffer.
'''
self.buff = ctypes.create_string_buffer('\x7F'*512*512)
image = QtGui.QImage(sip.voidptr(ctypes.addressof(self.buf f)), 512, 512, QtGui.QImage.Format_Indexed8)
image.setColorTable(self.colorTable)
self.images.append(image)

if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())