I’m new to JUCE and I’m trying to implement a drawing canvas in which I can pan and zoom. My first try was to create a new Component class called Canvas that stored an image. The main issue I have now is the zooming and the panning. I tried using the rescale method of the Image class but of course it changes the quality of the image a lot, so it’s not a suitable method. My next thought was to use a Viewport for the panning feature but still, I have no idea on how to implement the zooming.
And another problem I have is when I draw my strokes (between lastX and lastY) with a big line thickness, I got this stange behavior:
TL;DR:
To implement rescaling, the only sensible approach (outside of very specific bandlimited situations) is to store all your paint events as paths instead, redrawing them when rasterization changes. Or any other structure allowing you to interpolate/resample your discrete mouse events into continuous functions. This will also solve your other problem.
Bla bla:
The above rendering is correct, given the information you provide it. Consider your algorithm: You tell it to paint rectangles once in a while, not curves. Your algorithm will only look like a perfect curving rasterization if the distance between your mouse events is so small that any angle curvature will be covered by adjacent rectangles. The resolution required is inversely propertional to your sample frequency, ie. 1/x. When you draw with a line width of 1, you have sufficient information to reconstruct any representable curve on a quantized pixel grid.
so what could be a good solution according to you for my rendering issue ? I remember doing the same thing in Qt with rounded lines without the same issue. I thought about placing a circle at the beginning and end of the line , but the issue I’ll encounter then will be with line transparency, the circle will be alpha blended on top of the line (or on the bottom depending on the order) and this is clearly something I don’t want.
I tried this but it’s very slow (not surprised :p)
If I were to write such thing, I would have the path as member variable. Instead of having the image cached, just call strokePath in the paint. The positive effect (additional to speedup) is, you can scale without rasterisation artefacts.
The scaling is simply done by using an AffineTransform at strokePath.
No, you’re misunderstanding. Daniel’s suggesting you draw the entire thing as a single Path, which is the only way this could possibly work. If you just draw each line segment separately, then of course it’ll get the result you see above - the same would be true for any drawing API that exists. The only way to create a seamless stroke is to build the whole path and rasterise it in a single operation.
So indeed drawing the whole path resolve the visual issue but slows everything because for each mouseDrag I’m obliged to clear the image (fillRect, and by the way I want to render to an image) and stoke the path (with all the previous points). The path is quickly filling the memory with a bunch of points and it takes more time to render.
Thank you very much for your help, it will help me for sure !
So I’ll draw on the component directly. Is there a way then to save the current painting state as an image ?
Finally what I’ve done (and it’s not slow) is a ‘kinda’ brush system because I wanted to take the pressure into consideration. The cool thing is that now I can define a brush shape. It’s still not optimized but here is the result.