PDA

View Full Version : Problem displaying a QPixmap



franco.amato
27th September 2010, 17:18
Good morning.
I'm writing a camera viewer and I have problem displaying the frames.
To display them I wrote a very little CameraRenderer ( inherited from QWidget ) widget.
Here the code.

.h

#ifndef _CAMERARENDERER_H_
#define _CAMERARENDERER_H_

#include <QWidget>

class CCameraRenderer : public QWidget
{
Q_OBJECT

public:
CCameraRenderer(QWidget* parent=0);
~CCameraRenderer();

void setImage(QPixmap*);

protected:
/* paint event */
virtual void paintEvent( QPaintEvent* event );

private:
QPixmap* m_image;
};

#endif //#ifndef _CAMERARENDERER_H_

.cpp

#include "CameraRenderer.h"
/*Qt*/
#include <QPainter>

CCameraRenderer::CCameraRenderer(QWidget* parent)
: QWidget(parent)
{
setFixedSize( QSize(640, 480) );

m_image = new QPixmap();
}

CCameraRenderer::~CCameraRenderer()
{
}

void CCameraRenderer::setImage(QPixmap* image)
{
//m_image = QPixmap();
m_image = image;
}

void CCameraRenderer::paintEvent( QPaintEvent* pe )
{
QPainter p(this);
p.setRenderHint( QPainter::Antialiasing, true );

// image
p.drawPixmap( 0, 0, *m_image );
}


then I have the application where I have a QTimer and periodically I get a frame from the camera that I would display. The class that manage the camera is CVistaCamera.
Here the main code:

.h

class CVistaCamera : public QObject
{
Q_OBJECT

public:
CVistaCamera(QObject *parent = 0);
~CVistaCamera();
int InitCamera();
void CloseCamera();

VC_VARS* getStructPtr();

public slots:
void onUpdate(); //<-- called in a timer event where I get a camera frame

signals:
void sig_stopTimer();
void sig_startTimer( int );
void sig_updateDisplay( QPixmap* ); //<---should display the frame content

private:
int m_fVcOpen;

VC_VARS* pVar;

unsigned char* pImageData;
DWORD ImageSize;
DWORD vcVideoSource;

QPixmap* pixmap;
};

#endif //_VISTACAMERA_H_

and the main methods:


void CVistaCamera::onUpdate() //called periodically with a QTimer
{

VC_VARS* pVc = getStructPtr();
// get a frame
rc = VcGetImage( pImageData, ImageSize, &retLen );

if ( rc == VC_SUCCESS )
{
pixmap->loadFromData( pImageData, ImageSize );
emit sig_updateDisplay( pixmap );
}
else
{
// error - camera disconnected?
VcClose();
m_fVcOpen = 0;
}
}

the signal sig_updateDisplay is connected with a the slot onUpdateDisplay so:


connect( m_vistaCamera, SIGNAL( sig_updateDisplay(QPixmap*) ), this, SLOT( onUpdateDisplay(QPixmap*) ) );

and here the slot:

void VistaIrisCollector::onUpdateDisplay(QPixmap* pixmap )
{
ui.display->setImage( pixmap );
ui.display->repaint();
}

In the window I don't see nothing, I don't know why.
I would have a help.
Best Regards,
Franco

^NyAw^
27th September 2010, 17:23
Hi,

Take a look at this http://qt-apps.org/content/show.php/Qt+Opencv+webcam+viewer?content=89995

franco.amato
27th September 2010, 18:04
Hi,

Take a look at this http://qt-apps.org/content/show.php/Qt+Opencv+webcam+viewer?content=89995

Hi I don't use OpenCV to get images from my camera. My camera comes with its sdk.
Meanwhile I changed the code in the onUpdate() so:



// get the camera frame
rc = VcGetImage( pImageData, ImageSize, &retLen );
if ( rc == VC_SUCCESS )
{
if( (pixmap->loadFromData( (const uchar*)pImageData, ImageSize )) == true )
emit sig_updateDisplay( pixmap );
else
qWarning("Error loading data");
}

and I always get the error message so seems the problem is in the loadFromData.
Which can be the problem? pImage data contains the frame data and ImageSize is 640*480.

Regards

^NyAw^
27th September 2010, 18:25
Hi,

