Search code examples
qtbitmaparmqpixmap

QPixmap::load() crash - trying to avoid it


I am working on a project, using Qt 4.8.3 for an ARM platform. In my project, I use QGraphicsItems... one of which is a subclass of QGraphicsPixmapItem.

The code was tested with a 32 bit bitmap image - and it crashes.

The crash occurs not just when running on the ARM, but also in QVFB.

QPixmap p;
if (!p.load(filename))  // crashes here
    return false;

I have tried to surround this with a try...catch, but it did not help.

I seem unable to step in the Qt code for this version... but the crash occurs inside QImageReader::read(QImage*).

The stack trace:

QImageReader::read(QImage*)
QImageReader::read()
QPixmapData::fromFile(QString const&*, QFlags<QT::ImageConversionFlag>)
QPixmap::load(QString const&, char const*, QFlags<QT::ImageConversionFlag>)
QPixmapItem::loadItemFromFile  // mine, the code above

Any other type of image works... and the same 32 bit bitmap loads properly in windows, same Qt version. It fails to load (returning false) in the same Qt version, for Desktop.

I would be happy to exclude this type of file - but I don't know how.

Is there any way to check for the image type without loading the image and avoiding the crash ?

Is there a way to perhaps load the image header only, and verify its type ?


Solution

  • Since you want to exclude 32-bit BMP images, you have to read a BMP header. First two bytes are the characters "BM" and bytes 28, 29 contain bits per pixel.

    Here is a small example where we read a file into QByteArray, check its format and load it to QPixmap if OK.

    #include <QtCore>
    #include <QtGui>
    int main(int argc,char** argv)
    {
        QApplication app(argc,argv);
        QFile file("./plot.bmp");
        if (!file.open(QIODevice::ReadOnly)) return 1;
        QByteArray ba=file.readAll();
        if(ba[0]=='B' && ba[1]=='M' && ba[28] == 32) {
            qDebug() << "Wrong format!";
            return 1;
        }
        QPixmap pixmap;
        pixmap.loadFromData(ba);
        qDebug()<<"OK!";
        return 0;
    }
    

    Or if you don't want to read everything into memory, you can open a file using QFile, ifstream etc, check these bytes and then close it.