我們在LCD上顯示內容的時候,經常會有顯示bmp檔案的需求,例如顯示一個logo、選單圖示等,我們可以在應用程式中打開bmp檔案,然后將它決議成rgb格式的資料寫入frame buffer中就可以完成顯示,
1 BMP檔案的格式
BMP影像檔案格式是Windows采用的影像檔案存盤格式,在Windows環境下的所有影像處理軟體都支持這種格式,它是由3個部分組成:位圖檔案頭、位圖資訊頭、顏色點陣資料,
1.1 位圖檔案頭
位圖檔案頭分為4個部分,共占據14位元組:

1.2 位圖資訊頭
位圖資訊頭共40個位元組:

1.3 顏色資料
BMP檔案除了上述檔案頭、資訊頭所占據的內容外,剩余資料都是RGB顏色資料,其中需要注意的是:BMP的顏色資料是按照自下而上,自左向右的順序排列的,

這個排列的順序非常關鍵,因為我們LCD顯示的時候,是自上而下、自左向右的,所以我們在決議這個rgb資料的時候需要重新按照LCD的順序放入buffer中,
2 代碼實作
2.1 頭檔案<pic_operation.h>
/*
* 1、需要一個記憶體來保存從BMP檔案決議得到的顏色資料;
* 2、需要一個函式來判斷打開的檔案是否是我們需要的BMP檔案;
* 3、需要一個函式來完成對BMP檔案的決議;
* 4、需要一個函式來釋放分配給保存顏色資料的記憶體;
*/
/* 保存RGB資料的地方 */
typedef struct PixelDatas{
int iWideth;
int iHeight;
int iBpp;
unsigned char *aucPixelDatas;
}T_PixelDatas,*PT_PixelDatas;
/* 封裝好對一個檔案的處理 */
typedef struct PicFileParser{
char *name;
int (*isSupport)(unsigned char *aFileHead);
int (*GetPixelDatas)(unsigned char *aFileHead,PT_PixelDatas tPixelDatas);
int (*FreePixelDatas)(PT_PixelDatas tPixelDatas);
}T_PicFileParser,*PT_PicFileParser;
2.2 C檔案實作<bmp_operation.c>
#include <bmp_operation.h>
/*
* 1、需要定義一個struct PicFileParser 型別的結構體;
* 2、需要實作一個函式來判斷打開的檔案是否是我們需要的BMP檔案;
* 3、需要實作一個函式來釋放分配給保存RGB資料的記憶體;
* 4、需要實作一個函式來決議BMP檔案;
*/
static int isSupportBmp(unsigned char *aFileHead);
static int GetPixelDatasFormBmp(unsigned char *aFileHead,PT_PixelDatas ptPixelDatas);
static int FreePixelDatasForBmp(PT_PixelDatas tPixelDatas);
T_PicFileParser g_tBmpParser = {
.name = "bmp",
.isSupport = isSupportBmp,
.GetPixelDatas = GetPixelDatasFromBmp,
.FreePixelDatas = FreePixelDatasForBmp,
}
/* 功能:判斷一個檔案是否是BMP檔案
* 引數aFileHead : 讀入檔案的頭
* 回傳值:1-該檔案是BMP檔案;0-該檔案不是BMP檔案
*/
static int isSupportBmp(unsigned char *aFileHead){
if(aFileHead[0] != 0x42 || aFileHead[1] != 0x4d)
return 0;
else
return 1;
}
/* 功能:釋放分配給存盤RGB資料的記憶體
* 引數tPixelDatas: 從BMP檔案決議出來資料存盤的地方
* 回傳值:0
*/
static int FreePixelDatasForBmp(PT_PixelDatas tPixelDatas){
free(tPixelDatas->aucPixelDatas);
}
/******************************************************************/
/* 決議 BMP 檔案 */
/* 1、定義一個位圖檔案頭 */
typedef struct tagBITMAPFILEHEADER{
unsigned short bfType;
unsigned long bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned long bfOffBits;
}BITMAPFILEHEADER;
/* 2、定義一個位圖資訊頭 */
typedef struct tagBITMAPINFOHEADER{
unsigned long biSize;
unsigned long biWidth;
unsigned long biHeight;
unsigned short biPlanes;
unsigned short bitBitCount;
unsigned long bitCompression;
unsigned long bitSizeImage;
unsigned long biXPelPerMeter;
unsigned long biYPelPerMeter;
unsigned long biClrUsed;
unsigned long biClrImportant;
}BITMAPINFOHEADER;
/*
/* 3、決議BMP檔案 */
static int GetPixelDatasFormBmp(unsigned char *aFileHead,PT_PixelDatas ptPixelDatas){
/* 定義檔案頭和資訊頭 */
BITMAPFILEHEADER *ptBITMAPFILEHEADER;
BITMAPINFOHEADER *ptBITMAPINFOHEADER ;
/* 將檔案頭指標指向檔案的開始 */
ptBITMAPFILEHEADER = (BITMAPFILEHEADER *)aFileHead;
/*將資訊頭指標指向檔案中資訊頭的起始處*/
ptBITMAPINFOHEADER = (BITMAPINFOHEADER *)(aFileHead + sizeof(BITMAPFILEHEADER ));
/* 計算需要分配記憶體的大小 */
int iWidth = ptBITMAPINFOHEADER->biWidth;
int iHeight = ptBITMAPINFOHEADER->biHeight;
int iBpp = ptBITMAPINFOHEADER->bitBitCount;
ptPixelDatas->aucPixelDatas = malloc(iWidth*iHeight*iBpp/8);
if(NULL == ptPixelDatas->aucPixelDatas){
return -1;
}
/* 確定取資料以及存資料的位置 */
unsigned char *pucSrc;
unsigned char *pucData;
pucSrc = aFileHead + ptBITMAPFILEHEADER->bfOffBits;/*讓資料源指標指向檔案中數據的起始處*/
int iLineWidthReal = iWidth * iBpp /8; /*確定每行的位元組數*/
int iLineWidthAlign = (iLineWidthReal + 3)&~0x3;/*將每行的位元組數向4取整得到對齊后的每行位元組數*/
pucSrc = pucSrc + (iHeight-1) * iLineWidthAlign ; /*將資料源指標指向影像的最后一行起始處,該處的資料對應LCD顯示時的第一行*/
pucData = ptPixelDatas->aucPixelDatas;/*資料的目的地址就是剛分配的記憶體處*/
/* 一行一行的從源地址取出資料放入目的地址 */
int x;
int y;
for(y = 0;y < iHeight; y++){
memcpy(pucData,pucSrc,iLineWidthReal); /*每次從源地址拷貝iLienWidthReal長度的資料到目的地址*/
pucSrc -= iLineWidthAlign;/*完成一次拷貝后將源地址指向上一行*/
pucData += iLineWidthReal; /*完成一次拷貝后將目的地址指向下一行*/
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/227996.html
標籤:其他
