在线时间0 小时
UID90136
ST金币0
蝴蝶豆0
注册时间2008-5-6
新手上路
- 最后登录
- 1970-1-1
|
a0a.1 0b0c
<div style="padding-bottom: 5px; line-height: 1.5; background-color: rgb(255,255,255); margin: 0px; padding-left: 5px; padding-right: 5px; color: rgb(0,0,0); font-size: 12px; padding-top: 5px"> <a name="_Toc342394355">48.1 BMP编码简介
上一章,我们学习了各种图片格式的解码。本章,我们介绍最简单的图片编码方法:BMP图片编码。通过前面的了解,我们知道BMP文件是由文件头、位图信息头、颜色信息和图形数据等四部分组成。我们先来了解下这几个部分。
1、BMP文件头(14字节):BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。
//BMP文件头
typedef __packed struct
{
u16 bfType ; //文件标志.只对'BM',用来识别BMP位图类型
u32 bfSize ; //文件大小,占四个字节
u16 bfReserved1 ; //保留
u16 bfReserved2 ; //保留
u32 bfOffBits ; //从文件开始到位图数据(bitmap data)开始之间的的偏移量
}BITMAPFILEHEADER ;
2、位图信息头(40字节):BMP位图信息头数据用于说明位图的尺寸等信息。
typedef __packed struct
{
u32 biSize ; //说明BITMAPINFOHEADER结构所需要的字数。
long biWidth ; //说明图象的宽度,以象素为单位
long 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
long biXPelsPerMeter ;//说明水平分辨率,用象素/米表示
long biYPelsPerMeter ;//说明垂直分辨率,用象素/米表示
u32 biClrUsed ; //说明位图实际使用的彩色表中的颜色索引数
u32 biClrImportant ; //说明对图象显示有重要影响的颜色索引的数目,
//如果是0,表示都重要。
}BITMAPINFOHEADER ;
3、颜色表:颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。
typedef __packed struct
{
u8 rgbBlue ; //指定蓝色强度
u8 rgbGreen ; //指定绿色强度
u8 rgbRed ; //指定红色强度
u8 rgbReserved ; //保留,设置为0
}RGBQUAD ;
颜色表中RGBQUAD结构数据的个数由biBitCount来确定:当biBitCount=1、4、8时,分别有2、16、256个表项;当biBitCount大于8时,没有颜色表项。
BMP文件头、位图信息头和颜色表组成位图信息(我们将BMP文件头也加进来,方便处理),BITMAPINFO结构定义如下:
typedef __packed struct
{
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
}BITMAPINFO;
4、位图数据:位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:
当biBitCount=1时,8个像素占1个字节;
当biBitCount=4时,2个像素占1个字节;
当biBitCount=8时,1个像素占1个字节;
当biBitCount=16时,1个像素占2个字节;
当biBitCount=24时,1个像素占3个字节;
当biBitCount=32时,1个像素占4个字节;
biBitCount=1 表示位图最多有两种颜色,缺省情况下是黑色和白色,你也可以自己定义这两种颜色。图像信息头装调色板中将有两个调色板项,称为索引0和索引1。图象数据阵列中的每一位表示一个象素。如果一个位是0,显示时就使用索引0的RGB值,如果位是1,则使用索引1的RGB值。
biBitCount=16 表示位图最多有65536种颜色。每个色素用16位(2个字节)表示。这种格式叫作高彩色,或叫增强型16位色,或64K色。它的情况比较复杂,当biCompression成员的值是BI_RGB时,它没有调色板。16位中,最低的5位表示蓝色分量,中间的5位表示绿色分量,高的5位表示红色分量,一共占用了15位,最高的一位保留,设为0。这种格式也被称作555 16位位图。如果biCompression成员的值是BI_BITFIELDS,那么情况就复杂了,首先是原来调色板的位置被三个DWORD变量占据,称为红、绿、蓝掩码。分别用于描述红、绿、蓝分量在16位中所占的位置。在Windows 95(或98)中,系统可接受两种格式的位域:555和565,在555格式下,红、绿、蓝的掩码分别是:0x7C00、0x03E0、0x001F,而在565格式下,它们则分别为:0xF800、0x07E0、0x001F。你在读取一个像素之后,可以分别用掩码“与”上像素值,从而提取出想要的颜色分量(当然还要再经过适当的左右移操作)。在NT系统中,则没有格式限制,只不过要求掩码之间不能有重叠。(注:这种格式的图像使用起来是比较麻烦的,不过因为它的显示效果接近于真彩,而图像数据又比真彩图像小的多,所以,它更多的被用于游戏软件)。
biBitCount=32 表示位图最多有4294967296(2的32次方)种颜色。这种位图的结构与16位位图结构非常类似,当biCompression成员的值是BI_RGB时,它也没有调色板,32位中有24位用于存放RGB值,顺序是:最高位—保留,红8位、绿8位、蓝8位。这种格式也被成为888 32位图。如果 biCompression成员的值是BI_BITFIELDS时,原来调色板的位置将被三个DWORD变量占据,成为红、绿、蓝掩码,分别用于描述红、绿、蓝分量在32位中所占的位置。在Windows 95(or 98)中,系统只接受888格式,也就是说三个掩码的值将只能是:0xFF0000、0xFF00、0xFF。而在NT系统中,你只要注意使掩码之间不产生重叠就行。(注:这种图像格式比较规整,因为它是DWORD对齐的,所以在内存中进行图像处理时可进行汇编级的代码优化(简单))。
通过以上了解,我们对BMP有了一个比较深入的了解,本章,我们采用16位BMP编码(因为我们的LCD就是16位色的,而且16位BMP编码比24位BMP编码更省空间),故我们需要设置biBitCount的值为16,这样得到新的位图信息(BITMAPINFO)结构体:
typedef __packed struct
{
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bmiHeader;
u32 RGB_MASK[3]; //调色板用于存放RGB掩码.
}BITMAPINFO;
其实就是颜色表由3个RGB掩码代替。最后,我们来看看将LCD的显存保存为BMP格式的图片文件的步骤:
1)创建BMP位图信息,并初始化各个相关信息
这里,我们要设置BMP图片的分辨率为LCD分辨率(240*320)、BMP图片的大小(整个BMP文件大小)、BMP的像素位数(16位)和掩码等信息。
2)创建新BMP文件,写入BMP位图信息
我们要保存BMP,当然要存放在某个地方(文件),所以需要先创建文件,同时先保存BMP位图信息,之后才开始BMP数据的写入。
3)保存位图数据。
这里就比较简单了,只需要从LCD的GRAM里面读取各点的颜色值,依次写入第二步创建的BMP文件即可。注意:保存顺序(即读GRAM顺序)是从左到右,从下到上。
4)关闭文件。
使用FATFS,在文件创建之后,必须调用f_close,文件才会真正体现在文件系统里面,否则是不会写入的!这个要特别注意,写完之后,一定要调用f_close。
BMP编码就介绍到这里。
<a name="_Toc342394357">48.3 软件设计
打开上一章的工程,然后打开PICTURE组下的bmp.c文件,在该文件里面添加bmp编码函数bmp_encode,该函数代码如下:
//BMP编码函数
//将当前LCD屏幕的指定区域截图,存为16位格式的BMP文件 RGB565格式.
//保存为rgb565则需要掩码,利用原来的调色板位置增加掩码.这里我们已经增加了掩码.
//保存为rgb555格式则需要颜色转换,耗时间比较久,所以保存为565是最快速的办法.
//filename:存放路径
//x,y:在屏幕上的起始坐标
//mode:模式.0,仅仅创建新文件的方式编码;1,如果之前存在文件,则覆盖之前的文件.
//如果没有,则创建新的文件.
//返回值:0,成功;其他,错误码.
u8 bmp_encode(u8 *filename,u16 x,u16 y,u16 width,u16 height,u8 mode)
{
FIL* f_bmp;
u16 bmpheadsize; //bmp头大小
BITMAPINFO hbmp; //bmp头
u8 res=0;
u16 tx,ty; //图像尺寸
u16 *databuf; //数据缓存区地址
u16 pixcnt; //像素计数器
u16 bi4width; //水平像素字节数
if(width==0||height==0)return PIC_WINDOW_ERR; //区域错误
if((x+width-1)>lcddev.width)return PIC_WINDOW_ERR; //区域错误
if((y+height-1)>lcddev.height)return PIC_WINDOW_ERR; //区域错误
#if BMP_USE_MALLOC == 1 //使用malloc
databuf=(u16*)mymalloc(SRAMIN,1024); //开辟至少bi4width大小的字节的内存区域
//对240宽的屏,480个字节就够了.
if(databuf==NULL)return PIC_MEM_ERR; //内存申请失败.
f_bmp=(FIL *)mymalloc(SRAMIN,sizeof(FIL)); //开辟FIL字节的内存区域
if(f_bmp==NULL) //内存申请失败.
{
myfree(SRAMIN,databuf);
return PIC_MEM_ERR;
}
#else
databuf=(u16*)bmpreadbuf;
f_bmp=&f_bfile;
#endif
bmpheadsize=sizeof(hbmp);//得到bmp文件头的大小
mymemset((u8*)&hbmp,0,sizeof(hbmp));//置零空申请到的内存.
hbmp.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);//信息头大小
hbmp.bmiHeader.biWidth=width; //bmp的宽度
hbmp.bmiHeader.biHeight=height; //bmp的高度
hbmp.bmiHeader.biPlanes=1; //恒为1
hbmp.bmiHeader.biBitCount=16; //bmp为16位色bmp
hbmp.bmiHeader.biCompression=BI_BITFIELDS;//每个象素的比特由指定的掩码决定。 hbmp.bmiHeader.biSizeImage=hbmp.bmiHeader.biHeight*hbmp.bmiHeader.biWidth*
hbmp.bmiHeader.biBitCount/8;//bmp数据区大小
<div style="margin: 5px 0px"> hbmp.bmfHeader.bfType=((u16)'M' |
-
-
《STM32开发指南》第四十八章 照相机实验.rar
下载
546.97 KB, 下载次数: 11, 下载积分: ST金币 -1
-
-
819.7 KB, 下载次数: 14, 下载积分: ST金币 -1
|