色彩格式
色彩是显示屏的像素呈现出的样子。 这些色彩来自帧缓冲存储的值。 在传统意义上,绘图系统中能够表现、使用和显示的色彩数量是有限的。 这同样适用于TouchGFX和TouchGFX应用。
应用可能有的像素色彩数量会影响到应用的许多方面。 从显示屏上看到的实际内容到帧缓冲所需的内存消耗,以及整体性能。 本节将进一步介绍TouchGFX中的色彩和可用的色彩格式,并指出其优缺点。
色彩
TouchGFX中的色彩是红、绿和蓝分量的三元组,即RGB色彩。 每个色彩分量的范围为0至255。 0表示该分量无作用,255表示该分量处于最大值。
全黑色表示为RGB色彩 (0,0,0),全白色表示为 (255,255,255)。 亮绿色为 (0,255,0),半亮红为 (128,0,0),暗紫色为 (64,0,64),诸如此类。
灰度
灰度应用的所有色彩均为灰色,包括从黑色到白色之间的所有灰色,因此用灰色强度(而不是RGB值)表示。 可将灰度色彩理解为R = G = B的RGB色彩。
不透明度
在某些情况下,我们会考虑为色彩增加一个描述色彩不透明的分量。 与色彩的其他分量一样,不透明度的范围为0至255。 有不透明度的色彩称为RGBA色彩。 A表示alpha,是不透明度使用的传统名称。
完全不透明的黑色表示为 (0,0,0,255),有一些透明的红色表示为 (255,0,0,128),诸如此类。
当色彩并非完全不透明时,需将它与已存在的色彩进行混合。 这种色彩混合称为Alpha混合。
色深
色深是指帧缓冲存储的用于描述每种色彩的位数。 我们将该值表示为每像素位数,简称bpp。
使用的位数越多,可描述的色彩越多。
常用的色深为24 bpp。 由于每一位都可以是有或无,这表示可以呈现224 = 16777216种不同色彩。
另一个较少使用得稍色深是1 bpp。 此色深适用于黑白应用,只能呈现21 = 2种不同色彩。
TouchGFX支持下列色深:
- 32 bpp - 16777216种色彩及相应不透明度值
- 24 bpp - 16777216种色彩
- 16 bpp - 65536种色彩
- 6/8 bpp - 64种色彩
- 4 bpp - 16种灰度色彩
- 2 bpp - 4种灰度色彩
- 1 bpp - 2种灰度色彩
关于色彩分量范围的注释。 当使用的色深小于24 bpp时,红、绿和蓝分量中每一个的范围并不直接取0至255。 以16 bpp的红色分量为例,范围为0至31。 我们将值31视为16 bpp色深时能够表现的最红的色彩,即24 bpp色深时的值255。 一种理解方式是16 bpp色深的色彩只是24 bpp色深可能表现的色彩的一个子集。
在6/8 bpp色系中,每个像素使用6位表示色彩信息(2位分别表示红色、绿色和蓝色)。 为了简化帧缓存访问,每个像素从6位增加至8位(1字节)。 帧缓存中多余的两位未使用。
格式
在确定表示色彩所需的位数后,我们进一步研究位的内容。 色彩通过位来描述红色、绿色和蓝色,但色深本身并不能指定像素中位的顺序(格式)。 例如: 先是蓝色,再是绿色,接着是红,或者顺序相反。
像素色彩格式
根据应用的色深,可使用某些特定的色彩格式。
RGB888
在TouchGFX中,色深为24 bpp的色彩的色彩格式为RGB888。 这意味着对红、绿和蓝分量中的每一个使用8个比特位。
以亮紫色RGB (255,0,255) 为例,通过将分量组合成一个色彩值来表示这种色彩
uint32_t brightPurpleRGB888 = 255 << 16 | 0 << 8 | 255 << 0;
在这种格式中,红色位于最高的8位,然后是绿色,蓝色位于最低的8位。
RGB565
TouchGFX对16 bpp色彩使用色彩格式RGB565, 即红、绿和蓝色分别为5位、6位和5位。 由于红色有5位,完全亮起为31,因此代码中的亮紫色
为uint16_t brightPurpleRGB565=31<<11|0<<5|31<<0;
RGBx2222, xRGB2222, BGRx2222, xBGR2222
对于6 bpp色彩,TouchGFX支持4种不同色彩格式:RGBx2222、xRGB2222、BGRx2222和xBGR222。 前述格式中之所以有x,是因为6位色彩按字节的形式存储。 为了构成字节,用2个比特位填充色彩。 同时提供RGB和BGR是考虑到一些显示屏的需要,这样则无需在向显示屏发送像素前转换像素。 在RGBx2222模式下,表示亮黄色的代码如下:
uint8_t brightYellowRGBx2222 = 3 << 6 | 3 << 4 | 0 << 2;
GRAY4, GRAY2, BW
对于每种灰度色深,TouchGFX都相应的支持其对应的色彩格式。 4 bpp的色彩格式表示为GRAY4,2 bpp为GRAY2,1 bpp为BW(表示黑色和白色)。 对于4 bpp,全白色为
uint8_t whiteGRAY4 = 15;
TouchGFX有一项辅助功能,可返回色彩在当前色彩格式下的正确表示方法。
#include <touchgfx/Color.hpp>
...
aColor = Color::getColorFromRGB(255,0,128);
图像格式
图像是大多数UI应用的重要部分,图像由色彩填充而成。 在TouchGFX中,图像存储在存储器中,由特定格式的色彩填充而成。 在许多情况下,图像使用支持的像素色彩格式中的一种,但也可以使用其他图像格式。 在绘制前,特定图像色彩格式下的图像中的像素会被转换为合适的像素格式
图像色彩格式 | 说明 |
---|---|
ARGB8888 | 32位,每个分量8位 |
L8_ARGB8888 | 8位索引格式,ARGB8888调色板 |
RGB888 | 24位,每个分量8位。 |
L8_RGB888 | 8位索引格式,RGB888调色板 |
RGB666 | 24位,每个分量6位 |
RGB565 | 16位,红色5位、绿色6位和蓝色5位 |
L8_RGB565 | 8位索引格式,RGB565调色板 |
ARGB2222 | 8位,每个分量2位 |
ABGR2222 | 8位,每个分量2位 |
RGBA2222 | 8位,每个分量2位 |
BGRA2222 | 8位,每个分量2位 |
GRAY4 | 4位灰度 |
GRAY2 | 2位灰度 |
BW | 1位灰度 |
BW_RLE | 1位灰度运行长度编码 |
这些图像格式中的一些格式(L8)按照色彩查找表(称为CLUT)来呈现相关图像并索引到该表中。 L8图像中色彩数量的最大可能值为28 = 256。 L8格式占用的空间比非L8格式少,以包含200种不同色彩的100x100图像为例,存储为ARGB8888格式时的空间占用量为100x100x32位 = 40000字节,存储为L8_ARGB8888格式时为100x100x8位 + 200x32位 = 10800字节。 在此阅读使用L8格式的更多相关信息。
图像格式BW_RLE按连续的黑色和白色存储色彩,而不是存储单一像素色彩。 在许多情况下,这种格式也可以更高效地利用存储空间。
其余格式与以上像素色彩格式相同。
帧缓存格式
并非所有图像格式都可用作帧缓存格式。 L8格式不能用作TouchGFX中的帧缓存格式。 因为无法在帧缓存中混合两个图像。
字节和像素顺序
通常使用字节指针访问24位格式RGB888和32位格式ARGB888。 此时,须了解像素以小端顺序存储。
以32位色0xFFFF7700为例(alpha=0xFF,红色=0xFF,绿色=0x77,蓝色=0x00)。 当色彩位于32位变量或寄存器中时,值为0xFFFF7700。 当色彩存储在内存中时,存储的字节为{0x00、0x77、0xFF、0xFF}。 这与BGRA顺序对应。
同样,16位格式RGB565始终通过16位指针访问,因此字节顺序并不重要,但会在内存中交换。
对于8位格式,例如:ARGB2222,该色彩适合一个字节(两个最高位中的alpha),字节存储不变。
较小格式GRAY4、GRAY2和BW可按两种顺序存储。 低位可以是最左边的像素或最右边的像素。 如果低位是最左边的像素,我们称之为LSB模式,反之则为MSB模式。
帧缓存格式 | 顺序 | 说明 |
---|---|---|
ARGB8888 | BGRA | 32位,每个分量8位 |
XRGB8888 | BGRX | 32位,每个组件8位,忽略alpha字节 |
RGB888 | BGR | 24位,每个分量8位。 |
RGB565 | 16位,红色5位、绿色6位和蓝色5位 | |
ARGB2222 | 8位,每个分量2位 | |
ABGR2222 | 8位,每个分量2位 | |
RGBA2222 | 8位,每个分量2位 | |
BGRA2222 | 8位,每个分量2位 | |
GRAY4 | LSB | 4位灰度 |
GRAY2 | LSB | 2位灰度 |
BW | MSB | 1位灰度 |
文本格式
文本,更准确地说是字形,也以特定色彩格式存储在存储器中。 TouchGFX中可供使用的文本色彩格式为
文本色彩格式 | 说明 |
---|---|
A8 | 8位,不含透明度 |
A4 | 4位,不含透明度 |
A2 | 2位,不含透明度 |
A1 | 1位,不含透明度 |
字形格式犹如小幅图像,每个色彩条目都存储了每个像素的不透明度。 因此,之后不仅能应用实际色彩以及红、绿和蓝分量,还能绘制如存储字形“A”的蓝色和红色版本。
每个字形使用的位数越多,通常就会显得越平滑和美观。
视觉质量
对于嵌入式图形,我们希望获得最高视觉质量,但同时也需考虑内存的消耗量。
因此,通常趋向于使用RGB565色彩格式,而不是内存消耗量更大的RGB888色彩格式,一般而言,应在考虑存储需求的同时选择视觉质量最高的色彩格式。
抖动
在不同色彩格式下呈现图像时,TouchGFX使用抖动技术来改善图像的视觉质量。
抖动是一项广为人知的技术,它让图像的色彩看起来比实际色彩更丰富。 这是通过增加图像色彩的噪声来实现的。
例如,在将RGB888图像转换为RGB565图像时,不是简单地对每个色彩分量的低位进行斩波,而是在转换过程中为得到的每种色彩添加一些噪声,从而使转换后的图像看起来与原始RGB888图像相似但更丰富。
下面用图像而不是语言来表示,我们有一张原始RGB888图像和许多转换后的图像。 转换后的有和没有抖动的RGB565格式图像、xRGB2222格式图像和GRAY4格式图像。
由此可见,抖动可显著改善图像的感知质量。 在近距离观察有和没有抖动的RGB565图像时,可以看到有抖动的图像与原图像几乎完全相似,而没有抖动的图像的一些区域则存在明显的色带。 这表明在许多情况下,使用16位色彩足以获得看起来不错的界面。
如果需要显示的图像资源的渐变明显,即使在使用了抖动的图像中,也会看到一些色带。 下面是两个示例。 从RGB888 (64,190,222) 到黑色的带蓝色的渐变及转换后的有和没有抖动的RGB565图像。
另一幅从 (255,0,0) 到黑色的红色渐变。
近距离观察可以发现,有抖动和无抖动的RGB565图像中均存在色带。 红色图像中的色带最为明显。
务必密切注意所得图像和色彩格式,必要时修改原始图像或选择其他色彩格式。
性能
讨论的所有图像格式均针对绘制的“易用性”进行了优化。 这意味着可以将图像或多或少地复制到帧缓冲,无需进行大量转换。
这是有意为之,是TouchGFX能够在微控制器上获得流畅图形的原因之一。
在用TouchGFX设计UI时可使用.png图像,在编译时,会将每一幅图像转换为上述高效的图像格式中的一种。
Alpha 混合
在运行时间,图像数据的复制是通过常规CPU复制操作或使用MCU特性来完成的。 如果图像包含不完全透明或不透明的像素,则需要用alpha混合技术将像素混合到背景上。 在一些STM32 MCU中,硬件支持这种混合功能。
其他图像格式
如需在运行时间支持其他图像格式,如压缩图像格式.jpg或.png,可以利用TouchGFX 对动态位图的支持。