2025年3月22日 星期六 甲辰(龙)年 月廿一 设为首页 加入收藏
rss
您当前的位置:首页 > 电子 > 单片机

STM32 BMP图片解析

时间:03-26来源:作者:点击数:44

重新优化了bmp图片解析,这次主要针对有大容量RAM的STM32F4以及F7,使用的是文件加载到内存后解析,并将解析后的RGB数据存储到另外一块内存区域,支持16位(RGB555),24位(RGB888),32位(ARGB8888)的位图解析,目前没有做缩放支持,同时支持输出格式为RGB565,RGB888,ARGB8888的数据。

  • /*************************************************************************************************************
  • * 文件名 : BmpDecode.c
  • * 功能 : BMP图片软件解码
  • * 作者 : cp1300@139.com
  • * 创建时间 : 2011-09-19
  • * 最后修改时间 : 2020-02-06
  • * 详细 : 只支持16位(RGB555);24位(RGB888);32位(ARGB8888)图片解析,大部分图片都是24位。
  • *************************************************************************************************************/
  • #include "system.h"
  • #include "BmpDecode.h"
  • //RGB888 转 RGB565
  • #ifndef RGB565
  • #define RGB565(color) ((((color) >> 19) & 0x1f) << 11) \
  • |((((color) >> 10) & 0x3f) << 5) \
  • |(((color) >> 3) & 0x1f)
  • #endif //RGB565
  • //RGB565转RGB888
  • #ifndef RGB888
  • #define RGB888(color) ((((color) >> 8) & 0xF8) << 16) \
  • |((((color) >> 3) & 0xFC) << 8) \
  • |(((color) << 3) & 0xFC)
  • #endif //RGB888
  • //RGB888转ARGB8888
  • #ifndef RGB888toARGB
  • #define RGB888toARGB(color) (color|0xFF000000)
  • #endif //RGB888toARGB
  • //16,24,32位BMP文件头部信息结构
  • typedef __packed struct //__packed:让结构体的各个元素紧挨着存储
  • {
  • u16 bfType ; //文件标志.只对'BM',用来识别BMP位图类型
  • u32 bfSize ; //文件大小,占四个字节
  • u32 bfReserved1 ; //保留
  • u32 bfOffBits ; //从文件开始到位图数据(bitmap data)开始之间的的偏移
  • u32 bmfHeaderSize; //图像描述信息块的大小,常为28H
  • u32 biWidth ; //说明图象的宽度,以象素为单位
  • u32 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
  • u32 biXPelsPerMeter ; //说明水平分辨率,用象素/米表示
  • u32 biYPelsPerMeter ; //说明垂直分辨率,用象素/米表示
  • u32 biClrImportant ; //说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。
  • }BMP_FILE_HEADER;
  • //24BIT图像数据结构体
  • typedef __packed struct
  • {
  • u8 mR;
  • u8 mG;
  • u8 mB;
  • }BMP_RGB_24BIT;
  • //BMP图片完全解析所需的变量数据集合
  • typedef struct
  • {
  • BMP_INFO mBmpInfo; //图片信息
  • BMP_COLOR_MODE OutRGB_ColorMode; //输出数据像素格式
  • u32 *InData32bit; //临时指针,用于读取32BIT的图片颜色值-指向的是原始图片缓冲区
  • u16 *InData16bit; //临时指针,用于读取16BIT的图片颜色值-指向的是原始图片缓冲区
  • BMP_RGB_24BIT *InData24bit; //临时指针,用于读取24BIT的图片颜色值-指向的是原始图片缓冲区
  • u32 *OutData32bit; //临时指针,用于输出32BIT的RGB数据-指向输出RGB缓冲区
  • u16 *OutData16bit; //临时指针,用于输出16BIT的RGB数据-指向输出RGB缓冲区
  • BMP_RGB_24BIT *OutData24bit; //临时指针,用于输出24BIT的RGB数据-指向输出RGB缓冲区
  • u32 InBmpFileSize; //输入的图片数据文件大小
  • u32 FileOffset; //文件偏移,用于判断是否超出文件范围了
  • u16 uiTemp; //x轴方向实际存储的像素数据字节数
  • u16 xValid; //x轴方向有效的像素数据字节数
  • u16 x,y; //画点坐标
  • u16 xEnd; //画点的终点坐标
  • u32 OutPixelOffset; //数据输出偏移,像素偏移-用于16bit与32bit图片的索引,效率会比字节偏移高
  • u32 OutByteOffset; //数据输出偏移,字节偏移,用于24bit格式图片下的偏移计算
  • u8 OutPixelByte; //输出像素字节数,根据输出的像素格式决定,可以是2,3,4,对应RGB565,RGB888,ARGB8888
  • }BMP_FullDecodeDataType;
  • //子流程-24bit位图完全解析(从内存中读取图片数据,然后解析到内存中)
  • static BMP_ERROR BMP_FullDecode24bit_Module(BMP_FullDecodeDataType *pDecodeTempData);
  • //子流程-16it位图完全解析(从内存中读取图片数据,然后解析到内存中)
  • static BMP_ERROR BMP_FullDecode16bit_Module(BMP_FullDecodeDataType *pDecodeTempData);
  • //子流程-32bit位图完全解析(从内存中读取图片数据,然后解析到内存中)
  • static BMP_ERROR BMP_FullDecode32bit_Module(BMP_FullDecodeDataType *pDecodeTempData);
  • //RGB数据拷贝(系统自带的memcpy在某些对齐的情况下可能会导致程序崩溃)
  • static void BMP_memcpy(u8 *destin, u8 *source, u32 n)
  • {
  • while(n --)
  • {
  • *destin = *source;
  • destin ++;
  • source ++;
  • }
  • }
  • /*************************************************************************************************************************
  • * 函数 : bool BMP_GetInfo(const u8 pFileHeaderBuff[50], BMP_INFO *pBmpInfo)
  • * 功能 : 获取BMP图片的信息
  • * 参数 : pFileHeaderBuff:图片前面50字节信息缓冲区;pBmpInfo:图片信息
  • * 返回 : 无
  • * 依赖 : 底层
  • * 作者 : cp1300@139.com
  • * 时间 : 2011-09-19
  • * 最后修改时间 : 2020-02-06
  • * 说明 : 用于提前获取图片信息,好为解析后的图片申请内存
  • *************************************************************************************************************************/
  • bool BMP_GetInfo(const u8 pFileHeaderBuff[50], BMP_INFO *pBmpInfo)
  • {
  • BMP_FILE_HEADER *pBmpHeader;
  • pBmpHeader = (BMP_FILE_HEADER*)pFileHeaderBuff; //得到BMP的头部信息
  • pBmpInfo->bfOffBits = pBmpHeader->bfOffBits; //位图数据偏移地址偏移
  • pBmpInfo->biBitCount = pBmpHeader->biBitCount; //位图数据的颜色深度只支持16bit,24bit,32bit
  • pBmpInfo->biWidth = pBmpHeader->biWidth; //位图的水平像素数
  • pBmpInfo->biHeight = pBmpHeader->biHeight; //位图的垂直像素数
  • pBmpInfo->biSizeImage = pBmpHeader->biSizeImage; //位图的数据大小
  • /****************************************************/
  • //调试
  • printf("地址偏移:%d\r\n", pBmpInfo->bfOffBits);
  • printf("颜色深度:%d\r\n", pBmpInfo->biBitCount);
  • printf("水平分辨率:%d\r\n", pBmpInfo->biWidth);
  • printf("垂直分辨率:%d\r\n", pBmpInfo->biHeight);
  • printf("数据大小:%luB\r\n", pBmpInfo->biSizeImage);
  • printf("位图标志:%d\r\n", pBmpHeader->bfType);
  • printf("位图biCompression:0x%lx\r\n", pBmpHeader->biCompression);
  • /*****************************************************/
  • //判断是否是合法的头信息
  • if(pBmpHeader->bfType != 0x4d42)//BM,BMP文件的头信息
  • {
  • DEBUG("非法的BMP图片,没有找到BMP图片头信息\r\n");
  • return FALSE;
  • }
  • if(pBmpHeader->biCompression) //判断BMP图像是否是压缩的,如果是压缩的将不支持
  • {
  • DEBUG("不支持压缩的BMP图片\r\n");
  • return FALSE;
  • }
  • return TRUE;
  • }
  • /*************************************************************************************************************************
  • * 函数 : BMP_ERROR BMP_FullDecode(u8 *InBmpFileBuff, u32 InBmpFileSize, u8 *pOutRGB_DataBuff, u32 OutRGB_DataBuffSize, BMP_COLOR_MODE OutRGB_ColorMode, BMP_INFO *pOutBmpInfo)
  • * 功能 : BMP图片软解析(全部解析)
  • * 参数 : InBmpFileBuff:输入的图片文件缓冲区;InBmpFileSize:输入的图片文件大小;pOutRGB_DataBuff:输出的RGB数据缓冲区;OutRGB_DataBuffSize:输出的RGB数据缓冲区大小;
  • OutRGB_ColorMode:输出RGB像素格式,支持RGB565,RGB888,ARGB8888;pOutBmpInfo:解析后的图片基本信息
  • * 返回 : BMP_ERROR
  • * 依赖 : 底层
  • * 作者 : cp1300@139.com
  • * 时间 : 2011-09-19
  • * 最后修改时间 : 2020-02-06
  • * 说明 : 无
  • *************************************************************************************************************************/
  • BMP_ERROR BMP_FullDecode(u8 *InBmpFileBuff, u32 InBmpFileSize, u8 *pOutRGB_DataBuff, u32 OutRGB_DataBuffSize, BMP_COLOR_MODE OutRGB_ColorMode, BMP_INFO *pOutBmpInfo)
  • {
  • BMP_FILE_HEADER *pBmpHeader; //图片文件头
  • BMP_FullDecodeDataType mDecodeTempData; //图片解析所需的临时变量
  • BMP_ERROR mBmpError = BMP_OK; //图片解析状态
  • u32 temp;
  • //基本数据初始化
  • pBmpHeader = (BMP_FILE_HEADER*)InBmpFileBuff; //得到BMP的头部信息
  • mDecodeTempData.mBmpInfo.bfOffBits = pBmpHeader->bfOffBits; //位图数据偏移地址偏移
  • mDecodeTempData.mBmpInfo.biBitCount = pBmpHeader->biBitCount; //位图数据的颜色深度只支持16bit,24bit,32bit
  • mDecodeTempData.mBmpInfo.biWidth = pBmpHeader->biWidth; //位图的水平像素数
  • mDecodeTempData.mBmpInfo.biHeight = pBmpHeader->biHeight; //位图的垂直像素数
  • mDecodeTempData.mBmpInfo.biSizeImage = pBmpHeader->biSizeImage; //位图的数据大小
  • mDecodeTempData.OutPixelOffset = 0; //数据输出偏移,像素偏移-用于16bit与32bit图片的索引,效率会比字节偏移高
  • mDecodeTempData.OutByteOffset = 0; //数据输出偏移,字节偏移,用于24bit格式图片下的偏移计算
  • mDecodeTempData.OutRGB_ColorMode = OutRGB_ColorMode; //输出像素格式
  • mDecodeTempData.InBmpFileSize = InBmpFileSize; //输入的图片数据文件大小
  • /****************************************************/
  • //调试
  • printf("\r\n地址偏移:%d\r\n", mDecodeTempData.mBmpInfo.bfOffBits);
  • printf("颜色深度:%d\r\n", mDecodeTempData.mBmpInfo.biBitCount);
  • printf("水平分辨率:%d\r\n", mDecodeTempData.mBmpInfo.biWidth);
  • printf("垂直分辨率:%d\r\n", mDecodeTempData.mBmpInfo.biHeight);
  • printf("数据大小:%luB\r\n", mDecodeTempData.mBmpInfo.biSizeImage);
  • printf("位图标志:0x%04X\r\n", pBmpHeader->bfType);
  • printf("位图biCompression:0x%lx\r\n\r\n", pBmpHeader->biCompression);
  • /*****************************************************/
  • //水平像素必须是4的倍数!!
  • if((mDecodeTempData.mBmpInfo.biWidth * mDecodeTempData.mBmpInfo.biBitCount / 8) % 4) //水平像素字节数不是4的整数倍
  • mDecodeTempData.uiTemp = ((mDecodeTempData.mBmpInfo.biWidth * mDecodeTempData.mBmpInfo.biBitCount / 8) / 4 + 1) * 4; //将水平像素字节数扩展成4的整数倍
  • else
  • mDecodeTempData.uiTemp = mDecodeTempData.mBmpInfo.biWidth * mDecodeTempData.mBmpInfo.biBitCount / 8;
  • mDecodeTempData.xValid = mDecodeTempData.mBmpInfo.biWidth * (mDecodeTempData.mBmpInfo.biBitCount / 8); //计算水平有效地数据字节数
  • //判断是否是合法的头信息
  • if(pBmpHeader->bfType != 0x4d42)//BM,BMP文件的头信息
  • {
  • mBmpError = BMP_ILLEGAL_ERROR;
  • DEBUG("非法的BMP图片,没有找到BMP图片头信息\r\n");
  • goto end_loop;
  • }
  • if(pBmpHeader->biCompression) //判断BMP图像是否是压缩的,如果是压缩的将不支持
  • {
  • mBmpError = BMP_COMP_ERROR;
  • DEBUG("不支持压缩的BMP图片\r\n");
  • goto end_loop;
  • }
  • BMP_memcpy((u8 *)pOutBmpInfo, (u8 *)&mDecodeTempData.mBmpInfo, sizeof(BMP_INFO)); //拷贝图片信息
  • mDecodeTempData.y = mDecodeTempData.mBmpInfo.biHeight - 1; //BMP图片由左下角到右上角刷新,因此起点y坐标要加上图片的高度
  • mDecodeTempData.x = 0;
  • mDecodeTempData.xEnd = 0 + mDecodeTempData.mBmpInfo.biWidth; //x终点坐标
  • //输入指针初始化
  • mDecodeTempData.FileOffset = mDecodeTempData.mBmpInfo.bfOffBits; //文件偏移
  • mDecodeTempData.InData32bit = (u32 *)&InBmpFileBuff[mDecodeTempData.FileOffset]; //跳到图片数据区
  • mDecodeTempData.InData16bit = (u16 *)&InBmpFileBuff[mDecodeTempData.FileOffset]; //跳到图片数据区
  • mDecodeTempData.InData24bit = (BMP_RGB_24BIT *)&InBmpFileBuff[mDecodeTempData.FileOffset]; //跳到图片数据区
  • //输出指针初始化
  • mDecodeTempData.OutData32bit = (u32 *)pOutRGB_DataBuff; //临时指针,用于输出32BIT的RGB数据-指向输出RGB缓冲区
  • mDecodeTempData.OutData16bit = (u16 *)pOutRGB_DataBuff; //临时指针,用于输出16BIT的RGB数据-指向输出RGB缓冲区
  • mDecodeTempData.OutData24bit = (BMP_RGB_24BIT *)pOutRGB_DataBuff; //临时指针,用于输出16BIT的RGB数据-指向输出RGB缓冲区
  • switch(OutRGB_ColorMode) //输出像素数据格式
  • {
  • case BMP_COLOR_ARGB8888 : //32bit格式输出
  • {
  • mDecodeTempData.OutPixelByte = 4; //4字节
  • }break;
  • case BMP_COLOR_RGB888 : //24bit格式输出
  • {
  • mDecodeTempData.OutPixelByte = 3; //3字节
  • }break;
  • default: //默认为RGB555
  • {
  • mDecodeTempData.OutPixelByte = 2; //2字节
  • }break;
  • }
  • mDecodeTempData.OutPixelOffset = mDecodeTempData.y * mDecodeTempData.mBmpInfo.biWidth + mDecodeTempData.x; //计算偏移位置,从最下角开始
  • temp = (u32)mDecodeTempData.mBmpInfo.biWidth * mDecodeTempData.mBmpInfo.biHeight * mDecodeTempData.OutPixelByte; //计算需要的输出缓冲区大小
  • if(OutRGB_DataBuffSize < temp)
  • {
  • DEBUG("解析BMP图片出错,输出缓冲区(%luB)过小,至少需要%luB\r\n", OutRGB_DataBuffSize, temp);
  • }
  • switch (mDecodeTempData.mBmpInfo.biBitCount)//判断图片颜色深度
  • {
  • case 32: //32BIT ARGB8888
  • {
  • mBmpError = BMP_FullDecode32bit_Module(&mDecodeTempData); //子流程-32bit位图完全解析(从内存中读取图片数据,然后解析到内存中)
  • }break;
  • case 24: //24BIT RGB888 //可能存在4字节对齐问题
  • {
  • mBmpError = BMP_FullDecode24bit_Module(&mDecodeTempData); //调用子流程,解析24bit数据
  • }break;
  • case 16: //16BIT RGB555
  • {
  • mBmpError = BMP_FullDecode16bit_Module(&mDecodeTempData); //子流程-16it位图完全解析(从内存中读取图片数据,然后解析到内存中)
  • }break;
  • default : break;//只支持16BIT,24BIT,32BIT图片的解码
  • }
  • end_loop:
  • return mBmpError;
  • }
  • /*************************************************************************************************************************
  • * 函数 : static BMP_ERROR BMP_FullDecode24bit_Module(BMP_FullDecodeDataType *pDecodeTempData)
  • * 功能 : 子流程-24bit位图完全解析(从内存中读取图片数据,然后解析到内存中)
  • * 参数 : pDecodeTempData:解析所需的变量;
  • * 返回 : BMP_ERROR
  • * 依赖 : 底层
  • * 作者 : cp1300@139.com
  • * 时间 : 2011-09-19
  • * 最后修改时间 : 2020-02-06
  • * 说明 : 无
  • *************************************************************************************************************************/
  • static BMP_ERROR BMP_FullDecode24bit_Module(BMP_FullDecodeDataType *pDecodeTempData)
  • {
  • BMP_ERROR mBmpError = BMP_OK; //图片解析状态
  • u32 RGB_Data;
  • u8 *pData;
  • u8 InterByte = 0; //插值数据字节数
  • if(pDecodeTempData->uiTemp > pDecodeTempData->xValid) //有进行插值
  • {
  • InterByte = pDecodeTempData->uiTemp - pDecodeTempData->xValid; //计算插值
  • }
  • do
  • {
  • switch(pDecodeTempData->OutRGB_ColorMode) //输出像素数据格式
  • {
  • case BMP_COLOR_ARGB8888 : //32bit格式输出,24->32
  • {
  • BMP_memcpy((u8 *)&RGB_Data, (u8 *)pDecodeTempData->InData24bit, 3);
  • pDecodeTempData->OutData32bit[pDecodeTempData->OutPixelOffset + pDecodeTempData->x] = RGB888toARGB(RGB_Data); //转换为32bit
  • }break;
  • case BMP_COLOR_RGB888 : //24bit格式输出,无需转换
  • {
  • BMP_memcpy((u8 *)(&pDecodeTempData->OutData24bit[pDecodeTempData->OutPixelOffset + pDecodeTempData->x]), (u8 *)pDecodeTempData->InData24bit, 3);
  • }break;
  • default: //默认为RGB565
  • {
  • BMP_memcpy((u8 *)&RGB_Data, (u8 *)pDecodeTempData->InData24bit, 3);
  • pDecodeTempData->OutData16bit[pDecodeTempData->OutPixelOffset + pDecodeTempData->x] = RGB565(RGB_Data); //转换为16bit
  • }break;
  • }
  • pDecodeTempData->InData24bit ++;
  • pDecodeTempData->FileOffset += 3; //文件偏移
  • pDecodeTempData->x ++;
  • if(pDecodeTempData->x == pDecodeTempData->xEnd)
  • {
  • pDecodeTempData->x = 0;
  • if(pDecodeTempData->y == 0) //结束了
  • {
  • uart_printf("图片解析结束\r\n");
  • break;
  • }
  • pDecodeTempData->y --;
  • pDecodeTempData->OutPixelOffset -= pDecodeTempData->mBmpInfo.biWidth;
  • //此处检查是否有插值
  • if(InterByte) //有进行插值
  • {
  • pData = (u8 *) pDecodeTempData->InData24bit;
  • pData += InterByte; //跳过插值的像素
  • pDecodeTempData->InData24bit = (BMP_RGB_24BIT *)pData; //重新将InData24bit指针,跳过中间的插值数据
  • }
  • }
  • }
  • while(pDecodeTempData->FileOffset < pDecodeTempData->InBmpFileSize);
  • return mBmpError;
  • }
  • /*************************************************************************************************************************
  • * 函数 : static BMP_ERROR BMP_FullDecode16bit_Module(BMP_FullDecodeDataType *pDecodeTempData)
  • * 功能 : 子流程-16bit位图完全解析(从内存中读取图片数据,然后解析到内存中)
  • * 参数 : pDecodeTempData:解析所需的变量;
  • * 返回 : BMP_ERROR
  • * 依赖 : 底层
  • * 作者 : cp1300@139.com
  • * 时间 : 2011-09-19
  • * 最后修改时间 : 2020-02-06
  • * 说明 : 无
  • *************************************************************************************************************************/
  • static BMP_ERROR BMP_FullDecode16bit_Module(BMP_FullDecodeDataType *pDecodeTempData)
  • {
  • BMP_ERROR mBmpError = BMP_OK; //图片解析状态
  • u32 RGB_Data;
  • u8 *pData;
  • u8 InterByte = 0; //插值数据字节数
  • if(pDecodeTempData->uiTemp > pDecodeTempData->xValid) //有进行插值
  • {
  • InterByte = pDecodeTempData->uiTemp - pDecodeTempData->xValid; //计算插值
  • }
  • do
  • {
  • //RGB555 转 RGB565
  • *pDecodeTempData->InData16bit = ((*pDecodeTempData->InData16bit & 0xffe0) << 1) | (*pDecodeTempData->InData16bit & 0x001f);
  • if(*pDecodeTempData->InData16bit & BIT6) *pDecodeTempData->InData16bit |= BIT5;
  • switch(pDecodeTempData->OutRGB_ColorMode) //输出像素数据格式
  • {
  • case BMP_COLOR_ARGB8888 : //32bit格式输出,16->32
  • {
  • pDecodeTempData->OutData32bit[pDecodeTempData->OutPixelOffset + pDecodeTempData->x] = RGB888toARGB(RGB888(*pDecodeTempData->InData16bit)); //转换为32bit
  • }break;
  • case BMP_COLOR_RGB888 : //24bit格式输出
  • {
  • RGB_Data = RGB888(*pDecodeTempData->InData16bit);
  • BMP_memcpy((u8 *)(&pDecodeTempData->OutData24bit[pDecodeTempData->OutPixelOffset + pDecodeTempData->x]), (u8 *)&RGB_Data, 3);
  • }break;
  • default: //默认为RGB565
  • {
  • pDecodeTempData->OutData16bit[pDecodeTempData->OutPixelOffset + pDecodeTempData->x] = *pDecodeTempData->InData16bit; //转换为16bit
  • }break;
  • }
  • pDecodeTempData->InData16bit ++;
  • pDecodeTempData->FileOffset += 2; //文件偏移
  • pDecodeTempData->x ++;
  • if(pDecodeTempData->x == pDecodeTempData->xEnd)
  • {
  • pDecodeTempData->x = 0;
  • if(pDecodeTempData->y == 0) //结束了
  • {
  • uart_printf("图片解析结束\r\n");
  • break;
  • }
  • pDecodeTempData->y --;
  • pDecodeTempData->OutPixelOffset -= pDecodeTempData->mBmpInfo.biWidth;
  • //此处检查是否有插值
  • if(InterByte) //有进行插值
  • {
  • pData = (u8 *) pDecodeTempData->InData16bit;
  • pData += InterByte; //跳过插值的像素
  • pDecodeTempData->InData16bit = (u16 *)pData; //重新将16bit指针,跳过中间的插值数据
  • }
  • }
  • }
  • while(pDecodeTempData->FileOffset < pDecodeTempData->InBmpFileSize);
  • return mBmpError;
  • }
  • /*************************************************************************************************************************
  • * 函数 : static BMP_ERROR BMP_FullDecode32bit_Module(BMP_FullDecodeDataType *pDecodeTempData)
  • * 功能 : 子流程-32bit位图完全解析(从内存中读取图片数据,然后解析到内存中)
  • * 参数 : pDecodeTempData:解析所需的变量;
  • * 返回 : BMP_ERROR
  • * 依赖 : 底层
  • * 作者 : cp1300@139.com
  • * 时间 : 2011-09-19
  • * 最后修改时间 : 2020-02-06
  • * 说明 : 无
  • *************************************************************************************************************************/
  • static BMP_ERROR BMP_FullDecode32bit_Module(BMP_FullDecodeDataType *pDecodeTempData)
  • {
  • BMP_ERROR mBmpError = BMP_OK; //图片解析状态
  • u32 RGB_Data;
  • do
  • {
  • switch(pDecodeTempData->OutRGB_ColorMode) //输出像素数据格式
  • {
  • case BMP_COLOR_ARGB8888 : //32bit格式输出-注意:最高为A一直为0,需要修改为A=0xFF
  • {
  • pDecodeTempData->OutData32bit[pDecodeTempData->OutPixelOffset + pDecodeTempData->x] = RGB888toARGB(*pDecodeTempData->InData32bit);
  • }break;
  • case BMP_COLOR_RGB888 : //24bit格式输出
  • {
  • BMP_memcpy((u8 *)(&pDecodeTempData->OutData24bit[pDecodeTempData->OutPixelOffset + pDecodeTempData->x]), (u8 *)pDecodeTempData->InData32bit ,3);
  • }break;
  • default: //默认为RGB565
  • {
  • pDecodeTempData->OutData16bit[pDecodeTempData->OutPixelOffset + pDecodeTempData->x] = RGB565(*pDecodeTempData->InData32bit);
  • }break;
  • }
  • pDecodeTempData->InData32bit ++;
  • pDecodeTempData->FileOffset += 4; //文件偏移
  • pDecodeTempData->x ++;
  • if(pDecodeTempData->x == pDecodeTempData->xEnd)
  • {
  • pDecodeTempData->x = 0;
  • if(pDecodeTempData->y == 0) //结束了
  • {
  • uart_printf("图片解析结束\r\n");
  • break;
  • }
  • pDecodeTempData->y --;
  • pDecodeTempData->OutPixelOffset -= pDecodeTempData->mBmpInfo.biWidth;
  • }
  • }
  • while(pDecodeTempData->FileOffset < pDecodeTempData->InBmpFileSize);
  • return mBmpError;
  • }
  • /*************************************************************************************************************
  • * 文件名 : BmpDecode.h
  • * 功能 : BMP图片软件解码
  • * 作者 : cp1300@139.com
  • * 创建时间 : 2011-09-19
  • * 最后修改时间 : 2020-02-06
  • * 详细 :
  • *************************************************************************************************************/
  • #ifndef __BMP_DECODE_H__
  • #define __BMP_DECODE_H__
  • #include "system.h"
  • //软解码BMP状态
  • typedef enum
  • {
  • BMP_OK = 0, //解码成功
  • BMP_ILLEGAL_ERROR = 1, //非法的图片,没有找到BMP头
  • BMP_COMP_ERROR = 2, //不支持压缩bmp图片
  • }BMP_ERROR;
  • //BMP颜色模式
  • typedef enum
  • {
  • BMP_COLOR_ARGB8888 = 0,
  • BMP_COLOR_RGB888 = 1,
  • BMP_COLOR_RGB565 = 2,
  • }BMP_COLOR_MODE;
  • //软解码BMP图片相关的信息结构
  • typedef struct
  • {
  • u32 biSizeImage; //位图数据的大小-如果是RGB格式,此处可能会为0
  • u16 bfOffBits ; //从文件开始到位图数据(bitmap data)开始之间的的偏移
  • u16 biWidth ; //图象的宽度,以象素为单位
  • u16 biHeight ; //图象的高度,以象素为单位
  • u8 biBitCount ; //说明比特数/象素,其值为1、4、8、16、24、或32
  • }BMP_INFO;
  • bool BMP_GetInfo(const u8 pFileHeaderBuff[50], BMP_INFO *pBmpInfo); //获取BMP图片的信息
  • BMP_ERROR BMP_FullDecode(u8 *InBmpFileBuff, u32 InBmpFileSize, u8 *pOutRGB_DataBuff, u32 OutRGB_DataBuffSize, BMP_COLOR_MODE OutRGB_ColorMode, BMP_INFO *pOutBmpInfo);//BMP图片完全解析,需要输入输出缓冲区
  • #endif //__BMP_DECODE_H__

