-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
+115
−22
Merged
Changes from 15 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
978645b
Allow an image to indicate its own density and correct its intrinsic …
noamr 08e4a01
Use image request, refactor to use 'prepare' algo
noamr a0ff979
nit
noamr 9c1e85e
Fix CR comments
noamr 873dfb5
Bail from metadata reading for non-origin-clean images
noamr 7f09870
Apply same-origin clarifications after #5165
noamr cd6d4db
Nit req/img
noamr 84fce1d
Declare an img pointing to img's req
noamr 71af446
Use better terms for cross-origin
noamr fc718c4
More nits
noamr 00b5724
Fix typo px -> pt
zcorpan 9f5e047
Fix source formatting
zcorpan 98ccb1d
Apply review comments
noamr 550cd15
Apply review comments
noamr da9f571
CR comments
noamr 441ca72
Fix wrong variable references (img does not exist at the call sites) …
domenic File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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> | ||
|
@@ -28054,14 +28055,31 @@ was an English <a href="/wiki/Music_hall">music hall</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> | ||
|
||
<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 | ||
|
@@ -28345,7 +28363,8 @@ was an English <a href="/wiki/Music_hall">music hall</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> | ||
|
@@ -28583,13 +28602,16 @@ was an English <a href="/wiki/Music_hall">music hall</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> | ||
|
@@ -28609,9 +28631,10 @@ was an English <a href="/wiki/Music_hall">music hall</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 | ||
|
@@ -28653,7 +28676,8 @@ was an English <a href="/wiki/Music_hall">music hall</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> | ||
|
@@ -28687,7 +28711,6 @@ was an English <a href="/wiki/Music_hall">music hall</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
|
||
|
@@ -28701,6 +28724,75 @@ was an English <a href="/wiki/Music_hall">music hall</a> singer, ...</code | |
</ol> | ||
|
||
|
||
<h6>Preparing an image for presentation</h6> | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this still true? The discussion seems pretty settled. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
@@ -29277,8 +29369,9 @@ was an English <a href="/wiki/Music_hall">music hall</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> | ||
|
@@ -29288,7 +29381,8 @@ was an English <a href="/wiki/Music_hall">music hall</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> | ||
|
@@ -125457,6 +125551,7 @@ INSERT INTERFACES HERE | |
Niklas Gögge, | ||
Noah Mendelsohn, | ||
Noah Slater, | ||
Noam Rosenthal, | ||
Noel Gordon, | ||
Nolan Waite, | ||
NoozNooz42, | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.