STM32单片机图片解码
扫描二维码
随时随地手机看文章
图片解码首先是最简单的bmp图片解码,关于bmp的结构可自行查阅,代码如下
#ifndef __BMPDECODE_H_
#define __BMPDECODE_H_
#include "ff.h"
#include "lcd.h"
#include "stdlib.h"
#include "usb_type.h"
//重定义区
typedef char CHAR; //数据类型重定义,便于移植
typedef short SHORT;
//typedef int LONG;
//typedef unsigned int DWORD;
typedef int BOOL;
typedef u8 BYTE;
typedef unsigned short WORD;
//#define FALSE 0
//#define TRUE 1
//BMP图象数据压缩的类型
#define BI_RGB 0L //无压缩
#define BI_RLE8 1L //每个像素四个bit
#define BI_RLE4 2L //每个像素8个bit
#define BI_BITFIELDS 3L //每个像素的bit由指定的掩码决定
#define bufferToLong(buffer,t) (LONG)((((u32)bmpbuffer[t])) + (((u32)bmpbuffer[t+1])<<8) +(((u32)bmpbuffer[t+2])<<16) + (((u32)bmpbuffer[t+3])<<24))
#define bufferToWord(buffer,t) (WORD)(((u32)(buffer[t])) + (((u32)(buffer[t+1]))<<8))
#define bufferToDword(buffer,t) (DWORD)((((u32)bmpbuffer[t])) + (((u32)bmpbuffer[t+1])<<8) +(((u32)bmpbuffer[t+2])<<16) + (((u32)bmpbuffer[t+3])<<24))
#define RGB888buffertoRGB565(buffer,t) ((((u16)buffer[t])>>3) + ((((u16)buffer[t+1])>>2)<<5) + ((((u16)buffer[t+2])>>3)<<11))
//BMP文件头 14个字节
typedef __packed struct
{
WORD bfType ; //文件标志.只对'BM',用来识别BMP位图类型 2
DWORD bfSize ; //文件大小,占四个字节 4
WORD bfReserved1 ;//保留 2
WORD bfReserved2 ;//保留 2
DWORD bfOffBits ; //从文件开始到位图数据(bitmap data)开始之间的的偏移量,这一段中存放的就是文件信息 4
}BITMAPFILEHEADER ; //位图文件头
//位图信息头
typedef __packed struct
{
DWORD biSize ; //说明BITMAPINFOHEADER结构所需要的字数。
LONG biWidth ; //说明图象的宽度,以象素为单位
LONG biHeight ; //说明图象的高度,以象素为单位
WORD biPlanes ; //为目标设备说明位面数,其值将总是被设为1
WORD biBitCount ; //说明比特数/象素,其值为1、4、8、16、24、或32
DWORD biCompression ; //说明图象数据压缩的类型。其值可以是下述值之一:
/*BI_RGB:没有压缩;
*BI_RLE8:每个象素8比特的RLE压缩编码,压缩格式由2字节组成(重复象素计数和颜色索引);
*BI_RLE4:每个象素4比特的RLE压缩编码,压缩格式由2字节组成
*BI_BITFIELDS:每个象素的比特由指定的掩码决定。*/
DWORD biSizeImage ;//说明图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0
LONG biXPelsPerMeter ;//说明水平分辨率,用象素/米表示
LONG biYPelsPerMeter ;//说明垂直分辨率,用象素/米表示
DWORD biClrUsed ; //说明位图实际使用的彩色表中的颜色索引数
DWORD biClrImportant ; //说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。
}BITMAPINFOHEADER;
//颜色索引表,每个颜色索引占4个字节,16位以及以下才会有这个数据 也就是说 最多65535个数据
//当然,最好不要用16位色的,浪费空间
typedef __packed struct
{
BYTE rgbBlue ; //指定蓝色强度
BYTE rgbGreen ; //指定绿色强度
BYTE rgbRed ; //指定红色强度
BYTE rgbReserved ;//保留,设置为0
}RGBQUAD ;
BOOL BmpDecode(u8 *filename,u16 sx,u16 sy,u16 ex,u16 ey);
#endif
u8 bmpbuffer[1024] = {0}; //存储bmp文件的数组
//解码这个BMP文件
//设定显示起始位置以及终止位置
BOOL BmpDecode(u8 *filename,u16 sx,u16 sy,u16 ex,u16 ey)
{
FIL f_bmp; //文件系统变量,用于读取bmp文件
u16 filereadnum = 0; //用于记录文件字节读取数量
FRESULT res; //文件读取返回信息
BITMAPFILEHEADER bmpfileHead; //位图文件头
BITMAPINFOHEADER bmpinfoHead; //位图信息头
u8 colorByte = 0; //用于标记颜色位
u16 index = 0; //读取文件信息时候用来定位
u16 uitemp = 0; //记录实际数据一行有多少个点
u16 xtemp = 0;
u16 ytemp = 0; //显示时辅助计数
u16 colortemp = 0; //颜色缓冲
res=f_open(&f_bmp,(const TCHAR*)filename,FA_READ); //打开文件
if(res!=FR_OK) return FALSE;
res = f_read(&f_bmp,bmpbuffer,1024,(UINT*)&filereadnum); //读取文件
if(res!=FR_OK) return FALSE;
//获取位图文件头
bmpfileHead.bfType = (WORD)((((u16)bmpbuffer[0])<<8) + bmpbuffer[1+1]);
bmpfileHead.bfSize = bufferToDword(bmpbuffer,2);
bmpfileHead.bfReserved1 = bufferToWord(bmpbuffer,6);
bmpfileHead.bfReserved2 = bufferToWord(bmpbuffer,8);
bmpfileHead.bfOffBits = bufferToDword(bmpbuffer,10); //数据段开始地址
//获取位图信息头
bmpinfoHead.biSize = bufferToDword(bmpbuffer,14);
bmpinfoHead.biWidth = bufferToLong(bmpbuffer,18);
bmpinfoHead.biHeight = bufferToLong(bmpbuffer,22);
bmpinfoHead.biPlanes = bufferToWord(bmpbuffer,26);
bmpinfoHead.biBitCount = bufferToWord(bmpbuffer,28); //颜色位
bmpinfoHead.biCompression = bufferToDword(bmpbuffer,30);
bmpinfoHead.biSizeImage = bufferToDword(bmpbuffer,34);
bmpinfoHead.biXPelsPerMeter = bufferToLong(bmpbuffer,38);
bmpinfoHead.biYPelsPerMeter = bufferToLong(bmpbuffer,42);
bmpinfoHead.biClrUsed = bufferToDword(bmpbuffer,46);
bmpinfoHead.biClrImportant = bufferToDword(bmpbuffer,50);
index = bmpfileHead.bfOffBits;
//所有信息得到,这里应该进行测试了
colorByte = bmpinfoHead.biBitCount/8; //颜色位数 16 / 24 / 32 得到2/3/4
if((bmpinfoHead.biWidth%4) != 0) //不是4的倍数
{
uitemp = (((bmpinfoHead.biWidth/4) + 1) * 4);
}
else //是4的倍数
{
uitemp = bmpinfoHead.biWidth ;
}
if(colorByte == 3) //24位颜色
{
while(1)
{
if(index <= 1021)
{
colortemp = RGB888buffertoRGB565(bmpbuffer,index);
index = index +3;
if(sx+xtemp LCD_Draw_Point_Buffer(sx+xtemp,sy+ytemp,colortemp); xtemp++; if(xtemp >= uitemp) { xtemp = 0; ytemp++; } } else { if(index == 1022) { if(sx+xtemp LCD_Draw_Point_Buffer(sx+xtemp,sy+ytemp,colortemp); xtemp++;