Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Help optimize (or properly load) multiple images into a QListWidget (out of memory issue)



  • So I'm doing a small project, now I need to implement a simple image viewer (like a thumbnail list). I don't need anything fancy.

    A little background of what I'm trying to do:
    I need to be able to select a QListWidgetItem (thumbnail) and get it's name, image has a unique value associated with it, so I'm using it's name to acess these values on a matrix (which holds the filename and the value) and also be able to zoom the thumbnail when I click it (open full image on a floating widget for example).

    So I tried to implement a QListWidget to load my images (load a QListWidgetItem using Qicon). My issue is that my implementation is using too many resources and I get the error "QImage: out of memory, returning null image".

    I shouldn't have to load too many images (maybe max 400 in worse case possible) but I'm loading .tiff files and they are big-ish (400mb for 120 files) so I need some optimization.

    I tried to search this forum for solutions, I know there are multiple topics, I read that I should sub-class my QListWidget to have scroll slots, then I would only load the images that are in view (instead of loading all of them at the same time), maybe there are simpler solutions.

    The thing is that this is the first time I'm using QT and I'm having issues not to load all images at the same time. So I'd like to know if there is a simpler solution or if I could get some help / directed to a topic where this was clearly explained with full codes etc.

    Here is my very simple prototype code, when I have my real implementation I should only open a few of these images, not all of them, but before going further I'd like to fix this no memory issue.

    QDir directory("E:\\OneDrive\\Documentos\\TCC\\imagens");
    QStringList images = directory.entryList(QStringList() << "*.tif",QDir::Files);
    QFileInfo fi = new QFileInfo;
    
    if ( !images.empty() )
    {
        foreach(QString filename, images)
        {
            fi.setFile(filename);
            ui->displayList->addItem(new QListWidgetItem(QIcon("E:\\OneDrive\\Documentos\\TCC\\imagens\\"+filename), 
            fi.fileName()));
        }
     }
    else
       qDebug() << "Failed to load images";

  • Lifetime Qt Champion

    Hi
    QIcon keeps the full resolution image and will
    then give out scaled copies for various icon sizes.
    ( good concept in many cases )

    So you did the right thing and use QPixmap where you manually scaled the original image.
    In this case, only the thumbnails are left and hence the memory use is drastically lower.



  • If I don't use QIcon when inserting the QListWidgetItem and instead insert QPixMap scaled objects it works.

    My program was using almost 1gb of RAM before crashing, now it's about 50mb after loading all the images.

    Not sure what I was doing wrong with QIcon, if I understand correctly scaled( ) returns a copy of the image, I imagine this copy is smaller and lighter to load?
    So this doesn't break the memory usage when loading multiple images, on the other hand I have to scale all of the images before inserting, so might be a better way to solve, but I'll stick with this for now.

    QDir directory("E:\\OneDrive\\Documentos\\TCC\\imagens");
    const QStringList images = directory.entryList(QStringList() << "*.tif", QDir::Files);
    
    ui->displayList->setViewMode(QListView::IconMode);
    ui->displayList->setIconSize(QSize (250, 192));
    
    if ( !images.empty() )
    {
        foreach(const QString filename, images)
        {
            QListWidgetItem* tempItem = new QListWidgetItem(filename);
            QPixmap tempImage("E:\\OneDrive\\Documentos\\TCC\\imagens\\"+filename);
            tempItem->setData(Qt::DecorationRole, tempImage.scaled(250,190,Qt::KeepAspectRatio));
            ui->displayList->addItem(tempItem);
    
            //ui->displayList->addItem(new QListWidgetItem(QIcon(tempImage), fi->fileName()));
            //ui->displayList->addItem(new QListWidgetItem(QIcon("E:\\OneDrive\\Documentos\\TCC\\Imagem JPG\\"+filename), fi->fileName()));
        }
     }
    else
       qDebug() << "Failed to load images";

  • Lifetime Qt Champion

    Hi
    QIcon keeps the full resolution image and will
    then give out scaled copies for various icon sizes.
    ( good concept in many cases )

    So you did the right thing and use QPixmap where you manually scaled the original image.
    In this case, only the thumbnails are left and hence the memory use is drastically lower.



  • @mrjj

    I see, thank you. I'm going for that route then