Flutter Color 大调整,需适配迁移,颜色不再是 0-255,而是 0-1.0,支持更大色域

在之前的 3.10 里, Flutter 的 Impeller 在 iOS 上支持了 P3 广色域图像渲染,但是当时也仅仅是当具有广色域图像或渐变时,Impeller 才会在 iOS 上显示 P3 的广色域的颜色,而如果你使用的是 Color API,会发现使用的还是 sRGB 色域的绘制。

⚠️ 如果对原因和调整不感兴趣的,可以直接看后面的适配。

那么实现 sRGB 和 P3 有什么区别?简单来说,最直观的感受就是如下图所示的区别,在具备 P3 色域的设备屏幕上, P3 拥有更广的色域,所以可以看到更鲜艳的颜色,而在如今 2024 来看,其实大部分移动设备都已经具备了 P3 色域的硬件支持。

简单看下如下图所示 sRGB(白色三角形)与 Display P3(橙色三角形)的色域对比,从比例上说,P3 广色域可以比 sRGB 多出至少 25% 的颜色支持。

当然, 3.10 中 Flutter 只是为 Impeller 开启了图像渲染是的广色域支持,对于使用 Color 类 API 的情况,依然还停留在 sRGB 下,它没有对在 Flutter Widget 中渲染广色域提供 API 的支持。

所以 Flutter Team 在 2023 年开启了重构 Color 对象的提案,让 Color 也调整为支持 P3 广色域的能力,最直观的就是,原本参数的有效范围 [0, 255] 的整形,而现在颜色分量调整为 [0,1.0] 的浮点

你是不是奇怪,为什么 [0, 255] 变成 [0,1.0] ,但是色域居然还变大了?这其实是因为整形变成了浮点之后,精度带来的可用位数增加:

在此之前,整形的 [0, 255] 颜色也就是每个颜色只有 8 位,从 Dart 层传递到引擎的方式是:ARGB(4x8) 被打包成一个 32 位 alpha-red-blue-green 的 Dart 整数 ,每个 color 有 8 位(255),之后 color 会被转化为 Skia 的 SkColor,然后被处理为引擎中绘制需要的 DlColor ,都是整形数据。

在 Impeller 中,DlColor 会进一步被转换为 impeller::Colorimpeller::Color 是 128 位,每个颜色都具有 32 位标准化浮点,也就是精度让位数变高了。

那为什么提高位数对支持色域很重要?因为 P3 覆盖的颜色较多,8bit/channel 已经不能表达所有 P3 颜色了,所以至少需要用 10bit/channel 来表示

而很明显,在此之前 Flutter 的 sRGB [0, 255] 的整形表示,每个颜色只有 8 位,合起来一个整体 x4 也只有 32 位,而使用浮点 [0-1.0] 表示,则改变了这一格局:

从 3.27 beta 版本开始, dart:ui 中 Color 从最大 64 位变为最大 320 位。

为什么说是从 64 位变为 320 位?因为原本只有一个整型 int ,int 在 dart 里是 64 位,所以原本 Color 最大只有 64 位,而现在增加了 a、r、g、b 四个 double ,也就是多了四个 64 位精度的参数,所以 Color 现一共有 5 个参数,变成了最大 320 位,不过未来 value 会被弃用:

也就是每个 a、r、g、b 每个理论可用为 64 位之多,如果不考虑 value ,Color 就是从原本的 64 位整数更改为 256 位浮点数。

image-20241024163722126

之后,组件将颜色的 TypedData 发送到 C++,而前面说过,在 Engine 层的 DlColor 也调整到 128 位适配 impeller::Color , 也就是 DlColor 是 4 个 32 位的 float 组成,同时往后兼容 sRGB 色彩空间。

不要在意 Dart/64 => C++/32 ,只是语言特性导致的差异。

另外,ColorSpace 也新增了 displayP3 选项,至此整个 Color 广色域支持初步完成,但是真实的 P3 渲染效果目前只在 iOS 上可以看到,后续 Android 需要等 Vulkan Impeller 支持的成熟才能在底层进一步适配支持

代码兼容调整

随着 Color 底层支持的变化,Color 上层 API 也发生了不少调整,其实本次调整算是比较大的 break ,因为色域变化后其实上层 API 调整还是很明显的, 例如最明显的就是不再推荐用 fromARGB ,而是用 Color.from

// Before
final magenta = Color.fromARGB(0xff, 0xff, 0x0, 0xff);
// After
final magenta = Color.from(alpha: 1.0, red: 1.0, green: 0.0, blue: 1.0)

另外,在以前 Color 具有 “opacity” 的概念,所有会有 opacitywithOpacity() 的存在,以前引入 Opacity 是为了让 Color 具有浮点的 alpha 通道,而现在 alpha 是一个浮点值,所以 opacity 显得多余,未来opacitywithOpacity 已被弃用并计划删除:

