Bug 54256

Summary: Improve the compression of Canvas's toDataURL function
Product: WebKit Reporter: Tab Atkins <tabatkins>
Component: CanvasAssignee: Nobody <webkit-unassigned>
Status: NEW ---    
Severity: Normal CC: ap, guanqun.lu, mdelaney7, sam, scottmg
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: PC   
OS: Linux   

Description Tab Atkins 2011-02-10 16:05:40 PST
Canvas's toDataURL function has horrible PNG compression for simple images.  For example, running the following page gets me a data url 2.8kb in size:

<!doctype html>
<script>
var x = document.createElement('canvas');
x.width = 500;
x.height = 500;
var y = x.getContext('2d');
y.fillRect(0,0,500,500);
alert(x.toDataURL().length);
</script>

Saving the generated image and running it through http://www.pngoptimizer.com/ gives me an equivalent image that is only 125 bytes in size.  We should be able to generate images similar in size.
Comment 1 Sam Weinig 2011-02-10 17:34:37 PST
Tab, what platform are you testing on? I believe each port uses its own encoders for this so the knowing the platform is important.
Comment 2 Tab Atkins 2011-02-11 08:48:39 PST
I'm not sure of exactly what info you need, so I'll dump it all.  I'm running Chrome 9.0.597.94 beta on the modified Ubuntu we use in the office.
Comment 3 Alexey Proskuryakov 2011-02-11 09:55:04 PST
On Snow Leopard Safari, I get an alert saying 7274, so I guess that this should be split into at least two bugs.
Comment 4 Scott Graham 2011-07-06 12:15:19 PDT
I get a similar size (7270) now on Ubuntu as of Chrome 13.0.782.41.

The Skia path goes through PNGImageEncoder::encode, which contains the following:

    // Optimize compression for speed.
    // The parameters are the same as what libpng uses by default for RGB and RGBA images, except:
    // - the zlib compression level is 3 instead of 6, to avoid the lazy Ziv-Lempel match searching;
    // - the delta filter is 1 ("sub") instead of 5 ("all"), to reduce the filter computations.
    // The zlib memory level (8) and strategy (Z_FILTERED) will be set inside libpng.
    //
    // Avoid the zlib strategies Z_HUFFMAN_ONLY or Z_RLE.
    // Although they are the fastest for poorly-compressible images (e.g. photographs),
    // they are very slow for highly-compressible images (e.g. text, drawings or business graphics).

It seems sensible to sacrifice base64 size in exchange for encoding speed for cases where the data url is passed directly back into an img tag or similar.

That said, I'm not sure what a good benchmark would be to decide whether the parameters used currently are a good tradeoff.

http://philip.html5.org/tests/canvas/misc/todataurl-args.html hints that adding extra args such as "compression=9" after the MIME type might make sense to influence the compression, but that'd be purely ad hoc.