人眼感知的颜色是光波,计算机要存储它有一定的流程
Dart
连续光谱 -> 采样 -> 量化 -> 数字
采样:把连续光谱拆分成几个分量(通常是R,G,B三原色)
量化:每个分量有限位数表示(如8位 = 0 ~ 255)
通道
Dart
一个颜色由多个通道组成,每个通道是一个数值
RGB有3个通道
通道是颜色的最小组成单元
字节序
Dart
当一个像素被当作多字节整数读取的时候,就涉及字节序
字节序分为:大端 和 小端
像素在内存里怎么存储
Dart
每个通道一般用8bit表示
像素格式 = 通道数量 + 通道顺序 + 每通道位深
常用格式:RGB888(3字节),RGBA8888(4字节), ARGB8888(4字节)
最稳健的构造:Color.fromARGB
Dart
Color.fromARGB(255, r, g, b)
参数顺序 A → R → G → B,每个 0~255。
为什么它最稳?
不需要你拼整数
不需要你处理字节序
通道语义显式,不会搞反
1.颜色转字节
Dart
//取每个格子的颜色
Color color = Colors.black;
if (y < face.items.length && x < face.items[y].length) {
color = face.items[y][x].color;
}
//color.value 是 Flutter Color 对象里的一个 32 位整数,
// 把 A、R、G、B 四个通道打包在一起,格式是 AARRGGBB(十六进制)。
final value = color.value;
final r = (value >> 16) & 0xFF; //右移16位,得到RR
final g = (value >> 8) & 0xFF; //右移8位,得到GG
final b = value & 0xFF; //BB
//填入字节
framePixels.addAll([r & 0xFF, g & 0xFF, b & 0xFF,]);
解析
Dart
1.color.value是什么?
color.value 是 Flutter Color 对象里的一个 32 位整数,
0xAARRGGBB
││││││││
│└┴┴┴┴┴┴┴─ B (蓝, 低 8 位)
│ └┴┴┴┴┴┴─ G (绿, 中 8 位)
│ └┴┴┴┴┴─ R (红, 高 8 位中的低 8 位)
└────────── A (透明度, 最高 8 位)
2.为什么是 AARRGGBB,不是 RRGGBBAA?
逻辑格式:高位是 Alpha,低位是 Blue
便于位运算:R 在 bit 16~23,G 在 bit 8~15,B 在 bit 0~7
注意:这是"逻辑格式",不是"内存格式"。 内存里怎么排,取决于平台字节序。
2.字节转颜色
Dart
//i * 3 + 2 < pixelData.length,防止数组越界,确保b的存在
for (int i = 0; i < validPositions.length && i * 3 + 2 < pixelData.length; i++) {
final (x, y) = validPositions[i]; //第 i 颗灯在 12×12 矩阵里的坐标 (x, y)。
final r = pixelData[i * 3];
final g = pixelData[i * 3 + 1];
final b = pixelData[i * 3 + 2];
// ✅ RGB(0,0,0) 表示该灯珠关闭(透明)
if (r == 0 && g == 0 && b == 0) continue; /// 黑色=关闭,跳过
faceItem.setValue( //设置像素颜色
x: x,
y: y,
value: Color.fromARGB(255, r, g, b), //A=Alpha(透明度,255正常显示)、R=红、G=绿、B=蓝
);
}
pixelData长什么样?
索引: 0 1 2 3 4 5 6 7 8 ...
内容: [R0, G0, B0, R1, G1, B1, R2, G2, B2, ...]
└──第0颗灯──┘ └──第1颗灯──┘ └──第2颗灯──┘