<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[在RGB565屏上实现RGB888屏的显示质量]]></title><description><![CDATA[<p dir="auto"><strong>在RGB565屏上实现RGB888屏的显示质量</strong><br />
RGB888 → RGB565 量化抖动：一种基于视觉感知的实现</p>
<p dir="auto">在现代 UI 设计中，渐变色早已不是点缀，而是塑造品牌质感、传递产品调性的核心语言。从系统灵动背景到车载 HMI 沉浸式界面，渐变让冷冰冰的屏幕拥有了温度与层次。</p>
<p dir="auto">但硬件选型的现实，让不少嵌入式与 UI 开发者陷入两难：选用 RGB888 屏，色彩细腻过渡自然，却意味着更高的成本、更大的功耗开销、更慢的刷新帧率；选用 RGB565 屏，成本与功耗更低、交互更流畅——可一旦用上渐变色，量化伪影立刻暴露无遗。</p>
<p dir="auto">这套方案并非简单的位深截断或传统抖动算法，而是基于人眼视觉感知模型与色彩空间特性，重新设计量化误差的扩散与分布策略，从而抑制 RGB888 到 RGB565 有损量化过程中不可避免的视觉伪影。</p>
<p dir="auto">实际效果：在 RGB565 屏上，渐变过渡不再出现明显的色阶断层，低饱和区不再偏绿，色彩基调与整体观感更接近原始 RGB888 图像。下文通过五组典型场景的对比实验来验证。</p>
<p dir="auto"><strong>一、问题背景：为什么 RGB565 会出现伪影</strong><br />
RGB565 用 16 bit 表示一个像素：R 占 5 bit、G 占 6 bit、B 占 5 bit。相比 RGB888 每通道 8 bit，量化到 RGB565 相当于对每个通道做低位截断。最直接的做法是右移舍入（truncation / 四舍五入），但这会引入确定性的量化误差：</p>
<p dir="auto"><strong>量化误差 = 原始值 − 量化后重建值</strong></p>
<p dir="auto">在色彩平缓过渡的区域（渐变、阴影、低饱和度肤色等），这个误差在空间上高度相关，人眼会把相邻的同色误差“连成一片”，就看到了所谓的色阶断层（banding）。而 G 通道多 1 bit、R/B 少 1 bit 的不对称，又会让低亮度区域整体偏向绿色——这正是 RGB565 渐变最常见的两类伪影。</p>
<p dir="auto"><strong>二、传统方案及其局限</strong><br />
截断 / 四舍五入：实现最简单，误差全部“丢弃”，在渐变区必出断层。</p>
<p dir="auto">Floyd–Steinberg 误差扩散：把当前像素的量化误差按比例扩散到右侧、下方邻近像素，用空间噪声“打散”色块，是印刷/图像领域经典的做法。伪代码：<br />
for each pixel (x, y):<br />
old = image[x, y]<br />
new = quantize(old)          # 量化为 RGB565 可表示的最近色<br />
error = old - new<br />
image[x+1, y  ] += error * 7/16<br />
image[x-1, y+1] += error * 3/16<br />
image[x  , y+1] += error * 5/16<br />
image[x+1, y+1] += error * 1/16</p>
<p dir="auto"><strong><strong>FS 抖动确实能消除大面积断层，但直接搬到 RGB565 上仍有不足：</strong></strong><br />
① 它在线性 RGB 空间均匀扩散误差，而人眼对亮度（尤其是暗部）的敏感度是非线性的；<br />
② R/B 与 G 的位深不同，统一扩散系数会放大 G 通道的视觉残留；<br />
③ 对低饱和度、接近灰阶的区域不够敏感，容易残留偏色。</p>
<p dir="auto"><strong>三、改进思路：面向视觉感知的量化抖动</strong><br />
核心思想：不追求“数值误差最小”，而追求“视觉误差最小”。具体从四个方向改进。<br />
<strong>1. 转换到感知更均匀的色彩空间</strong><br />
先把 RGB 转到 CIE Lab 或 YUV/YCoCg 空间再量化、扩散。Lab 的 L* 通道近似与人眼亮度感知成线性，在 L* 上做误差扩散，可以避免暗部被过度量化、亮部浪费精度的问题。<br />
<strong>2. 按通道视觉权重分配误差</strong><br />
利用人眼对绿通道最敏感、对蓝最不敏感的特性，为 R/G/B 的量化误差设置不同权重。例如对亮度（Luma）误差赋予更高优先级，让有限的 16 bit 位宽优先保证明暗过渡平滑。<br />
<strong>3. 误差扩散系数的自适应化</strong><br />
根据局部梯度与饱和度动态调整扩散强度：在平缓渐变区加强扩散以打碎色块，在纹理/边缘区减弱扩散以保护细节、避免“脏噪点”。<br />
<strong>4. 误差能量再分配</strong><br />
根据CSF（Contrast Sensitivity Function，对比敏感度函数）模型, 将误差能量从敏感频段搬迁到不敏感频段, 改善人眼视觉质量。</p>
<p dir="auto"><strong>四、实现参考（C 语言，适用于嵌入式 GUI / LVGL 离线转换）</strong><br />
#define R5(v)  (((v) &gt;&gt; 3) &amp; 0x1F)   // 8bit -&gt; 5bit<br />
#define G6(v)  (((v) &gt;&gt; 2) &amp; 0x3F)   // 8bit -&gt; 6bit<br />
#define B5(v)  (((v) &gt;&gt; 3) &amp; 0x1F)<br />
// 单像素量化：对误差按感知权重扩散（示意，非完整实现）<br />
void quantize_pixel(uint8_t *r, uint8_t *g, uint8_t *b, float err[3]) {<br />
float er = (float)*r * 0.299f, eg = (float)*g * 0.587f, eb = (float)*b * 0.114f;<br />
*r = (R5(*r + (int)err[0]) &lt;&lt; 3) | 0x07;  // 重建并补低位<br />
*g = (G6(*g + (int)err[1]) &lt;&lt; 2) | 0x03;<br />
*b = (B5(*b + (int)err[2]) &lt;&lt; 3) | 0x07;<br />
// 将剩余误差按 7/16、3/16、5/16、1/16 传播给邻域像素<br />
}</p>
<p dir="auto"><strong>五、参数与适配要点</strong><br />
抖动效果与目标屏的特性强相关，实际落地建议关注几点：<br />
• Gamma 校正：面板的实际灰阶响应通常是非线性的，量化前应先做 Gamma 解码、量化后再编码回，否则暗部色阶会明显加重；<br />
• 观察距离与分辨率：小尺寸、高 PPI 或观看距离较远的屏，人眼对细粒度误差不敏感，可适当降低扩散强度以节省算力；<br />
• 色温 / 白平衡：若面板本身偏色，可在量化阶段对 R/B 通道做轻微偏移补偿，缓解偏绿；<br />
• 离线 vs 实时：静态资源（图标、背景）建议离线预量化，运行时零开销；动态 UI 若需实时量化，可采用查表（LUT）+ 有序抖动以降低 CPU/GPU 占用。</p>
<p dir="auto"><strong>六、效果验证：五组典型场景对比</strong><br />
下面用五组对 RGB565 最“不友好”的场景做对比：左为 RGB888 原图，中为采用上述感知抖动方法后的 RGB565 结果，右为 LVGL 默认的 RGB565 量化抖动，用以观察不同方法在色阶、偏色、跨色过渡上的差异。（图片可点击放大查看细节）<br />
<img src="/assets/uploads/files/1789562855029-compare_page_2x-resized.png" alt="compare_page_2x.png" class=" img-responsive img-markdown" /></p>
]]></description><link>https://bbs.aw-ol.com/topic/7163/在rgb565屏上实现rgb888屏的显示质量</link><generator>RSS for Node</generator><lastBuildDate>Wed, 23 Sep 2026 22:08:39 GMT</lastBuildDate><atom:link href="https://bbs.aw-ol.com/topic/7163.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 16 Sep 2026 12:52:19 GMT</pubDate><ttl>60</ttl></channel></rss>