Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow an image to indicate its own density and correct its intrinsic size #5574

Merged
merged 16 commits into from
Jul 8, 2021
141 changes: 118 additions & 23 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -3704,6 +3704,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<li>The <dfn data-x-href="https://drafts.csswg.org/css-values/#vw">'vw'</dfn> unit</li>
<li>The <dfn data-x-href="https://drafts.csswg.org/css-values/#in">'in'</dfn> unit</li>
<li>The <dfn data-x-href="https://drafts.csswg.org/css-values/#px">'px'</dfn> unit</li>
<li>The <dfn data-x-href="https://drafts.csswg.org/css-values/#pt">'pt'</dfn> unit</li>
<li>The <dfn data-x-href="https://drafts.csswg.org/css-values/#funcdef-attr">'attr()'</dfn> function</li>
<li>The <dfn data-x-href="https://drafts.csswg.org/css-values/#math-function">math functions</dfn></li>
</ul>
Expand Down Expand Up @@ -28054,14 +28055,31 @@ was an English &lt;a href="/wiki/Music_hall">music hall&lt;/a> singer, ...</code
<p>Each <code>img</code> element has a <dfn>last selected source</dfn>, which must initially be
null.</p>

<p>Each <span>image request</span> has a <dfn>current pixel density</dfn>, which must initially be undefined.</p>
<p>Each <span>image request</span> has a <dfn>current pixel density</dfn>, which must initially be
1.</p>

<p>Each <span>image request</span> has <dfn>preferred density-corrected dimensions</dfn>,
Null or set to a struct consisting of a width and a height, which must initially be
null.</p>

<p>To determine the <dfn>density-corrected intrinsic width and height</dfn> of an
<code>img</code> element <var>img</var>:</p>

<ol>
<li><p>Let <var>dim</var> be <var>img</var>'s <span>current request</span>'s <span>preferred
density-corrected dimensions</span>.</p></li>

<li><p>If <var>dim</var> is null, set <var>dim</var> to <var>img</var>'s <span>intrinsic
dimensions</span>.</p></li>

<li><p>Set <var>dim</var>'s width to <var>dim</var>'s width divided by <span>current request</span>'s
<span>current pixel density</span>.</p></li>

<p>When an <code>img</code> element has a <span>current pixel density</span> that is not 1.0, the
element's image data must be treated as if its resolution, in device pixels per <span
data-x="'px'">CSS pixels</span>, was the <span>current pixel density</span>. The image's
<dfn>density-corrected intrinsic width and height</dfn> are the <span data-x="intrinsic
dimensions">intrinsic width and height</span> after taking into account the <span>current pixel
density</span>.</p>
<li><p>Set <var>dim</var>'s height to <var>dim</var>'s height divided by <span>current request</span>'s
<span>current pixel density</span>.</p></li>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this then require the UA to retrieve the EXIF block directly or can the values be obtained indirectly through the use of the retrieval of XMP? I would hope that both would be supported, since a UA may want the more comprehensive XMP and could then make a single call to load image metadata.

Copy link
Contributor Author

@noamr noamr Jul 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, this is about reading EXIF directly., as that's also where orientation is read from and it keeps images small (XMP is verbose if you're just specifying numbers). It's possible to add XMP in the future, of course

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@noamr - As I read the text, what you say is not actually true. It simply says that you use the values from EXIF - not anything about where or how you obtain them. That therefore would indeed allow an arbitrary UA to choose whatever model works best for them.

It should be noted that while you may find more Photos (.jpg) with native EXIF, you will find many more images (GIF, PNG, AV1F, WebP, etc.) which use XMP instead - since it is the more modern and open (by being an ISO standard) approach to asset metadata.

So restricting XMP from this work would be quite limiting.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True enough. The current proposal leaves this open to how EXIF is embedded in the image. The initial jpeg implementation is, however, limited to binary exif.


<li><p>Return <var>dim</var>.
</ol>

<p class="example">For example, if the <span>current pixel density</span> is 3.125, that means
that there are 300 device pixels per <span data-x="'in'">CSS inch</span>, and thus if the image
Expand Down Expand Up @@ -28345,7 +28363,8 @@ was an English &lt;a href="/wiki/Music_hall">music hall&lt;/a> singer, ...</code
data-x="img-req-state">state</span> is <span data-x="img-all">completely
available</span>.</p></li>

<li><p>Update the presentation of the image appropriately.</p></li>
<li><p><span data-x="prepare an image for presentation">Prepare <var>current request</var>
for presentation</span> given <var>img</var>.</p></li>

