[RISC-V MCU 创新应用比赛]

沁恒 CH32V103 解码bmp格式位图并显示到12864

[复制链接]
7323|58
手机看帖
扫描二维码
随时随地手机跟帖
gtbestom|  楼主 | 2021-8-19 17:18 | 显示全部楼层 |阅读模式
本帖最后由 gtbestom 于 2021-8-19 17:19 编辑

#申请原创#   @21小跑堂
  在 CH32V103 上移植成功 FATFS 文件系统后,就可以对存储卡里的 电子书,图片,音乐 等文件进行读取了
  每种文件都有特定的格式,记录文件的信息
  就拿 BMP 格式的位图来说
  BMP 文件特定区域记录着文件的 宽度、高度、位深 等信息
  BMP 格式文件 编解码相对简单
  我们化繁为简,长话短说
  先上图,要读取内存卡里的 2 张单色位图,并显示在 oled 12864 上
88244611e1afe232ae.png




56859611e1bc5f29eb.png

  图片竖向保存,方便按字节顺序直接显示在 oled 屏上

  BMP 格式文件有个信息头,记录文件的各种信息
  前2字节是 “BM” 标识这是一个 BMP 格式的文件
  长话短说,用结构体表示
//BMP头文件结构体
typedef struct
{
  u16 bfType;           // 文件标志.只对'BM' 0x424D ,用来识别BMP位图类型
  u32 bfSize;                // 文件大小,包括这14个字节
  u16 bfReserved1;      // 保留
  u16 bfReserved2;      // 保留
  u32 bfOffBits;        // 从文件开始到位图数据(bitmap data)开始之间的的偏移量,前三个部分的长度之和
}__attribute__((packed)) BITMAPFILEHEADER;      // 固定14个字节
  这开头的14字节就标识了一些文件信息,紧接着又是固定的40字节
//BMP信息头
typedef struct
{
  u32 biSize;                    // 说明BITMAPINFOHEADER结构所需要的字数
  s32 biWidth;          // 说明图象的宽度,以象素为单位
  s32 biHeight;         // 说明图象的高度,以象素为单位
  u16 biPlanes;         // 为目标设备说明位面数,其值将总是被设为1
  u16 biBitCount;       // 说明比特数/象素,其值为1、4、8、16、24、或32
  u32 biCompression;    // 说明图象数据压缩的类型。其值可以是下述值之一:
                            // BI_RGB:没有压缩;
                            // BI_RLE8:每个象素8比特的RLE压缩编码,压缩格式由2字节组成(重复象素计数和颜色索引);
                            // BI_RLE4:每个象素4比特的RLE压缩编码,压缩格式由2字节组成
                            // BI_BITFIELDS:每个象素的比特由指定的掩码决定。
  u32 biSizeImage;      // 说明图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0
  s32 biXPelsPerMeter;  // 说明水平分辨率,用象素/米表示
  s32 biYPelsPerMeter;  // 说明垂直分辨率,用象素/米表示
  u32 biClrUsed;        // 说明位图实际使用的彩色表中的颜色索引数
  u32 biClrImportant;   //  说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。
}__attribute__((packed)) BITMAPINFOHEADER ;        // 固定40个字节
  进一步说明了文件的各种信息,其中重要的就是 文件宽度 biWidth,高度 biHeight,位深 biBitCount,数据偏移 bfOffBits
  紧接着还有一个颜色对照表,文末再说,不影响单色位图解码
  单色位图也有颜色对照表,但是我发现 Win10 系统不会对照表显示,都是显示黑白两色,所以我们不做对照表
  根据数据偏移 bfOffBits 信息,我们可以直接跳转到图像数据区(跳过 54 字节信息表、n 字节颜色对照表)
  f_lseek(&imginfo->FileInfo, imginfo->OffsetByte);
  读取图像信息
  f_read(&imginfo->FileInfo, Buff, 1024, &cout);
  由于我们使用的是 12864 点阵屏,128x64/8 = 1024 为了简要说明,所以直接读取全部图像数据
  接着对读取的数据进行排列和整理,以防止出现错乱和颠倒
  for(i=0;i<128;i++)
  {
    for(j=0;j<8;j++)
    {
      gd_DispBuf[j][i] = ~SWAP(Buff[i*8+j]);
    }
  }
  SWAP 函数用来交换高低位
  这样处理后,gd_DispBuf 的数据就可以直接写到 OLED12864了
14258611e1d0b8aaac.png

  至于位深更高的 16 色图、256 色图,需要用到颜色对照表
  还有 24 位图,就是我们比较常见的 RGB888 也就是 16,777,216 色图了,24 位图就不需要对照表了,直接读数据显示
13124611e1ef7666e3.png

  16 色图、256 色图涉及的颜色转换表,也用结构体表示:
  // 彩色表
  typedef struct
  {
    u8 rgbBlue;           // 指定蓝色强度
    u8 rgbGreen;          // 指定绿色强度
    u8 rgbRed;            // 指定红色强度
    u8 rgbReserved;       // 保留,设置为0
  }__attribute__((packed)) RGBQUAD;
  16 色图因为只有 16 种颜色,只需要 16 个对照表,也就是 16x4=64 字节的对照表
  256 色图因为有 256 种颜色,需要 256 个对照表,也就是 256x4=1024 字节的对照表
  获取偏移位置后的图像数据后,不能直接显示,要经过对照表处理,转换成 RGB888 数据,才能正常使用

  24 位图转 RGB565 换算如下
