Canvas-based image helpers. Each transform returns an offscreen canvas rather than a data URL,
so several of them can be chained without encoding and decoding a PNG at every step.
Prefers ctx.filter (GPU-accelerated); where unsupported it falls back to rewriting the alpha
channel pixel by pixel. The fallback skips pixels whose alpha is already 0, so fully transparent
regions cannot pick up a non-zero value.
Build a 2D Gaussian weight matrix, normalised so the weights sum to 1.
Normalisation is required: without it, convolving with the matrix changes the image's overall
brightness. sigma defaults to radius / 3, at which point the Gaussian has decayed to nearly
zero by the radius, so the truncation error is negligible.