drawImage bug?

I just noticed that if I have an Image, and a Graphics object that uses that image (Graphics(myImage)).

Then drawing that image ( g.drawImageAt(myImage,0, 0) ) can fail in a very interesting way.

Specifically, if I alter the image only via the Graphics object, and repaint it (all within the Component::paint method), it won’t actually repaint. I think this is because the system doesn’t know the image as been changed.

I currently get around it by just adding a quick: myImage.setPixelAt(10, 10, Colours::red);

All works as expected, unless I comment that line out, and then it fails to continuously draw.

void myComponent::paint(Graphics& g)
{
    
    myGraphic->fillEllipse(x - dim/2, getHeight() - 30 - dim/2, dim, dim);
    // myImage.setPixelAt(10, 10, Colours::red);  ---> fails to redraw the image, unless this is added
    g.drawImageAt(myImage, 0, 0);
    
}

Why not just store the altered image in your Component class, and keep drawing the stored altered image?

I alter it every time the paint routine is called (which is on a timer).

This code is a simplified case.

Generally speaking, you probably don’t want to count on the rate of paint calls to be something fixed, because the OS/JUCE calls it additional times, or they might stack a few of your repaint() calls together.

Instead, just change the image/do any other stateful operations on a timer (something you control) and then call repaint() for a passive drawing of the already modified state.

//Member variable
Image image;

void timerCallback() override
{
    image = getAlteredImage();
    repaint();
}

I knew you would say this :wink:

And yes, generally I do, but didn’t care in this case about the refresh rate.

In any event, it was just quizzical to me that it would fail in this way … any insight into that?

What kind of graphics context and/or image are you using? IIRC, the OpenGL graphics context may not flush image modifications until the Graphics instance itself is destroyed (more details here). In that case, reusing a Graphics instance across multiple paint calls won’t produce the expected results, because the instance is not destroyed after rendering to the image.

Other renderers might do something similar. To see whether this is the problem, you could try creating a Graphics instance that is local to the function, and that is destroyed before calling g.drawImageAt.

2 Likes

That’s it !!! I figured it was something similar.

Ok, thanks for the clarity, onward :wink:

I assume that the Graphics object is lightweight enough that I should just create a new one for the image each time the timer needs to redraw anything? That way it goes out of scope and redraws properly of course.