百为STM32开发板教程之十九——BMP图片显示
实验目的:从FATFS文件系统的SD卡内读取BMP图片显示到LCD上
主要内容:
一、BMP文件格式
二、用程序定义BMP文件结构
三、把SD卡内(FATFS文件系统)的图片显示到LCD上
参考文档:
微软官方bitmap相关文档(英文):
http://msdn.microsoft.com/en-us/library/dd183377(v=vs.85).aspx
BMP格式文档(英文)——Microsoft Windows Bitmap Format
http://www.fileformat.info/format/bmp/spec/e27073c25463436f8a64fa789c886d9c/view.htm
BMP文件格式
一个.bmp文件包括以下四个部分,位图文件头,位图文件信息头,颜色表,点阵字节数据:
BITMAPFILEHEADER bmfh; //位图文件头
BITMAPINFOHEADER bmih; //位图文件信息头
RGBQUAD aColors[]; //颜色表
BYTE aBitmapBits[]; //点阵字节数据
BMP文件结构具体内容:
二、用程序定义BMP文件结构
1、位图文件头
BITMAPFILEHEADER结构定义如下:
typedef struct tagBITMAPFILEHEADER {
WORD bfType; //位图文件的类型
DWORD bfSize; //位图文件的大小,以字节为单位
WORD bfReserved1; //位图文件保留字
WORD bfReserved2; //位图文件保留字
DWORD bfOffBits; //位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
2、位图文件信息头
BITMAPINFOHEADER结构定义如下:
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; //本结构所占用字节数
LONG biWidth; //位图的宽度,以像素为单位
LONG biHeight; //位图的高度,以像素为单位
WORD biPlanes; //Specifies the number of planes for the target device. This value must be set to 1.
WORD biBitCount; //每个像素所占的位数,1(黑白),4(16色),8(256色),16(65535色),24(真彩色),32(真彩色)
DWORD biCompression; //位图压缩类型,0(不压缩),1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)
DWORD biSizeImage; //位图的大小,以字节为单位
LONG biXPelsPerMeter; //位图水平分辨率,用像素/米表示
LONG biYPelsPerMeter; //位图垂直分辨率,用像素/米表示
DWORD biClrUsed; //位图实际使用的颜色表中的颜色数目
DWORD biClrImportant; //位图显示所需要的颜色数目,若为0,则所有颜色被使用
} BITMAPINFOHEADER;
3、颜色表
RGBQUAD结构定义如下:
typedef struct tagRGBQUAD {
BYTE rgbBlue; //蓝色的强度
BYTE rgbGreen; //绿色的强度
BYTE rgbRed; //红色的强度
BYTE rgbReserved;
} RGBQUAD;
三、把SD卡内(FATFS文件系统)的图片显示到LCD上
/* draw_bmp.c */
/**
* @摘要 从SD卡读出一个BMP图片显示到LCD上.
* @参数 Xpos: X坐标
* @参数 Ypos: Y坐标
* @参数 BmpName: SD卡内的BMP文件名(可包含路径)
* @返回值 无
*/
void GUI_DrawBMP(uint32_t Xpos, uint32_t Ypos, const char* BmpName)
{
uint32_t size = 0, offset = 0;
uint32_t width = 0, height = 0;
uint32_t compression, clrUsed;
uint16_t type, bitCount;
uint32_t BmpAddress;
uint32_t x, y;
uint32_t Color, BkColor, MixColor;
FIL F;
f_open (&F, BmpName, FA_READ); //打开BMP文件
f_read (&F, Buffer, 54, &BytesRead); //读出54字节数据,取出BMP文件信息
BmpAddress = (uint32_t)Buffer;
// type = *(uint16_t *) (BmpAddress); //位图文件的类型
size = *(uint16_t *) (BmpAddress + 2); //位图文件的大小
size |= (*(uint16_t *) (BmpAddress + 4)) << 16;
offset = *(uint16_t *) (BmpAddress + 10); //位图数据的起始位置
offset |= (*(uint16_t *) (BmpAddress + 12)) << 16;
width = *(uint16_t *) (BmpAddress + 18); //位图的宽度
width |= (*(uint16_t *) (BmpAddress + 20)) << 16;
height = *(uint16_t *) (BmpAddress + 22); //位图的高度
height |= (*(uint16_t *) (BmpAddress + 24)) << 16;
bitCount = *(uint16_t *) (BmpAddress + 28); //每个像素所占的位数
compression = *(uint16_t *) (BmpAddress + 30); //位图压缩类型
compression |= *(uint16_t *) (BmpAddress + 32) << 16;
clrUsed = *(uint16_t *) (BmpAddress + 46); //位图实际使用的颜色表中的颜色数目
clrUsed |= *(uint16_t *) (BmpAddress + 48) << 16;
size = (size - offset)/2;
f_read (&F, Buffer, offset - 54, &BytesRead); //把读指针指向位图数据的起始位置
switch (bitCount)
{
case 1:
case 4:
case 8:
break;
case 16: //这里用的是16位565格式的BMP
for (y = height - 1; (y < height) && (y >= 0); y -= 1)
{
if(width*2>512) //如果显示一行的数据超过512,分两次读
{
f_read (&F, Buffer, width, &BytesRead);
f_read (&F, Buffer + width, width, &BytesRead);
}
else
{
f_read (&F, Buffer, width*2, &BytesRead);
}
for(x = 0; x < width; x++) //显示一行图象数据
{
Color = *(uint16_t*)(Buffer + 2*x); //16位565格式,一个像素数据占两个字节
LCD_SetCursor(Xpos + x, Ypos + y);
LCD_WriteRAM_Prepare(); /* Prepare to write GRAM */
LCD_WriteRAM(Color);
}
}
f_close (&F); //显示完,关闭文件
break;
case 24:
case 32:
break;
}
}
/* main.c */
调用GUI_DrawBMP函数在坐标(0,0)显示图像
GUI_DrawBMP(0,0,"STFILES/ST**.bmp");
程序源码已上传到网盘:
百为STM32_SDIO_FATFS_BMP程序.rar
|