PDA

View Full Version : QImage::loadFromData() behaviour



Caius Aérobus
19th November 2007, 15:51
Hello,
below a piece of code, which consists in loading image data in false color mode (or at least this is what I expected to do!) and retrieving them immediatly. I have deleted additionnal code, which includes a color table construction, to be attached to the image.
I obviously make a mistake somewhere or more likely I have not understood the way QImage interprets the raw data. I have not found any response to this specific problem in reading the various posts on loadFromData method, including http://www.qtcentre.org/forum/f-qt-programming-2/t-creating-a-qimage-from-uchar-data-5413.html/?highlight=loadFromData so this is the reason I create a new topic.
Thanks in advance for your help.

Code:



this->Print("size is (%u,%u)", size[0], size[1]);
uchar *data;
if ((data = (uchar *)malloc(size[0]*size[1]*sizeof(uchar))) == NULL) {
this->Error("memory allocation error (%d)", size[0]*size[1]*sizeof(uchar));
return;
}
QImage *image = new QImage(QSize(size[0], size[1]), QImage::Format_Indexed8);
for (int j=0 ; j<size[1] ; j++)
for (int i=0 ; i<size[0] ; i++)
data[j*size[0]+i] = i==0 && j==0 ? 255 : 0;
for (int j=0 ; j<size[1] ; j++) {
for (int i=0 ; i<size[0] ; i++) {
this->Print(" %u\r", data[j*size[0]+i]);
}
this->Print("\n");
}
image->loadFromData(data, field.size());
for (int j=0 ; j<size[1] ; j++) {
for (int i=0 ; i<size[0] ; i++) {
QRgb rgb = image->pixel(i, j);
this->Print(" %u\r", image->bits()[j*size[0]+i]);
}
this->Print("\n");
}


Output:



wlFieldImage: size is (4,4)
wlFieldImage: Original values:
wlFieldImage: 255 0 0 0
wlFieldImage: 0 0 0 0
wlFieldImage: 0 0 0 0
wlFieldImage: 0 0 0 0
wlFieldImage: Extracted values:
wlFieldImage: 40 59 19 8
wlFieldImage: 0 0 0 0
wlFieldImage: 216 103 12 8
wlFieldImage: 184 193 9 8

^NyAw^
19th November 2007, 16:30
Hi,

Maybe you have a problem setting the data using integers. "data" is defined as "uchar*" and you are indexing it using "ints".
The first pixel must be "data", second pixel "data+1 (byte)", and so on. One integer is 32 bytes so you are jumping to a different position.

Is this your problem? I had been using QImage like you one year ago and I made some similar error.

Caius Aérobus
19th November 2007, 17:11
Hi,

Maybe you have a problem setting the data using integers. "data" is defined as "uchar*" and you are indexing it using "ints".
The first pixel must be "data", second pixel "data+1 (byte)", and so on. One integer is 32 bytes so you are jumping to a different position.

Is this your problem? I had been using QImage like you one year ago and I made some similar error.

indexing cannot be done but with ints! :)
Your error was probably more likely something like this:
int *p = data;
for (...)
*p++ = some value;
or int *data then loadFromImage(data, ....)
which is of course a mistake.
But nothing wrong in adressing the data in my code...unfortunately because my error remains :(

^NyAw^
19th November 2007, 17:23
Hi,



But nothing wrong in adressing the data in my code...unfortunately because my error remains


So nothing is wrong but it doesn't works. What are you expecting the code do?

Caius Aérobus
19th November 2007, 18:02
Hi,



So nothing is wrong but it doesn't works. What are you expecting the code do?

I am expecting to get the same data I entered before as I extract them using QImage::bits()!

Caius Aérobus
19th November 2007, 18:04
Hi,



So nothing is wrong but it doesn't works. What are you expecting the code do?

I am expecting to get the same data I entered before as I extract them using QImage::bits()!
Actually I build a pixmap from this image and obviously the pixmap is wrong!
That is the reason I checked which data I get from the image and discovered data have been altered during their storage in QImage. So probably this is a normal behaviour but at least:
- I would like to understand this behaviour,
- I would like to know how to create a false color image from a list of color table indexes.

mchara
20th November 2007, 07:04
Hi,
loadFromData method isn't meant to read image from raw pixels matrix, but to read binary data in a specific format, i.e. when you read contents of *.png file and pass it to loadFromData method.

You shall create an empty image with given size & use setPixel to fill it.

If you really want to generate data outside the image, see PPM format - it's matrix of pixel values (with color depth and dimensions at the beginning) but in textual format.

Caius Aérobus
20th November 2007, 10:56
Ok, thanks for these explainations, I will use setPixel() instead.
Regards.

anarsynd
20th November 2007, 17:39
In many situations it is quite slow to loop through the image using setPixel. What I do is to use a constructor that accepts raw data, I cite:

###
QImage::QImage ( uchar * data, int width, int height, Format format )

Constructs an image with the given width, height and format, that uses an existing memory buffer, data. The width and height must be specified in pixels, data must be 32-bit aligned, and each scanline of data in the image must also be 32-bit aligned.
### ref: http://doc.trolltech.com/4.2/qimage.html#QImage-4

mchara
21st November 2007, 06:40
Yeah,
anarsynd is right: constructors data is a raw data, it's not the same as data in loadFromData which is binary image coded to some format, so this is what you need.

Caius Aérobus
29th November 2007, 21:21
Yeah,
anarsynd is right: constructors data is a raw data, it's not the same as data in loadFromData which is binary image coded to some format, so this is what you need.

not exactly because I have to assign new content to the image after it has been constructed, in a slot, and I cannot create a new image because I would have to take care of the image state, which would be complicated, so setPixel() is ok for me, although not so efficient.