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

Add "HDR AVIF" image support #6504

Open
gregbenz opened this issue Oct 23, 2022 · 8 comments
Open

Add "HDR AVIF" image support #6504

gregbenz opened this issue Oct 23, 2022 · 8 comments

Comments

@gregbenz
Copy link

The current feature tracking for AVIF and JXL is not complete. Implementation of AVIF does not guarantee support for HDR images (ie they may not properly render images with the PQ or HLG transfer functions requested in the CICP data for the image). For example, FireFox v105.0 renders these images extremely dark and Safari clips highlights in iOS 16.0. So they render AVIF images, but HDR AVIF images are not properly supported.

Given legacy file formats like JPG do not support HDR, it is very important to have a clear understanding of browser support for HDR images. AVIF is properly supported in Chrome (and looks amazing with a 1000+ nits screen like the M1 MacBook Pro).

For example/test images and more information on HDR display, see https://gregbenzphotography.com/hdr/.
Note, this name is confusing and has nothing to do with the "HDR" many people know. This is a different technology which requires supporting display hardware for brighter pixels, and is already available on most Apple devices sold in the last 4 years.

Note: it would also be very useful to track HDR JXL support. Chrome already provides proper support if you enable a developer flag. Adobe Camera RAW v15 supports exporting of HDR images as JXL files. See the 9:20 point in this video for a demo: https://gregbenzphotography.com/photography-tips/acr-15-adds-high-dynamic-range-output/

@mdrejhon
Copy link

mdrejhon commented Nov 15, 2022

HDR AVIF support while supporting drawing to HDR CANVAS is functioning in these:

  • Safari 16.1 or later (e.g. new M2 iPad or Ventura on Apple XDR displays), CANVAS tag in Safari supports "display-p3"
  • Chrome Canary 108 or later, CANVAS tag in Canary supports "rec2100-pq" and "rec2100-hlg"

For Canary:
Install latest Chrome Canary -> chrome://flags --> Experimental Web Platform features -> Enabled -> Restart Browser

Experimental HDR canvas/webgl support has not yet been migrated outside Canary, but we are witnessing incubating of HDR in two different browser lines.

We are doing early bleeding edge work in this territory, with upgrading TestUFO to support HDR

@gregbenz
Copy link
Author

@mdrejhon Thank you for that info.

Do you know of any working examples showing how to use the HDR CANVAS with Safari to show an HDR AVIF image properly?

Chrome supports HDR AVIF normally on MacOS (no need for the HDR canvas there), but not iOS. Do you know of any working examples for Chrome that would be supported on an iOS device?

@mdrejhon
Copy link

mdrejhon commented Nov 15, 2022

@gregbenz thanks for your follow up!

What I am doing requires Canary (not retail), with a custom chrome://flags enabled. I have only tested this on Windows platform at this time. Your photography page looks great in Chrome on Windows!

We needed that new experimental HDR Canvas (Works! Takes a bit of setup tho), due to animations we do with HDR AVIF sprites. Our canvas is using using rec2100-pq (via IEEE754 FP16 at 48 bits per canvas pixel) format and HDR AVIF written to it looks the same as HDR AVIF in IMG SRC now. We have to make 3 calls (canvas creation & configuring the colorspace) before it worked. Also we found out that creating a canvas using "display-p3" works under the newer Safari 16.1 (MacOS Ventura or M2 iPad), but we don't yet have data.

We've already created an internal site that uses HDR CANVAS, that successfully shows HDR AVIF images in Chrome Canary (Experimental Fetures = ON). This is a brand new feature only available in certain browser engines.

It is essentially a working HDR version of https://www.testufo.com (30 selectable tests at upper right corner such as https://www.testufo.com/eyetracking and https://www.testufo.com/ghosting and https://www.testufo.com/photo)

We plan to launch an HDR compatible version of this within weeks, as we work with display manufacturers / reviewers (e.g. LinusTechTips, RTINGS etc) on upcoming high-refresh-rate HDR displays -- This will allow you to test on Mac. Keep tuned -- I will follow up here.

If you'd love to be a private beta tester of TestUFO HDR, please contact me privatey at mark [at] blurbusters.com -- we believe we're probably going to be one of the world's first HTML5-based HDR-display motion testing website. (Our motion tests are used in some scientific papers, by manufacturers (I'm cited in Samsung/NVIDIA research papers) as well as by over 500 content creators, some with millions of subscribers -- https://www.blurbusters.com/area51 ...)

