Re: [whatwg] Proposal: toDataURL “image/png” compression control
On Wed, May 28, 2014 at 10:36 PM, Noel Gordon noel.gor...@gmail.com wrote: canvas.toDataURL supports an optional quality argument for the “image/jpeg” mime type to control image compression. Developers have no control over “image/png” compression. “image/png” is a lossless image compression format and the proposal is to allow developers some control over the compression process. For example, a developer might request maximum compression once their art work is complete to minimize the encoded image size for transmission or storage. Encoding speed might be more important while creating the work, and less compression (faster encoding) could be requested in that case. An optional toDataURL parameter on [0.0 ... 1.0], similar to the optional quality argument used for image/jpeg, could be defined for “image/png” to control compression: canvas.toDataURL(“image/png”, [compression-control-value]); The default value, and how the browser controls the image encoder to gain more compression with increasing values, would be internal implementation details of the browser. This has been requested before. ie http://lists.whatwg.org/pipermail/help-whatwg.org/2013-May/001209.html The conclusion was that this can be accomplished using JavaScript. There are JS libraries that can compress images and performance is very good these days. If you're worried about blocking the main thread, you can use workers to do offline processing.
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On Thu, May 29, 2014 at 1:32 AM, Rik Cabanier caban...@gmail.com wrote: This has been requested before. ie http://lists.whatwg.org/pipermail/help-whatwg.org/2013-May/001209.html The conclusion was that this can be accomplished using JavaScript. There are JS libraries that can compress images and performance is very good these days. This is a nonsensical conclusion. People shouldn't have to pull in a PNG compressor and deflate code when a PNG compression API already exists on the platform. This is an argument against adding toDataURL at all, which is a decision that's already been made. -- Glenn Maynard
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On Thu, May 29, 2014 at 9:59 AM, Glenn Maynard gl...@zewt.org wrote: On Thu, May 29, 2014 at 1:32 AM, Rik Cabanier caban...@gmail.com wrote: This has been requested before. ie http://lists.whatwg.org/pipermail/help-whatwg.org/2013-May/001209.html The conclusion was that this can be accomplished using JavaScript. There are JS libraries that can compress images and performance is very good these days. This is a nonsensical conclusion. People shouldn't have to pull in a PNG compressor and deflate code when a PNG compression API already exists on the platform. This is an argument against adding toDataURL at all, which is a decision that's already been made. +1 I would add that the fact that such libraries even exist despite the fact that the platform provides a competing API proves that the API is not what it should be. Also, an encoder written in JavaScript cannot produce color-managed results because we do not have any APIs that expose color profiles. I am guessing that png encoders written in JS probably assume that data returned by getImageData is in sRGB, which is often not the case. toDataURL, on the other hand, has the possibility of encoding into the png, a color profile that expresses the canvas backing store's color space. I know current implementations of toDataURL don't do that, but we could and should. -Justin -- Glenn Maynard
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On Thu, May 29, 2014 at 7:45 AM, Justin Novosad ju...@google.com wrote: On Thu, May 29, 2014 at 9:59 AM, Glenn Maynard gl...@zewt.org wrote: On Thu, May 29, 2014 at 1:32 AM, Rik Cabanier caban...@gmail.com wrote: This has been requested before. ie http://lists.whatwg.org/pipermail/help-whatwg.org/2013-May/001209.html The conclusion was that this can be accomplished using JavaScript. There are JS libraries that can compress images and performance is very good these days. This is a nonsensical conclusion. People shouldn't have to pull in a PNG compressor and deflate code when a PNG compression API already exists on the platform. This is an argument against adding toDataURL at all, which is a decision that's already been made. +1 I would add that the fact that such libraries even exist despite the fact that the platform provides a competing API proves that the API is not what it should be. Also, an encoder written in JavaScript cannot produce color-managed results because we do not have any APIs that expose color profiles. I am guessing that png encoders written in JS probably assume that data returned by getImageData is in sRGB, which is often not the case. toDataURL, on the other hand, has the possibility of encoding into the png, a color profile that expresses the canvas backing store's color space. I know current implementations of toDataURL don't do that, but we could and should. I'm not sure if we want to bake in the device's color profile into the output bitmap by default because on re-import it will then go through color management and its pixels will look different from the unmanaged canvas ones.
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On Thu, May 29, 2014 at 6:59 AM, Glenn Maynard gl...@zewt.org wrote: On Thu, May 29, 2014 at 1:32 AM, Rik Cabanier caban...@gmail.com wrote: This has been requested before. ie http://lists.whatwg.org/pipermail/help-whatwg.org/2013-May/001209.html The conclusion was that this can be accomplished using JavaScript. There are JS libraries that can compress images and performance is very good these days. This is a nonsensical conclusion. People shouldn't have to pull in a PNG compressor and deflate code when a PNG compression API already exists on the platform. This is an argument against adding toDataURL at all, which is a decision that's already been made. If performance is good, why would this not be acceptable? It seems that this would be a fragmented solution as file formats and features would be added at different stages to browser engines. Would there be a way to feature test that the optional arguments are supported?
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On Thu, May 29, 2014 at 11:21 AM, Rik Cabanier caban...@gmail.com wrote: On Thu, May 29, 2014 at 7:45 AM, Justin Novosad ju...@google.com wrote: On Thu, May 29, 2014 at 9:59 AM, Glenn Maynard gl...@zewt.org wrote: On Thu, May 29, 2014 at 1:32 AM, Rik Cabanier caban...@gmail.com wrote: This has been requested before. ie http://lists.whatwg.org/pipermail/help-whatwg.org/2013-May/001209.html The conclusion was that this can be accomplished using JavaScript. There are JS libraries that can compress images and performance is very good these days. This is a nonsensical conclusion. People shouldn't have to pull in a PNG compressor and deflate code when a PNG compression API already exists on the platform. This is an argument against adding toDataURL at all, which is a decision that's already been made. +1 I would add that the fact that such libraries even exist despite the fact that the platform provides a competing API proves that the API is not what it should be. Also, an encoder written in JavaScript cannot produce color-managed results because we do not have any APIs that expose color profiles. I am guessing that png encoders written in JS probably assume that data returned by getImageData is in sRGB, which is often not the case. toDataURL, on the other hand, has the possibility of encoding into the png, a color profile that expresses the canvas backing store's color space. I know current implementations of toDataURL don't do that, but we could and should. I'm not sure if we want to bake in the device's color profile into the output bitmap by default because on re-import it will then go through color management and its pixels will look different from the unmanaged canvas ones. I think you meant encode rather than bake in that above sentence. Correct? Currently, the non-color managed output of toDataURL has the display profile baked in. Take the following code: var image = newImage() image.src = canvas.toDataURL('image/png'); image.onload = function() { canvas.drawImage(image, 0, 0); } Under a non color managed implementation, the above code will not modify the content of the canvas in any way because there are no color space conversions since the png is not color managed... All is good. If toDataURL encoded a color profile, the behavior would remain unchanged because the color correction applied during the image decode would do nothing (converting to and from the same color space). Again, all is good. However, if the data URL was to be sent over the network to be decoded on a different machine, then you are screwed with a non-color managed png, because the sender's display's color profile is baked-in to the image but there is no color profile meta data to allow the receiver to bring the image into a known color space. -Justin
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On Thu, May 29, 2014 at 8:50 AM, Justin Novosad ju...@google.com wrote: On Thu, May 29, 2014 at 11:21 AM, Rik Cabanier caban...@gmail.com wrote: On Thu, May 29, 2014 at 7:45 AM, Justin Novosad ju...@google.com wrote: On Thu, May 29, 2014 at 9:59 AM, Glenn Maynard gl...@zewt.org wrote: On Thu, May 29, 2014 at 1:32 AM, Rik Cabanier caban...@gmail.com wrote: This has been requested before. ie http://lists.whatwg.org/pipermail/help-whatwg.org/2013-May/001209.html The conclusion was that this can be accomplished using JavaScript. There are JS libraries that can compress images and performance is very good these days. This is a nonsensical conclusion. People shouldn't have to pull in a PNG compressor and deflate code when a PNG compression API already exists on the platform. This is an argument against adding toDataURL at all, which is a decision that's already been made. +1 I would add that the fact that such libraries even exist despite the fact that the platform provides a competing API proves that the API is not what it should be. Also, an encoder written in JavaScript cannot produce color-managed results because we do not have any APIs that expose color profiles. I am guessing that png encoders written in JS probably assume that data returned by getImageData is in sRGB, which is often not the case. toDataURL, on the other hand, has the possibility of encoding into the png, a color profile that expresses the canvas backing store's color space. I know current implementations of toDataURL don't do that, but we could and should. I'm not sure if we want to bake in the device's color profile into the output bitmap by default because on re-import it will then go through color management and its pixels will look different from the unmanaged canvas ones. I think you meant encode rather than bake in that above sentence. Correct? Currently, the non-color managed output of toDataURL has the display profile baked in. Take the following code: var image = newImage() image.src = canvas.toDataURL('image/png'); image.onload = function() { canvas.drawImage(image, 0, 0); } Under a non color managed implementation, the above code will not modify the content of the canvas in any way because there are no color space conversions since the png is not color managed... All is good. If toDataURL encoded a color profile, the behavior would remain unchanged because the color correction applied during the image decode would do nothing (converting to and from the same color space). Again, all is good. That's right. The values of pixels on the canvas are the same on every machine, but we have many different types of monitors. The png's that are generated should all be identical pixel-wise but their attached profiles might be different. However, if the data URL was to be sent over the network to be decoded on a different machine, then you are screwed with a non-color managed png, because the sender's display's color profile is baked-in to the image but there is no color profile meta data to allow the receiver to bring the image into a known color space. You are screwed either way :-) I think authors are going to be surprised that pixels will end up different. (Imagine taking screenshots of achievements in a game that are put in an online gallery) If you put the profile in and it is different from sRGB, the png will look different from the original canvas because you now will go through an intermediate sRGB space which will warp the color range. As an example, I did a toDataURL of this codepen example: http://codepen.io/Boshnik/pen/vFbgw I then opened it up in Photoshop, attached my monitor profile and wrote a small script that does a difference on them: http://cabanier.github.io/BlendExamples/images.htm If you run windows, you will see that there's content in the canvas output. For some reason, Mac doesn't do any color conversion on any browser. Even on my own system, there's a difference because of the sRGB conversion: http://cabanier.github.io/BlendExamples/screenshot.png
[whatwg] Proposal: toDataURL “image/png” compression control
On Thu, May 29, 2014 at 10:29 AM, Rik Cabanier caban...@gmail.com javascript:_e(%7B%7D,'cvml','caban...@gmail.com'); wrote: If performance is good, why would this not be acceptable? I don't know why we'd provide an API to compress PNGs, then tell people to use a script reimplementation if they want to set a common option. As far as performance, I'm not sure about PNG, but there's no way that a JS compressor would compete with native for JPEG. Assembly (MMX, SSE) optimization gives a significant performance improvement over C, so I doubt JS will ever be in the running. ( http://www.libjpeg-turbo.org/About/Performance) It seems that this would be a fragmented solution as file formats and features would be added at different stages to browser engines. Would there be a way to feature test that the optional arguments are supported? No more than any other new feature. I don't know if feature testing for dictionary arguments has been solved yet (it's come up before), but if not that's something that needs to be figured out in general. -- Glenn Maynard -- Glenn Maynard
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On Thu, May 29, 2014 at 12:17 PM, Glenn Maynard gl...@zewt.org wrote: On Thu, May 29, 2014 at 10:29 AM, Rik Cabanier caban...@gmail.com wrote: If performance is good, why would this not be acceptable? I don't know why we'd provide an API to compress PNGs, then tell people to use a script reimplementation if they want to set a common option. As far as performance, I'm not sure about PNG, but there's no way that a JS compressor would compete with native for JPEG. Assembly (MMX, SSE) optimization gives a significant performance improvement over C, so I doubt JS will ever be in the running. ( http://www.libjpeg-turbo.org/About/Performance) MMX, SSE is being addressed using asm.js. We're also just dealing with screenshots here. I doubt people are going to do toDataURL at 60fps. It seems that this would be a fragmented solution as file formats and features would be added at different stages to browser engines. Would there be a way to feature test that the optional arguments are supported? No more than any other new feature. I don't know if feature testing for dictionary arguments has been solved yet (it's come up before), but if not that's something that needs to be figured out in general.
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On Thu, May 29, 2014 at 1:33 PM, Rik Cabanier caban...@gmail.com wrote: On Thu, May 29, 2014 at 12:17 PM, Glenn Maynard gl...@zewt.org wrote: On Thu, May 29, 2014 at 10:29 AM, Rik Cabanier caban...@gmail.com wrote: If performance is good, why would this not be acceptable? I don't know why we'd provide an API to compress PNGs, then tell people to use a script reimplementation if they want to set a common option. As far as performance, I'm not sure about PNG, but there's no way that a JS compressor would compete with native for JPEG. Assembly (MMX, SSE) optimization gives a significant performance improvement over C, so I doubt JS will ever be in the running. ( http://www.libjpeg-turbo.org/About/Performance) MMX, SSE is being addressed using asm.js. We're also just dealing with screenshots here. I doubt people are going to do toDataURL at 60fps. Here's a link to an experiment: http://multimedia.cx/eggs/playing-with-emscripten-and-asm-js/ It seems that this would be a fragmented solution as file formats and features would be added at different stages to browser engines. Would there be a way to feature test that the optional arguments are supported? No more than any other new feature. I don't know if feature testing for dictionary arguments has been solved yet (it's come up before), but if not that's something that needs to be figured out in general.
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On Thu, May 29, 2014 at 3:33 PM, Rik Cabanier caban...@gmail.com wrote: MMX, SSE is being addressed using asm.js. Assembly language is inherently incompatible with the Web. We already have an API for compressing images, and compression level is an ordinary input to image compressors, yet you're arguing that rather than add the option to the API we have, we should require people to bundle their own image compressors and write MMX assembly on the Web to make it fast. Sorry if I think that's a bizarre argument... We're also just dealing with screenshots here. I doubt people are going to do toDataURL at 60fps. (I hope we can all see more use cases than just screenshots.) -- Glenn Maynard
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On 5/29/14, 5:13 PM, Glenn Maynard wrote: Assembly language is inherently incompatible with the Web. A SIMD API, however is not. Under the hood, it can be implemented in terms of MMX, SSE, NEON, or just by forgetting about the SIMD bit and pretending like you have separate operations. In particular, you could have a SIMD API that desugars to plain JS as the default implementation in browsers but that JITs can recognize and vectorize as they desire. This sort of API will happen, for sure. No opinion on the PNG encoder thing. -Boris
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On Thu, May 29, 2014 at 4:21 PM, Boris Zbarsky bzbar...@mit.edu wrote: On 5/29/14, 5:13 PM, Glenn Maynard wrote: Assembly language is inherently incompatible with the Web. A SIMD API, however is not. Under the hood, it can be implemented in terms of MMX, SSE, NEON, or just by forgetting about the SIMD bit and pretending like you have separate operations. In particular, you could have a SIMD API that desugars to plain JS as the default implementation in browsers but that JITs can recognize and vectorize as they desire. This sort of API will happen, for sure. I doubt it, at least with performance competitive with native assembly. We certainly shouldn't delay features while we hope for it. -- Glenn Maynard
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On Thu, May 29, 2014 at 2:28 PM, Glenn Maynard gl...@zewt.org wrote: On Thu, May 29, 2014 at 4:21 PM, Boris Zbarsky bzbar...@mit.edu wrote: On 5/29/14, 5:13 PM, Glenn Maynard wrote: Assembly language is inherently incompatible with the Web. A SIMD API, however is not. Under the hood, it can be implemented in terms of MMX, SSE, NEON, or just by forgetting about the SIMD bit and pretending like you have separate operations. In particular, you could have a SIMD API that desugars to plain JS as the default implementation in browsers but that JITs can recognize and vectorize as they desire. This sort of API will happen, for sure. I doubt it, at least with performance competitive with native assembly. We certainly shouldn't delay features while we hope for it. You don't need to hope for it. The future is already here: http://www.j15r.com/blog/2014/05/23/Box2d_2014_Update asm.js will be fast on all modern browsers before this feature would ship. As an author, I'd certainly prefer the most flexible solution that works everywhere.
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On Thu, May 29, 2014 at 4:50 PM, Rik Cabanier caban...@gmail.com wrote: You don't need to hope for it. The future is already here: http://www.j15r.com/blog/2014/05/23/Box2d_2014_Update asm.js will be fast on all modern browsers before this feature would ship. As an author, I'd certainly prefer the most flexible solution that works everywhere. I don't have the time to read all of this, but it doesn't seem to have anything to do with SIMD instruction sets (which are notoriously difficult to generalize). Anyway, this has derailed the thread. We have an API for compression already. It already supports a compression level argument for JPEG. Having an equivalent argument for PNG is a no-brainer. The only difference to JPEG is that it should be described as the compression level rather than quality level, since with PNG it has no effect on quality, only the file size and time it takes to compress. -- Glenn Maynard
Re: [whatwg] Proposal: toDataURL “image/png” compression control
Glenn Maynard gl...@zewt.org writes: We have an API for compression already. It already supports a compression level argument for JPEG. Having an equivalent argument for PNG is a no-brainer. The only difference to JPEG is that it should be described as the compression level rather than quality level, since with PNG it has no effect on quality, only the file size and time it takes to compress. What benefit does it give then if the result is the same perceptually? -- Nils Dagsson Moskopp // erlehmann http://dieweltistgarnichtso.net
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On 29.05.2014, at 23:19, Glenn Maynard gl...@zewt.org wrote: Anyway, this has derailed the thread. We have an API for compression already. It already supports a compression level argument for JPEG. Having an equivalent argument for PNG is a no-brainer. The only difference to JPEG is that it should be described as the compression level rather than quality level, since with PNG it has no effect on quality, only the file size and time it takes to compress. I don't think it's a no-brainer. There are several ways it could be interpreted: 1. As zlib's compression level However, this has marginal utility, because these days even the maximum level, even on mobile devices, is reasonably fast. Lower level would be useful only for very large images on very slow devices, but UAs can have a good heuristic for ensuring reasonable compression time without any input from the page's author. I expect exponential increase in computing power make this setting completely irrelevant by the time it's implemented in most browsers. 2. Enable brute-force search for best combinations of zlib's compression level, memory level and window size OptiPNG and pngcrush show that maximum settings in zlib don't always give smallest file and best compression is obtained by trying hundreds of combinations of zlib parameters. If browsers choose this approach for a high compression level that will be a couple of *orders of magnitude* slower than the first option. If different vendors don't agree on orders of magnitude of time it takes to compress an image, such parameter could be unusable. 3. Compression parameters in other gzip implementations For example Zopfli compressor produces files smaller than zlib, but is much much slower. Instead of 1-9 scale it takes number of iterations as the compression level. And it can even use a totally different approach to compression level: I've modified Zopfli[1] to make it aim for constant processing time on any machine. Faster machines will just produce smaller files. Browsers could use this approach to ensure every PNG is compressed in 0.5s or so, or the compression level parameter could be a number of seconds to spend on the compression. And that's just for lossless PNG. It's possible to encode standard PNG in a *lossy* fashion (http://pngmini.com/lossypng.html), and there are few ways to do it: Images can be converted to PNG-8 (vector quantization is a form of lossy compression) and then compression level could be interpreted as number of unique colors or mean square error of the quantized image (the latter option is used by http://pngquant.org). This generally makes files 3-4 times smaller, but has a limit on maximum quality that can be achieved. For higher quality it's possible to make truecolor PNG lossy by taking advantage of the fact that PNG filters are predictors. Instead of writing all pixels as they are in the input image the encoder can replace some pixels with values matching filters' prediction. This simplifies the data and generally halves the file size (and costs almost no extra CPU time). The threshold used to choose between source and predicted values for pixels acts similarly to JPEG's quality level. So there are multiple ways such parameter can be interpreted, and it can result in wildly different visual quality, file size and time taken to compress the image. -- regards, Kornel [1] https://github.com/pornel/zopfli
Re: [whatwg] Proposal: toDataURL “image/png” compression control
On Thu, May 29, 2014 at 5:34 PM, Nils Dagsson Moskopp n...@dieweltistgarnichtso.net wrote: and time it takes to compress. What benefit does it give then if the result is the same perceptually? Time it takes to compress. There's a big difference between waiting one second for a quick save and 60 seconds for a high-compression final export. On Thu, May 29, 2014 at 7:31 PM, Kornel Lesiński kor...@geekhood.net wrote: I don't think it's a no-brainer. There are several ways it could be interpreted: The API is a no-brainer. That doesn't mean it should be done carelessly. That said, how it's implemented is an implementation detail, just like the JPEG quality parameter, though it should probably be required to never use lossy compression (strictly speaking this may not actually be required today...). FYI, I don't plan to spend much time arguing for this feature. My main issue is with the just do it in script argument. It would probably help for people more strongly interested in this to show a comparison of resulting file sizes and the relative amount of time it takes to compress them. -- Glenn Maynard