PDA

View Full Version : convert QPixmap to std::vector<unsigned char>



saman_artorious
15th September 2013, 10:05
I get the following when I grab a screen shot:

QPixmap originalPixmap = QPixmap::grabWidget(this);

I need to convert originalPixmap to std::vector<unsigned char>.
The problem I face is when I convert this grabbed pixmap to qbytearray or qbuffer it's value becomes NULL! as an example:


QVariant myPixmap(QPixmap(QPixmap::grabWidget(this)));

QByteArray myByteArray = myPixmap.toByteArray() ;

qDebug() << myByteArray.size(); // 0 size


or


QPixmap originalPixmap = QPixmap::grabWidget(this);

QImage *image = new QImage(originalPixmap.toImage());

QByteArray Array;

QBuffer buffer(&Array);

buffer.open(QIODevice::WriteOnly);

image->save(&buffer);


again returns null string. am I missing something in the code?

ChrisW67
15th September 2013, 10:40
Your entire question presupposes that there is some natural meaning to "I need to convert originalPixmap to std::vector<unsigned char>." You can convert an image into a list of bytes in a near-infinite number of ways. Most of these will not be a "string" in the human readable sense . What exactly are you expecting to see in your array of bytes?

A QVariant of type QVariant::Pixmap is not a QVariant of type QVariant::ByteArray and cannot be magically converted.

In your second example there is no string, so what do you mean by "returns null string"? Line 11 is probably failing because you have not specified the format in which to save() (and there is no file name from which to infer one) but you do not check the return value so we cannot say.

wysota
15th September 2013, 11:18
In addition to what Chris already said, you are doing a lot of totally unneeded conversions and it is not the first time I see them in your code. You are converting a pixmap to an image and then saving it to a byte array. QPixmap has a save() method which can do it directly. Not speaking about memory you spill all over your code.

Instead of inventing weird code for weird data transformations, when asking a question it is better to just state what your goal is and what you already tried to obtain that goal. I doubt your goal is to "convert QPixmap into std::vector<unsigned char>".

saman_artorious
15th September 2013, 12:18
I am using lodePNG library to encode and decode png files. The library take std:vector<unsigned char> image as an input:

unsigned encode(std::vector<unsigned char>& out,
const std::vector<unsigned char>& in, unsigned w, unsigned h,
LodePNGColorType colortype, unsigned bitdepth)

I need to print screen and encode it. Therefore, I asked you how to convert QPixmap to std::vector<unsigned char>.
Furthermore, I have written the following code so far (the problem of getting null was corrected once I specified the image type, thanks Chris)


int width = 400;
int height = 300;

QPixmap originalPixmap = QPixmap::grabWidget(this);
QImage *image = new QImage(originalPixmap.toImage());
QByteArray ba;
QBuffer qbuffer;
qbuffer.setBuffer(&ba);
qbuffer.open(QIODevice::WriteOnly);
image->save(&qbuffer, "PNG");

QByteArray rawPixels = qbuffer.buffer();

int size = rawPixels.size();
char* temp = (char*) rawPixels.constData();

std::vector<unsigned char> imageVector;
imageVector.resize(size);

for(int index = 0; index < size; index++)
{
imageVector.push_back(temp[index]);
}

/* compress PNG */
std::vector<unsigned char> png;
png.resize(size);
unsigned error = lodepng::encode(png, imageVector, width, height);
if(error) qDebug() << "encoder error " << error << ": "<< lodepng_error_text(error);



that's all.

anda_skoa
15th September 2013, 22:06
If your goal is to have the image data encoded as PNG, you are done after line 10.

Even shorter because you can call save on orginalPixmap, no need to explicitly convert to QImage.

You also don't need to set a QByteArray on the buffer because it will do that when being opened for WriteOnly.

Cheers,
_

saman_artorious
16th September 2013, 11:58
If your goal is to have the image data encoded as PNG, you are done after line 10.

Gee, I didn't know that by the end of line 10 the image is compressed! That's why in line 25 I tried to compress the image again. Could you explain why this compressing/encoding is automatically done by the end of line 10 please?

Furthermore, this encoding of line 10 can be proved as the byte array associated with the buffer is only of size 1216! which is much less than the real size, 300(width) * 400(height) * 4(RGB).

Now, is there a qt function to decode png again after line 10? or I need to use the decode function associated with line 25.

Thank you

wysota
16th September 2013, 12:11
Could you explain why this compressing/encoding is automatically done by the end of line 10 please?
libpng does that as part of file saving.


Now, is there a qt function to decode png again after line 10?
Load the file to QImage :)

saman_artorious
16th September 2013, 12:28
Bingo

QImage image((const uchar* )bytes.constData(), 400, 300, QImage::Format_RGB32);
qDebug() << image.byteCount(); // size = 480000

Thank You All :)

anda_skoa
16th September 2013, 13:16
Could you explain why this compressing/encoding is automatically done by the end of line 10 please?


wysota already gave explaination on how it is done, but just conceptually: you are asking the class (QPixmap or QImage) to "save as PNG".
PNG is a compressed format, so in order to create PNG data it needs to be compressed by the image saving code.
Delegated to a plugin which uses libpng, but that is merely a technical detail :)

Cheers,
_