// Before
final x = color.opacity;
// After
final x = color.a;


// Before
final x = color.withOpacity(0.0);
// After
final x = color.withValues(alpha: 0.0);

另外,如果有对于 Color 的继承最好暂时换成 implements ,也就是不需要再实现 super 相关部分逻辑,另外为什么说是暂时,因为目前 Flutter 团队计划未来 Color 会锁定并通过 sealed 封闭,所以如果通过 sealed 封闭 ,那以后基本不会有 Color 的外部实现了

class Foo implements Color {
  int _red;

  
  double get r => _red * 255.0;
}

其次,现在使用 Color 并对颜色执行任何类型的计算,都需要首先检查颜色的 ColorSpace ,然后再执行计算逻辑,这里推荐使用新的 Color.withValues 方法来执行颜色空间转换:

// Before
double redRatio(Color x, Color y) => x.red / y.red;

// After
double redRatio(Color x, Color y) {
  final xPrime = x.withValues(colorSpace: ColorSpace.extendedSRGB);
  final yPrime = y.withValues(colorSpace: ColorSpace.extendedSRGB);
  return xPrime.r / yPrime.r;
}

使用颜色进行计算,如果不对齐色彩空间可能会导致细微的意外结果,例如在上面的示例中,如果使用不同的颜色空间与对齐的颜色空间进行计算时,redRatio 的差异为 0.09。

最后

事实上,本次调整虽然看起来就像是一个简单的 toDouble 过程,但是它对于 Flutter 的 UI 影响确实不小,不管是颜色 API 的适配,还是计算方式的变化,甚至是色域的支持等场景,如果单从影响效果看,这个合并可以说是影响广泛,整出边界渲染问题其实并非不可能,所以这个合并也是憋了这么久才被合并到 beta ,也许不久之后,我们就可以在正式版本中看到它了。

参考资料:

https://github.com/flutter/flutter/issues/55092

https://github.com/dart-lang/sdk/issues/56363

https://github.com/flutter/flutter/issues/127852

https://github.com/flutter/flutter/issues/127855

https://docs.flutter.dev/release/breaking-changes/wide-gamut-framework

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/907367.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android平台RTSP转RTMP推送之采集麦克风音频转发

技术背景 RTSP转RTMP推送,好多开发者第一想到的是采用ffmpeg命令行的形式,如果对ffmpeg比较熟,而且产品不要额外的定制和更高阶的要求,未尝不可,如果对产品稳定性、时延、断网重连等有更高的技术诉求,比较…

【十九周】文献阅读:图像识别的深度残差学习

目录 摘要Abstract图像识别的深度残差学习研究背景研究动机解决办法Residual LearningShortcut Connections网络结构 实验结果代码实践论文原文总结 摘要 在之前对神经网络的基础学习中,师兄推荐了我去了解一下 ResNet。因此本周对 ResNet 的开山之作—Deep Residu…

MATLAB/Simulink学习|在Simulink中调用C语言-01使用C Function 实现比例运算

前面的博客中,提到如果想将Simulink仿真推进至硬件实验,需要将积木式的仿真搭建,变换成C语言实现,那么如何在Simulink中验证C代码的正确性呢?我将一边学习,一边更新,一边比较不同方法实现C语言&…

基于BP神经网络的手写体数字图像识别

基于BP神经网络的手写体数字图像识别 摘要 在信息化飞速发展的时代,光学字符识别是一个重要的信息录入与信息转化的手段,其中手写体数字的识别有着广泛地应用,如:邮政编码、统计报表、银行票据等等,因其广泛地应用范围…

分享一个免费的网页转EXE的工具

HTML2EXE是一款在Windows系统下将Web项目或网站打包成EXE执行程序的免费工具。这款工具能够将单页面应用、传统HTMLJavaScriptCSS生成的网站、Web客户端,以及通过现代前端框架(如Vue)生成的应用转换成独立的EXE程序运行。它支持将任何网站打包…

ubuntu安装与配置Nginx(2)

1. 配置 Nginx Nginx 的配置文件通常位于 /etc/nginx/nginx.conf,而虚拟主机的配置文件通常在 /etc/nginx/sites-available/ 和 /etc/nginx/sites-enabled/ 目录中。 在/etc/nginx/conf.d目录下新建xx.conf文件,配置文件, nginx -t 检查语法…

C++_day2

目录 1. 引用 reference(重点) 1.1 基础使用 1.2 特性 1.3 引用参数 2. C窄化(了解) 3. 输入(熟悉) 4. string 字符串类(掌握) 4.1 基础使用 4.2 取出元素 4.3 字符串与数字转换 5. …

