flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
165.37k stars 27.29k forks source link

Implement wide gamut color support in the Framework #127855

Closed gaaclarke closed 1 week ago

gaaclarke commented 1 year ago

After https://github.com/flutter/flutter/issues/55092 we have wide gamut support in the iOS engine, and after https://github.com/flutter/flutter/issues/127852 we'll have wide gamut support on Android.

Users have asked for ways to represent those colors inside of the framework so they can do things like:

Container(color: Color.displayP3(0.0, 0.0, 1.0, 1.0))

It's important that we don't change the meaning of old colors, that's why a normalized constructor for the Display P3 colorspace would be preferable.

I presume users would want to clip wide gamut colors to sRGB if their app is run on a device/platform without wide gamut support. It's unclear to me if that's acceptable to designers. If someone is making an iOS only app though they can pretty confidently known that wide gamut support will be supported.

This should have almost no effect on engine performance since the capability for wide gamut will already exist by virtue of having support for images.

We have to consider also the ramifications for Web and Desktop platforms. The absence of support for wide gamut colors in those platforms will become more apparent if the framework is updated to support them.

jtkeyva commented 1 year ago

awesome, thanks for clarifying this here. from a designers perspective, i don't know what good wide gamut images are without wide gamut UI or wide gamut video. i feel this is essential for a consistent ui/ux that has all the polish, shine and vibrant interface that consumers want and need.

what about video? there is no mention of wide gamut color is/can be in video? do you need a separate issue for that?

the user experience is what matters most to the users. this "dull / flat" color and the touch response latency issues (and 2 finger scroll speed lol) are essentially the only thing that doesn't feel native. if you patch those up, flutter is essentially indistinguishable from native.

go team! go flutter! thanks for listening to the community and implementing what's important to us :) Cheers!

Maistho commented 1 year ago

We have to consider also the ramifications for Web and Desktop platforms. The absence of support for wide gamut colors in those platforms will become more apparent if the framework is updated to support them.

I don't know about Desktop, but Web supports wide gamut colors for both images and UI. Theres a good article on the chrome developer blog regarding this: https://developer.chrome.com/articles/high-definition-css-color-guide/

Around 80% of people already use browsers that support wide gamut colors: https://caniuse.com/css-color-function

jabedamin commented 1 year ago

After #55092 we have wide gamut support in the iOS engine, and after #127852 we'll have wide gamut support on Android.

Users have asked for ways to represent those colors inside of the framework so they can do things like:

Container(color: Color.displayP3(0.0, 0.0, 1.0, 1.0))

It's important that we don't change the meaning of old colors, that's why a normalized constructor for the Display P3 colorspace would be preferable.

I presume users would want to clip wide gamut colors to sRGB if their app is run on a device/platform without wide gamut support. It's unclear to me if that's acceptable to designers. If someone is making an iOS only app though they can pretty confidently known that wide gamut support will be supported.

This should have almost no effect on engine performance since the capability for wide gamut will already exist by virtue of having support for images.

We have to consider also the ramifications for Web and Desktop platforms. The absence of support for wide gamut colors in those platforms will become more apparent if the framework is updated to support them.

This is great, thank you! This step really is crucial to completing the support for wide gamut colours. Absolutely agree with the points made by @jtkeyva.

I'm not sure how many variations to this there are but, when designing, I'd choose the Colour space to work with in the design software based on the target platform. Then input varying colour codes for different objects. If we had to specify the colour space for every object, wouldn't be scalable. If we could set the colour space at an app level however, then whatever RGB values we enter would get converted ideally based on what the device supports. So essentially, whatever colour space we set on the design project, we'd apply to the app. That way the output is consistent.

jabedamin commented 1 year ago

@gaaclarke If I apply an App Icon directly in xcode, as an iOS developer would. And the image is created using displayP3 color profile. Is there any reason flutter would override how that icon is displayed?

It seems, the app icon even if configured in xcode, doesn't use displayP3 and looks duller. Is that expected behaviour?

gaaclarke commented 1 year ago

@jabedamin in the future can you file issues when you run into a novel problem please =)

It seems, the app icon even if configured in xcode, doesn't use displayP3 and looks duller. Is that expected behaviour?

App icon rendering is handled by the operating system, not Flutter. Flutter just sets up the xcode project so it's surprising to me if you aren't getting the right colors. Are you using some software to generate the different icon sizes that might be throwing it away? I'd make sure all the sizes have the correct colorspace and colors. If you can't figure it out feel free to file an issue and make sure to send a screenshot and the icon images.

jabedamin commented 1 year ago

App icon rendering is handled by the operating system, not Flutter. Flutter just sets up the xcode project so it's surprising to me if you aren't getting the right colors.