Since you have paved some groundwork; I have questions:

(1) For end-user testing purposes, we are looking for a HDR colorswatch test similiar to your (hdr-test-greg-benz.avif). How did you create that HDR swatch? We need something similar to that.

(2) Also, we are looking for a HDR color picker since the background color is configurable in some of our tests, and we want to allow people to select HDR colors for our canvas. We use but that's an SDR color picker. Has anyone created an open source HTML5 HDR colorpicker that I could use in place of the HTML5 standard?

@gregbenz
Copy link
Author

@mdrejhon Will be very interesting to see your page! Does this work with latest Safari on iOS as is? A key missing piece at this time is support for HDR photography on iOS devices, so that would be very powerful.

(1) I created that image in Photoshop. Please feel free to use it on your site for your testing. If you feel so inclined, a link back to https://gregbenzphotography.com/hdr/ would be appreciated, but feel free to use as you need. Note that it is a controlled image in PS (real measurable stops - ie absolute rendering), but not as an AVIF due to tone mapping in the browser (ie relative rendering, with no metadata available to control intended HDR luminance - though you could probably hack that if you assume other browsers will follow Google's lead for tonemapping).

(2) I'm not aware of any such HDR picker. I'm not even aware of a decent way to create CSS for HDR (I've read some support over-range values like L>100% is planned, but have yet to see it - and I believe even CSS4 is incomplete for HDR). Other methods generally fail, as screen recording and screenshots generally clip to SDR limits. Photoshop has a great picker for pulling from anything on screen, but it also clips to SDR limits.

@mdrejhon
Copy link

mdrejhon commented Nov 17, 2022

I am in communications with a team member from Chromium who has given me instructions on how to properly activate HDR canvas. I have extrapolated it to Safari and would love for you to test the brand new Safari HDR Canvas implementation (if it actually works).

Observation that Safari successfully creates DCI-P3 Canvas

I notice canvas creation fails on Safari if I attempt rec2100-hq or rec2100-hlg canvas (both succeeds in Canary) but creating a display-p3 canvas succeeds. Which means Safari at least seems to internally supports HDR canvas already, so I would be very happy for you to test it if actually works! I got your email, I will contact you today.

There is apparently a 3-step method (that I think is identical in both Safari and Canary, just with different HDR colorspaces), involving creating the canvas, followed by two additional calls to configure it -- before HDR AVIFs successfully looks the same in a canvas as outside.

On Canary, my canvas uses 48 bits per pixel as three IEEE754-derived FP16s per pixel (I am currently using rec2100-pq for now). One that I can byte-encode manually to create custom HDR colors via .getImageData() then .putImageData() the modified HDR pixels.... Chrome team told me this works and I'm rolling with this temporarily until a color picker API becomes available. It's hacky and requires knowing how to calculate HDR pixels. But it bypasses lack of ability to set HDR colors, and I can create a 2nd canvas as a HDR swatch to bitmap-plot to my main HDR canvas. So I can create HDR pixels via low-levelish means. The workarounds I have to do at this early juncture...


(To be crossposted / moved to a different github issue)

Lack of HDR Color Picker Problem

Shame about the lack of a HDR color picker, I may have to hack one together that is nominally similar to the Unity gaming engine's HDR color picker ( https://docs.unity3d.com/Manual/HDRColorPicker.html )

image

This would be very hacky but would continue to let me use the existing RGB color picker system, but supplemented by a 2nd adjuster representing intensity. I would need formulas to convert it to DCI-P3 or Rec2100 (PQ and HLG verisons), and it would have to clip results for things outside gamut. The formulas are easy if I'm coming from CIE XYZ values.

It would be a very imperfect solution, but I am open to temporary interim color picker standards that does not require too much development time (e.g. allow me to continue using existing RGB color picker). For my use case, initially, fine-tunability of HDR color shades is less critical than ability to pick HDR colors outside the #000000-#FFFFFF color gamut.

Long term, I'd love to see a <form type="hdr-color"> or something, which would pop up the operating systems' preferred HDR color picker (dci-p3, rec2100-pq, rec2100-hlg, etc), which I can then use along with formulas to convert between HDR color gamuts or slip to SDR, or internally use a floating point linearized rgb format that can be converted to any HDR color picker. I need to research what W3C and WHATWG is thinking about, long-term for a HDR color picker.

Basically I need to be able choose HDR colors for the background colors of https://www.testufo.com/chase and https://www.testufo.com/ghosting -- and I currently use <form type="color"> as the color picker.

Communicating HDR Colors Across Different Browsers

Example:

  1. User One does colorpicker in Chrome Canary (rec2100-pq)
  2. User One Shares URL to Safari
  3. User Two sees result with same HDR color value (display-p3)
  4. My software can optionally inform user whether color was preserved or clipped during colorspace conversion.

I need to find a HDR-colorspace-independent interim standard of sharing HDR colors. For encoding in variables, in parameters, etc, that is only converted/clipped to specific colorspaces upon rendertime (e.g. SDR, rec2100-pq, rec2100-hlg, and display-p3), with the ability to alert user if the color was clipped/adjusted.

So I dislike colorpicker proposals that are completely colorspace-specific without also providing a colorspace-independent method of encoding colorspace -- e.g. the ability to query the color coordinates in CIE (X,Y,Z) and encode them as floating point in a URL parameter that works in BOTH Chrome (rec2100) and Safari (dci-p3).

Sure, the colorpicker can be colorspace-specific for best UX experience on specific platforms. But any future W3C or WHATWG colorpicker API should be standardized to internally provide generic coordinates (CIE XYZ) that I can choose to share to other different browsers. So if they have to do different encodings, I feel any future HDR colorpicker standard should at least be able to provide native colorspace values (OS/browser preferred) as well as original CIE XYZ's.

color(xyz 0.13 0.12 0.04)

versus:

 color(sRGB 0.41587 0.503670 0.36664);
 color(display-p3 0.43313 0.50108 0.37950);
 color(a98-rgb 0.44091 0.49971 0.37408);
 color(prophoto-rgb 0.36589 0.41717 0.31333);
 color(rec2020 0.42210 0.47580 0.35605);

So if the upcoming colorpicker standard returns CSS4 formatting as above -- https://www.w3.org/TR/css-color-4/ -- I want to be able to query xyz format, not just the platform's native preferred colorspace format. Even if the user was presented a color picker for a specific HDR colorspace. That way, I can standardize HDR communications between browsers. Ideally, developers should not have to force the use of copypasta formulas to get generic CIE XYZ's -- since it's essentially the root standard of all display color spaces.

Could even be 3 full precision floats -- easily based64'd as a single URL parameter (replacing the #000000-#FFFFFF), so that it doesn't lose bits when translated to rec2100-pq FP16 triads vs rec2100-hlg FP16 triads vs dci-p3 (whatever format Safari uses). Many web standards say it's not the Right Way, but I need an interim HDR-agnostic format that is colorspace-convertible and URL-parameter-embeddable. So this, nominally, needs to be at least standardized, for communicating of CIE coordinates across the Internet, whereupon Chrome and Safari can share reasonably-very-close HDR colors successfully via the same value (despite different HDR colorspaces).

This is probably best organically done as XYZ's floats from CIE (CIE 1931 or newer), kept at extreme high precision (far beyond FP16), since HLG will compress bits (lose precision) at one end of the curve, when converting to final gamut (FP16). So the HDR-colorspace-independent 'communication'/'conveyance' format cannot be FP16, and thus need far more than 48bit to prevent less-than-48bit precision on any final HDR formats. CIE XYZ's can easily be converted/clipped to any theoretical color gamut (SDR, rec2100-pq, rec2100-hlg, display-p3) via standard formulas, so I like that as a communications/conveyance format for specifying HDR colors.

So I need web standards to support CIE XYZ's or other compromises like linearized RGB's via floats outside 0.0 thru 1.0 range -- something colorspace independent that is easily translated/clipped between color gamuts. It won't be perfect, but we need a common conveyance standard -- and I can't think of anything better than plain old CIE coordinates...

After all, all colorspace standards are simply triangles on CIE after all (or polygons for multi-primary displays, e.g. addition of pure cyan and/or yellow pixels in addition to RGB -- for HDR on future Quattron-style displays). CIE coordinates doesn't care how many primaries a display has, or even if the display is two-color or monochrome! It's just clipped to gamut in final conversion steps. So, beautifully generic, as a standard used since year 1931 (with only minor corrections since)...

So encoding as XYZ's is the most "organic" to share HDR color values between platforms (of different colorspaces) in things like URL parameters. But I can go with any other solution (extended linearized RGB) that are formula-convertible to CIE coordinates, and then consequently to destination gamuts and apply any formulas needed (e.g. gamma correction if required).

This solves the problem is how to embed a bookmarkable HDR color into a URL parameter (all TestUFO URLs are bookmarkable, including its color arguments), so I would have to come up with a common encoding standard that is HDR-colorspace-independent (either extended linearized RGB, or as CIE XYZ), so I can accomodate both Safari and Canary with the same bookmarked TestUFO URL!

What a rabbit hole HDR is... ;)

