Display an image at device’s physical resolution


#1

As a 4K-monitor owner, I’m using OS-level scale of 200%, and I’ve encountered the need to guaranteedly display some raster images in web browser at their actual size without ANY scaling.

By actual size, I mean exact mapping of each single image pixel to single physical display pixel (as opposed to CSS pixels that are affected by OS-level or browser-level scaling that does not allow to view image at full available physical clarity/definition/sharpness of the display and also usually results in blur as for raster images).

Note that this has nothing to do with responsive images (displaying different images at predefined set of different pixel ratios in particular).

##Usecases

Some of usecases:

  1. Web-based image viewer. Most of popular desktop image-viewers (e.g. XnView) have ability to display an image at its actual size without any scaling (and blur as a consequence of scaling) (in XnView, via menu “View → Zoom → 100%”). Web-based viewer should have a straightforward way to do the same.

  2. Display tests:

##Syntax

###Keyword for size values

On CSS level, this feature could be implemented as a new keyword like physical applicable to both background-size (for background images) and width / height properties (for IMG elements):

DIV {background-size: physical; }

IMG {
    width:  physical;
    height: physical;
}

Or just IMG {size: physical} with my proposal on width/height shorthand.

Instead of the physical keyword, we could use real, or natural, or actual, or anything else reasonable and clear enough (physical just looks most clear for me).

###Property for per-element pixel ratio

Alternatively, we could have a CSS property like pixel-ratio which value would correspond to JS’s window.devicePixelRatio by default (for example, for scale of 200% in Windows, it would be equal to 2) and could be set on per-element basis:

.example {pixel-ratio: 1; }
/* The element's size and other px-defined properties
   now depend on this local pixel ratio instead of global
  (defined by OS- or browser-level scale) pixel ratio. */

##JS drawbacks

Currently, we are forced to use JavaScript to calculate/restore an approximate compensated (!) image size based on window.devicePixelRatio, but:

  • JavaScript does not work with JavaScript disabled;

  • resulting physical size based on calculated CSS size may be wrong (and is wrong at least in Opera 29 and IE 11 e.g. at Windows-level scale of 186% according to my tests) due to rounding errors caused by nature of floating-point math;

  • recalculating/restoring approximately something that browser already knows exactly looks at least somewhat unreasonable / suboptimal. We can do much better.

Thanks.


Exposing hardware pixel density and other screen metrics via window.screen
One inch is not an inch
API to get list of available fonts
#2

The screen testing use cases sound fairly niche to me, so on their own, I personally wouldn’t think they constitute a strong case.

I am more receptive to the photography / image viewer use case. But there as well, maybe things are a bit more subtle. If the image is very large, and you need to zoom in to inspect the details, you do want a level of zoom that doesn’t blur the details. But if the image already fits the intended viewing area at image-resolution:1dppx, then I am not sure that zooming it out is always desirable. Might depend on the application.

If we should do it, the image-resolution property seems to be a good candidate for a per element property having this kind of switch: https://drafts.csswg.org/css-images-3/#propdef-image-resolution


#3

Why the “pure CSS” requirement? The HTML syntax for responsive images includes srcset with x descriptors which enable you to define the size of high resolution images on the page. Please correct me if I misunderstood your requirements.


#4

Florian, do I understand correctly that the image-resolution property does not currently support what I’ve proposed? In general, I’m open to using e.g. this property if it would be extended to achieve the goal I’ve described. Thanks.


#5

Šime, my point is to guarantee that each image pixel will precisely correspond to exactly one physical pixel, so that there is no any blur.

Note that my proposal is about displaying a same single image pixel-perfectly without blur; this has nothing to do with displaying different images at different pixel ratios.


#6

@MT The image-resolution property lets you ask for 1 image pixel per CSS pixel, or 2, or 3 or any number you want, or a number specified in the image file.

It does not let you ask for 1 image pixel per device pixel, which is what you ask.

If we agreed that having this would be desirable (and I expected heated discussion about that), then it seems to me we could add a value (physical? no-adjust? hardware? etc) to image-resolution asking for 1 image pixel per device pixel.


#7

As others said, ‘image-resolution’ is the property that controls what resolution images are displayed at.

It defaults to specifying the ratio of image pixels to CSS px, as that’s all there’s real use-cases for, but the specific thing you want to do happens to have a convenient hack - set image-resolution: 9999dppx snap;. The 9999dppx says “put 10k image pixels in each CSS px” (thus, “multiple image pixels in each device pixel, as long as the screen resolution is less than 10000x”), then snap says “adjust that so each image pixel is an integer number of device pixels”. The closest such ratio is 1 image pixel to 1 device pixel, getting you the result you want.

Dunno if this is implemented sufficiently to make the hack work, but it’s fine per-spec. Like others have said, I’m not seeing any decent use-cases for doing this that would justify adding a non-hacky method. Any time you have an integer ratio of image pixels and device pixels you won’t have any blur, so just saying image-resolution: from-image snap; should be fine.