QPixmap tryies to read an image with a Header(BMP,GIF,PNG, ...).
I supose that your SDK will get your image data directly. Try creating a QImage instead.
The application that I show you uses a QImage as I'm explaining you. I know that you are not using OpenCV but it's the same problem.

franco.amato
27th September 2010, 18:31
Hi,

QPixmap tryies to read an image with a Header(BMP,GIF,PNG, ...).
I supose that your SDK will get your image data directly. Try creating a QImage instead.
The application that I show you uses a QImage as I'm explaining you. I know that you are not using OpenCV but it's the same problem.

Hi,
I changed the code so:



// get the camera frame
rc = VcGetImage( pImageData, ImageSize, &retLen );
if ( rc == VC_SUCCESS )
{
QImage image(640, 480, QImage::Format_Indexed8); //grayscale image
if( image.loadFromData((const uchar*)pImageData, 640*480) == true )
qDebug("Ok");
else
qWarning("Error loading data");
}

and again I always get error

^NyAw^
27th September 2010, 19:03
Hi,

Wich error are you getting? The image is not created or is not displayed?
Think that if you are using 8 bit indexed image you have to create a palette and assing it to the QImage.

franco.amato
27th September 2010, 19:55
I can not display the image.
The loadFromData returns false and I don't know why. The camera give to me frames at 640*480 grayscale frames,
and I can not display them.
Do you have an idea?
Regards,
Franco

wysota
27th September 2010, 20:33
loadFromData() expects a format header. What you need to do is to copy your pixel data directly into the image's pixel buffer (QImage::bits()).

franco.amato
27th September 2010, 20:49
loadFromData() expects a format header. What you need to do is to copy your pixel data directly into the image's pixel buffer (QImage::bits()).

Wysota hi,
I didn't get you.
I understood that QImage::bits() returns a pointer to the pixel data, but how can I set such pixel data?

Thanx

wysota
27th September 2010, 20:56
You can use memcpy().

franco.amato
27th September 2010, 21:01
You can use memcpy().

Is not clear for me, sorry.
I have to copy from the frame bytes to where?
And how can I pass the final buffer to the Qimage?

Regards

I did this:


QImage image( 640, 480, QImage::Format_Indexed8);
uchar* imagedata = image.bits();
memcpy( imagedata, pImageData, ImageSize );
pixmap->fromImage( image );
emit sig_updateDisplay( pixmap );

but I alway get a gray image instead of the frame content.
Is my code correct?

Regards,
Franco

wysota
27th September 2010, 22:06
but I alway get a gray image instead of the frame content.
Is my code correct?
You didn't set a palette for your image.

franco.amato
27th September 2010, 22:44
You didn't set a palette for your image.

I tried this code:


QImage image(640,480, QImage::Format_Indexed8);
QVector<QRgb> colorTable;
for(int i = 0; i < 256; i++)
colorTable.push_back(qRgb(i,i,i));
image.setColorTable(colorTable);
uchar *imagedata = imagedata = image.bits();
memcpy( imagedata, pImageData, ImageSize );

pixmap->fromImage( image );
emit sig_updateDisplay( pixmap );