<li><p>Set <span>current request</span>'s <span>current pixel density</span> to <var>selected
pixel density</var>.</p></li>
Expand Down Expand Up @@ -28583,13 +28602,16 @@ was an English &lt;a href="/wiki/Music_hall">music hall&lt;/a> singer, ...</code

<p>Each <span data-x="concept-task">task</span> that is <span data-x="queue a
task">queued</span> by the <span>networking task source</span> while the image is being
fetched must update the presentation of the image, but as each new body part comes in, it must
replace the previous image. Once one body part has been completely decoded, the user agent
must set the <code>img</code> element's <span>current request</span>'s <span
data-x="img-req-state">state</span> to <span data-x="img-all">completely available</span> and
<span>queue an element task</span> on the <span>DOM manipulation task source</span> given the
<code>img</code> element to <span data-x="concept-event-fire">fire an event</span> named <code
data-x="event-load">load</code> at the <code>img</code> element.</p>
fetched must update the presentation of the image, but as each new body part comes in, if the
user agent is able to determine the image's width and height, it must <span data-x="prepare
an image for presentation">prepare the <code>img</code> element's <span>current request</span>
for presentation</span> and replace the previous image. Once one body part has been
completely decoded, the user agent must set the <code>img</code> element's <span>current
request</span>'s <span data-x="img-req-state">state</span> to <span
data-x="img-all">completely available</span> and <span>queue an element task</span> on the
<span>DOM manipulation task source</span> given the <code>img</code> element to <span
data-x="concept-event-fire">fire an event</span> named <code data-x="event-load">load</code>
at the <code>img</code> element.</p>
<!--TODO what if the image is broken?
TODO change state and fire in the same task? -->
</dd>
Expand All @@ -28609,9 +28631,10 @@ was an English &lt;a href="/wiki/Music_hall">music hall&lt;/a> singer, ...</code
available</span>.</p></li>

<li><p>Otherwise, if the user agent is able to determine <var>image request</var>'s image's
width and height, and <var>image request</var> is <span>current request</span>, update the
<code>img</code> element's presentation appropriately and set <var>image request</var>'s
<span data-x="img-req-state">state</span> to <span data-x="img-inc">partially
width and height, and <var>image request</var> is <span>current request</span>, <span
data-x="prepare an image for presentation">prepare <var>image request</var> for
presentation</span> given <var>img</var> and set <var>image request</var>'s <span
data-x="img-req-state">state</span> to <span data-x="img-inc">partially
available</span>.</p></li>

<li><p>Otherwise, if the user agent is able to determine that <var>image request</var>'s
Expand Down Expand Up @@ -28653,7 +28676,8 @@ was an English &lt;a href="/wiki/Music_hall">music hall&lt;/a> singer, ...</code
<li><p>If <var>image request</var> is the <span>pending request</span>,
<span>abort the image request</span> for the <span>current request</span>,
<span>upgrade the pending request to the current request</span> and
update the <code>img</code> element's presentation appropriately.</p></li>
<span data-x="prepare an image for presentation">prepare <var>image request</var> for
presentation</span> given <var>img</var>.</p></li>

<li><p>Set <var>image request</var> to the <span data-x="img-all">completely
available</span> state.</p></li>
Expand Down Expand Up @@ -28687,7 +28711,6 @@ was an English &lt;a href="/wiki/Music_hall">music hall&lt;/a> singer, ...</code

<ol>
<li><p>Forget <var>image request</var>'s <span data-x="img-req-data">image data</span>, if any.</p></li>
noamr marked this conversation as resolved.
Show resolved Hide resolved

<li><p>Abort any instance of the <span data-x="concept-fetch">fetching</span> algorithm for
<var>image request</var>, discarding any pending tasks generated by that algorithm.</p></li>
</ol>
noamr marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -28701,6 +28724,75 @@ was an English &lt;a href="/wiki/Music_hall">music hall&lt;/a> singer, ...</code
</ol>


<h6>Preparing an image for presentation</h6>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still true? The discussion seems pretty settled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep it until the issue is formally closed.

<p>When asked to <dfn>prepare an image for presentation</dfn> for an <span>image request</span>
<var>req</var> given image element <var>img</var>, user agents must do the following:</p>

<ol>
<li><p>Let <var>exifTagMap</var> be the EXIF tags obtained from <var>req</var>'s
<span data-x="img-req-data">image data</span>, as defined by the relevant codec.<ref spec=EXIF></p></li>

<li><p>Let <var>physicalWidth</var> and <var>physicalHeight</var> be the width and height
obtained from <var>req</var>'s <span data-x="img-req-data">image data</span>, as defined by the
relevant codec.</p></li>

