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

QQuickImageProvider: images are not updated (cache not released ?)



  • Hi,

    i need to display .tga files in QML.
    i use QQuickImageProvider to load .tga images and it works.
    But if i modify the .tga file outside my application and if i try to load it again, the image is not updated.
    i have read in this documentation that images returned by a QQuickImageProvider are automatically cached and i need to set "cache:false" property in my qml image.
    https://doc.qt.io/qt-5/qquickimageprovider.html#details

    But it does not work. If i reload the same image, modifications are not displayed.
    Here is my QML code:

    Image
    {
    	id: idImg
    	width : 256;height:256
    	cache: false
    	source : "image://TGAImageProvider/C:/temp/image.tga"
    }
    
    Connections
    {
    	target:cppOwner
    	onNewImageGenerated:
    	{
    		idImg.source = "image://TGAImageProvider/C:/temp/image.tga";
    	}
    }
    

    My QQuickImageProvider code is something like that:

    QPixmap TGAImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
    {
    	QString fileName = id;
    
    	data = loader.LoadFromFile((char*)fileName.toStdString().c_str(),(unsigned char*)data);
        if( data == NULL )
        {
            return false;
        }
    
        QImage::Format bpp =  QImage::Format_RGB888; // Format RGB
        if( loader.BPP == 4)
            bpp = QImage::Format_RGBA8888; // Format RGBA
    
        QPixmap pixmap = QPixmap::fromImage(
            QImage(
                (unsigned char *) data,
                loader.width,
                loader.height,
                loader.bpp
            )
        );
    
        free(data);
        data = NULL;
        return pixmap;
    }
    

    i use QT 5.8



  • @Greg13 Yeah. There's an image cache (I think more of a texture cache) inside QML.

    The key is the URL. Several of my slightly weird apps, notably my pixel painter hit this and I had to work around it. You'll probably notice that your loader isn't even invoked if image.source is assigned the value already in image.source.

    The thing to do is to keep a "cache key" and append that to the URL. It doesn't actually matter what it is (time might be a good example or a monotonically incrementing counter). Your loader can ignore it but it means that the URL differs and thus you won't pick up cached "duff" values.

    I have some demo code I can upload to GitHub but please forgive the quality of it as I haven't had time to finish it to my satisfaction. It is actually based on getting an image from the camera to an SQLITE table and back again but shows some of the principles.

    https://github.com/kuiash/qml_sqlite_camera_database



  • Thanks @matthew-kuiash
    I will try that.

    But according to the documentation "cache:false" should prevent QML to cahe texture... How many Giga of texture memory does QML store before releasing memory... !?


  • Qt Champions 2018

    cache: false does indeed prevent to cache image textures.
    Your problem is that you don't actually change the source of the image so the engine doesn't know that it has to reload it.

    To force a change you could do:

    Connections {
        target:cppOwner
        onNewImageGenerated: {
            idImg.source = "";
    	idImg.source = "image://TGAImageProvider/C:/temp/image.tga";
        }
    }


  • @GrecKo i try your solution. It does not work. Even if i display another image.



  • @GrecKo I haven't used this property and I'm not quite sure what the docs imply.

    "Setting cache to false is useful when dealing with large images, to make sure that they aren't cached at the expense of small 'ui element' images."

    Does this mean no caching at all or does it mean that the image is not cached only in texture memory? I'm not sure.


Log in to reply