1. 基础知识
调色板(Palette):也可以叫颜色查找表LUT(Look Up Table)。例如ARGB8888格式,一个像素占32位,如果采用调色板,将实际图片用到的颜色采用一张表作为索引,即0-255作为索引,每个值对应真正的ARGB8888值,这样保存图片时只需要1/4的大小。比如图片的某个像素的颜色是0xFFFF000000(即红色),在LUT中记录0x00对应0xFFFF000000,在Index中这个像素位置的颜色数据就只要记录0x00,而显示图片时就只要在LUT中查找到0x00对应的ARGB8888值就能还原这个像素的颜色。
FT80x仅支持一种调色板PALETTED(对应ARGB8888),FT81x、BT81x支持PALETTED8(对应ARGB8888)、PALETTED4444(对应ARGB4444)、PALETTED565(对应RGB565)。另外,FT80x有一个RAM_PL的空间对应LUT,即所有图片只能用一个LUT,而FT81x和BT81x的PALETTED中用到的LUT是和INDEX一起放在RAM_G,可以一个图片对应一个LUT。
EVE芯片支持JPEG(baseline)格式的图片,只是FT80x是软件解压,而FT81x是硬件解压,FT81x可支持png格式的软解压。即资源是JPG或PNG(仅限位深8的PNG,无隔行扫描),然后EVE芯片解压到RAM_G中。
ASTC:这是一种压缩格式的图片,是ARM为移动设备开发的开源标准。ASTC是一种基于块、有损压缩格式,是一种纹理压缩方式。压缩的图像被分割成若干大小一致的块,每个块都是固定的128bit的大小,但是这些bits可以代表不同大小的像素。对于2D图像,块能代表的像素范围是4到12。下表是块像素大小与像素占用资源情况,比如4x4表示16个像素使用128bit,所以每个像素用到128/16=8bits,那一张800x480的图片,原始空间大小为800x480x4=1536000(ARGB8888格式是4字节/像素),而使用4x4的块大小,生成的ASTC文件为800x480x8/8 = 384000byte,仅为原图0.25大小,如使用8x8,ASTC文件为800x480x2/8 = 96000,仅为原图的0.0625,可以大大得节省Memory空间。另外,ASTC有一个特点,图片如果比较简单,比如只是黑白,可能显示效果反而不如其他格式。
Block Size | Bits Per Pixel |
4x4 | 8.00 |
5x4 | 6.40 |
5x5 | 5.12 |
6x5 | 4.27 |
6x6 | 3.56 |
8x5 | 3.20 |
8x6 | 2.67 |
10x5 | 2.56 |
10x6 | 2.13 |
8x8 | 2.00 |
10x8 | 1.60 |
10x10 | 1.28 |
12x10 | 1.07 |
12x12 | 0.89 |
目前EVE支持的格式如下:
0 : ARGB1555,ARGB分别表示Alpha,Red,Green,Blue,1555表示每个通道上的bit数,该格式表示1个像素2个字节表示,alpha通道只有1个bit,所以该像素只能表示显示或不显示。
1 : L1,一个像素1bit表示,只有黑白2种颜色。
2 : L4,一个像素4bit表示,即能4bit的灰度显示。
3 : L8,一个像素8bit表示,即能8bit的灰度显示。
4 : RGB332,一个像素1个byte表示,Red:Green:Blue = 3:3:2。
5 : ARGB2,一个像素1个byte表示,Alpha:Red:Green:Blue = 2:2:2:2。
6 : ARGB4,一个像素2个byte表示,Alpha:Red:Green:Blue = 4:4:4:4。
7 : RGB565,一个像素2个byte表示,Red:Green:Blue =5:6:5。
8 : PALETTEED [FT80X only],一个像素4个byte表示,RAMG中只用一个byte表示,LUT表需要加载到RAM_PAL。
9 : L2 [FT81X only],一个像素2个bit表示,即能2bit的灰度显示。
10 : PALETTED565 [FT81X/BT81x],显示效果等同RGB565
11 : PALETTED4444 [FT81X/BT81x],显示效果等同ARGB4
12 : PALETTED8 [FT81X/BT81x],这种格式并不是直接支持,需要特殊指令显示,显示效果约等同ARGB8888,空间是1/4。
13. ASTC[BT81X only], 可以实现ARGB8888的效果
原图:
显示效果:
2. Handle申明
EVE是使用Handle来定义图片的信息,是图片的句柄。Handle的申明格式(非ASTC格式)如下:
ftWrDispCmd(BITMAP_HANDLE(n));
ftWrDispCmd(BITMAP_SOURCE(RAM_G + addr));
ftWrDispCmd(BITMAP_LAYOUT(format, stride, height));
ftWrDispCmd(BITMAP_LAYOUT_H(stride, height));
ftWrDispCmd(BITMAP_SIZE(NEAREST, BORDER, BORDER, width, height));
ftWrDispCmd(BITMAP_SIZE_H(width, height));
【handle值n】有效值0-31,其中0为默认值,16-31为内部字库使用,15用于手写输入的图片
【地址addr】图片raw数据在RAM_G中的起始地址,对于BT81x来说,地址是可以是在SPI Nor Flash的地址,即图片信息不需要加载到RAM_G(仅限ASTC图片格式),其地址格式是:0x800000 | (sfileAddr / 32),0x800000是表示该地址是Nor Flash地址,地址要除以32是因为BT81x要求地址必须32字节对齐,即图片在Nor Flash上的起始地址必须是32字节对齐的。
【图片格式format】图片转换时使用的格式,例如ARGB1555,L1,L4等
【线跨stride】图片显示一线的跨度,以byte为单位,需byte对齐,比如一个图片宽度为2,使用L1的格式,那么stride为1((2 + 7) / 8),如果宽度为10,stride则为2((10 + 7) / 8);如果格式为L4,宽度为2时stride为1((2 + 1) / 2),宽度为10时stride为5((10 + 1) / 2)。linestride的计算公式:设该图片每个像素占用N字节,比如L1为1/8字节,ARGB1555为2字节。设图片宽度为W
if(N < 1)
linestride = (W + 1/N – 1) / (1/N);
else
Linestride = W * N;
【高度height】图片的高度
【高度weight】图片的宽度
【BITMAP_LAYOUT】BITMAP_LAYOUT是图片在RAMG中的摆放方式
【BITMAP_SIZE】BITMAP_SIZE是图片在屏幕上显示的大小,不一定和实际图片大小一样,例如如果涉及到图片放大显示,BITMAP_SIZE设置的W,H都会比实际图片大小大。一般情况是实际大小就可。
假设一张图片的大小为50x120,转换格式为ARGB4,raw数据加载到RAM_G中0x1000的位置,其handle申明代码如下:
ftWrDispCmd(BITMAP_HANDLE(1));
ftWrDispCmd(BITMAP_SOURCE(RAM_G + 0x1000));
ftWrDispCmd(BITMAP_LAYOUT(ARGB4, 50*2, 120));
ftWrDispCmd(BITMAP_LAYOUT_H(50*2, 120));
ftWrDispCmd(BITMAP_SIZE(NEAREST, BORDER, BORDER, 50*2, 120));
ftWrDispCmd(BITMAP_SIZE_H(50*2, 120));
对于ASTC格式的图片,建议使用CMD_SETBITMAP命令,其全部命令如下:
ftWrDispCmd(BITMAP_HANDLE(handle));
ftWrDispCmd(CMD_SETBITMAP);
ftWrDispCmd(RAM_G + addr);
ftWrDispCmd(((uint32_t)w << 16) | format);
ftWrDispCmd(h);
ftWrDispCmd(CELL(0));
2. CELL是什么
当一组图片具有一样的长宽和格式的时候,可以用CELL的方式申明这一组图片,这组图片使用一个hanlde,这组图片的资源在RAM_G中是连续放置的,这样就可以使用CELL来指定哪张图片。
3. 显示图片
ftWrDispCmd(BEGIN(BITMAPS)); //开始图片显示
ftWrDispCmd(BITMAP_HANDLE(n)); //可选,如果handle有变化要重新指定
ftWrDispCmd(CELL(0)); //可选,如果cell值有变化要重新指定
ftWrDispCmd(VERTEX2F(0 * 16, 0 * 16)); //设置图片显示的x,y坐标,乘以16是因为命令VERTEX2F支持1/16个像素点访问
CELL是如果一组图片大小格式都相同,可以连续放在RAM_G空间中,定义Handle时只定义第一个图片的handle,其他图片就可以用CELL来以此选定。
BITMAP_HANDLE、CELL、VERTEX2F这3条指令可以用VERTEX2II替换,即
ftWrDispCmd(VERTEX2II(0, 0, 1, 0));
参数依次为x, y, handle, cell,不过这个命令只支持1个像素点访问,并且最大寻址范围为512,512,并且只能设置正空间坐标,即坐标只能为正,而VERTEX2F可以设置-1024到1023,所以一般情况还是建议使用VERTEX2F。
4. 调色板显示
FT80x和FT81x的调色板显示是不同的。
a) FT80x
和ARGB1555,L1等格式不同的地方是调色板数据分2部分,一部分是index数据,加载到RAM_G空间中,另一部分是lut数据,大小为1024个字节(256x4),加载到RAM_PAL空间中,handle申明方式是一样的。
b) FT81x/BT81x
FT81x没有RAM_PAL空间,调色板的lut数据也是加载到RAM_G中,通过命令PALETTE_SOURCE设置lut数据的起始地址。
PALETTED565和PALETTED4444的handle申明和其他是一样的,而PALETTED8则不同。
以PALETTED4444为例:
ftWrDispCmd(BITMAP_HANDLE(2));
ftWrDispCmd(BITMAP_SOURCE(RAM_G + 1024));
ftWrDispCmd(BITMAP_LAYOUT(PALETTED4444, 140, 140));
ftWrDispCmd(BITMAP_LAYOUT_H(140, 140));
ftWrDispCmd(BITMAP_SIZE(NEAREST, BORDER, BORDER, 140, 140));
ftWrDispCmd(BITMAP_SIZE_H(140, 140));
ftWrDispCmd(PALETTE_SOURCE(RAM_G));
ftWrDispCmd(VERTEX2F(400 * 16, 100 * 16));
lut数据放在RAM_G位置,占1024个字节,index数据放RAM_G+1024位置。
PALETTED8的handle申明和其他调试板格式一样,区别是显示部分,需要使用到FT81x的混合着色Blend功能。
void ft8xxShowPaletted8(int16_t x, int16_t y, uint32_t palAddr)
{
ftWrDispCmd(SAVE_CONTEXT());
ftWrDispCmd(BLEND_FUNC(ONE, ZERO));
ftWrDispCmd(COLOR_MASK(0, 0, 0, 1));
ftWrDispCmd(PALETTE_SOURCE(palAddr + 3));
ftWrDispCmd(VERTEX2F(x * 16, y * 16));
ftWrDispCmd(BLEND_FUNC(DST_ALPHA, ONE_MINUS_DST_ALPHA));
ftWrDispCmd(COLOR_MASK(1, 0, 0, 0));
ftWrDispCmd(PALETTE_SOURCE(palAddr + 2));
ftWrDispCmd(VERTEX2F(x * 16, y * 16));
ftWrDispCmd(COLOR_MASK(0, 1, 0, 0));
ftWrDispCmd(PALETTE_SOURCE(palAddr + 1));
ftWrDispCmd(VERTEX2F(x * 16, y * 16));
ftWrDispCmd(COLOR_MASK(0, 0, 1, 0));
ftWrDispCmd(PALETTE_SOURCE(palAddr + 0));
ftWrDispCmd(VERTEX2F(x * 16, y * 16));
ftWrDispCmd(RESTORE_CONTEXT());
}
由代码可见,显示一张图片实际刷新了4次,所以建议不要采用太多该格式的图片。
BT81x的ASTC格式目前是最好用的,具有显示效果好,空间占用小的特点,其次是PALETTED8,具体选择哪种格式要根据图片的复杂程度选择,做到显示效果与存储空间的平衡。