4 ms·
The speed is achieved by using the fillRect() command with globalCompositeOperation. This is a single draw operation rather than a per pixel algorithm while the
by shaneos 3y ago
The speed is achieved by using the fillRect() command with globalCompositeOperation. This is a single draw operation rather than a per pixel algorithm while the user waits. Anything more involved than this would, I think, be slower as perceived by the user
- TeMPOraL 3y agoMakes me wonder if this could be even faster, if you cheated and just generated copies of the masks already colored, for every color available. From looking at the video, I see you have 10-11 colors available at any given moment with possibility of changing them to, presumably, arbitrary RGB value. That means you only need to keep 11 color variants of each mask, which should still fit in RAM. You also need to be able to replace a single group of masks with a new set of masks faster than the user can switch colors in the custom color picker. (I know, it's a dumb idea in this case; I'm posting it as a reminder to both myself and everyone else, that many problems can be solved by checking or caching every possible state.)
- shaneos 3y agoThe user can select from thousands of colours unfortunately :-) Tap the top left icon in the app, or just play with it for fun! https://kidzfun.art https://kidzfun.art
- TeMPOraL 3y agoSure, but at any given moment, they can use only ~12 of them (+ the rainbow thing, now that I played a bit and know how it works). Meaning, you can keep 12 pre-filled variants of each mask, one for each color on the main palette, and recolor all masks of a given color when the user picks a new one from the top-left color picker. I bet you can do this update faster than they can dismiss the color picker and tap on the canvas. I see you have drawing tools there as well, but they seem to be ignored by flood filling (e.g. if I draw a closed circular border myself and use flood-fill on the empty centre, the fill will just paint over my circle border and continue filling to the boundaries of the initial region of the original image) - so they don't even make a counterpoint I was worrying they would.
- deleted 3y ago[deleted]
- deleted 3y ago[deleted]
- TazeTSchnitzel 3y agoI implemented my suggestion: https://hikari.noyu.me/etc/2023-05-24-js-canvas-software-color-replacement/ https://hikari.noyu.me/etc/2023-05-24-js-canvas-software-col... It seems that doing this per-pixel loop on the CPU in JS is slow, but it's not too bad: the first click might take 300ms, subsequent clicks are just 100ms. While this is about ten times slower than I was hoping, it's still fast enough to seem responsive to most users. This is also at 4K resolution, because I wanted a realistic worst-case. It's much faster at 1080p since it has four times less pixels to work with. You could of course do better with WebGL.
- shaneos 3y agoVery nice - yes that's quite quick and definitely uses less memory. When I tested it on an older iPad and on an Android device the difference in speed between the two approaches is a bit more obvious. Watching my kids bash away at this and expect it to keep up makes me more willing to use extra memory to do so. All that said though, I really like your implementation, it would likely be the right choice for a lot of use cases
- TazeTSchnitzel 3y agoThanks! By the way, I realised just now I was leaving a bit of performance on the table: getImageData() is slow, but I don't need to do it on click, I can do it just once after loading the image. Changing that gets it to be consistently under 100ms for clicks after the first one.