Thanks for getting back to me, very helpful to have the clarification. I thought the same, just wanted to rule out Flutter as the cause so I know where to point the issue. When I built the equivalent on iOS using swift/xcode exclusively I used the same brand files but didn't have the issue.

Are you using some software to generate the different icon sizes that might be throwing it away?

I followed iOS and Flutter guidelines for implementing AppIcon in terms of size/colors. Logos/Branding created in Sketch using displayP3 profile and exported using iOS config. So it should work..

MaherSafadii commented 3 months ago

this is a major issue in flutter which should be fixed asap imo.

gaaclarke commented 2 months ago

I've written a design doc for this: https://docs.google.com/document/d/1JaJg34uB7bVssr3oyS-QLe2FlZHUIHcR6aG83JlKwak/edit

bernaferrari commented 2 months ago

My feedback:

knopp commented 2 months ago

Can't add comments to the design doc. I'm wondering if 320bits for Color instance is bit of an overkill. Android Color packs everything into 64bits even for wide gamut (16 bits per channel, 10bit alpha, 6 bit colorspace). This might be problematic when compiling to javascript, but I'm not certain if supporting wide gamut for web/js is even feasible.

bernaferrari commented 2 months ago

web supports rec2020, p3 and srgb: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/color-gamut

Theoretically, you could make Flutter also support rec2020 which is better than p3 😛

https://developer.chrome.com/docs/css-ui/high-definition-css-color-guide

Also this: https://developer.chrome.com/docs/css-ui/access-colors-spaces

Screenshot 2024-07-22 at 19 05 47
knopp commented 2 months ago

Right, but that's for CSS. I'm wondering if this works with CanvasKit/WebGL.

gaaclarke commented 2 months ago

Thanks for the suggestions, I will grant comment access if requested. Responding here is fine for me too.

  • Maybe it makes sense to provide a way to change the default color scheme of an app to be p3 only, without changing every single Color object. Maybe something like kColorSpace = .p3 and then it applies automatically unless otherwise written. CSS allows a fallback option for non-p3. Not sure if we want that, but it is interesting you can have both.

If someone wants to do that just to be less verbose they can create a helper function or extension method to be less verbose. I don't think someone will want to across the board blow out the saturation of their app by switching from srgb to displayp3 though so I don't think it's important to have some sort of global switch for colors that have already been specified in sRGB.

Android has a very nice Color API, maybe some inspiration could be taken from there (https://developer.android.com/reference/kotlin/android/graphics/Color). It supports rgb/srgb/xyz/lab,as well as many (many!) helper funtions.

My take is that those may be better suited as libraries since they are great to have but not required to be in the engine to get that functionality. It's worth filling an issue regardless of this proposal.

I'm wondering if 320bits for Color instance is bit of an overkill. Android Color packs everything into 64bits even for wide gamut (16 bits per channel, 10bit alpha, 6 bit colorspace).

The design doc is proposing 2 things, a public API and how to hook that public API to the engine (which includes how things are stored under the hood). I feel strongly that doubles is what we want for our public API. I go into a few of the options for storage in the design doc because I was concerned at first about the size too. However I'm less concerned after thinking about it for the following reasons:

1) Most people will be using canonicalized colors (shared immutable instances). 1) A UI will probably have like 100 colors (ignoring images and gradients). 1) Storing things in doubles avoids oddities where the color component queried isn't the same as what you sent it. 1) The dart team seemed receptive to expanding support for Float32x4 if we want to shrink it. We need a const constructor for it (https://github.com/dart-lang/sdk/issues/56363) for one.

This might be problematic when compiling to javascript, but I'm not certain if supporting wide gamut for web/js is even feasible. Right, but that's for CSS. I'm wondering if this works with CanvasKit/WebGL.

I'm not sure either. Browsers can render wide gamut images, I'm not sure what all the steps are to connect flutter to that or if it's possible today. For our purposes I think we should assume it is or will be possible.

Theoretically, you could make Flutter also support rec2020 which is better than p3 😛

Thanks for pointing this out. This design allows for the addition of new colorspaces in the future. Right now display p3 is a real profile we can target on a large swath of devices we care about.

gaaclarke commented 1 week ago

There's no further planned work here. All the related PR's have landed, rolled and stuck.

squirelboy360 commented 1 week ago

There's no further planned work here. All the related PR's have landed, rolled and stuck.

I just saw this, how can we use this. Is it enabled by default?

gaaclarke commented 1 week ago

I just saw this, how can we use this. Is it enabled by default?

It's available by default in the framework, see https://github.com/flutter/engine/blob/a49703b6383e54b48ebb710a92d81dffd0bd3d33/lib/ui/painting.dart#L118

It will however only be rendered as a wide gamut / high bitrate color on iOS. There is the design doc above that you can check out too ( http://flutter.dev/go/wide-gamut-framework ).