如何给显示文字加一层黑色边框
2010-02-03 11:27
225 查看
在工作中遇到这样一个问题,在实时监视的视频显示中需要在视频中显示当前时间,通道名等额外信息,无论信息内容在视频画面上采用何种颜色显示,当信息显示区域背景的视频画面的颜色正好与显示信息内容的颜色一致或差不多相似时,这个时候,很难看清显示的内容,尽管这种情况出现的概率并不大,但可能性仍然存在,解决这个问题最好的方法是在信息文字的外围加上一层和文字颜色不一样的外边。下面我们以文字为白色,外围加黑边为例来分析这个问题。
以下分析基于在windows操作系统的PC机上实现。
如何在白色文字的外围加裹一层黑边,目前我知道的有两种方式。
1.通过获得windows显示设备句柄,利用windows的textout()函数可以直接裹上黑边。具体代码如下:
bool drawText(CDC *pDC,
LPCTSTR lpszText,
const CRect& rctDraw,
UINT nFormat,
COLORREF clrText,
COLORREF clrBack)
{
ASSERT(pDC != NULL);
if (pDC->GetSafeHdc() == NULL) return false;
COLORREF oldColor = pDC->GetTextColor();
int oldBkMod = pDC->SetBkMode(TRANSPARENT);
CRect rect = rctDraw;
pDC->SetTextColor(clrBack);
rect.OffsetRect(-1, -1); pDC->DrawText(lpszText, rect, nFormat);
rect.OffsetRect( 1, 0); pDC->DrawText(lpszText, rect, nFormat);
rect.OffsetRect( 1, 0); pDC->DrawText(lpszText, rect, nFormat);
rect.OffsetRect( 0, 1); pDC->DrawText(lpszText, rect, nFormat);
rect.OffsetRect( 0, 1); pDC->DrawText(lpszText, rect, nFormat);
rect.OffsetRect(-1, 0); pDC->DrawText(lpszText, rect, nFormat);
rect.OffsetRect(-1, 0); pDC->DrawText(lpszText, rect, nFormat);
rect.OffsetRect( 0, -1); pDC->DrawText(lpszText, rect, nFormat);
pDC->SetTextColor(clrText);
rect.OffsetRect( 1, 0); pDC->DrawText(lpszText, rect, nFormat);
pDC->SetBkMode(oldBkMod);
pDC->SetTextColor(oldColor);
return true;
}
2.通过已获取的点阵字符库,然后构建一个新的包含黑边的字符库结构,显示时,对这个新的字符库结构显示。
以16*16的点阵字符库为例,一个汉字需要16*16位即32个字节来表示,如下图
在32个字节里存取的都是字模显示的位信息,2个字节表示一行,按位从左到右显示,0表示无色,1表示文字色,一共16行。
为了在字的外围加一层黑边,需要定义一个新的数据结构,用两个位来保存点阵信息,00表示无色,11表示文字色,01表示边框色,这样考虑到为了在字的边缘处也可能有黑边,新的字符矩阵应为18*18,其中两个位表示一个点阵信息,这样每一行需要18*2位,为了方便存取,每一行用5个字节表示,从左到右按位填充信息,多余位补0。
具体算法思路:
将含单色信息的字符模数据展开到内存,然后第一次逐行扫描点,凡是扫到某点位文字色,那么在加黑边后,新的数据结构中,其周围8个点,只有两种情况,一种是黑边色点,一种是文字色点,暂时不去理会它是否文字色点,将其周围8个点一律设为黑边色点,其自身设为文字色点,这样一次扫描完所有点后,显然在新的数据结构中,有很多文字点被设为了黑边色点,这样需要再对单色信息的字符模数据再扫描一遍,如扫到点为文字色,将新的数据结构中对应的点调为文字色,这样就将上一次扫描中本是文字色点却设为黑边色点的所有点信息全部调整过来了。
具体源码如下:
void AddShadowToZM(BYTE *pZM,int nWidth,int nHeight,BYTE **ppShadowZM)
{
if(pZM == NULL)
{
return;
}
if(*ppShadowZM != NULL)
{
delete []*ppShadowZM;
}
//由于需要加上黑边,考虑用两个比特位来表示一位象素,00表示无象素显示,01表示该象素为黑边象素,11表示该象素为文字象素
//同时考虑到外围需要加一层,在宽度上需要增加4个比特位,和位图对应从左至右,最前两个比特位对应位图左上角原点
//在高度上增加两行
*ppShadowZM = new BYTE[(nWidth*2+1)*(nHeight+2)];
memset(*ppShadowZM,0,(nWidth*2+1)*(nHeight+2));
int i,j,k;
//SHADOW
for(i = 0;i < nHeight;i++)
{
for(j = 0;j < nWidth;j++)
{
for(k = 0;k < 8;k++)
{
if((pZM[i*nWidth+j] >> (7-k))&0x01)
{
//TRACE("0");
//如果某一位为1,将其四周象素全部置为01,表示为加黑边
for(int m = 0;m < 3;m++)
{
for(int n = 0;n < 3;n++)
{
(*ppShadowZM)[(i+m)*(nWidth*2+1)+(j*8+k+n)*2/8] |= 1<<((3-(k+n)%4))*2;
//TRACE("2");
}
}
}
else
{
//TRACE(" ");
}
}
}
//TRACE("/n");
}
for(i = 0;i < nHeight;i++)
{
for(j = 0;j < nWidth;j++)
{
for(k = 0;k < 8;k++)
{
if((pZM[i*nWidth+j] >> (7-k))&0x01)
{
(*ppShadowZM)[(i+1)*(nWidth*2+1)+(j*8+k+1)*2/8] |= 3<<((3-(k+1)%4))*2;
//TRACE("0");
}
else
{
//TRACE("*");
}
}
}
}
}
在获取了新的点阵数据结构后,可以根据显示的要求将其显示在视频画面上。
上述的第二种方法,虽然比较麻烦,但在获取了点阵字符模数据文件后,这种方法更具普遍性。关于点阵字符模数据的获取将另行讨论。
以下分析基于在windows操作系统的PC机上实现。
如何在白色文字的外围加裹一层黑边,目前我知道的有两种方式。
1.通过获得windows显示设备句柄,利用windows的textout()函数可以直接裹上黑边。具体代码如下:
bool drawText(CDC *pDC,
LPCTSTR lpszText,
const CRect& rctDraw,
UINT nFormat,
COLORREF clrText,
COLORREF clrBack)
{
ASSERT(pDC != NULL);
if (pDC->GetSafeHdc() == NULL) return false;
COLORREF oldColor = pDC->GetTextColor();
int oldBkMod = pDC->SetBkMode(TRANSPARENT);
CRect rect = rctDraw;
pDC->SetTextColor(clrBack);
rect.OffsetRect(-1, -1); pDC->DrawText(lpszText, rect, nFormat);
rect.OffsetRect( 1, 0); pDC->DrawText(lpszText, rect, nFormat);
rect.OffsetRect( 1, 0); pDC->DrawText(lpszText, rect, nFormat);
rect.OffsetRect( 0, 1); pDC->DrawText(lpszText, rect, nFormat);
rect.OffsetRect( 0, 1); pDC->DrawText(lpszText, rect, nFormat);
rect.OffsetRect(-1, 0); pDC->DrawText(lpszText, rect, nFormat);
rect.OffsetRect(-1, 0); pDC->DrawText(lpszText, rect, nFormat);
rect.OffsetRect( 0, -1); pDC->DrawText(lpszText, rect, nFormat);
pDC->SetTextColor(clrText);
rect.OffsetRect( 1, 0); pDC->DrawText(lpszText, rect, nFormat);
pDC->SetBkMode(oldBkMod);
pDC->SetTextColor(oldColor);
return true;
}
2.通过已获取的点阵字符库,然后构建一个新的包含黑边的字符库结构,显示时,对这个新的字符库结构显示。
以16*16的点阵字符库为例,一个汉字需要16*16位即32个字节来表示,如下图
在32个字节里存取的都是字模显示的位信息,2个字节表示一行,按位从左到右显示,0表示无色,1表示文字色,一共16行。
为了在字的外围加一层黑边,需要定义一个新的数据结构,用两个位来保存点阵信息,00表示无色,11表示文字色,01表示边框色,这样考虑到为了在字的边缘处也可能有黑边,新的字符矩阵应为18*18,其中两个位表示一个点阵信息,这样每一行需要18*2位,为了方便存取,每一行用5个字节表示,从左到右按位填充信息,多余位补0。
具体算法思路:
将含单色信息的字符模数据展开到内存,然后第一次逐行扫描点,凡是扫到某点位文字色,那么在加黑边后,新的数据结构中,其周围8个点,只有两种情况,一种是黑边色点,一种是文字色点,暂时不去理会它是否文字色点,将其周围8个点一律设为黑边色点,其自身设为文字色点,这样一次扫描完所有点后,显然在新的数据结构中,有很多文字点被设为了黑边色点,这样需要再对单色信息的字符模数据再扫描一遍,如扫到点为文字色,将新的数据结构中对应的点调为文字色,这样就将上一次扫描中本是文字色点却设为黑边色点的所有点信息全部调整过来了。
具体源码如下:
void AddShadowToZM(BYTE *pZM,int nWidth,int nHeight,BYTE **ppShadowZM)
{
if(pZM == NULL)
{
return;
}
if(*ppShadowZM != NULL)
{
delete []*ppShadowZM;
}
//由于需要加上黑边,考虑用两个比特位来表示一位象素,00表示无象素显示,01表示该象素为黑边象素,11表示该象素为文字象素
//同时考虑到外围需要加一层,在宽度上需要增加4个比特位,和位图对应从左至右,最前两个比特位对应位图左上角原点
//在高度上增加两行
*ppShadowZM = new BYTE[(nWidth*2+1)*(nHeight+2)];
memset(*ppShadowZM,0,(nWidth*2+1)*(nHeight+2));
int i,j,k;
//SHADOW
for(i = 0;i < nHeight;i++)
{
for(j = 0;j < nWidth;j++)
{
for(k = 0;k < 8;k++)
{
if((pZM[i*nWidth+j] >> (7-k))&0x01)
{
//TRACE("0");
//如果某一位为1,将其四周象素全部置为01,表示为加黑边
for(int m = 0;m < 3;m++)
{
for(int n = 0;n < 3;n++)
{
(*ppShadowZM)[(i+m)*(nWidth*2+1)+(j*8+k+n)*2/8] |= 1<<((3-(k+n)%4))*2;
//TRACE("2");
}
}
}
else
{
//TRACE(" ");
}
}
}
//TRACE("/n");
}
for(i = 0;i < nHeight;i++)
{
for(j = 0;j < nWidth;j++)
{
for(k = 0;k < 8;k++)
{
if((pZM[i*nWidth+j] >> (7-k))&0x01)
{
(*ppShadowZM)[(i+1)*(nWidth*2+1)+(j*8+k+1)*2/8] |= 3<<((3-(k+1)%4))*2;
//TRACE("0");
}
else
{
//TRACE("*");
}
}
}
}
}
在获取了新的点阵数据结构后,可以根据显示的要求将其显示在视频画面上。
上述的第二种方法,虽然比较麻烦,但在获取了点阵字符模数据文件后,这种方法更具普遍性。关于点阵字符模数据的获取将另行讨论。
相关文章推荐
- 如何在ImageView里同时显示图片和文字甚至更复杂的内容
- 如何让div中的文字只显示一行,多余的文字隐藏并加上省略号 .
- Android TextView如何显示html样式的文字
- 如何利用CSS代码使图片和文字在同一行显示且对齐
- 如何在zen cart的Bestsellers栏目显示图片和文字
- 如何实现flex布局下div等宽且内部文字可以溢出显示
- Android 自定义dialog,去除系统默认黑色背景,边框并设置dialog的显示位置
- 如何用C#做一个即能显示文字又能显示图片的控件
- 如何在sencha-touch barchart中的column上显示文字
- 如何用C#显示竖排文字?
- C# WinForm中工具栏上如何既显示文字又显示图片
- [Excel VBA]状态栏如何显示文字 ?
- PADS 如何显示铺铜边框 删除死铜 删除铺铜
- a标签中写有文字如何隐藏文字显示图片兼容360模式渲染
- 如何在游戏中将文字显示为外星语?(将中文字符转换为乱码)
- 如何使cmd窗口正确显示utf-8编码的文字
- yii CGridView 如何根据字段值来显示不同的自定义按钮或者文字?
- ios开发如何让navigationItem自带的返回按钮设置成图片或者不显示文字
- 使用mmit进行移动开发,如何在一行同时显示图片和文字.
- 如何在图像上显示多样且变化的图形或文字