打印
[应用相关]

STM32 BMP图片解析

[复制链接]
767|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
guanjiaer|  楼主 | 2021-8-2 10:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
重新优化了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 ++;
        }
}



使用特权

评论回复
沙发
guanjiaer|  楼主 | 2021-8-2 10:58 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        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;
}



使用特权

评论回复
板凳
guanjiaer|  楼主 | 2021-8-2 10:59 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        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;
}



使用特权

评论回复
地板
guanjiaer|  楼主 | 2021-8-2 11:00 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        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;
}



使用特权

评论回复
5
guanjiaer|  楼主 | 2021-8-2 11:00 | 只看该作者

/*************************************************************************************************************************
* 函数                        :        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;
}



使用特权

评论回复
6
guanjiaer|  楼主 | 2021-8-2 11:01 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        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;
}



使用特权

评论回复
7
guanjiaer|  楼主 | 2021-8-2 11:02 | 只看该作者

/*************************************************************************************************************
* 文件名                :        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__


使用特权

评论回复
8
guanjiaer|  楼主 | 2021-8-2 11:04 | 只看该作者
测试代码如下(循环播放一个目录中的所有图片,都是事先准备好的,图片可以用光影魔术手进行批量处理,处理为支持的图片大小),我自己做了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图片完全解析,需要输入输出缓冲区

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

4146

帖子

2

粉丝