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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

web自动化测试平台开发之核心执行器

web自动化测试平台开发之核心执行器 一、如何从自动化框架到核心执行器二、核心执行器框架逻辑梳理三、核心执行器利用命令驱动执行 一、如何从自动化框架到核心执行器 脚本:底层用了三个内容:pythonpytestselenium,线性脚本,只是单纯的把功能测试用例转…

Rust 力扣 - 2090. 半径为 k 的子数组平均值

文章目录 题目描述题解思路题解代码题解链接 题目描述 题解思路 半径为 k 的子数组平均值 等价于 子数组长度为2 * k 1的总和 除于 2 * k 1 我们遍历长度为2 * k 1的窗口,我们只需要记录窗口内的平均值即可 题解代码 impl Solution {pub fn get_averages(num…

直接内存、死锁、方法句柄

直接内存 1. 不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域 2. 直接内存是在Java堆外、直接向系统申请的内存区间 3. 来源于NIO,通过存在堆中的DirectByteBuffer操作Native内存 4. 通常,访问直接内存的速度会优于Java堆&am…

C++《list》

在本篇当中我们将学习STL中的list,在此list就是我们之前在数据结构学习过的链表,在本篇中我们要来了解list当中的成员函数该如何使用,由于list各个函数的接口和之前学习过的vector类型,因此在学习list的使用就较为轻松。在lis篇章…

【牛客刷题实战】二叉树遍历

大家好,我是小卡皮巴拉 文章目录 目录 牛客题目: 二叉树遍历 题目描述 输入描述: 输出描述: 示例1 解题思路 问题理解 算法选择 具体思路 解题要点 完整代码(C语言) 兄弟们共勉 !&…

vmvare启动freebsd操作系统密码忘记了怎么办?

本章教程,主要介绍,通过vmvare安装的freebsd操作系统,密码忘记了,如何重置密码。 一、重启虚拟机 在重启过程中,按键盘中是数字2,进入单用户模式。 二、进入到shell界面 在出现“Enter full pathname of shell or RETURN for /bin/sh:”直接按回车键。 三、输入命令 mou…

【设计模式系列】代理模式(八)

一、什么是代理模式 代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。代理模式在不直接访问实际对象的情况下,提供了对目标对象的间接访问。通过引入一个代理对象来间接操作实际对…

WPS查询函数VLOOKUP,匹配寻找值自动带入值

想实现在下表输入物料名称后,把上表中的单位自动带入 那就要用到VLOOKUP函数,获取第2个表第1列的值后去第1个表的第1列匹配,匹配到后得到行数值,把第1个表的第2列赋值给第2个表的第2列。 Vlookup函数参数为Vlookup(查找值&#…

sqoop问题汇总记录

此篇博客仅记录在使用sqoop时遇到的各种问题。持续更新,有问题评论区一起探讨,写得有不足之处见谅。 Oracle_to_hive 1. main ERROR Could not register mbeans java.security.AccessControlException: access denied ("javax.management.MBeanTr…

简单说明vuex

vuex 知识结构配置调用 知识结构 vue用于管理公共数据的仓库 配置 state:所有公共数据的初始状态(初始值) export default {state: {count: 0,} };mutations:修改state内容的方法(必须为同步方法) export …

分类算法——决策树 详解

决策树的底层原理 决策树是一种常用的分类和回归算法,其基本原理是通过一系列的简单决策,将数据集划分为多个子集,从而实现分类。决策树的核心思想是通过树形结构表示决策过程,节点代表特征,边代表决策,叶子…

Nature Electronics 用于语音识别的液体声传感器,基于悬浮在载液的钕-铁-硼磁性纳米颗粒

近年来,工程师们开发了一系列越来越复杂的传感器,用于机器人、便携式、可穿戴甚至植入式监测。然后,可以使用最先进的机器学习来分析这些传感器收集的数据,使设备能够识别音频中的特定声音、图像中的对象或其他信息。加州大学洛杉…

NVR批量管理软件/平台EasyNVR多个NVR同时管理支持视频投放在电视墙上

在当今智能化、数字化的时代,视频监控已经成为各行各业不可或缺的一部分,无论是公共安全、交通管理、企业监控还是智慧城市建设,都离不开高效、稳定的视频监控系统的支持。而在这些应用场景中,将监控视频实时投放到大屏幕电视墙上…

【GeoJSON在线编辑平台】(0)项目启动与前言

前言 事情是这样的…… 有这么一个项目,需要开发一个在线的标注平台。以天地图为底图,在天地图上标注出一些特征地物,比如描出农田耕地房屋建筑之类的要素。 这个需求简化一下其实就是一个在线的矢量编辑平台,通过绘制多边形功能…

豆包,攻克数字是个什么工具?《GKData-挖掘数据的无限可能》(数据爬虫采集工具)

豆包,攻克数字是个什么工具? “攻克数字” 指的是 “攻克数字(GKData)” 这样一款工具。是一款针对网页、APP中数据自动解析转表存入数据库的软件,为数据工作者而生。它是一个不会编程也能用的可视化数据解析为标准二…

【成都新篇】龙信科技电子取证实验室,引领科技取证新时代

文章关键词:电子数据取证实验室、手机取证、介质取证、云取证、现场勘查、电子物证 在科技创新的浪潮中,龙信科技成都实验室以其卓越的电子数据取证服务,成为了中西部地区一颗璀璨的明珠。随着新址的搬迁,我们不仅扩大了业务范围…

【C/C++】字符/字符串函数(1)——由string.h提供

零.导言 什么是字符/字符串函数呢? 其实就是一类用于处理字符和字符串的函数。 而其中一部分函数包含在头文件 string.h 中,有 strlen strcpy strcat strcmp strncpy strncat strncmp strstr strtok strerror 等等 接下来我将逐个讲解这些函数。 一.str…

硅谷甄选(11)角色管理

角色管理模块 10.1 角色管理模块静态搭建 还是熟悉的组件&#xff1a;el-card、el-table 、el-pagination、el-form <template><el-card><el-form :inline"true" class"form"><el-form-item label"职位搜索"><el-…

鸿蒙UI开发——基于全屏方案实现沉浸式界面

1、概 述 典型应用全屏窗口UI元素包括状态栏、应用界面和底部导航条。 其中状态栏和导航条&#xff0c;通常在沉浸式布局下称为避让区&#xff0c;避让区之外的区域称为安全区。 开发应用沉浸式效果主要指&#xff1a;通过调整状态栏、应用界面和导航条的显示效果来减少状态…

规划误差降低27%,碰撞率降低33%Senna: 大规模视觉-语言模型与端到端自动驾驶相结合

Abstract 端到端自动驾驶在大规模数据中展示了强大的规划能力&#xff0c;但在复杂、罕见的场景中仍然因常识有限而表现不佳。相比之下&#xff0c;大型视觉语言模型&#xff08;LVLMs&#xff09;在场景理解和推理方面表现出色。前进的方向在于融合两者的优势。以往利用LVLMs…