Best way to "animate images" in Juce

Hey Folks,

while doing a bit of plugin development, I decided to make the LookAndFeel of the plugin I am doing right now quite funny.

So the idea is to have kind of an Avatar, thats “animated”. Animated in the sense of:

if (thisSlider == 0)
Image = Image1
else
Image = Image2

(really simplified)

Think of SAUSAGE FATTENER and the SAUSAGE that corelates with the “fatness” knob. :smiley:

The avatar does different poses - These are all single .png Images for now.

First, I feel like the Images lose Quality when beeing rescaled…

And second, would there not be a simpler way to animate the Images, instead of Setting the Image to a different Image at different conditions and then “repaint()” ?

Maybe someone has an idea for that.

Thanks for reading,

Franz

Yes, that is unfortunately the case. Plus you have only discrete versions of it.

That is already the simplest. The repaint is a discrete event, and only you can provide a state.

The best way to start is to create a procedural version of primitives, where you can use a parameter. Pull it together with Graphics::drawXX commands, that way you can have smooth transitions. Later you can start becoming fancy, adding gradients, shadows etc.

Maybe start with a smiley and have the mouth like:

float smile = 1.0;  // -1.0 .. 1.0
Path p;
p.addEllipse ( 50, 50, 30, 40);
p.addEllipse (120, 50, 30, 40);
p.startNewSubPath (50, 100);
p.cubicTo (100, 100 + 20 * smile,
           100, 100 + 20 * smile,
           150, 100);
g.setColour (Colours::grey);
g.strokePath (p, PathStrokeType (4, curved, rounded), AffineTransform::translated (-4, 4));
g.setColour (Colours::green);
g.strokePath (p, PathStrokeType (4, curved, rounded));
2 Likes

You can use “Filmstrips” - that is: One single image consisting of multiple equal-sized images stitched together horizontally or vertically. Then you can easily select the correct image from the filmstrip, based on the value of a float parameter.

1 Like

float parameter is the keyword here. This technique exists and works, but only for discrete values (opposite of floating point). It works like a flip-book, so you won’t get smooth transitions between values.

But if you are ok with a discrete number of states and you are prepared to provide an image for each state, that is also a good technology.

1 Like

From the question, I figured this would be the case. Drawing dynamically is not always possible or practical. Both in terms of speed and image fidelity/style.

1 Like

You are absolutely right, didn’t mean to be disrespectful. That is a valid approach and often used.

I just have my preference :wink:

2 Likes

Thanks for the answers, you two. :slight_smile:

Both are good approaches.

@daniel Is the loss of Quality Happening for all Images in Juce? Or only for the rescaled ones?

How do you guys think did the sausage fattener People do this, with rendered Images or by drawing the sausage in the Code itsself? :smiley:

That is not JUCE specific, but all bitmap graphics will have artefacts when they are rescaled. They happen less noticeable for power of two scale factors.
You can draw without scaling, but then you are bound to a certain size of your editor. You cannot have resizable UI, which is something to aim for nowadays.

For me the killer feature for vector is, you can scale it on any dpi, vs. with bitmaps, when machines use higher resolutions in the future, you might have to re-do the bitmaps.

In fairness, vector graphics also result in an antialias effect, which is also a slight blur, but since the mathematical model is known, it can still be rendered much more precise than the pixel scaling.

I haven’t used the Saussage Fattener myself. But most of the time, if it is comic art it is often vector graphics, if it is photo realistic, it is often bitmaps.

I have seen crafty people doing photorealistic vector graphics, that are amazing.

One link I found here:

There were more amazing screenshots I can’t find right now…

Thanks! That helps :slight_smile:

You mentioned vector graphics. I know SVG as a vector graphic format… can I use .svg in JUCE as a Vector Graphic? Is this possible or do I really have to redraw that cartoon with code? :sweat_smile:

Wow, that GUI is really awesome… and that all painted with JUCE…

Yes, you can use Drawable::createFromImageData(). That reads SVG into a tree of Drawables from BinaryData, that you can draw using drawable.drawAt (g, …);.

And they are much smaller in memory than bitmaps.

By using the AffineTransform, you can do the rotation for a knob for example…

2 Likes

Awesome. That’ll work for me.

Thanks for your time, folks :slight_smile:

The rescaling is done with interpolation (and you can choose different quality settings). I found with using source images that are much larger than you need and scaling down there isn’t a loss of quality (but maybe my threshold for what constitutes “loss of quality” is much higher than yours :smile: ).

1 Like

We use 2x oversampled images for our knobs and sliders. That way, we can draw them on Hi PDI screens in their original resolution and scale them down for normal screens.

What I found is that scaling down by more than 2x can result in realy ugly moire artifacts when the image has small patterns that can not be resolved by the lower resolution. This was with the highest resampling quality selected. When I scale down the same image in Gimp to the same target resolution, the result was much prettier. Here, there was no moire, the pattern was simply blurred, as one would expect.
I worked around that by scaling the original image down so that I never have to downsample by more than 2x, but I would prefer a better resampling algorithm.

hey again @daniel !

I wrote down the line “std::unique_ptr testDrawable (Drawable::createFromImageData(BinaryData::testone_svg, BinaryData::testone_svgSize));”

But right now I cannot figure out how to use the drawAt function you mentioned…

I thought I would go with something like testDrawable.drawAt, but this does not seem to work o:

Franz

Can you specify what means “does not work?”
Does not compile?
Does not link?
Doesn’t show up?
Crashes?

since testDrawable is an unique_ptr, testDrawable.drawAt wouldn’t compile, you would need to use testDrawable->drawAt(...)

Yeaah, just figured it out!
Coming from C#, I forgot about the arrow that I need to use for a pointer, how dumb :smiley:

Thanks anyway :slight_smile:

Ah cool, wasn’t sure, if that was literally what you were calling

1 Like