If you let context2d() handle the scaling of the canvas, you must call ctx.resetTransform() before .drawImage().
I also recommend to always set ctx.canvas.style.maxWidth = '100%'
For the record, none of these things fix the drawing behavior on my Linux FF machine. I guess it's one of those Canvas API inconsistencies that enables fingerprinting