一.介绍
本项目是接收卫星视频流,并将视频播出,同时可在视频上编辑字幕的内容、位置、字体大小等。字幕编辑功能是通过C++编写的dll文件来实现,C#调用dll完成字幕编辑功能,这个功能将在下一篇文章中描述,C#调用dll。
二.步骤
1.以vs2015为开发平台,选择“文件->新建项目”
2.在模板-Visual C++中找到MFC DLL
3.接来下按照提示一步一步完成新建项目。
三.代码
1.申明
extern "C" void CG_DLL_EXP _cdecl loadText2(TCHAR *strText,int uiTextX,int uiTextY,PULONG pTextBuffer,int x,int y,int fHeight,int fWidth,TCHAR *fontStr,int r,int g,int b);
extern "C" void CG_DLL_EXP _cdecl loadText3(TCHAR *strText,int uiTextX,int uiTextY,PULONG pTextBuffer,int x,int y,int &bmw,int fh,int fw,TCHAR *fontStr,int r,int g,int b);
extern "C" void CG_DLL_EXP _cdecl backPic(bool ifBack,TCHAR * strText,int uiTextX,int uiTextY,PULONG pTextBuffer,int x,int y);
extern "C" void CG_DLL_EXP _cdecl loadText(TCHAR *strText1,int uiTextX,int uiTextY,PULONG pTextBuffer,int x,int y,TCHAR *fontStr,int r,int g,int b);
extern "C" void CG_DLL_EXP _cdecl AreaMove(ULONG fieldNo,PULONG pCgSrcBuffer,PULONG pCgDecBuffer,ULONG ulWidth,ULONG ulHeight,ULONG ulMoveDirection,ULONG ulMoveStep,LONG &m_ulUp);
extern "C" void CG_DLL_EXP _cdecl AreaMove2(PULONG pCgSrcBuffer,PULONG pCgDecBuffer,ULONG ulWidth,ULONG ulHeight,ULONG ulMoveStep,int bmw);
3.代码之实现
void AreaMove(ULONG fieldNo,PULONG pCgSrcBuffer,PULONG pCgDecBuffer,ULONG ulWidth,ULONG ulHeight,ULONG ulMoveDirection,ULONG ulMoveStep,LONG &m_ulUp)
{
unsigned int j;
static int left = 0;
static ULONG LastFieldNo ;
static bool FirstField = true ;
static ULONG MoveDiretion = 0;
ULONG test[1920];
if(!pCgSrcBuffer&&!pCgDecBuffer)return;
if (FirstField)
{
FirstField = false ;
}
else
{
if (LastFieldNo + 1 != fieldNo)
TRACE("error! LastFieldNo : %d, fieldNo : %d\n", LastFieldNo, fieldNo);
}
LastFieldNo = fieldNo ;
CString str;
//MessageBox(NULL,_T("start"),NULL,NULL);
switch( ulMoveDirection )
{
case 0:
switch( MoveDiretion )
{
case 0:
case 1:
case 2:
//MessageBox(NULL,_T("1"),NULL,NULL);
for( j = ( fieldNo + 1 )% 2;j<ulHeight;j+=2 )
{
if( ( j + m_ulUp ) < ulHeight )
memcpy(&pCgDecBuffer[j*ulWidth],&pCgSrcBuffer[( j + m_ulUp )*ulWidth],ulWidth*4);
else
memcpy(&pCgDecBuffer[j*ulWidth],&pCgSrcBuffer[( j + m_ulUp-ulHeight )*ulWidth],ulWidth*4);
}
break;
case 3:
case 4:
//MessageBox(NULL,_T("2"),NULL,NULL);
for( j = ( fieldNo + 1 )% 2;j<ulHeight;j+=2 )
{
memcpy(&pCgDecBuffer[j*ulWidth],&pCgSrcBuffer[ j*ulWidth+left],(ulWidth-left)*4);
memcpy(&pCgDecBuffer[j*ulWidth+ulWidth-left],&pCgSrcBuffer[ j*ulWidth],left*4);
}
break;
}
break;
case 1 :// m_ulUp
m_ulUp += ulMoveStep;
m_ulUp = m_ulUp % ulHeight;
MoveDiretion = ulMoveDirection;
//MessageBox(NULL,_T("3"),NULL,NULL);
for( j = ( fieldNo + 1 )% 2;j<ulHeight;j+=2 )
{
if( ( j + m_ulUp ) < ulHeight )
memcpy(&pCgDecBuffer[j*ulWidth],&pCgSrcBuffer[( j + m_ulUp )*ulWidth],ulWidth*4);
else
memcpy(&pCgDecBuffer[j*ulWidth],&pCgSrcBuffer[( j + m_ulUp-ulHeight )*ulWidth],ulWidth*4);
}
break;
case 2 :// Down
m_ulUp -= ulMoveStep;
MoveDiretion = ulMoveDirection;
if( m_ulUp < 0 )
m_ulUp = m_ulUp + ulHeight;
m_ulUp = m_ulUp % ulHeight;
//MessageBox(NULL,_T("4"),NULL,NULL);
for( j = ( fieldNo+1)% 2;j<ulHeight;j+=2 )
{
if( ( j + m_ulUp ) < ulHeight )
memcpy(&pCgDecBuffer[j*ulWidth],&pCgSrcBuffer[( j + m_ulUp )*ulWidth],ulWidth*4);
else
memcpy(&pCgDecBuffer[j*ulWidth],&pCgSrcBuffer[( j + m_ulUp-ulHeight )*ulWidth],ulWidth*4);
}
break;
case 4 :
left -= ulMoveStep;
MoveDiretion = ulMoveDirection;
if( left < 0 )
left = ulWidth + left;
for( j = ( fieldNo + 1 )% 2;j<ulHeight;j+=2 )
{
memcpy(&pCgDecBuffer[j*ulWidth],&pCgSrcBuffer[ j*ulWidth+left],(ulWidth-left)*4);
memcpy(&pCgDecBuffer[j*ulWidth+ulWidth-left],&pCgSrcBuffer[ j*ulWidth],left*4);
}
break;
case 3 :
left += ulMoveStep;
MoveDiretion = ulMoveDirection;
left = left % ulWidth;
//str.Format(_T("ulHeight=%d"),ulHeight);
//MessageBox(NULL,str,NULL,NULL);
for( j = ( fieldNo + 1 )% 2;j<ulHeight;j+=2 )
{
//str.Format(_T("j*ulWidth=%d;j*ulWidth+left=%d;"),j);
//MessageBox(NULL,str,NULL,NULL);
memcpy(&pCgDecBuffer[j*ulWidth],&pCgSrcBuffer[ j*ulWidth+left],(ulWidth-left)*4);
memcpy(&pCgDecBuffer[j*ulWidth+ulWidth-left],&pCgSrcBuffer[ j*ulWidth],left*4);
}
break;
}
return;
}
void AreaMove2(PULONG pCgSrcBuffer,PULONG pCgDecBuffer,ULONG ulWidth,ULONG ulHeight,ULONG ulMoveStep,int bmw)
{
unsigned int j;
static int left = 0; //重复调用,不是重复值
static int left2 = 0; //图片内存偏移量
if(!pCgSrcBuffer&&!pCgDecBuffer)return;
left += ulMoveStep;
left2 += ulMoveStep;
left = left % ulWidth;
for( j = 0;j<ulHeight;j+=1 )
{
memcpy(&pCgDecBuffer[j*ulWidth],&pCgSrcBuffer[ j*bmw+left2],ulWidth*4);
}
left2 = left2 % bmw;
}
void loadText2(TCHAR *strText1,int uiTextX,int uiTextY,PULONG pTextBuffer,int x,int y,int fHeight,int fWidth,TCHAR *fontStr,int r,int g,int b)
{
CString strText(strText1);
CString str;
CSize uiVideoSize(x,y);
memset(pTextBuffer,0,1920*1080);
if((pTextBuffer == NULL))
return ;
CBitmap * pBitmap ;
pBitmap = new CBitmap;
CClientDC dc(NULL);
CDC memDC;
//
ULONG *pPicture,*ptemp,ulLeftDistance,ulUpDistance;
//CString bless ;
CFont font1;
COLORREF colorbk,colortext;
unsigned int i,j,k,bmw,bmh,sizebl;
ULONG pa,pr,pb,pg,pels,pelsf,pelsb;
//创建字体对话框对象
CFontDialog dlg;
//修改字体对话框相关属性
dlg.m_cf.Flags |= CF_USESTYLE;
colortext=RGB(r,g,b);
LOGFONT lf;
memset(&lf,0,sizeof(LOGFONT));
lf.lfWidth=uiVideoSize.cx/48+fWidth; //以后用字体对话框代替
lf.lfHeight=lf.lfWidth*7/4+fHeight;
//
// str.Format(_T("lfWidth:%d, lfHeight:%d"),lf.lfWidth,lf.lfHeight);
// MessageBox(NULL,str,NULL,NULL);
//lf.lfWeight=1000;
CString lfontStr(fontStr);
_tcscpy((TCHAR*)&(lf.lfFaceName),lfontStr);
font1.CreateFontIndirect(&lf); //创建字体
colorbk=RGB(0,0,0);
memDC.CreateCompatibleDC(&dc); //创建DC
memDC.SelectObject(&font1);//将字体选入设备描述表
#ifdef UNICODE
sizebl=strText.GetLength()*2+1; //1:修正量 //7
// str.Format(_T("getLength(sizebl):%d"),sizebl);
// MessageBox(NULL,str,NULL,NULL);
//
// sizebl = sizeof(strText);
//
#else
sizebl=strText.GetLength()+1; //1:修正量
#endif
// str.Format(_T("sizeof(sizebl):%d"),sizebl);
// MessageBox(NULL,str,NULL,NULL);
//str.Format(_T("字间距:%d"),memDC.GetTextCharacterExtra());
//MessageBox(NULL,str,NULL,NULL);
bmw=lf.lfWidth*sizebl+memDC.GetTextCharacterExtra()*sizebl;
bmh=lf.lfHeight+2;
pBitmap->CreateCompatibleBitmap(&dc,bmw,bmh);
CBitmap *pOld=memDC.SelectObject(pBitmap);
//memDC.FillSolidRect(0,0,bmw,bmh,RGB(10,10,10));
memDC.FillSolidRect(0,0,bmw,bmh,RGB(0,0,0));
memDC.SetBkColor(colorbk);
memDC.SetTextColor(colortext);
memDC.TextOut(0,1,strText);
//str.Format(_T("宽是:%d, 高是:%d"),bmw,bmh);
//MessageBox(NULL,str,NULL,NULL);
pPicture = new ULONG[ bmw*bmh];
ptemp=new ULONG[ bmw*bmh ];
pBitmap ->GetBitmapBits(bmw*bmh*4,pPicture);
for( i=0;i<bmw*bmh ;i++)
{
if (pPicture[i]!=0x00000000) //如果不是黑色.颜色的16进制,可为任意颜色
pPicture[i]=pPicture[i]|0xff000000; //按位作或操作,使alpha通道为255
}
memcpy(ptemp,pPicture,bmw*bmh*4);
if( uiVideoSize.cx > bmw)
ulLeftDistance = uiTextX;
else
ulLeftDistance = 0;
ulUpDistance = uiTextY;
//MessageBox(NULL,_T("1"),NULL,NULL);
//开始写数据到字幕卡缓存
for( j=0;j<uiVideoSize.cy;j++ )
{
if( ( j < ( bmh + ulUpDistance ) ) && ( j >= ulUpDistance /*+2*/))
{
for( k=0; k<uiVideoSize.cx; k++ )
if( ( k < ( /*tmp*/bmw + ulLeftDistance ) ) && ( k >= ulLeftDistance ) )
{
//MessageBox(NULL,_T("2"),NULL,NULL);
pTextBuffer[ j*uiVideoSize.cx + k ] = ( pPicture[ ( j - ulUpDistance )*bmw + k - ulLeftDistance ] );
}
else
{
//MessageBox(NULL,_T("3"),NULL,NULL);
pTextBuffer[ j*uiVideoSize.cx + k ] = 0;
}
}
else
{
/*MessageBox(NULL,_T("4"),NULL,NULL);*/
for( k=0; k<uiVideoSize.cx ; k++ )
{
// str.Format(_T("j是:%d, j*uiVideosize.cx+k是:%d"),j,j*uiVideoSize.cx + k);
// MessageBox(NULL,str,NULL,NULL);
pTextBuffer[ j*uiVideoSize.cx + k ] = 0;
}
/*MessageBox(NULL,_T("5"),NULL,NULL);*/
}
}
delete [] ptemp;
delete [] pPicture;
memDC.SelectObject(pOld);
delete pBitmap;
font1.~CFont();
}
void loadText3(TCHAR *strText1,int uiTextX,int uiTextY,PULONG pTextBuffer,int x,int y,int &bmw,int fh,int fw,TCHAR *fontStr,int r,int g,int b)
{
CString strText(strText1);
CString str;
CSize uiVideoSize(x,y);
memset(pTextBuffer,0,1920*1080);
if((pTextBuffer == NULL))
return ;
CBitmap * pBitmap ;
pBitmap = new CBitmap;
CClientDC dc(NULL);
CDC memDC;
//
ULONG *pPicture,*ptemp,ulLeftDistance,ulUpDistance;
//CString bless ;
CFont font1;
COLORREF colorbk,colortext;
unsigned int i,j,k,bmh,sizebl;
ULONG pa,pr,pb,pg,pels,pelsf,pelsb;
//创建字体对话框对象
CFontDialog dlg;
//修改字体对话框相关属性
dlg.m_cf.Flags |= CF_USESTYLE;
colortext=RGB(r,g,b);
LOGFONT lf;
memset(&lf,0,sizeof(LOGFONT));
lf.lfWidth=uiVideoSize.cx/48+fw; //以后用字体对话框代替
lf.lfHeight=lf.lfWidth*7/4+fh;
//
// str.Format(_T("lfWidth:%d, lfHeight:%d"),lf.lfWidth,lf.lfHeight);
// MessageBox(NULL,str,NULL,NULL);
//lf.lfWeight=1000;
CString lfontStr(fontStr);
_tcscpy((TCHAR*)&(lf.lfFaceName),lfontStr);
font1.CreateFontIndirect(&lf); //创建字体
colorbk=RGB(0,0,0);
memDC.CreateCompatibleDC(&dc); //创建DC
memDC.SelectObject(&font1);//将字体选入设备描述表
#ifdef UNICODE
sizebl=strText.GetLength()*2+1; //1:修正量 //7
// str.Format(_T("getLength(sizebl):%d"),sizebl);
// MessageBox(NULL,str,NULL,NULL);
//
// sizebl = sizeof(strText);
//
#else
sizebl=strText.GetLength()+1; //1:修正量
#endif
// str.Format(_T("sizeof(sizebl):%d"),sizebl);
// MessageBox(NULL,str,NULL,NULL);
//str.Format(_T("字间距:%d"),memDC.GetTextCharacterExtra());
bmw=lf.lfWidth*sizebl+memDC.GetTextCharacterExtra()*sizebl;
bmh=lf.lfHeight+2;
pBitmap->CreateCompatibleBitmap(&dc,bmw,bmh);
CBitmap *pOld=memDC.SelectObject(pBitmap);
//memDC.FillSolidRect(0,0,bmw,bmh,RGB(10,10,10));
memDC.FillSolidRect(0,0,bmw,bmh,RGB(0,0,0));
memDC.SetBkColor(colorbk);
memDC.SetTextColor(colortext);
memDC.TextOut(0,1,strText);
pPicture = new ULONG[ bmw*bmh*10];//10代表可输出的行数
ptemp=new ULONG[ bmw*bmh ];
pBitmap ->GetBitmapBits(bmw*bmh*4,pPicture);
for( i=0;i<bmw*bmh;i++)
{
if (pPicture[i]!=0x00000000) //如果不是黑色.颜色的16进制,可为任意颜色
pPicture[i]=pPicture[i]|0xff000000; //按位作或操作,使alpha通道为255
}
if( uiVideoSize.cx > bmw)
{
ulLeftDistance = uiTextX;
}
else
{
ulLeftDistance = 0;
}
ulUpDistance = uiTextY;
for( j=0;j<uiVideoSize.cy;j++ )
{
if( ( j < ( bmh + ulUpDistance ) ) && ( j >= ulUpDistance ))
{
for( k=0; k< bmw /*uiVideoSize.cx*/; k++ )
{
if( k < ( bmw + ulLeftDistance) && ( k >= ulLeftDistance ) )
{
pTextBuffer[ j*bmw+k ] = ( pPicture[ ( j - ulUpDistance )*bmw + k - ulLeftDistance ] );
}
else
{
pTextBuffer[ j*bmw + k ] = 0;
}
}
}
else
{
for( k=0; k< bmw/*uiVideoSize.cx*/ ; k++ )
{
pTextBuffer[ j*bmw + k ] = 0;
}
}
}
delete [] ptemp;
delete [] pPicture;
memDC.SelectObject(pOld);
delete pBitmap;
font1.~CFont();
}
PULONG m_pText = new ULONG[1920*1080];
void loadText(TCHAR *strText1,int uiTextX,int uiTextY,PULONG pTextBuffer,int x,int y,TCHAR *fontStr,int r,int g,int b)
{
CString strText(strText1);
CString str;
CSize uiVideoSize(x,y);
if((pTextBuffer == NULL))
return ;
CBitmap * pBitmap ;
pBitmap = new CBitmap;
CClientDC dc(NULL);
CDC memDC;
//
ULONG *pPicture,*ptemp,ulLeftDistance,ulUpDistance;
//CString bless ;
CFont font1;
COLORREF colorbk,colortext;
unsigned int i,j,k,bmw,bmh,sizebl;
ULONG pa,pr,pb,pg,pels,pelsf,pelsb;
//创建字体对话框对象
CFontDialog dlg;
//修改字体对话框相关属性
dlg.m_cf.Flags |= CF_USESTYLE;
colortext=RGB(r,g,b);
LOGFONT lf;
memset(&lf,0,sizeof(LOGFONT));
lf.lfWidth=uiVideoSize.cx/48; //以后用字体对话框代替
lf.lfHeight=lf.lfWidth*7/4;
// str.Format(_T("lfWidth:%d, lfHeight:%d"),lf.lfWidth,lf.lfHeight);
// MessageBox(NULL,str,NULL,NULL);
lf.lfWeight=1000;
CString lfontStr(fontStr);
_tcscpy((TCHAR*)&(lf.lfFaceName),lfontStr);
font1.CreateFontIndirect(&lf); //创建字体
colorbk=RGB(0,0,0);
memDC.CreateCompatibleDC(&dc); //创建DC
memDC.SelectObject(&font1);//将字体选入设备描述表
#ifdef UNICODE
sizebl=strText.GetLength()*2+1; //1:修正量 //7
// str.Format(_T("getLength(sizebl):%d"),sizebl);
// MessageBox(NULL,str,NULL,NULL);
//
// sizebl = sizeof(strText);
//
#else
sizebl=strText.GetLength()+1; //1:修正量
#endif
// str.Format(_T("sizeof(sizebl):%d"),sizebl);
// MessageBox(NULL,str,NULL,NULL);
//str.Format(_T("字间距:%d"),memDC.GetTextCharacterExtra());
//MessageBox(NULL,str,NULL,NULL);
bmw=lf.lfWidth*sizebl+memDC.GetTextCharacterExtra()*sizebl;
bmh=lf.lfHeight+2;
pBitmap->CreateCompatibleBitmap(&dc,bmw,bmh);
CBitmap *pOld=memDC.SelectObject(pBitmap);
//memDC.FillSolidRect(0,0,bmw,bmh,RGB(10,10,10));
memDC.FillSolidRect(0,0,bmw,bmh,RGB(0,0,0));
memDC.SetBkColor(colorbk);
memDC.SetTextColor(colortext);
memDC.TextOut(0,1,strText);
//str.Format(_T("宽是:%d, 高是:%d"),bmw,bmh);
//MessageBox(NULL,str,NULL,NULL);
pPicture = new ULONG[ bmw*bmh ];
ptemp=new ULONG[ bmw*bmh ];
pBitmap ->GetBitmapBits(bmw*bmh*4,pPicture);
for( i=0;i<bmw*bmh ;i++)
{
if (pPicture[i]!=0x00000000) //如果不是黑色.颜色的16进制,可为任意颜色
pPicture[i]=pPicture[i]|0xff000000; //按位作或操作,使alpha通道为255
}
memcpy(ptemp,pPicture,bmw*bmh*4);
if( uiVideoSize.cx > bmw)
ulLeftDistance = uiTextX;
else
ulLeftDistance = 0;
ulUpDistance = uiTextY;
/* MessageBox(NULL,_T("1"),NULL,NULL);*/
//开始写数据到字幕卡缓存
for( j=0;j<uiVideoSize.cy;j++ )
{
if( ( j < ( bmh + ulUpDistance ) ) && ( j >= ulUpDistance /*+2*/))
{
for( k=0; k<uiVideoSize.cx; k++ )
if( ( k < ( /*tmp*/bmw + ulLeftDistance ) ) && ( k >= ulLeftDistance ) )
{
/* MessageBox(NULL,_T("2"),NULL,NULL);*/
m_pText[ j*uiVideoSize.cx + k ] = ( pPicture[ ( j - ulUpDistance )*bmw + k - ulLeftDistance ] );
}
else
{
/* MessageBox(NULL,_T("3"),NULL,NULL);*/
m_pText[ j*uiVideoSize.cx + k ] = 0;
}
}
else
{
//MessageBox(NULL,_T("4"),NULL,NULL);
for( k=0; k<uiVideoSize.cx ; k++ )
{
m_pText[ j*uiVideoSize.cx + k ] = 0;
}
}
}
delete [] ptemp;
delete [] pPicture;
memDC.SelectObject(pOld);
delete pBitmap;
MessageBox(NULL,_T("6"),NULL,NULL);
while (true)
{
// AreaMove(1,m_pText,pTextBuffer,x,y,3,2,m_);
//
// AreaMove(0,m_pText,pTextBuffer,x,y,3,2);
}
}