http://guliqun1983.blog.163.com/blog/static/501116852011730535314/
全部博文(120)
分类: 嵌入式
2011-02-15 11:12:20
在lcd上显示bmp图像
实现需要了解bmp图像文件的格式
位图文件结构表 | ||
---|---|---|
位图文件 | 位图文件头 | 14 字节 |
位图信息头 | 40 字节 | |
彩色表(调色板) | 4N 字节 | |
位图数据 | x 字节 |
位图文件头包含文件类型、文件大小、存放位置等信息。结构定义如下:
typedef struct tagBITMAPFILEHEADER
{
UNIT bfType;
DWORD bfSize;
UINT bfReserved1;
UINT bfReserved2;
DWORD bfOffBits;
}BITMAPFILEHEADER;
其中:
bfType 说明文件类型,在windows系统中为BM。
bfSize 说明文件大小。
bfReserved1 bfReserved2 保留,设置为0。
bfOffBits 说明实际图形数据的偏移量。
位图信息头包含位图的大小、压缩类型、和颜色格式,结构定义如下:
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMerer;
LONG biYPelsPerMerer;
DWORD biClrUsed;
DWORD biClrImportant;
}BITMAPINFOHEADER;
其中:
biSize 说明BITMAPINFOHEADER结构所需字节数,在windows系统中为28h
biWidth 说明图像宽度
biHeight 说明图像高度
biPlanes 为目标设备说明位面数,其值设为1
biBitCount每个像素的位数,单色位图为1,256色为8,24bit为24。
biCompression压缩说明,BI_RGB:无压缩,BI_RLE8:8位RLE压缩,BI_RLE4:4位RLE压缩
biSizeImage说明图像大小,如无压缩,可设为0
biXPelsPerMeter水平分辨率
biYPelsPerMeter垂直分辨率
biClrUsed 位图使用的颜色数
biImportant重要颜色数目
彩色表包含的元素与位图所具有的颜色数目相同,像素颜色用结构RGBQUAD来表示:
typedef struct tagRGBQUAD { BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved; }RGBQUAD;其中:
rgbBlue 指定蓝色强度
rgbGreen 指定绿色强度
rgbRed 指定红色强度
rgbReserved保留,设为0
位图数据
紧跟在彩色表后的是图像数据阵列,图像每一扫描行有连续的字节组成,扫描行由底向上存储,阵列中第一字节为左下角像素,最后一字节为右上角像素
显示bmp图像程序如下(显示一幅320*240的bmp图像):
#define BYTE_PER_PIXEL 2
#define MAX_X 320
#define MAX_Y 240
#pragma pack(1)
typedef struct
{
short bfType;
long bfSize;
short bfReserved1;
short bfReserved2;
long bfoffBits;
} BITMAPFILEHEADER;
#pragma pack()
int showbmp(char *bmpfile)
{
int fp_bmp;
long height;
long width;
int length, offset = 0;
int i, y1 = 0, x1 = 0;
BITMAPFILEHEADER bfile;
unsigned char *pDIBData = NULL;
unsigned char r = 0, g = 0, b = 0;
unsigned short R = 0, G = 0, B = 0;
unsigned short color = 0;
printf("open bmp file\n");
fp_bmp = open( bmpfile, O_RDONLY);//打开文件
if ( fp_bmp < 0 )
{
printf("can not open file %s\n",bmpfile);
return 0;
}
read( fp_bmp, &bfile, sizeof(bfile) );//读取文件头信息
printf("bfsize=%d, bfoffbits=%d\n",
bfile.bfSize, bfile.bfoffBits);
lseek( fp_bmp, 18, SEEK_SET );
read( fp_bmp, (void *)&width, sizeof(long) );//获取文件的宽度
read( fp_bmp, (void *)&height, sizeof(long) );//获取文件的高度
printf("width=%d\n",width);
printf("height=%d\n",height);
//分配图像数据存储空间,实际的图像数据大小为文件大小 减去 图像数据与文件头的偏移量
pDIBData = (unsigned char *)malloc(bfile.bfSize - bfile.bfoffBits);
if(pDIBData == NULL)
{
printf("mem allocate failed\n");
return 0;
}
lseek( fp_bmp, bfile.bfoffBits, SEEK_SET );
read( fp_bmp, pDIBData, bfile.bfSize - bfile.bfoffBits);//读取图像数据至分配的存储空间
//显示图像,这里需要注意如何将RGB24转换为RGB565
//从bmp文件读出的图像数据是RGB24格式,LCD显示需要RGB565数据格式
for (y1 = 0; y1 < MAX_Y; y1++)
for (x1 = 0; x1 < MAX_X; x1++)
{
//注意从bmp文件中读出的图像数据连续的三个字节中第一个字节为蓝色分量
//第二个字节为绿色分量 第三个字节为红色分量
b = *pDIBData ; g = *(pDIBData + 1) ; r = *(pDIBData + 2);
//下面5跳语句实现了RGB24转换为RGB565
//红色r占5为屏蔽低三位 绿色g占6为屏蔽低两位 蓝色b占5为屏蔽低三位
r = r & (~(0x07)); g = g & (~(0x03)); b = b & (~(0x7));
R = (unsigned short)r << 8;
G = (unsigned short)g << 3;
B = (unsigned short)b >> 3;
color = R | G | B;
//计算偏移量 ,注意最先读出的三个字节对应的是图像中的左下角的那个像素,最后三个字节对应图像
// 中右上 角 的那个像素
offset = (MAX_Y - y1 -1) * MAX_X * BYTE_PER_PIXEL + (x1 * BYTE_PER_PIXEL);
//将颜色数据写入显存
*(unsigned short *)(fb_mem + offset) = color;
pDIBData += 3;
}
close(fp_bmp);
free(pDIBData);
}