#8

Dunno if this is implemented sufficiently to make the hack work, but it’s fine per-spec.

Are you aware of whether any vendor has implemented the image-resolution property? It’s not listed on caniuse, not documented on MDN, and, according to my tests in browsers (Firefox, Opera, IE11, Edge), it has currently no effect neither prefixed, nor unprefixed, regardless of whether it’s applied to IMG elements or to elements with background-image.

Like others have said, I’m not seeing any decent use-cases for doing this that would justify adding a non-hacky method.

Sometimes you said that having a hacky way is a reason to consider adding a nonhacky way to achieve the same. To be fair, “others” here are actually the other one — Florian (Šime seemed not to get the point at all), and he did not reject the idea in general.

Any time you have an integer ratio of image pixels and device pixels you won’t have any blur, so just saying image-resolution: from-image snap; should be fine.

This would probably be fine for preventing from blur, but the image would still be displayed several times larger (e.g. 4x larger at 200% OS-level scale) than needed. Preventing from blur is a secondary goal (even not a goal, but actually a consequence of having no scaling) in my proposal while the primary one is displaying an image without any scaling (regardless of with blur or not) — with one image pixel corresponding to exactly one physical pixel like it’s possible in desktop image viewers.

Web-based image viewers are quite common today, so the proposed feature deserves a legitimate pure-CSS solution.


#9

Are you aware of whether any vendor has implemented the image-resolution property?

I’m not sure anyone’s implemented it, as I said.

Sometimes you said that having a hacky way is a reason to consider adding a nonhacky way to achieve the same.

Context is different there. There, it’s a situation where the group has wanted to do it and recognizes the valuable use-cases it allows, but it’s guaranteed to be slow, so it was less desirable to implement. Seeing that it can be done hackily anyway shows that we won’t be losing anything by implementing it, just making the syntax a little more bearable.

Here, tho, I’m not seeing decent use-cases. The presence of a hacky solution thus actually reduces pressure to implement it, because it means that in the tiny corner cases that care about it, it’s already doable; we don’t need to burden the rest of the platform with a new feature.

the primary one is displaying an image without any scaling (regardless of with blur or not)

That’s what I’m saying is the weak use-case. Aside from a corner-case involving building an image-viewer application on the web, this doesn’t seem to be useful. I’m not even sure it’s useful for image-viewers - taking an image designed for 1x and displaying it on a 3x screen with this feature means it’ll be teensy, only 1/9th the size it was authored for.

Maybe you just want to be able to display CSS images at their “intended” resolution? That’s what the from-image value is for.


#10

I’m not sure how I could be more clear, but here is another take:

If I’m viewing a 4K (3840×2160) image on a 4K monitor, I want to be able to see the entire image pixel-perfectly instead of its 1/4 part with correspondingly lower clarity and the need for unreasonable scrolling. Pixel-perfectly means that physical pixel = image pixel regardless of OS-level or browser-level zoom settings and without dealing with zoomed CSS pixels at all.

Does from-image allow to achieve that and doesn’t it deal with CSS pixels anyway? So if I have 200% OS-level scale, and use image-resolution: from-image, would the image be displayed with physical pixel = image pixel?

This surely makes some sense for a regular webpage context, but not for an image alone, and, all the more, not for an image-viewer web-application in particular. Try to consider the subject in terms of a desktop application instead of a web page.

If I shot a photo, it is not authored for a context of a webpage at all, it is just a photo that I should be able to view at clarity that my display is physically capable of — and that’s what the corresponding mode of a desktop image viewer (e.g. XnView as I’ve described above) is intended for. Viewing image itself as a single self-contained entity has nothing to do with scaling UI in general and with scaling text and in-page images in particular.

And please don’t forget, this is just one of multiple modes of an image viewer. So if a user has expressed an explicit wish to view an image at 100% scale by explicit switching to a corresponding mode in his image viewer, he should be able to do this just like it is possible in desktop image viewers.

CSS-pixel abstraction should not hinder to use full physical resolution when needed.


#11

To accept or reject a feature, shouldn’t the majority of the corresponding WG members explicitly express their opinion, not just one of members?

This could be done via a publicly available official poll system like used in PHP development, so that decisions could be much more impartial, transparent, substantive, and explicitly expressing the opinion of the majority.


#12

We don’t have a strict process of “rejecting” a feature here. What @tabatkins has said is that he doesn’t see widely applicable use cases here. Lack of interest from others may suggest that he has a point.

Otherwise, it seems like what you are trying to do is achievable using JS and will be achievable using (slightly hacky) CSS in the future, once currently specced features would be implemented.

Therefore, maybe the easiest route to prove demand for this feature is to create a JS library that achieves the effect you’re after, and show usage of that in the wild.


#13

A formal voting procedure would save us from guessing and would give us substantial data instead.

