Bitmap數(shù)據(jù)結(jié)構(gòu)
BMP文件的數(shù)據(jù)可分為四個部分
Bmp文件頭:提供文件的格式,大小,位圖數(shù)據(jù)的起始偏移 (14 bytes)
Bmp信息頭:提供圖像數(shù)據(jù)的尺寸、位平面數(shù)奴艾、壓縮方式弛车、位圖數(shù)據(jù)大小,位深度 (40 bytes)
調(diào)色板:根據(jù)位深度(24,32則不采用)來判斷是否采用這種模式巷帝,調(diào)色板就是索引與其對應(yīng)的顏色的映射表 (一般1024 bytes 256色 * 4)
位圖數(shù)據(jù):圖像數(shù)據(jù)
Bitmap 文件頭定義
extern struct BMPFILE {
BITMAPFILEHEADER file_head;
BITMAPINFOHEADER bmp_info_head;
}BMPFILE;
//**** sHeader *****
//14 byte
typedef struct tagBITMAPFILEHEADER {
//== BM in windows
unsigned short bfType;
//File Size
unsigned long bfSize;
//always 0
unsigned short bfReserved1;
unsigned short bfReserved2;
//offset of data area
unsigned long bfOffBits;
} BITMAPFILEHEADER;
//**** bitmap information header *****
//40byte
typedef struct tagBITMAPINFOHEADER{
//in Windows always == 0x28
long biSize;
//bmp info
long biWidth;
long biHeight;
//always 1
short int biPlanes;
//bits count for a pixel
short int biBitCount;
// 0 [no compression]
// 1 [BI_RLE8]
// 2 [BI_RLE4]
short int biCompression;
/*****************************************************************
數(shù)據(jù)區(qū)大小,單位字節(jié)
數(shù)據(jù)區(qū)每行像素數(shù)據(jù)大小必須為4字節(jié)倍數(shù)扫夜,不夠則以0補(bǔ)齊
biSizeImage = ((biWidth + 0x3) & ~0x3) * biHeight
****************************************************************/
long biSizeImage;
long biXPelsPerMeter;
long biYPelsPerMeter;
//used color in Palette
long biClrUsed;
//Important color in Palette
long biClrImportant;
} BITMAPINFOHEADER;
調(diào)色板
位深度為8位一般采用調(diào)色板模式楞泼,調(diào)色板一般有256色* 4 bytes 驰徊,按照 (blue,green,red,alpha) 順序排列
調(diào)色板其實(shí)就是一張映射表堕阔,標(biāo)識顏色索引號與其代表的顏色對應(yīng)關(guān)系辣垒,可以看成一個二維數(shù)組palette[N][4],N表示顏色索引數(shù)。
位圖(圖像)數(shù)據(jù)
上面說到采用位深度為8位則調(diào)色板模式印蔬,則每個像素占一個字節(jié)勋桶,這個字節(jié)表示的索引去查找調(diào)色板顯示出來,位圖數(shù)據(jù)的排列順序是從左下角到右上角侥猬,以行主序排列的例驹。
實(shí)際應(yīng)用
從海思的回調(diào)接口中獲取Subtitle數(shù)據(jù),然后對其圖像數(shù)據(jù)進(jìn)行處理
返回的結(jié)構(gòu)體如下:
/** Information of bitmap subtitle *//** CNcomment:圖像字幕信息 */
typedef struct hiSVR_SO_GFX_S
{
HI_S64 s64Pts; /**<Start a display time, unit is Millisecond *//**<CNcomment:顯示時間戳退唠,單位ms */
HI_U32 u32Duration; /**<Duration of displaying, unit is Millisecond *//**<CNcomment:顯示時長鹃锈,單位ms */
HI_U32 u32Len; /**<Bytes of subtitle data *//**<CNcomment:數(shù)據(jù)長度,單位字節(jié) */
HI_U8* pu8PixData; /**<Data of subtitle *//**<CNcomment:圖像數(shù)據(jù) */
HI_SVR_SO_DISP_MSG_TYPE_E enMsgType; /**<Type of display message *//**<CNcomment:顯示消息類型 */
HI_SVR_SO_COLOR_S stPalette[HI_SVR_SO_PALETTE_ENTRY]; /**<Palette *//**<CNcomment:調(diào)色板瞧预,ARGB8888 */
HI_S32 s32BitWidth; /**<Bits of Pix *//**<CNcomment:象素位寬 , 可以為 2,4,8位*/
HI_U32 x, y, w, h; /**<Position of display subtitle *//**<CNcomment:顯示位置和高寬信息 */
HI_U32 u32CanvasWidth; /**<Display canvas width *//**<CNcomment:顯示畫布的寬度信息 */
HI_U32 u32CanvasHeight; /**<Display canvas height *//**<CNcomment:顯示畫布的高度信息 */
} HI_SVR_SO_GFX_S;
通過上面結(jié)構(gòu)體拼接成位圖(32位)處理如下
/**
*拼接Bitmap文件頭屎债,位圖信息頭
*/
static int getBitmapheader(HI_SVR_SO_GFX_S stGfx,struct BMPFILE *header)
{
if (header == (struct BMPFILE *) NULL)
{
return -1;
}
//file info header
header->file_head.bfType = 0x4d42; //BM
header->file_head.bfSize = stGfx.u32Len * 4 + sizeof(BMPFILE);
header->file_head.bfReserved1 = 0;
header->file_head.bfReserved2 = 0;
header->file_head.bfOffBits = sizeof(BMPFILE);
//bitmap info header
header->bmp_info_head.biSize = 0x28; //40 byte
header->bmp_info_head.biWidth = stGfx.w;
header->bmp_info_head.biHeight = stGfx.h;
header->bmp_info_head.biPlanes = 1;
header->bmp_info_head.biBitCount = 0x20;
header->bmp_info_head.biCompression = 0;
header->bmp_info_head.biSizeImage = stGfx.u32Len;
header->bmp_info_head.biXPelsPerMeter = 0;
header->bmp_info_head.biYPelsPerMeter = 0;
header->bmp_info_head.biClrUsed = 0;
header->bmp_info_head.biClrImportant = 0;
}
/*
* 裁剪圖片,對透明以及圖片多余的內(nèi)容進(jìn)行裁剪計算
*/
int cropBmp(HI_SVR_SO_GFX_S* pstGfx, unsigned long* newheight, unsigned long* topoffset)
{
unsigned short u8Alpha = 0;
unsigned long i = 0, j = 0, k = 0;
if (pstGfx->u32Len == 0)
{
return -1;
}
//clear head and end transparent line
//from top to bottom, i lines blank
for (i = 0; i < pstGfx->h; i++)
{
u8Alpha = 0;
for (k = 0; k < pstGfx->w; k++)
{
if (pstGfx->stPalette[pstGfx->pu8PixData[i * pstGfx->w + k]].u8Alpha > 0)
{
u8Alpha = 1;
break;
}
}
if (u8Alpha > 0)
{ break; }
}
if (i == pstGfx->h) //reach to bottom
{
return -1;
}
//from bottom to i, pstGfx->h -j lines blank
for (j = pstGfx->h - 1; j > i; j--)
{
u8Alpha = 0;
for (k = 0; k < pstGfx->w; k++)
{
if (pstGfx->stPalette[pstGfx->pu8PixData[j * pstGfx->w + k]].u8Alpha > 0)
{
u8Alpha = 1;
break;
}
}
if ( u8Alpha > 0)
{ break; }
}
j += 1;
*topoffset = i;
*newheight = (j - i);
return 0;
}
/*
* 根據(jù)調(diào)色板以及圖像信息處理每個像素
*/
static void getPixels(HI_SVR_SO_GFX_S pstGfx,char *buf)
{
unsigned long i = 0,j = 0,index = 0;
//normal 2d subtitle
//from pallete to RGBA data
for (i = 0; i < pstGfx.h; i++)
{
for (j = 0; j < pstGfx.w; j++)
{
index = pstGfx.pu8PixData[pstGfx.u32Len - i * pstGfx.w + j];
buf[(i * pstGfx.w + j) * 4 + 0 ] = pstGfx.stPalette[ index ].u8Red;
buf[(i * pstGfx.w + j) * 4 + 1 ] = pstGfx.stPalette[ index ].u8Green;
buf[(i * pstGfx.w + j) * 4 + 2 ] = pstGfx.stPalette[ index ].u8Blue;
buf[(i * pstGfx.w + j) * 4 + 3 ] = pstGfx.stPalette[ index ].u8Alpha;
if (buf[(i * pstGfx.w + j) * 4 + 3] == 0) //alpha=0,clear RGB
{
memset(&buf[(i * pstGfx.w + j) * 4], 0x00, 4);
}
}
}
}
/**
* 處理位圖接口
*/
int loadBmpToBuffer(unsigned long handler)
{
int ret;
struct BMPFILE *header;
//位圖數(shù)據(jù)
char *buf = NULL ;
//包含Bitmap垢油,Text盆驹,ASS類型數(shù)據(jù)
HI_SVR_SO_SUBTITLE_INFO_S* pstInfo = (HI_SVR_SO_SUBTITLE_INFO_S*)handler;
unsigned long pdata_length,file_length;
int i;
unsigned long newheight,topoffset;
HI_SVR_SO_GFX_S stGfx;
header = (struct BMPFILE*)malloc(sizeof(BMPFILE));
//這里只對圖像數(shù)據(jù)進(jìn)行處理
stGfx = pstInfo->unSubtitleParam.stGfx;
ret = cropBmp(&stGfx,&newheight,&topoffset);
if(ret == 0)
{
stGfx.h = newheight;
stGfx.y = stGfx.y + topoffset; //update h
stGfx.u32Len = stGfx.h * stGfx.w;
memcpy(stGfx.pu8PixData, &(stGfx.pu8PixData[topoffset * stGfx.w]), stGfx.w * newheight);
}
else
{
stGfx.h = 0;
stGfx.y = 0;
stGfx.u32Len = 0;
}
//裁剪之后位圖數(shù)據(jù)改變,重新計算
pdata_length = stGfx.w * stGfx.h;
//拼接位圖頭
getBitmapheader(stGfx,header);
//長度為每個像素 * 4 + 頭長度
file_length = pdata_length * 4 + sizeof(BMPFILE);
buf = (char*)malloc(file_length);
if (buf == NULL)
{
return -1;
}
memset(buf,0,file_length);
memcpy(buf,header,sizeof(BMPFILE));
getPixels(stGfx,buf + sizeof(BMPFILE));
//buf為位圖文件數(shù)據(jù)滩愁,
return 1;
}
這樣得到最終的buf為位圖數(shù)據(jù)躯喇,可以直接通過BitmapFactory.decodeByteArray() 形成Subtitle位圖顯示在屏幕上