文章目录
- 1、bmp数据提取
- 1.1、bmp 文件格式
- 1.2、文件信息头
- 1.3、位图信息头
- 1.4、RGB 颜色阵列
- 1.5、关于pic_operation.h
- 1.6、关于bmp.c
- 2、图片缩放
- 3、图片合并
- 4、测试
上一节:9、数码相框编写程序之框架分析
下一节:11、数码相框编写程序之MainPage显存管理与页面规划
代码见:项目数码相框全部源码_图片_文档\源码(含讲课过程中即时编写的文档)\12.数码相框项目\14.digital_photo_frame_8.3 节_文档_图片_图标_源码
。
1、bmp数据提取
数码相框显示效果图:
上面的这些图标就是对应我们上节中的框架的具体的图片,这些图标已经提供好了的,我们这些图标的大小是128*128
,而我们的LCD
的分辨率是320*240
,我们要显示涉及图片涉及两个问题:Bmp格式文件的解析和图片缩放。
关于bmp
文件可以在网上搜索,项目里面有介绍的资料:
1.1、bmp 文件格式
bmp
文件里面一般含有三个部分:文件信息头
(14 个字节),位图信息头
(40 个字节),剩下的就是 RGB 颜色阵列
(由图像长宽尺寸决定)。从这里可以看到,bmp
文件里存储的是RGB
颜色,我们基本上可以把 bmp
里面的 RGB
颜色直接放到 LCD
上面去显示。
1.2、文件信息头
占 14 个字节
PC 机是小端模式:低字节在低位,高字节在高位
bfType 0x4D42 : 表文件类型是 bmp
bfsize 0x00018038 : 表文件大小
bfReserved1 保留,必须设为 0
bfReserved2 保留,必须设为 0
bfOffBits 0x00000036 说明从文件头开始到实际的图象数据之间的字节的偏移量
1.3、位图信息头
占 40 个字节
1.4、RGB 颜色阵列
bmp
的 RGB
数据信息从图片的左下角开始描绘图片,描绘完最下面一行之后再从左至右描绘倒数第二行,以此类推。
而我们 LCD
上显示图片是从左上角开始显示图片,显示完第一行之后,再从左只有显示第二行,一次类推。
在我们现在做的数码相框试验中,我们的图片只支持bmp
格式,以后自己可以拓展,我们现在render
里面一个format
文件夹,里面建立一个bmp.c
,现在来写这个文件,以面向对象的思想写这个文件,先定义一个结构体方便以后拓展,在include
里面添加对应的.h
文件。
1.5、关于pic_operation.h
这个结构体就是用来判断我们的文件解析是否支持各种类型的文件,当前我们只支持bmp格式的,所以有名字
,该格式文件是否支持被解析
,获得要被解析的文件的图像数据
,释放内存
四个成员。
那么获得到的图像数据存在哪里,我们还要定义一个结构体:
上面的数据成员分别是宽度、高度、像素、行字节数、具体的像素数据(它是个指针)。我们的具体像素数据是个指针,我们使用GetPixelDatas
获取他之前还要malloc
一片内存,所以我们还要释放他,所以我们在PicFileParser
里面还要有释放内存的函数。
1.6、关于bmp.c
先定义一个结构体然后申明要实现的三个函数:
关于isBMPFormat
,我们怎么知道这个文件是不是bmp
文件呢,刚刚读bmp
资料知道他的数据头部必须是0x424d
。
这里bmp
文件使用大端存储,即数据的高字节数据存放在低地址:
关于释放PixelDatas
里面的aucPixelDatas
。
关于GetPixelDatasFrmBMP
获取bmp
里面的数据,我们知道bmp
文件内的数据分为如下三部分:
我们定义两个结构体分别表示文件信息头
和位图信息头
:
先确定这个bmp
文件的分辨率和位宽才能去malloc
分配一个内存来保存RGB
数据,也就是下面方框的数据:
我们在头部数据里面就可以得到分辨率和位宽:
然后把这些数据保存到我们的PT_PixelDatas ptPixelDatas
中。
在bmp
文件里面最开始的一个RGB
数据,实际上对应的是bmp
图片里面的左下角的数据,也就是说我们想在LCD
上显示bmp
图片的左上角的第一个数据,实际上对应bmp
左下角的第一个数据,这里经过了两个坐标的变化。
我们要在LCD
左上角开始显示我们图片的第一个数据,实际上对应在bmp
文件应该从左下角取,也就是x不变、y颠倒,我们刚才已经取出来了一行的宽度:
但是我们要向4取整:
我们要在LCD
显示出来就要知道:源、目的、长度。
这样传递给LCD
就可以显示了。
2、图片缩放
代码见:第 1 个项目数码相框全部源码_图片_文档\源码(含讲课过程中即时编写的文档)\12.数码相框项目\14.digital_photo_frame_8.3 节_文档_图片_图标_源码
。
图片缩放算法:
逐行处理,每行里面再逐点处理:
这里写的 BMP
格式解析函数(GetPixelDatasFrmBMP
)和图片的缩放函数(PicZoom
)都只支持 24 位
的 BPP
。
在我们使用 BMP
格式解析函数(GetPixelDatasFrmBMP
)和图片的缩放函数(PicZoom
)时,BPP
都不会发生改变 。2440
的 BPP
有可能是 16 位
的,也有可能是 32 位
的,所以我们必须要进行 BPP
位数的转换。在 BMP
格式解析函数(GetPixelDatasFrmBMP
)里添加使 24 位 BPP
转化为 16 位
或 32 位
。
3、图片合并
我们已经有了从 BMP
文件里面获得数据函数和缩放函数,下面我们要将缩放处理之后得到的数组放入 LCD
的 FrameBuffe
来将图片在 LCD
上面显示。
LCD
的 FrameBuffer
非常大,怎样把一个小块的数据放入非常大的 FrameBuffer
里面呢? 需要些一个合并函数。
上一节:9、数码相框编写程序之框架分析
下一节:11、数码相框编写程序之MainPage显存管理与页面规划
4、测试
在前两个小节里面我们完成了 BMP
图片的解析,提取,缩放和合并。现在我们来写一个测试程序,看看我们之前的工作是否有问题。你当然可以把整个数码相框写完之后再测试,但是那样错误肯定一大推。
我们参照之前的main
函数,来写一个测试函数,由于是个测试程序,写的比较简单,main
里面没有加返回值的判断。代码见:第 1 个项目数码相框全部源码_图片_文档\源码(含讲课过程中即时编写的文档)\12.数码相框项目\14.digital_photo_frame_8.3 节_文档_图片_图标_源码\14.digial_photo_frame
。
修改好 Makefile
之后拖到 ubuntu
测试:
用法:
查看有哪些 BMP 文件:
但是我们构造的文件信息头结构体各个成员加起来确实是 14 字节
,怎么打印出来的是 16 字节
呢?
原因是未考虑到结构体对齐问题。sizeof(结构体)
,由于结构体对齐问题,导致计算结构体错误:
解决办法,设置宏,自己设置结构体的对齐方式:
上一节:9、数码相框编写程序之框架分析
下一节:11、数码相框编写程序之MainPage显存管理与页面规划