All replies

You use a <canvas> element, copy the image to the canvas using its context.drawImage method, make edits using other canvas context APIs, and then get the bits from context.getImageData, which you then pass to an image encoder. Here's a piece of code
from my book (Chapter 10 of the first edition) that shows the process (choosing a file and saving canvas content):

This is just a matter of translating input events (e.g. pointerdown + pointermove + pointerup) into a higher level UI for drawing shapes, etc. via the canvas APIs shown in the article. level API.

I can recommend that that to show the interactive part of drawing a shape that you use a second canvas element overlaid on top of the one with the image. The overlay canvas is where you show the lines, circles, etc. as the user is moving around, and when
they release and thus commit to a shape, you then make the equivalent canvas API calls onto the one with the image.