在 Qt 中使用 FreeImage

Using FreeImage with Qt

我有一段 C++/Qt 代码,我想在其中使用 FreeImage 库 (http://freeimage.sourceforge.net/) 加载图像并将最终结果存储在 QImage 中。我知道 Qt 可以直接加载一堆图像格式,但我希望能够直接加载一些 Qt 不支持的格式......我尝试了各种方法让它工作,但是 none他们工作。

在我展示我的一些失败尝试之前,这是对所有尝试都相同的其余函数。下面的代码片段只是复制并粘贴到这个函数中:

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] ....

}

我的前两次尝试非常相似。第一个尝试将图像加载到 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;

第二个大致相同,但使用 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();

我的第三次尝试是尝试让 FreeImage 以 JPEG 格式将图像保存到内存中,然后在构建图像之前将其加载到 QByteArray 中:

    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 这些尝试都奏效了。我检查它是否早些时候失败了,但直到最后我获得 NULL 图像时它才 return 任何错误。但是,我不确定我是否以正确的方式思考它......有人知道我可以尝试什么 ideas/hints 吗?

好吧,其实我自己解决了:)

这个解决方案和我上次的尝试有点相似,它涉及将加载的图像保存到内存(确保它是 24 位图像后)和 "acquiring" 内存(仍然是 FreeImage),之后它可以加载到 QByteArray 中准备好由 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);

}