HTMLCanvasElement.toBlob failing with 'image/webp' on a large image
Reported by
cyril.au...@gmail.com,
Dec 31 2016
|
||||||||
Issue descriptionUserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36 Steps to reproduce the problem: 1. demo: https://jsfiddle.net/crl/6jvcwwd3/ 2. 3. What is the expected behavior? .toBlob should produce a blob file What went wrong? it returns null Did this work before? N/A Does this work in other browsers? N/A Chrome version: 55.0.2883.87 Channel: stable OS Version: 10.0 Flash Version: Shockwave Flash 24.0 r0
,
Jan 5 2017
,
Jan 5 2017
It works if you reduce the size of the canvas. My best guess is that the codec is experiencing a memory allocation failure. The strict spec-compliant behavior would be to crash the browser with an out-of-memory exception because the spec has no path for handling encoder errors: https://html.spec.whatwg.org/multipage/scripting.html#a-serialisation-of-the-bitmap-as-a-file But let's not do that because it wouldn't be nice. Let's instead: a) See if we can avoid the failure. Jpg and png have no trouble, so what is so special about webp? b) Output relevant message to the console when this happens so that dev don't scratch their heads for too long.
,
Jan 5 2017
FWIW, The canvas backing in the provided example requires 61MB of storage for its pixels, which should not be impossible to handle on a modern computer. My workstation has 64GB of RAM, and it fails the fiddle. There is definitely something fishy going on.
,
Jan 16 2017
I have investigated and found that the reason why webp encoding fails is that the height of image used in this example (25600) is exceeding the maximum threshold set in Chromium (16383). I raised the WEBP_MAX_DIMENSION threshold and this example then worked; it returned a blob with size 605064, which is much higher than the blob returned from firefox (59899) and I must admit that the encoding process is a little bit long. +cc junov, noel@: Is it spec-compliant if I raise the maximum dimension threshold for images passed into webp image encoders? I feel that there might be some performance problem in the webp library used for large images; maybe we should keep the MAX dimension as same as now unless that webp library can encode large images fast.
,
Jan 16 2017
The max dimension was added when libwebp was updated to v0.1.3, 5 years ago: https://chromium.googlesource.com/chromium/src/+/b7afef7463d25d0a6c366760ee507e62e4c052bd If Firefox does not have that limitation, they are most likely using a long outdated version of the library, or they forked it. +jzern for guidance.
,
Jan 16 2017
> The max dimension was added when libwebp was updated to v0.1.3, 5 years ago: 16383x16383 is a format limitation derived from the lossy (VP8) codec [1]; width and height are coded with 14-bits and because it isn't width/height-1 16383 is the max. The lossless codec was given a similar restriction for coherency. > If Firefox does not have that limitation, they are most likely using a long outdated version of the library, or they forked it. As far as I know libwebp support has yet to land in firefox [2], so I'd expect the blob isn't really a webp. If it were one it would contain invalid dimensions given the 14-bit limitation. [1] https://tools.ietf.org/html/rfc6386#section-9.1 [2] https://bugzilla.mozilla.org/show_bug.cgi?id=1294490
,
Jan 17 2017
jzern@: Thanks for the detailed input. You're right; firefox returns "image/png" for the example so my previous comparison was not valid. In this case, I would conclude that an example like that exceeds the format limitation. cyril.auburtin@: you could either use a png or jpeg format for your example or reduce the size for the webp.
,
Jan 17 2017
Yes, thanks for the investigation (it was for generating a spritesheets of webfonts) I can totally use other formats
,
Jan 17 2017
Re-opening. The behavior of chrome is still not acceptable here. Developers currently get no feedback on the failure. We should at least output an error message to the dev console to let devs know what happened. Also, I would like to argue that we should fallback to a PNG encoding when this happens. This is what the spec says (https://html.spec.whatwg.org/multipage/scripting.html#a-serialisation-of-the-bitmap-as-a-file): "If the user agent does not support the requested type, then it must create the file using the PNG format." It is not 100% clear how to interpret that statement for this case. I would suggest interpreting it this way: webp is not supported for bitmaps with a dimension greater 16k, therefore png must be used. We should propose a clarification to the spec. Perhaps we should add a non-normative note explaining to behave as if the requested type is not supported in cases where the bitmaps dimension exceed the maximum dimensions supported by the requested type.
,
Jan 17 2017
It is a bit confusing: the spec prose a few paragraphs back from where you quoted says something more exact ... "When a user agent is to create a serialization of the bitmap as a file, given an optional type and quality, it must create an image file in the format given by type, or if type was not supplied, in the PNG format. [PNG]". In the current issue, type was supplied "image/webp" (the above paragraph) and chrome supports that type (the paragraph you quoted). In that case we should not fallback to PNG in my reading of the current spec prose. > Developers currently get no feedback on the failure. IIRC, earlier versions of the spec prose had the remedy for that: return "data:," and I'm pretty sure that's what we and WebKit currently do. I do not see that text in the prose anymore, but it was there for said developer feedback. If "data:," is returned, the encoder failed (OOM, bad arguments, size etc). toBlob() has the same requirement: in its case, return a null blob to signal the encoding failure back to the developer.
,
Jan 20 2017
> IIRC, earlier versions of the spec prose had the remedy for that: return "data:," and I'm pretty sure that's what we and WebKit currently do.
Hacked the webp encoder in my Chrome checkout to fail always, and yeap, Chrome returns "data:," when I call canvas.toDataURL('image/webp').
,
Feb 7 2017
I agree with noel@ that even if users calling webp image exceeding its MAX dimension, it is not equivalent to "the webp type was not supplied" as in the spec. Not only that, I have another reason: The behaviors in toDataURL and toBlob are consistent: toDataURL return "data:" whilst toBlob return null blob in the case when the encoding fails. The spec restricts the condition of such null return as only "if this canvas element's bitmap has no pixels (i.e. either its horizontal dimension or its vertical dimension is zero)". However, in the implementation, we return null or "data:" not only for this condition, but also for the case of Jpeg memory out of bound, webp version mismatch, webp memory error, or a sequence of other unexpected config values in encoder, or webp exceeding max dimension as in this example, etc. If we fall back to default png mode when webp exceeds max dimension, based on the interpretation that "webp image exceeding MAX == not supporting this image type", then how are we going to deal with the rest of cases about memory error, version mismatch and so on? Are we going to do the same for consistency? But some of the these failures can only be detected when the encoding has already started. I feel that these all belong to internal problems of the encoders, not due to an invalid user input. We should simply treat webp exceeding MAX as another internal encoder failure as in the rest of cases. My suggestion would be to add one more condition to the spec to relax the condition of null return by saying "if this canvas element's bitmap...or there is a failure in image encoding internally".
,
Feb 7 2017
Checking other implementations, encoding can fail for myriad reasons and "data:," in the case of toDataURL is used to signal that ... https://trac.webkit.org/changeset/205405/trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
,
Feb 8 2017
Here is the spec change I am proposing: https://github.com/whatwg/html/pull/2343
,
Feb 9 2017
#16 looks pretty good: "if an irremediable error occurs", maybe s/irremediable//
,
Feb 17 2017
https://github.com/whatwg/html/pull/2343 is already merged so that "If an error occurs during the creation of the image file (e.g. an internal encoder error), then the result of the serialization is null." Now toBlob is meeting the spec requirement. I'll close this bug.
,
Feb 18 2017
OK, good. Mozilla does not comply with the spec; they fallback to PNG on error, which leads to various issues as xlai@ correctly mentioned in #13. junov@ How do we get Mozilla fixed? |
||||||||
►
Sign in to add a comment |
||||||||
Comment 1 by brajkumar@chromium.org
, Jan 3 2017Status: Untriaged (was: Unconfirmed)