PDA

View Full Version : Paint streaming pixel data



jmsbc
15th September 2008, 19:46
Hello,

Please help me figure out what the best method is to load a file of pixel data (each pixel is 8bits) and paint it to the screen. The data is supposed to stream down the screen (i.e waterfall). (So basically read one line at a time from the file and stream the image from the top of the screen)

I'm currently just testing with a regular QImage file and scrolling it down the screen. I first tried the basic method of loading a QImage and calling paintEvent on a set timer. PaintEvent will just redraw the image (drawImage) one line lower each time.

However, the image scrolls down the screen very slowly, and i'm sure there is a better way to do this.

I also found a basic example of QGraphicsScene and QGraphicsView which uses animation->setPosAt(...) after a certain QTimeLine. However I'm not sure if this is what I want for my application (to repeatedly read the pixel data file 1 line at a time and stream it down the screen).

Thank you very much for your help
-James

jmsbc
17th September 2008, 00:53
Hello,

Please help me figure out what the best method is to stream in pixel data (each pixel is 8bits) and paint it to the screen. The data is supposed to stream down the screen (i.e waterfall). (So basically read one line of pixels at a time and display at the top of the screen, pushing the rest of the image down.

I'm currently just testing with a regular QImage file and scrolling it down the screen. I tried the basic method of loading a QImage and repeately calling paintEvent. PaintEvent will just redraw the image (drawImage) one line lower each time.

However, the image scrolls down the screen very slowly, and i'm sure there is a better way to do this.


Thank you very much for your help
-James

newqtuser
17th September 2008, 02:29
Jimsbc

I have a an qt app here that im able to stream pixel data from a QByteArray over the network line by line "waterfall" and it uses udp for the protocal and is pretty quick. Are you trying this over the network? If not this app i have my still help you. Basically on one side it opens a QImage and reads the data into a QByteArray then it streams each line to the other end with QDataStream. Each line that is painted on the client side is converted to a QPixMap and each QPixMap is painted on the screen, so everyline is dropped down each time a new one comes in until the image is displayed. I had to put in a QTimer on the sending side because it was so quick and i wanted make sure it was doing what i needed. This was created on linux. Let me know if your interested in the code and i will send it your way.

jmsbc
17th September 2008, 16:25
Newqtuser,

Sure that would be great! I'm curious how much of a difference there is in performance, thanks a lot. The speed that I'm interested is on your receiving end, and how fast it can paint the image to screen. (My application will keep receiving streaming pixel data to draw) Also If anyone knows of a more optimized way to please share. Thanks.

-James

newqtuser
23rd September 2008, 04:15
// server

#include <QDialog>
#include <QWidget>
#include <QString>
#include <QThread>
#include <QtGui>
#include <unistd.h>
#include <Qt/QtNetwork>

class ImgServer : public QObject
{
Q_OBJECT
public:
ImgServer();
QUdpSocket* socket;
QImage* image;
quint64 value;
private slots:
void streamImage();
};

ImgServer::ImgServer()
{
socket = new QUdpSocket(this);
image = new QImage("/tmp/someimage.jpg");
QTimer *timer = new QTimer(this);
timer->setInterval(0);
timer->start();
QTimer::singleShot(0, this, SLOT(streamImage()));
}

void ImgServer::streamImage()
{
for (int y=0; y < image->height(); y++)
{
QByteArray sndBuffer(image->width(), 0);
QDataStream sndStream(&sndBuffer, QIODevice::WriteOnly);
sndStream.setVersion(QDataStream::Qt_4_4);
sndStream << (quint16)image->height() << (quint16)image->width();

quint16 y_in = y;
sndStream << y_in;

for(int x=0; x < image->width(); x++)
{
QRgb rgb = image->pixel(x, y);
sndStream << (quint8)qRed(rgb) << (quint8)qGreen(rgb) << (quint8)qBlue(rgb);
usleep(45);
}

QHostAddress clientIp;
clientIp = "127.0.0.1";
socket->writeDatagram(sndBuffer, clientIp, 9988 );
}
}

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
ImgServer imageServer;
return app.exec();
}
#include "moc_ImgServer.cpp"



/******************* client code *********************/

#include <QApplication>
#include <QDialog>
#include <QWidget>
#include <QString>
#include <QThread>
#include <QtGui>
#include <unistd.h>
#include <Qt/QtNetwork>
#include <QObject>

class ImgReciever : public QLabel
{
Q_OBJECT
public:
ImgReciever(QWidget* parent=0);
QUdpSocket* socket;
QImage* image;
QGraphicsScene* scene;
QLabel myLabel;
QImage mirroredImage;

private slots:
void dataPending();
};

ImgReciever::ImgReciever(QWidget* parent) : QLabel( parent )
{
scene = new QGraphicsScene();
image = 0;
socket = new QUdpSocket(this);
socket->bind(9988);
connect(socket, SIGNAL(readyRead()), this, SLOT(dataPending() ) );
}

void ImgReciever::dataPending()
{
qDebug() << "ScpImageRcvr::dataPending()";
while( socket->hasPendingDatagrams() )
{
QByteArray buffer(socket->pendingDatagramSize(), 0);
socket->readDatagram(buffer.data(), buffer.size());
QDataStream stream(buffer);
stream.setVersion(QDataStream::Qt_4_4);

quint16 width, height, y;
stream >> height >> width >> y;

QImage new_line(width, 1, QImage::Format_RGB32);
if ( !image )
image = new QImage(new_line);
else if( image->width() !=width || image->height() != height )
{
QImage* new_image = new QImage( width, image->height()+1, QImage::Format_RGB32 );

if(image->height()+1 == height )
qDebug() << "Image complete!";

for ( int imgHeight = 0; imgHeight < image->height()+1; imgHeight++ )
{
for ( int incomingImgWidth = 0; incomingImgWidth < width; incomingImgWidth++ )
{
if ( imgHeight == 0 )
{
quint8 red, green, blue;
stream >> red >> green >> blue;
new_image->setPixel( incomingImgWidth, imgHeight, qRgb(red, green, blue) );
}
else
{
new_image->setPixel(incomingImgWidth,
imgHeight,
image->pixel( incomingImgWidth, imgHeight-1) );
}
}
}
delete image;
image = new_image;
mirroredImage = image->mirrored(false, true);
}

myLabel.setPixmap(QPixmap::fromImage(mirroredImage ));
myLabel.resize(900, 900);
myLabel.show();
}
}

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
ImgReciever rcvImgData;

return app.exec();
}

#include "moc_ImgReciever.cpp"

Thats it, sorry i took so long.
Oh and i ran moc by hand for the 2 cpp file and included them in the bottem as you can see. Here was the moc command i ran from the command line

moc ImgReciever.cpp > moc_ImgReciever.cpp

that way i could have the declartions and implementation all in the same cpp files. This was for testing so i wanted it all together. Hope that works for you let me know how it goes.