How to find the memory size of a dynamically created Image

I am creating an Image dynamically in several places to speed up redrawing, i.e.:

        myImage = Image(Image::ARGB, bounds.getWidth() * 4, bounds.getHeight() * 4, true);

…using 4x the real size so as to allow the GUI to be scaled up without any visible pixelation.

I’m curious as to how much memory it is using, but I can’t seem to find an easy way to display the amount of memory being used. If I just do a sizeof() on the Image object, it’s 16, which is tiny. I tried a sizeof() on Image::getPixelData() but I must not be doing this correctly either because the number still is tiny and makes no sense. I realize I could probably manually compute this based on height and width, but as I use this in several places, it would be nice to have an easy way to display it.

For an ARGB image, each pixel will use 4 bytes (4 channels, each of 1 byte).

To get the number of pixels you can simply multiply the width by the height.

Some images my have some extra metadata too, but if you’re just creating it in memory like this I don’t think there’ll be any.

So the memory usage should be 4 * width * height.

sizeof returns the size of the object on the stack. Since the actual pixel data is on the heap, sizeof won’t work with juce::Image.

1 Like

Thanks. So let me see if I’ve got this: if the component being drawn this way at 4x resolution, has a bounds of 693 w x 470 h, that would be:

(693 * 4) * (470 * 4) * 4 = 20,845,440
20,845,440 / 1024 / 1024 = 19.879 mb ???

Wow, that’s a lot… gonna have to rethink this…

I think it would just be 20.8mb, they go up by a factor of 1000. I believe it’s bits that uses 1024.

Either way, yes it’s quite a lot but most modern systems will have plenty of memory to spare. Even 4gb is considered a small amount of memory these days so if it’s literally just the one image it won’t make much difference.

@ImJimmi is correct that on a desktop system 20mb is not a big problem. But I would indeed advise against drawing in a oversampled image.
The data has to go each time through the graphics bus. It only makes sense for images that rarely change, but then setBufferedToImage() might already do what you hope for.

And last but not least the conversion between logical and physical pixels and other OS quirks might not play too well with your idea. Chances are you are effectively painting twice each time for no gain.

1 Like

Thanks - I’ve basically already given up on this idea. I have maybe 25 images to do like this, so it’s not a good idea. But let me explain more in case you have more to add:

The issue is that I have an editor with let’s say 25 different editing tabs. I’ve been creating a background for each one automatically by generating a complex path based on the positions of the child components, then filling and stroking the path. The background doesn’t change from when it is first shown. The complex path takes some time to compute.

When I wrote this I was thinking about how to optimize it by making an image out of the results, but I’ve since realized that was the wrong approach and what I am doing now is storing the Path in each editor page, so it only gets created the first time it is shown and after that I can just fill/stroke it.

Would applying setBufferedToImage() actually improve anything in this scenario?

I think what you are doing is already a very good approach. There are more optimisations available:

If the path changes and gets recreated, calling preallocateSpace() seems to help. Reusing like you do is even better ofc.

Drawing rectangles using RectangleList seems to be the fastest operation, that’s why it is used in e.g. AudioThumbnail.

Any further tricks I would investigate once you know you actually have a problem to solve. Premature optimisation and such…

But this list could be continued, if someone knows any other need to know tip…

1 Like