PDA

View Full Version : Convert RAW 8 bit pixels into a QImage



danielperaza
9th March 2008, 02:06
Hi, I would like to know how can I convert an array of unsigned chars which represents a grayscale image in raw format into a QImage object, since I have been trying with Qt's QImage::loadFromData() unsuccessfully. Also, if there is any source of information on Qt's native image processing API, please let me know because Trolltech's official C++ Qt GUI Programming with Qt has become not enough for me.

jpn
9th March 2008, 08:15
QImage::loadFromData() expects the data to contain a header. Just construct a QImage object with suitable size and format and access its bits().

pherthyl
9th March 2008, 19:13
Hi, I would like to know how can I convert an array of unsigned chars which represents a grayscale image in raw format into a QImage object, since I have been trying with Qt's QImage::loadFromData() unsuccessfully. Also, if there is any source of information on Qt's native image processing API, please let me know because Trolltech's official C++ Qt GUI Programming with Qt has become not enough for me.

This is how I do it:



uchar** currImageData = &(frameData.value(frameName)->imageData);

// check if the frame dimensions have changed
if(!(*currImageData) || frame->width != frameData.value(frameName)->width || frame->height != frameData.value(frameName)->height) {
if(*currImageData) {
qDebug() << "deleting data";
delete[] *currImageData;
}
qDebug() << "allocating" << frame->nChannels << " channel image of size" << frame->width << frame->height << "and depth" << frame->depth;
imageHeight = frame->height;
*currImageData = new unsigned char[4*imageWidth*imageHeight];
for(int i = 0; i < imageWidth*imageHeight; i++) {
(*currImageData)[i*4+3] = 0xFF;
}
}

int pixels =frame->width * frame->height;

uchar* src = (uchar*)(frame->imageData);
uchar* srcEnd = src + (frame->nChannels*pixels);
uchar* dest = *currImageData;
if(frame->nChannels == 3) {
do {
memcpy(dest, src, 3);
dest += 4;
src += 3;
} while(src < srcEnd);
}
else if(frame->nChannels == 1) {
//qDebug() << "single channel";
int index = 0;
do {
// RGB pixels are written with the same value
memset(dest, *src, 3);
// increment past alpha
dest+=4;
// increment source to next pixel
src++;
index++;
} while(src < srcEnd);
}
}
}


The first part is just memory allocation for the data, then it copies it (depending on the number of channels) and when you want a QImage from that data you can use the QImage constructor that takes uchar* data and give it the correct dimensions.

spud
10th March 2008, 15:53
I would follow JPN's suggestion, but using QImage::scanLine() like this:


QImage image(width, height, QImage::Format_Indexed8);
for (int y = 0;y<height; y++)
memcpy(image.scanLine(y), rawData + y*width, width);

The problem with QImage::bits() is that Qt might add padding to each row to align the rows to 32 bits.

Then you need to set the Color table like this:


QVector<QRgb> colorTable(256);
for(int i=0;i<256;i++)
colorTable[i] = qRgb(i,i,i);
image.setColorTable(colorTable);