测试代码如下(循环播放一个目录中的所有图片,都是事先准备好的,图片可以用光影魔术手进行批量处理,处理为支持的图片大小),我自己做了LCD驱动,以及FATFS封装,后面再分享。

  • //循环播放图片测试,需要先获取到目录中所有的图片信息,然后循环播放
  • if(1)
  • {
  • FILE_ERROR mFileError;
  • u8 *pFileBuff;
  • u32 FileSize;
  • BMP_INFO mBmpInfo;
  • u16 index = 0;
  • GRAM_HANDLE *pGramHandle = GRAM_Create(480, 272, DMA2D_COLOR_RGB888);
  • GDI_Clear(pGramHandle, 0xFFFFFF);
  • //获取目录中所有的bmp图片文件
  • if(FILE_GetFolderFileInfo("C:\\iTools壁纸", &g_PublicResource.mFoldeFileInfo, E_BMP, &mFileError) == TRUE)
  • {
  • if(FILE_SetPath("C:\\iTools壁纸", &mFileError) == TRUE) //设置相对路径
  • {
  • while(1)
  • {
  • for(index = 0;index < g_PublicResource.mFoldeFileInfo.TargetFileCnt; index ++)
  • {
  • if(FILE_Load_malloc(g_PublicResource.mFoldeFileInfo.pFileNameListBuff[index].NameBuff, &pFileBuff, &FileSize, 512*1024, &mFileError) == TRUE)
  • {
  • if(FileSize > 50)
  • {
  • BMP_FullDecode(pFileBuff, FileSize, (u8 *)pGramHandle->GRAM_Addr, pGramHandle->GRAM_Size, BMP_COLOR_RGB888, &mBmpInfo);//BMP图片完全解析,需要输入输出缓冲区
  • //GRAM_LocalCopy(pLTDC_Layer1_GRAM_HANDLE, 0, 0, pGramHandle, 0, 0, pGramHandle->Width, pGramHandle->Height); //GRAM局部拷贝(不支持Alpha)
  • GRAM_AllCopy(pLTDC_Layer1_GRAM_HANDLE, pGramHandle); //GRAM全部拷贝(2个显存宽高必须一致,不支持Alpha)
  • SYS_DelayMS(1000);
  • }
  • FILE_Load_Free(pFileBuff); //释放掉FILE_Load_malloc()申请的内存
  • }
  • else
  • {
  • SYS_DelayMS(100);
  • }
  • }
  • }
  • }
  • }
  • }

核心就是

  • BMP_FullDecode(pFileBuff, FileSize, (u8 *)pGramHandle->GRAM_Addr, pGramHandle->GRAM_Size, BMP_COLOR_RGB888, &mBmpInfo);//BMP图片完全解析,需要输入输出缓冲区

 

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门