(Buff>>3) | ((Buff[i+1]>>2)<<5) | ((Buff[i+2]>>3))<<11
  256 色转 RGB565 换算如下
(imginfo->ColorTab[Buff].rgbBlue>>3) | ((imginfo->ColorTab[Buff].rgbGreen>>2)<<5) | ((imginfo->ColorTab[Buff].rgbRed>>3)<<11)
  16 色转 RGB565 换算如下

(imginfo->ColorTab[Buff>>4].rgbBlue>>3) | ((imginfo->ColorTab[Buff>>4].rgbGreen>>2)<<5) | ((imginfo->ColorTab[Buff>>4].rgbRed>>3)<<11)
(imginfo->ColorTab[Buff&0x0f].rgbBlue>>3) | ((imginfo->ColorTab[Buff&0x0f].rgbGreen>>2)<<5) | ((imginfo->ColorTab[Buff&0x0f].rgbRed>>3)<<11)

使用特权

评论回复

相关帖子

gtbestom|  楼主 | 2021-8-19 17:51 | 显示全部楼层
换算公式里的Buff后面有[i],没显示全
BMP格式文件图像数据区还有个4字节整数倍的填充规则,也就是一行图像数据不是4字节的整数倍,就会在末尾填充数据到整数倍,需要判断并去除这些填充数据

使用特权

评论回复
sheflynn| | 2021-9-8 10:28 | 显示全部楼层
怎么把彩色图文变成黑白色的?        

使用特权

评论回复
ccook11| | 2021-9-8 10:28 | 显示全部楼层
这个彩色图片可以?      

使用特权

评论回复
qiufengsd| | 2021-9-8 10:28 | 显示全部楼层
是fatfs自己解析的吗?      

使用特权

评论回复
kmzuaz| | 2021-9-8 10:28 | 显示全部楼层
CH32V103 速度怎么样   

使用特权

评论回复
评论
gtbestom 2021-9-8 23:06 回复TA
够用,特别是小分辨率图像很快 
kmzuaz| | 2021-9-8 10:29 | 显示全部楼层
解码bmp格式位图占用资源大吗   

使用特权

评论回复
plsbackup| | 2021-9-8 10:29 | 显示全部楼层
可以使用ch32f307性能可以。   

使用特权

评论回复
soodesyt| | 2021-9-8 10:30 | 显示全部楼层
BMP 文件是24位彩色吧   

使用特权

评论回复
评论
gtbestom 2021-9-8 23:09 回复TA
BMP 图片有 单色 1位的,有彩色 4位、8位、16位、24位、32位,都可以进行解析 
ghuca| | 2021-9-8 10:33 | 显示全部楼层
可以驱动5V的LCD吗   

使用特权

评论回复
232321122| | 2021-9-8 10:34 | 显示全部楼层
移植成功 FATFS 文件系统教程有吗   

使用特权

评论回复
aspoke| | 2021-9-8 10:34 | 显示全部楼层
bmp是怎么解析的?   

使用特权

评论回复
gtbestom|  楼主 | 2021-9-8 23:04 | 显示全部楼层
sheflynn 发表于 2021-9-8 10:28
怎么把彩色图文变成黑白色的?

一般计算成灰度就行 P=0.299×Red+0.587×Green+0.114×Blue
为了计算简单,还可以直接 RGB 分量相加除 3
各有各的优点

使用特权

评论回复
gtbestom|  楼主 | 2021-9-8 23:04 | 显示全部楼层
ccook11 发表于 2021-9-8 10:28
这个彩色图片可以?

可以的

使用特权

评论回复
gtbestom|  楼主 | 2021-9-8 23:05 | 显示全部楼层
qiufengsd 发表于 2021-9-8 10:28
是fatfs自己解析的吗?

fatfs 解析文件系统,获取图片地址,图片解析是另外做的

使用特权

评论回复
gtbestom|  楼主 | 2021-9-8 23:07 | 显示全部楼层
kmzuaz 发表于 2021-9-8 10:29
解码bmp格式位图占用资源大吗

不占用多少资源,边解析边刷新

使用特权

评论回复
gtbestom|  楼主 | 2021-9-8 23:08 | 显示全部楼层
plsbackup 发表于 2021-9-8 10:29
可以使用ch32f307性能可以。

可以的,307肯定是更好了,但目前手上只有103

使用特权

评论回复
gtbestom|  楼主 | 2021-9-8 23:09 | 显示全部楼层
ghuca 发表于 2021-9-8 10:33
可以驱动5V的LCD吗

可以,跟电压无关

使用特权

评论回复
gtbestom|  楼主 | 2021-9-8 23:10 | 显示全部楼层
232321122 发表于 2021-9-8 10:34
移植成功 FATFS 文件系统教程有吗

沁恒官方有移植好的,可以直接用

使用特权

评论回复
gtbestom|  楼主 | 2021-9-8 23:11 | 显示全部楼层
aspoke 发表于 2021-9-8 10:34
bmp是怎么解析的?

根据文件头获取分辨率,位深,数据偏移,颜色表 等数据,再跳转到数据区进行颜色转换

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

98

帖子

0

粉丝