How PNG to JPG Conversion Works in Your Browser
The pipeline starts when your PNG is turned into a Blob URL and handed to an HTMLImageElement. The browser's PNG decoder inflates the DEFLATE-compressed scanlines — undoing the filters, decoding the zlib stream, and reassembling an RGBA bitmap. Nothing about this touches the network: PNG decoding is built into every browser engine and happens in native code before any JavaScript runs. Once the image fires its onload event, the decoded dimensions are read from naturalWidth and naturalHeight and used to size a Canvas 2D context.
The critical step is the color-space handoff. Because JPEG has no alpha channel, the code first paints the entire canvas opaque white with ctx.fillStyle = '#ffffff' followed by a full-canvas fillRect(). Only then is the decoded bitmap composited with drawImage(), so semi-transparent edges blend against white exactly as they would in a real compositor. Calling canvas.toBlob(..., 'image/jpeg', 0.92) hands the RGBA buffer to the browser's native JPEG encoder, which converts to YCbCr, applies 4:2:0 chroma subsampling, runs the 8×8 block DCT, quantizes at the requested 92% quality, and writes entropy-coded output into a Blob.
For images that arrive as true RGBA, the encoder discards the alpha plane during the YCbCr conversion; for an opaque PNG the output is simply a re-encode of identical color values. The decoded bitmap could also be inspected programmatically via getImageData() if pixel-level analysis were needed — but for a straight re-encode, handing the canvas directly to toBlob() avoids an unnecessary RGBA round trip through JavaScript. The result is a standards-compliant baseline JPEG that every browser, OS, and photo application can open, produced with zero server involvement.