What is the point of ImageCache if it constantly dumps the images?

I don’t quite understand how this is supposed to work…

I have an App Logo image in the upper corner of my app; I want to create the image one time, and then just get it from the ImageCache when it needs to be redrawn

int dataSize = 0;
const char* resourceName = "kmoLogo_png";
 
auto hashCode = (juce::String(resourceName) + "_iconCacheSalt").hashCode64();
auto appIcon = juce::ImageCache::getFromHashCode(hashCode);
if (appIcon.isNull())
{
	const char* imageData = BinaryData::getNamedResource(resourceName, dataSize);
	appIcon = ImageFileFormat::loadFrom(imageData, (size_t) dataSize);
	ImageCache::addImageToCache(appIcon, hashCode);

	DBG(“create new image”);
}

g.drawImageWithin(appIcon, iconRect.getX(), iconRect.getY(), iconRect.getWidth(), iconRect.getHeight(), RectanglePlacement::centred  );

The problem is, the image is apparently released from the cache after a certain period (by the Timer in ImageCache), and debugging shows it is constantly being recreated
Am I misunderstanding the concept? Why does the timeout default to removing an image after about 5 seconds? I suppose I could just call ImageCache::setCacheTimeout() with some really large integer, but why does it work like this?

Related:

1 Like

The image data is already in memory (BinaryData), so the normal pattern would be to use the higher level ImageCache::getFromMemory vs. interacting directly with the cache, I think. But it’s a good question about the timeout. Is it 5 seconds after the last juce::Image goes out of scope?

Actually, I didn’t show it, but the main reason I do it that way is because on Windows I’m using the gin module to resize the image before adding it to the cache, for better results.

        auto iconRect = getLocalBounds();
        int dataSize = 0;
        const char* resourceName = "kmoLogo_png";

        // since we are using gin (on WINDOWS), we must add and retrieve the image
        // from/to the cache manually with a hashcode, which makes this whole thing more complicated
        auto hashCode = (juce::String(resourceName) + "_iconCacheSalt").hashCode64();
        auto appIcon = juce::ImageCache::getFromHashCode(hashCode);

        if (appIcon.isNull())
        {
            const char* imageData = BinaryData::getNamedResource(resourceName, dataSize);
            
        #if WIN_VERSION // - use gin
            auto ginScaleFactor = 2; 
            auto image = ImageFileFormat::loadFrom(imageData, (size_t) dataSize);
            appIcon = gin::applyResize(image, iconWidth * ginScaleFactor, iconWidth * ginScaleFactor); // double-size
        #else
            appIcon = ImageFileFormat::loadFrom(imageData, (size_t) dataSize);
        #endif //WIN_VERSION
            ImageCache::addImageToCache(appIcon, hashCode);
        }

        g.drawImageWithin(appIcon, iconRect.getX(), iconRect.getY(), iconRect.getWidth(), iconRect.getHeight(), RectanglePlacement::centred  );

But yes, for some reason the default timeout is 5 seconds and I don’t understand what use case this is for, then… I assumed it was so you don’t have to keep recreating images…

https://docs.juce.com/master/classImageCache.html#a7e8f2a2260acf7ca4f4a62c36ce99332

I’m also curious. To me the short timeout and the history going back 17+ years indicates that the existence of ImageCache is to resolve a specific internal need (e.g. sharing an underlying image vs. allocating new memory when image is used in more than one place) vs. being a good generalized solution. But I don’t have experience with it directly.

Unless appIcon is being used in multiple places, could you keep things simple and persist it as a member variable of the component?