JAVA WEB — HTML CSS 入门学习

本文为JAVAWEB 关于HTML 的基础学习 一 概述 HTML 超文本标记语言 超文本 超越文本的限制 比普通文本更强大 除了文字信息 还可以存储图片 音频 视频等标记语言 由标签构成的语言HTML标签都是预定义的 HTML直接在浏览器中运行 在浏览器解析 CSS 是一种用来表现HTML或XML等文…

第十五章 Vue工程化开发及Vue CLI脚手架

目录 一、引言 二、Vue CLI 基本介绍 三、安装Vue CLI 3.1. 安装npm和yarn 3.2. 安装Vue CLI 3.3. 查看 Vue 版本 四、创建启动工程 4.1. 创建项目架子 4.2. 启动工程 五、脚手架目录文件介绍 六、核心文件讲解 6.1. index.html 6.2. main.js 6.3. App.vue 一、…

【1个月速成Java】基于Android平台开发个人记账app学习日记——第4天,注册登录功能设计

24.11.03 1.修改项目目录 从今天开始将正式进行功能的设计,首先需要对原来的项目结构进行修改,主要是添加新的文件夹用于存放新的文件。下面进行展示和讲解: 我用红圈圈出了新添加的文件夹,介绍下它们都是干啥的: da…

动态库实现lua网络请求GET, POST, 下载文件

DLL需要使用的网络封装 WinHttp异步实现GET, POST, 多线程下载文件_webclient post下载文件-CSDN博客文章浏览阅读726次。基于WinHttp封装, 实现异步多线程文件下载, GET请求, POST请求_webclient post下载文件https://blog.csdn.net/Flame_Cyclone/article/details/142644088…

unet中的attn_processor的修改(用于设计新的注意力模块)

参考资料 文章目录 unet中的一些变量的数据情况attn_processorunet.configunet_sd 自己定义自己的attn Processor ,对原始的attn Processor进行修改 IP-adapter中设置attn的方法 参考的代码: 腾讯ailabipadapter 的官方训练代码 unet中的一些变量的数据…

深度学习基础—序列采样

引言 深度学习基础—循环神经网络(RNN)https://blog.csdn.net/sniper_fandc/article/details/143417972?fromshareblogdetail&sharetypeblogdetail&sharerId143417972&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link …

Qt中的Model与View5: QStyledItemDelegate

目录 QStyledItemDelegate API 重载公共函数 保护函数 重载保护函数 当在 Qt 项目视图中显示模型数据时,例如 QTableView,每个项目由代理绘制。此外,当项目被编辑时,提供一个编辑器小部件,该小部件在编辑时显示在项…

AI打造超写实虚拟人物:是科技奇迹还是伦理挑战?

内容概要 在这个科技飞速发展的时代,超写实虚拟人物仿佛从科幻小说中走进了我们的日常生活。它们以生动的形象和细腻的动作,不仅在影视、广告和游戏中吸引了无数目光,更让我们对AI技术的未来充满了期待和疑惑。这些数字化身在逼真的外貌下&a…

海浪中的记忆:海滨学院班级回忆录开发

3系统分析 3.1可行性分析 通过对本海滨学院班级回忆录实行的目的初步调查和分析,提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本海滨学院班级回忆录采用SSM框架,JAVA作为开…

文本串的应用(1)

一、文本串的加密解密操作 一个文本串可用事先给定的字母映射表进行加密。 例如,假设字母映射表为: a b c d e f g h i j k l m n o p q r s t u v w x y z n g z q t c o b m u h e l k p d a w x f y i v r s j 则字符串“encrypt”被加密为“tkz…

MCU裸机任务调度架构

第1章 方式一(平均主义) int main(int argc, char **argv){/* RTC 初始化 */bsp_RTC_Init(&rtc);/* 串口初始化 */uartInit(115200);/* LED初始化 */ledInit();while(1){// 任务1(获取传感器数据)// 任务2// 任务3} } 1.1 平均主义的缺陷 获取传感器数据可以600ms去读取一…

【力扣专题栏】面试题 01.02. 判定是否互为字符重排,如何利用数组模拟哈希表解决两字符串互排问题?

题解目录 1、题目描述解释2、算法原理解析3、代码编写(1)、两个数组分别模拟哈希表解决(2)、利用一个数组模拟哈希表解决问题 1、题目描述解释 2、算法原理解析 3、代码编写 (1)、两个数组分别模拟哈希表解决 class Solution { public:bool CheckPermutation(string s1, stri…

【OJ题解】C++实现反转字符串中的每个单词

💵个人主页: 起名字真南 💵个人专栏:【数据结构初阶】 【C语言】 【C】 【OJ题解】 题目要求:给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。 题目链接: 反转字符串中的所…