@gregbenz
Copy link
Author

gregbenz commented Nov 17, 2022

Seems like some form of XYZ would make sense as an adaptable standard for a PCS (unlike LAB)
https://svgees.us/ICC%20July%202020/Towards%20an%20HDR-capable%20ICC%20PCS.html

Ultimately, I assume the Windows/Apple CMMs will probably support this (though it should be simple to do color transforms to a limited set of working RGB colorspaces to/from XYZ with libraries such as https://colorjs.io/).

@mdrejhon
Copy link

mdrejhon commented Feb 11, 2023

Photo proof of HDR AVIF successfully doing brighter-than-white on my HDR display, in a HDR <canvas> (rec2100-pq in fp16 format, 48-bit per pixel).

image

Real brighter-than-white, brighter than RGB #FFFFFF.

Chrome version 110+ with chrome://flags "Experimental Features" = ON, with canvas created via:

// Create HDR canvas in Chrome/Edge 110+if enabled in chrome://flags "Experimental Features ON"
surface = canvas.getContext("2d", {colorSpace:'rec2100-pq', pixelFormat:'float16'});
canvas.drawingBufferColorSpace = 'rec2100-pq';
canvas.unpackColorSpace = 'rec2100-pq';

Then merely draw true HDR canvas supporting HDR JPG (Edge) or HDR AVIF (Edge/Chrome) via standard drawBitmap function used for PNG/JPG. You can detect rec2100 failures via existing APIs.

  • If display is HDR
  • If browser is chrome
  • If rec2100-pq canvas creation succeeds

For Mac, the equivalent HDR canvas is:

  • If display is HDR
  • If browser is safari
  • If display-p3 canvas creation succeeds

Then true HDR AVIF definitely works fine when all the respective three's succeeds.

For the task of "display and browser is HDR" HTML5.x APIs that can be used for HDR capability detection, I have found these and using some combinations gives me confidence of brighter-than-white pixels being able to be pushed out of the GPU output;

  • window.matchMedia("(dynamic-range: high)").matches
  • window.matchMedia('(color-gamut: p3)').matches
  • window.matchMedia('(color-gamut: rec2020)').matches
  • screen.colorDepth > 24

I haven't tested consistency across Chrome vs Safari, except for the first one. Be warned, you can have a "display is HDR but the browser is not HDR" detection situation in some browsers, you must have both concurrently in order for HDR AVIFs to work. So that's why you need to check if HDR canvas creation succeeds; before feeling confident you are preserving HDR to the GPU output (DisplayPort or HDMI).

And remember, regular re-automatic-detect is sometimes needed.

Dragging windows on a multimonitor from a HDR display to SDR displays or vice versa will automatically change the true/false result of detection APIs, based on which display has more than 50% of the pixels of the window (same behavior for detecting sudden changes to screen resolution).

Also, HDR canvas works fine on SDR displays too! Colors will just be clipped. You can detect for this when window.matchMedia("(dynamic-range: standard)").matches ...

This will not necessarily prevent the successful creation of a HDR canvas on SDR-only displays (even single monitor systems), as long as the browser supports HDR canvas. It just means colors stay stubbornly in SDR until you drag the window back to a HDR display, whereupon the HDR pops and (seems) to work fine.

So you thusly need to detect HDR display, HDR browser and HDR canvas creation success, my experience is this triple-true situation means you're confident HDR pixels are preserved all the way to the operating system and its graphics driver.

@gregbenz
Copy link
Author

Related topic: Ultra UDR JPG (gain map): #6759

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants