你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

查看: 1599|回复: 1

【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第四十八章 照相机实验

[复制链接]

50

主题

7

回帖

0

蝴蝶豆

新手上路

最后登录
1970-1-1
发表于 2013-4-10 23:08:08 | 显示全部楼层 |阅读模式

<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

实验43 照相机实验.rar

下载

819.7 KB, 下载次数: 14, 下载积分: ST金币 -1

<
回复

使用道具 举报

0

主题

12

回帖

0

蝴蝶豆

初级会员

最后登录
2020-9-17
发表于 2014-4-10 08:54:32 | 显示全部楼层

回复:【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第四十八章 照相机实验

 
回复 支持 反对

使用道具 举报

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版