[Qt-jambi-interest] Instantiating 'QImage(byte[], ..)' in a loop crashes the Java-VM
Gunnar Sletta
gunnar at trolltech.com
Mon Nov 17 09:28:03 CET 2008
> I'm experimenting with a tool to visualize raw image data (i.e 14bit grey
> values) using a QImage with 'Format_RGB32', following I convert the raw data to a
> byty[] array with 4 byte rgb data.
> To support playback I instanziate the images with
> 'image = new QImage(imgRgbBuf, 128, 128, QImage.Format.Format_RGB32);'
ouch... this function should not have been in the API. It cannot be used
without causing crashes.
The problem is that the image buffer that you pass to QImage on the C++
side is a "unsigned char *" which has to remain valid throughout the
lifetime of the original QImage. What happens to the byte[] buffer is
that it is converted to a memory managed temporary unsighed char * and
if GC kicks in between when you constructed the QImage and when you draw
it, it will crash.
The right function to use is the overload that takes a QNativePointer,
where you manually build up and preserve the databuffer until after the
QImage is gone.
QNativePointer data = new QNativePointer(QNativePointer.Int, width *
height);
// fill data with some pixels, the below should be
// a green / blue gradient
for (int y=0; y<height; ++y) {
for (int x=0; x<width; ++x) {
data.setIntAt(y * width + x,
0xff000000
| (x * 255 / width)
| ((y * 255 / height) << 8));
}
}
QImage image =
new QImage(data,
width,
height,
width * 4, // bytes per line: 1 int == 4 bytes
QImage.Format.Format_RGB32);
// use the image for what you need it for..
painter.drawImage(0, 0, image);
// Make sure we data outlives the image
image.dispose();
data = null;
pixel manipulation with QImage is rather tedious because of the C++ /
Java bridge, unfortunately.
I'll deprecate this function for the next release.
best regards,
Gunnar
More information about the Qt-jambi-interest
mailing list