<li><p>Let <var>dimX</var> be the value of <var>exifTagMap</var>'s tag <code
data-x="">0xA002</code> (<code data-x="">PixelXDimension</code>).</p></li>

<li><p>Let <var>dimY</var> be the value of <var>exifTagMap</var>'s tag <code
data-x="">0xA003</code> (<code data-x="">PixelYDimension</code>).</p></li>

<li><p>Let <var>resX</var> be the value of <var>exifTagMap</var>'s tag <code
data-x="">0x011A</code> (<code data-x="">XResolution</code>).</p></li>

<li><p>Let <var>resY</var> be the value of <var>exifTagMap</var>'s tag <code
data-x="">0x011B</code> (<code data-x="">YResolution</code>).</p></li>

<li><p>Let <var>resUnit</var> be the value of <var>exifTagMap</var>'s tag <code
data-x="">0x0128</code> (<code data-x="">ResolutionUnit</code>).</p></li>

<li><p>If either <var>dimX</var> or <var>dimY</var> is not a positive integer, then
return.</p></li>

<li><p>If either <var>resX</var> or <var>resY</var> is not a positive floating-point number,
then return.</p></li>

<li><p>If <var>resUnit</var> is not equal to <code data-x="">2</code> (<code
data-x="">Inch</code>), then return.</p></li>

<li><p>Let <var>widthFromDensity</var> be the value of <var>physicalWidth</var>, multiplied by 72
and divided by <var>resX</var>.</p></li>

<li><p>Let <var>heightFromDensity</var> be the value of <var>physicalHeight</var>, multiplied by
72 and divided by <var>resY</var>.</p></li>

<li><p>If <var>widthFromDensity</var> is not equal to <var>dimX</var> or
<var>heightFromDensity</var> is not equal to <var>dimY</var>, then return.</p></li>

<li>
<p>If <var>req</var>'s <span data-x="img-req-data">image data</span> is
<span>CORS-cross-origin</span>, then set <var>img</var>'s <span>intrinsic dimensions</span> to
<var>dimX</var> and <var>dimY</var>, scale <var>img</var>'s pixel data accordingly, and
return.</p>
</li>

<li><p>Set <var>req</var>'s <span>preferred density-corrected dimensions</span> to
a struct with its width set to <var>dimX</var> and its height set to <var>dimY</var>.</p></li>

<li><p>Update <var>req</var>'s <code>img</code> element's presentation appropriately.</p></li>
</ol>

<p class="note">Resolution in EXIF is equivalent to <span data-x="'pt'">CSS points per
inch</span>, therefore <code data-x="">72</code> is the base for computing size from
resolution.</p>

<p class="XXX">It is not yet specified what would be the case if EXIF arrives after the image is
already presented. See <a href="https://github.com/w3c/csswg-drafts/issues/4929">issue
#4929</a>.</p>



<h6>Selecting an image source</h6>

<p>When asked to <dfn>select an image source</dfn> for a given <code>img</code> or
Expand Down Expand Up @@ -29277,8 +29369,9 @@ was an English &lt;a href="/wiki/Music_hall">music hall&lt;/a> singer, ...</code
since this algorithm started, then let <span>pending request</span> be null and abort these
steps.</p>

<li><p>Let the <code>img</code> element's <span>last selected source</span> be <var>selected source</var>
and the <code>img</code> element's <span>current pixel density</span> be <var>selected pixel density</var>.</p></li>
<li><p>Let the <code>img</code> element's <span>last selected source</span> be <var>selected
source</var> and the <code>img</code> element's <span>current pixel density</span> be
<var>selected pixel density</var>.</p></li>

<li><p>Set the <var>image request</var>'s <span data-x="img-req-state">state</span> to <span
data-x="img-all">completely available</span>.</p></li>
Expand All @@ -29288,7 +29381,8 @@ was an English &lt;a href="/wiki/Music_hall">music hall&lt;/a> singer, ...</code

<li><p><span>Upgrade the pending request to the current request</span>.</p></li>

<li><p>Update the <code>img</code> element's presentation appropriately.</p></li>
<li><p><span data-x="prepare an image for presentation">Prepare <var>image request</var> for
presentation</span> given <var>img</var>.</p></li>

<li><p><span data-x="concept-event-fire">Fire an event</span> named <code
data-x="event-load">load</code> at the <code>img</code> element.</p></li>
Expand Down Expand Up @@ -125457,6 +125551,7 @@ INSERT INTERFACES HERE
Niklas Gögge,
Noah Mendelsohn,
Noah Slater,
Noam Rosenthal,
Noel Gordon,
Nolan Waite,
NoozNooz42,
Expand Down