I have a piece of C++/Qt code where I want to load images using the FreeImage library (http://freeimage.sourceforge.net/) and store the final result in a QImage
. I know that Qt can load a bunch of image formats directly, but I want to be able to load some formats that are not supported by Qt directly... I tried various approaches to get it to work, but none of them work.
Before I show some of my failed attempts, this is the rest of the function that is the same for all of them. The code snippets below are just copy&paste into this function:
QImage load(QString filename) {
FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(filename.toStdString().c_str(), 0);
if(fif == FIF_UNKNOWN)
fif = FreeImage_GetFIFFromFilename(filename.toStdString().c_str());
if(fif == FIF_UNKNOWN)
return QImage();
FIBITMAP *dib = nullptr;
if(FreeImage_FIFSupportsReading(fif)) {
dib = FreeImage_Load(fif, filename.toStdString().c_str());
if(dib == nullptr)
return QImage();
} else
return QImage();
.... [conversion code comes here] ....
}
My first two attempts are very similar. The first one tries to load the image into a QImage:
int width = FreeImage_GetWidth(dib);
int height = FreeImage_GetHeight(dib);
int bpp = FreeImage_GetBPP(dib);
int size = width * height * (bpp / 8);
BYTE *pixels = FreeImage_GetBits(dib);
QImage img;
img = img.fromData(pixels, size);
return img;
The second one does more or less the same, but with a QPixmap:
int width = FreeImage_GetWidth(dib);
int height = FreeImage_GetHeight(dib);
int bits = FreeImage_GetBPP(dib);
int size = width * height * (bits / 8);
BYTE *pixels = FreeImage_GetBits(dib);
QPixmap pix;
pix.loadFromData(pixels,size);
return pix.toImage();
My third attempt was to try to get FreeImage to save the image to memory as JPEG and then load it into a QByteArray before constructing the image:
FIMEMORY *stream = FreeImage_OpenMemory();
FreeImage_SaveToMemory(FIF_JPEG, dib, stream);
FreeImage_Unload(dib);
long size = FreeImage_TellMemory(stream);
QByteArray array = QByteArray::fromRawData((char*)stream->data, size);
QImage img;
img.loadFromData(array);
return img;
None of these attempts work. I checked to see if it fails earlier, but it doesn't return any error until the very end when I obtain a NULL image. However, I am not sure if I am even thinking about it the right way... Anybody got any ideas/hints what I could try?
Okay, I actually ended up solving it myself :)
The solution is somewhat similar to my last attempt, it involves saving the loaded image to memory (after ensuring it is a 24bit image) and "acquiring" the memory (still with FreeImage) after which it can be loaded into a QByteArray ready to read in by QImage:
QImage load(QString filename) {
// Get image format
FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(filename.toStdString().c_str(), 0);
if(fif == FIF_UNKNOWN)
fif = FreeImage_GetFIFFromFilename(filename.toStdString().c_str());
if(fif == FIF_UNKNOWN)
return QImage();
// Load image if possible
FIBITMAP *dib = nullptr;
if(FreeImage_FIFSupportsReading(fif)) {
dib = FreeImage_Load(fif, filename.toStdString().c_str());
if(dib == nullptr)
return QImage();
} else
return QImage();
// Convert to 24bits and save to memory as JPEG
FIMEMORY *stream = FreeImage_OpenMemory();
// FreeImage can only save 24-bit highcolor or 8-bit greyscale/palette bitmaps as JPEG
dib = FreeImage_ConvertTo24Bits(dib);
FreeImage_SaveToMemory(FIF_JPEG, dib, stream);
// Free memory
FreeImage_Unload(dib);
// Load JPEG data
BYTE *mem_buffer = nullptr;
DWORD size_in_bytes = 0;
FreeImage_AcquireMemory(stream, &mem_buffer, &size_in_bytes);
// Load raw data into QImage and return
QByteArray array = QByteArray::fromRawData((char*)mem_buffer, size_in_bytes);
return QImage::fromData(array);
}