If you call getImageData for you basically copy over the entire canvas for every single pixel. What's more efficient is calling getImageData once with the entire image array, then going over the pixels
That works much better now. thanks for your help. I did have some issues for a while because I'm on a retainer display so the original image is larger. so I added a conditional to .drawImage to adjust the original height and width based on the device pixel ratio.
Ah yeah, sorry I always forget to include checks for retina displays, not having one myself. Glad I could help out, and thanks for making such a cool notebook in the first place!