/*******************************************************************************
* File name : Osdchar.c
* Description : 实现yuv上的字幕叠加,同时支持滚动,颜色变换,逐渐消隐,大小可调等功能.
该文件为纯C文件,不依赖第三方库及其他系统调用。可实现跨平台功能。
* Wrote by/Date : gaoc@devison.com/2010.02.27
* Modify/Date :
* Project : V30E
*******************************************************************************/
#include "Osdchar.h"
//缓冲分配
unsigned char srcRGBBuf[IMAGEWIDTH*IMAGEHEIGHT*3];
unsigned char dstRGBBuf[IMAGEWIDTH*IMAGEHEIGHT*3];
unsigned char srcYUVBuf[IMAGEWIDTH*IMAGEHEIGHT*3/2];
unsigned char dstYUVBuf[IMAGEWIDTH*IMAGEHEIGHT*3/2];
unsigned char subYUVBuf[IMAGEWIDTH*IMAGEHEIGHT*3/2];
//转换表空间
long int crv_tab[256];
long int cbu_tab[256];
long int cgu_tab[256];
long int cgv_tab[256];
long int tab_76309[256];
unsigned char clp[1024];
//全局量
char g_szDefault[128]="请在此处设置缺省叠加文字";
O_OBJCHAR *g_pAllObjCharObj[64];
char *g_szAllCharObj[64];
FILE *g_fpHZKLIB = NULL;
FILE *g_fpASCII = NULL;
unsigned int g_frameCounter=0;
//转换矩阵
#define MY(a,b,c) (( a* 0.2989 + b* 0.5866 + c* 0.1145))
#define MU(a,b,c) (( a*(-0.1688) + b*(-0.3312) + c* 0.5000 + 128))
#define MV(a,b,c) (( a* 0.5000 + b*(-0.4184) + c*(-0.0816) + 128))
//大小判断
#define DY(a,b,c) (MY(a,b,c) > 255 ? 255 : (MY(a,b,c) < 0 ? 0 : MY(a,b,c)))
#define DU(a,b,c) (MU(a,b,c) > 255 ? 255 : (MU(a,b,c) < 0 ? 0 : MU(a,b,c)))
#define DV(a,b,c) (MV(a,b,c) > 255 ? 255 : (MV(a,b,c) < 0 ? 0 : MV(a,b,c)))
//转换矩阵
double YuvToRgb[3][3]= {1, 0, 1.4022,
1, -0.3456,-0.7145,
1, 1.771, 0};
/*******************************************************************************
说明:
1.所有函数前向申明
2.以OSD_XXX(XX,XX,...)形式出现的函数均为接口函数
3.以_XXX(XX,XX,...)形式出现的函数均为私有函数
4.以p_XXX形式的均为指针量,以g_XXX形式出现的均为全局量
WroteBy/Date:
gaoc@Dvision.com/2010.03.05
Modify:
*******************************************************************************/
//接口函数
char OSD_CreateObjCharObj(int strID,char *szStr,O_STRINGATTR OAttrCharObj);
char OSD_DeleteObjCharObj(int strID);
char OSD_SetContentCharObj(int strID,char *szStr);
char OSD_SetPositionCharObj(int strID,int x,int y);
char OSD_SetAttrCharObj(int strID,O_STRINGATTR OAttrCharObj);
void OSD_FeedFrameYUV420(char* pYUV420Frame,int iSrcWidth, int iSrcHeight);
char OSD_Init(char *szPathHZK,char *szPathASCII);
void OSD_Release();
//内部函数
void _InitDitherTab();
void _RGB24ToYUV420(unsigned char *RGB, int nWidth,int nHeight, //源
unsigned char *YUV, unsigned long nLen);//目标
void _YUV420ToRGB24(unsigned char *src_yuv, //源
unsigned char *dst_rgb, int width, int height);//目标
void _YUV420ToYUV422(char* pYUV420Buf, int iSrcWidth, int iSrcHeight, //源
char* pYUV422Buf);//目标
void _YUV422ToYUV420(char* pYUV422Buf, int iSrcWidth, int iSrcHeight, //源
char* pYUV420Buf);//目标
void _GetSubReginFromYUV420(unsigned char *src_yuv, int srcW, int srcH, //yuv源图
unsigned char *sub_yuv, int x, int y, int subW, int subH); //yuv子区域
void _SetSubReginToYUV420(unsigned char *src_yuv, int srcW, int srcH, //yuv源图
unsigned char *sub_yuv, int x, int y, int subW, int subH); //yuv子区域
void _OverlapCaptionOnRGB(unsigned char* srcRgbBuf, int nWidth,int nHeight,//rgb源图
char* pCaption, O_STRINGATTR *pOAttrCharObj);//要叠加的文字,叠加属性及输出
char _OverLapCaptionOnYUV420(unsigned char *src_yuv, int srcW, int srcH,//源图及宽高
int xStart, int yStart, int dstW, int dstH, //要叠加的文字及区域
char* pCaption,O_STRINGATTR *pOAttrCharObj);//要叠加的文字及叠加属性
void _OverLapCaptionOnYUV422Raw(char* pCharcode,int column, int row, int imageWidth, int imageHeight, char *pYUVbuffer,
char OsdY,char OsdU,char OsdV);
/*******************************************************************************
说明:
以下以OSD_XXX(XX,XX,...)形式出现的函数均为接口函数
WroteBy/Date:
gaoc@Dvision.com/2010.03.05
Modify:
*******************************************************************************/
//创建叠加的字符串对象,用于字符串叠加
char OSD_CreateObjCharObj(int strID,char *szStr,O_STRINGATTR OAttrCharObj)
{
szStr=strlen(szStr)==0?g_szDefault:szStr;
if(g_pAllObjCharObj[strID]==NULL){
g_pAllObjCharObj[strID]=(O_OBJCHAR *)malloc(sizeof(O_OBJCHAR));
assert(g_pAllObjCharObj[strID]);
strcpy(g_pAllObjCharObj[strID]->szStr,szStr);
g_pAllObjCharObj[strID]->oAttrChar=OAttrCharObj;
g_pAllObjCharObj[strID]->w=g_pAllObjCharObj[strID]->oAttrChar.sizeW;
g_pAllObjCharObj[strID]->h=g_pAllObjCharObj[strID]->oAttrChar.sizeH;
}else{
return ERR_OBJEXIST;//返回错误码,对象已经存在
}
return ERR_NONE;
}
//删除叠加的字符串对象
char OSD_DeleteObjCharObj(int strID)
{
if(g_pAllObjCharObj[strID]==NULL)
return ERR_OBJNOTEXIST;//返回错误码,对象不存在
else{
free(g_pAllObjCharObj[strID]);
g_pAllObjCharObj[strID]=NULL;
}
return ERR_NONE;
}
//改变该字符串的属性
char OSD_SetAttrCharObj(int strID,O_STRINGATTR OAttrCharObj)
{
if(g_pAllObjCharObj[strID]==NULL)
return ERR_OBJNOTEXIST;//返回错误码,对象不存在
else{
g_pAllObjCharObj[strID]->oAttrChar=OAttrCharObj;
}
return ERR_NONE;
}
//改变字符串的内容
char OSD_SetContentCharObj(int strID,char *szStr)
{
if(g_pAllObjCharObj[strID]==NULL)
return ERR_OBJNOTEXIST;//返回错误码,对象不存在
else{
strcpy(g_pAllObjCharObj[strID]->szStr,szStr);
}
return ERR_NONE;
}
//改变字符串叠加位置
char OSD_SetPositionCharObj(int strID,int x,int y)
{
if(g_pAllObjCharObj[strID]==NULL)
return ERR_OBJNOTEXIST;//返回错误码,对象不存在
else{
g_pAllObjCharObj[strID]->x=x;
g_pAllObjCharObj[strID]->y=y;
}
return ERR_NONE;
}
//当设置完要叠加的字符后通过该函数装填图像的连续帧
void OSD_FeedFrameYUV420(char* pYUV420Frame,int iSrcWidth, int iSrcHeight)
{
int i=0;
g_frameCounter++;
//遍历列表叠加所有字符串对象
for(i=0;i<64;i++){
//如果空项,则检查下一个
if(g_pAllObjCharObj[i]==NULL)
continue;
switch(g_pAllObjCharObj[i]->oAttrChar.eActionType){
case e_SCROLL_LEFT://如果是滚动字幕,则需要修改属性中叠加位置参数
g_pAllObjCharObj[i]->x=g_frameCounter%
(g_pAllObjCharObj[i]->oAttrChar.actionValue1)==0?
g_pAllObjCharObj[i]->x-g_pAllObjCharObj[i]->oAttrChar.actionValue2:
g_pAllObjCharObj[i]->x;
break;
case e_SCROLL_RIGHT://如果是滚动字幕,则需要修改属性中叠加位置参数
g_pAllObjCharObj[i]->x=g_frameCounter%
(g_pAllObjCharObj[i]->oAttrChar.actionValue1)==0?
g_pAllObjCharObj[i]->x+g_pAllObjCharObj[i]->oAttrChar.actionValue2:
g_pAllObjCharObj[i]->x;
break;
case e_SCROLL_UP://如果是滚动字幕,则需要修改属性中叠加位置参数
g_pAllObjCharObj[i]->y=g_frameCounter%
(g_pAllObjCharObj[i]->oAttrChar.actionValue1)==0?
g_pAllObjCharObj[i]->y-g_pAllObjCharObj[i]->oAttrChar.actionValue2:
g_pAllObjCharObj[i]->y;
break;
case e_SCROLL_DOWN://如果是滚动字幕,则需要修改属性中叠加位置参数
g_pAllObjCharObj[i]->y=g_frameCounter%
(g_pAllObjCharObj[i]->oAttrChar.actionValue1)==0?
g_pAllObjCharObj[i]->y+g_pAllObjCharObj[i]->oAttrChar.actionValue2:
g_pAllObjCharObj[i]->y;
break;
case e_STATIC://如果是静态字幕
break;
case e_SLOWHIDE://如果是逐渐消隐的字幕
break;
case e_SPARK://如果是闪烁字幕
break;
default:
break;
}
_OverLapCaptionOnYUV420(pYUV420Frame, iSrcWidth, iSrcHeight,//源图及宽高
g_pAllObjCharObj[i]->x, g_pAllObjCharObj[i]->y,g_pAllObjCharObj[i]->w, g_pAllObjCharObj[i]->h, //要叠加的位置
g_pAllObjCharObj[i]->szStr,&(g_pAllObjCharObj[i]->oAttrChar));//要叠加的文字及叠加属性
}
}
//初始化
char OSD_Init(char *szPathHZK,char *szPathASCII)
{
//加载汉字点阵字库
if((g_fpHZKLIB=fopen(szPathHZK,"rb"
- 1
- 2
- 3
- 4
前往页