As I said, pixel-perfect (one image pixel exactly and guaranteedly corresponding to one physical pixel) result cannot be achieved via JS without native support for addressing physical pixels directly. This is not a pure CSS issue, the entire web platform in general lacks enough level of control.


#14

So the issue here is that we have no way to get the “physical pixels to CSS pixels” ratio without taking OS zoom into account?


#15

Please read the “JS drawbacks” section of my starting message.

Even if we were able to get a floating-point pixel ratio, this could not guaranteedly save us from errors caused by the approximate nature of floating-point math, and, as a result, displaying e.g. 842px-wide image with a calculated width of 841px or 843px.

We should have an explicit straightforward way to say to browser: “Display this image using physical pixels — with no scaling, no approximation, no rounding errors. Just directly map each single image pixel to exactly one physical pixel like desktop applications are able to”.


#16

In general, no. The editors of the relevant specification are usually trusted to make such decisions, with other interested members chiming in when they wish. For contentious issues we do seek consensus from the entire WG, as the WG itself is technically the producer of the spec.

Again, your use-case is already possible, via a slightly hacky syntax that nevertheless reliably achieves what you want. You’re just asking for syntax that achieves your goal more directly. I don’t see a strong need for it, not enough to justify new syntax, particularly since it’s possible in whatever rare cases you want it for. This case is almost always a bad idea; virtually no use-cases for photo display on the web want this, and offering it as an explicit option suggests that it is useful for something and risks people using it inappropriately. Just deal with the fact that your niche use-case happens to still be perfectly doable regardless?


#17

This was actually a sort of rhetorical question. It would be nice to see some feedback from other CSSWG people responsible to make decisions. Tab’s opinion is already quite clear (and thanks for the info about a possible hack involving image-resolution).

The editors of the relevant specification are usually trusted to make such decisions, with other interested members chiming in when they wish.

This is probably not quite an effective system in terms of objectiveness and, eventually, in terms of correspondence between what developers need and what spec editors do. Any single person may easily be wrong. Probability of this as for majority of people is much lower. And having a formal procedure to vote is a good way to involve all decision makers to make decisions — this works great, for example, for PHP.

offering it as an explicit option suggests that it is useful

It is.

your niche use-case

Viewing images in the web is a niche use-case, really? o_O

risks people using it inappropriately

Please note that “people” here means “developers”. Developers typically know what and why they do.

Do you probably think that direct access to device resolution is unneeded or harmful for desktop applications as well, just because you believe platform developers always know better what is better for application developers? Or do you think that web developers are not as smart as desktop-app developers?


#18

This is veering pretty quickly into hostility, but what the hey.

I’m the person generally responsible to make decisions about the Images spec. The group can override me, but we mostly operate under the benevolent dictator model.

This is a deliberate misreading of my statement. Your precise use-case, that of viewing an image such that one image pixel maps to exactly one device pixel, without regard for the screen’s density, the image’s intended density, or the final layout size of the image, is niche.

Devs (of which I am one) very commonly reach for tools without fully understanding how they should be used. Giving people easy access to too-powerful tools risks them innocently misusing them, and is a disservice when you can instead hand them tools of the correct power and hide the high-power stuff behind nuisance walls. You don’t need a jackhammer to pull up tile.

When given easy access to device-pixel information, devs often mess up and accidentally write code that works well on their device and others with similar resolution, but is broken on lesser/greater resolutions. This happens all the time, and you can find tons of examples by looking into the reasoning for introducing “device-independent pixels” or similar ideas in every platform - they’re always justified by “devs keep screwing up pixels and making things too small/big on some devices”.

This is why we instead try to produce tools of the appropriate power level, such as the declarative image-resolution property, or the <picture> element. These use the device pixel information, but directly expose only the minimum of power necessary to achieve useful ends.

Giving people footguns would make me an irresponsible spec writer. Denying people useful tools would also make me an irresponsible spec writer. Exploding the language with a million niche tools would also make me an irresponsible spec writer. My job is to find a good balance between all of these. In this case, the tool you need already exists, it’s just (very slightly) inconvenient to use for your exact purpose. That’s fine, because your use-case is satisfied, and it’s not common enough to justify growing the language to make it more convenient. (In my opinion.)


#19

Looks like you tend to see hostility whenever someone intends just to get a substantive answer.

As I said, this is a common standard feature of native image viewers. Web apps are currently trying to compete with native apps, but actually cannot since the web platform lacks the enough level of control.

So what makes native applications different from web applications in terms of access to device pixels?

For some reason, I’m almost sure that, once implemented, image-resolution will not work using your suggested hacky way, and, once bug-reported, there will be arguments that this is niche, so won’t fix. %)


#20

Nothing. As I said, devs screw this up in native apps all the time, leading to those native platforms to introduce device-independent lengths and recommend using them nearly-exclusively.

The web has learned a lot about being careful about what level of power to expose, in what form, to developers, largely from the missteps of native platforms.

lol ok