But again my images are all gray and no frame content is displayed so I imagine
there are other problems :-(

wysota
27th September 2010, 23:07
There is no setPalette method in QImage.

franco.amato
27th September 2010, 23:10
There is no setPalette method in QImage.

Yes please give a look at my changed code in my last post

wysota
27th September 2010, 23:26
You are setting all colors to gray shades so no wonder it all comes out gray. Also make sure the pixel data contains indexes from the palette and not actual colours.

franco.amato
27th September 2010, 23:29
You are setting all colors to gray shades so no wonder it all comes out gray. Also make sure the pixel data contains indexes from the palette and not actual colours.

Sorry but I can not solve this problem alone, please write to me 2 lines of code.

wysota
27th September 2010, 23:32
Here you go:
10 print "I have no idea what you want of me"
20 goto 10

franco.amato
27th September 2010, 23:36
Here you go:
10 print "I have no idea what you want of me"
20 goto 10

Your way to help me is very funny but doesn't help me.


You are setting all colors to gray shades so no wonder it all comes out gray.
The camera gives grayscale images so what I have to set?


Also make sure the pixel data contains indexes from the palette and not actual colours.
I didn't get you with this suggestion.
That's all!!

wysota
27th September 2010, 23:39
Your way to help me is very funny but doesn't help me.
Try expressing your problems better, maybe you will get better answers.


The camera gives grayscale images so what I have to set?
How should I know what you should set? If you are using some sdk, read its docs to see what kind of output it provides.


I didn't get you with this suggestion.
I'm not going to teach you what is the internal structure of indexed and full colour images. You have all the Web to find it out yourself. When you do that you will know what I am talking about.

franco.amato
27th September 2010, 23:45
How should I know what you should set? If you are using some sdk, read its docs to see what kind of output it provides.
There is no much to read.
I have a routine from my sdk that returns 8bits depht images and I WOULD display them.

^NyAw^
28th September 2010, 09:31
Hi,


I tried this code:


QImage image(640,480, QImage::Format_Indexed8);
QVector<QRgb> colorTable;
for(int i = 0; i < 256; i++)
colorTable.push_back(qRgb(i,i,i));
image.setColorTable(colorTable);
uchar *imagedata = imagedata = image.bits();
memcpy( imagedata, pImageData, ImageSize );

pixmap->fromImage( image );
emit sig_updateDisplay( pixmap );



Have you tryied to save your image to disk and check if it is correct?

franco.amato
28th September 2010, 20:56
Hi,
effectively the saved image ( *.bmp ) is all black.
I tried to use an IplImage structure so:


// Intel structure
IplImage* m_cameraImage;
// get the preview image
rc = VcGetImage( pImageData, ImageSize, &retLen ); //in pImageData I should have the frame content of ImageSize bytes

if ( rc == VC_SUCCESS )
{
m_cameraImage = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 1);
m_cameraImage->imageData = pImageData;
cvFlip( m_cameraImage, m_cameraImage, -1);// rotate the image (180º)
cvNamedWindow("image");//create a simple window to show the frame
cvShowImage("image", m_cameraImage); //show the frame content
}

and I can show the frames without problems, so I think the problem is the QImage

wysota
28th September 2010, 21:00
Is the created image RGB or HLS or YUV or...?

franco.amato
28th September 2010, 21:23
Is the created image RGB or HLS or YUV or...?

I used this code to save the image with QImage:



rc = VcGetImage( pImageData, ImageSize, &retLen );

if ( rc == VC_SUCCESS )
{
QImage image(640,480, QImage::Format_Indexed8);
QVector<QRgb> colorTable(256);
for(int i = 0; i < 256; i++)
colorTable.push_back(qRgb(i,i,i));
image.setColorTable(colorTable);

uchar *imagedata = imagedata = image.bits();
memcpy( imagedata, pImageData, ImageSize );

image.save("foo.bmp"); //THIS IMAGE HAS ALL PIXELS OF BLACK COLOR AND DOESN'T CONTAIN THE CAMERA'S FRAME

pixmap->fromImage( image );
emit sig_updateDisplay( pixmap );
}

franco.amato
28th September 2010, 23:25
I solved my problem passing through OPenCV and a IplImageToQImage routine so:


// get the camera frame
rc = VcGetImage( pImageData, ImageSize, &retLen );

if ( rc == VC_SUCCESS )
{
m_cameraImage->imageData = pImageData; //m_cameraImage is a IplImage*
emit sig_updateDisplay( m_cameraImage );
}

else
{
// error - camera disconnected?
VcClose();
m_fVcOpen = 0;
}

Where the signal sig_updateDisplay is connected to the onUpdateDisplay slot:


void VistaIrisCollector::onUpdateDisplay(IplImage* frame )
{
ui.display->setImage( frame ); //ui.display is a QWidget
ui.display->update();
}

and finally the setImage:

void CCameraRenderer::setImage(IplImage* frame)
{
image = IplImageToQImage( frame ); //image is a QImage
m_pixmap = QPixmap::fromImage(image);
}

I'm sure is not the better code but at least I can see the frames of my Vista Imaging camera

wysota
28th September 2010, 23:28
I used this code to save the image with QImage:
Your reply has nothing to do with what I asked you about. I was asking about the format of images the camera sdk returns.

franco.amato
28th September 2010, 23:40
Your reply has nothing to do with what I asked you about. I was asking about the format of images the camera sdk returns.

I set the camera to return rgb 8 bits grey scale images