Optional destination size for `HTMLImageElement.decode()`
What is the issue with the HTML Standard?
What problem are you trying to solve?
If the destination size of an Image is much smaller than its natural size, too much memory will be wasted when decoding the image. Image decoding sub-sampling is a very useful technique in reducing the decoding memory. For example if an image of size 4000x4000 is displayed in 400x400 rectangle, each 100 pixels from the image will be drawn in one pixel. So image decoders allow sub-sampling especially for this case. The sub-sampled image does not necessarily have to have the same destination size but it can be very close to it. For example if an image of size 4000x4000 is displayed in 400x400 rectangle, the sub-sampled size might be 500x500 which is still a significant reduction.
What solutions exist today?
HTMLImageElement.decode() can be used to decode an image in advance. But when it is called, sub-sampling has to be disabled. Therefore the image has to be decoded with its natural size.
How would you solve it?
If the size of the destination element is known, passing an optional width and height to HTMLImageElement.decode() should reduce the decoding memory:
<img id="small-image" width="100" height="100">
<script>
const img = new Image();
img.src = "4000x4000.jpg";
img.decode(100, 100).then(() => {
document.querySelector("#small-image").src = img.src;
})
<script>
Anything else?
This issue was inspired by this webkit bug which has provided this test case.
I like this proposal. This will help with canvas use-cases (WebGL, 2D), in addition to the original motivation of allowing flicker-free image loading UX.
A couple of comments though:
Image identity
I think the decoded size should only apply to the const img = new Image() object exclusively. The example seems to imply that the decoded size will apply to all images source from the same src value, i.e. globally to everything sourced from "4000x4000.jpg". That means the same image cannot be decoded at different sizes, which I think is an unnecessary limitation. Consider alternatives, such as cloning the decoded image element, object URLs, or a new method for transferring an image from one element to another (a la transferFromImageBitmap).
Updating decoded size
Maybe this is implied in the proposal, but it would be nice to make it explicit. While the destination size may be known ahead of time, there's no guarantee that it won't change. So the same image may need to be resampled to something else. One way to do this is to allow calling decode multiple times, supplying different target dimensions.
Stronger memory guarantees
After the image is decoded and transferred to, say, WebGL, the Image object may no longer be necessary. However, it's unclear when the underlying memory would be freed. Theoretically, setting the src value to "" would leave no strong references to the underlying image data, and browsers could reclaim memory eagerly. However, the spec doesn't seem to specify this. It would be nice to add it to the spec so developers could rely on it.
I'm going to copy @whatwg/canvas on this given the likely overlap of audiences and the lack of a similar group of people for images.