Bitmap数据结构
BMP文件的数据可分为四个部分
-
Bmp文件头:提供文件的格式,大小,位图数据的起始偏移 (14 bytes)
-
Bmp信息头:提供图像数据的尺寸、位平面数、压缩方式、位图数据大小,位深度 (40 bytes)
-
调色板:根据位深度(24,32则不采用)来判断是否采用这种模式,调色板就是索引与其对应的颜色的映射表 (一般1024 bytes 256色 * 4)
-
位图数据:图像数据
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;
/*****************************************************************
数据区大小,单位字节
数据区每行像素数据大小必须为4字节倍数,不够则以0补齐
biSizeImage = ((biWidth + 0x3) & ~0x3) * biHeight
****************************************************************/
long biSizeImage;
long biXPelsPerMeter;
long biYPelsPerMeter;
//used color in Palette
long biClrUsed;
//Important color in Palette
long biClrImportant;
} BITMAPINFOHEADER;
调色板
位深度为8位一般采用调色板模式,调色板一般有256色* 4 bytes ,按照 (blue,green,red,alpha) 顺序排列
调色板其实就是一张映射表,标识颜色索引号与其代表的颜色对应关系,可以看成一个二维数组palette[N][4],N表示颜色索引数。
位图(图像)数据
上面说到采用位深度为8位则调色板模式,则每个像素占一个字节,这个字节表示的索引去查找调色板显示出来,位图数据的排列顺序是从左下角到右上角,以行主序排列的。
实际应用
从海思的回调接口中获取Subtitle数据,然后对其图像数据进行处理
返回的结构体如下:
/** 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:数据长度,单位字节 */
HI_U8* pu8PixData; /**<Data of subtitle *//**<CNcomment:图像数据 */
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:调色板,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;
通过上面结构体拼接成位图(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;
}
/*
* 裁剪图片,对透明以及图片多余的内容进行裁剪计算
*/
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;
}
/*
* 根据调色板以及图像信息处理每个像素
*/
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;
//位图数据
char *buf = NULL ;
//包含Bitmap,Text,ASS类型数据
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));
//这里只对图像数据进行处理
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;
}
//裁剪之后位图数据改变,重新计算
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为位图文件数据,
return 1;
}
这样得到最终的buf为位图数据,可以直接通过BitmapFactory.decodeByteArray() 形成Subtitle位图显示在屏幕上
网友评论