【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 5113|回复: 1

[转帖]如何取得字符点阵数据(GetGlyphOutline函数简单应用)

[复制链接]
发表于 2007-7-28 13:28:21 | 显示全部楼层 |阅读模式
   近日做的程序需要取得字符点阵数据的功能,研究了一下,费了点周折才成功,现将方法总结如下。

       取得字符点阵主要用GetGlyphOutline函数:

DWORD GetGlyphOutline

(

UINT nChar,

UINT nFormat,

LPGLYPHMETRICS lpgm,

DWORD cbBuffer,

LPVOID lPBuffer,

const MAT2 FAR* lpmat2

)

它需要类型为GLYPHMETRICSMAT2的变量;MAT2 结构要手动填充, GLYPHMETRICS结构则由GetGlyphOutline填充;GLYPHMETRICS包含了点阵数据的一些有用的信息:

typedef struct _GLYPHMETRICS {

    UINT    gmBlackBoxX;      //点阵数据轮廓矩形的宽

    UINT    gmBlackBoxY;     //点阵数据轮廓矩形的高

    POINT   gmptGlyphOrigin;       

    short   gmCellIncX;

    short   gmCellIncY;

} GLYPHMETRICS, FAR *LPGLYPHMETRICS;

       GetGlyphOutline函数要调用两次,第一次调用将LPVOID lpBuffer指定为NULL,函数将返回点阵数据需要的缓冲区大小(以字节为单位),将它传给cbBuffer参数,并依此值申请内存,将内存指针传给lpBuffer,再次调用GetGlyphOutline函数,lpBuffer缓冲区将被填充。

CClientDC
     DC
(this);

. . . . . .

//获取本字符需要的缓冲区大小

cbBuffer=DC.GetGlyphOutline(nChar,GGO_BITMAP,&lpgm,0,NULL,&mat2);

if(cbBuffer <0 ) return NULL;      //调用失败将返回负数

//开辟缓冲区

lpVBuffer=new BYTE[cbBuffer];

//填充字符图像缓冲区lpvBuffer

cbBuffer=DC.GetGlyphOutline(nChar,GGO_BITMAP,&lpgm,cbBuffer,lpvBuffer,&mat2);

      

       lpBuffer缓冲区内的数据是DWORD对齐的,即如果取得点阵宽度是12位,只需要三个字节存放一行数据(一个位对应一个点),但实际要占用四个字节;再如,如果点阵宽度是17位,则一行数据占用8个字节。数据的提取方式因应用的不同而不同,再次不再赘述。

注:以上只针对点阵数据提取,即UINT nFormat 的值是GGO_BITMAP,轮廓提取请参考MSDN

       以上用法VC6/SP5 WIN XP/SP2下测试通过,欢迎交流!

 楼主| 发表于 2007-7-28 13:34:10 | 显示全部楼层
望各位大侠赐教:
我调用pdc->GetGlyphOutline(uChar,GGO_BITMAP,&glyph,cbBuf,pBuf,&mat)获得字模点阵,使用汉子“二”。glyph.gmBlackBoxY=10,glyph.gmBlackBoxX=29。如何输出这个点阵?我想在32×32的点阵中输出,如何确定点阵左上角的坐标?glphy.gmptGlyphOrigin具体是怎么用的?
我设置字体宽和高是16×16,点阵却是29×10。有办法得到16×16的点阵吗?或者我的方法不对?
是要保存在位图中再处理吗?可是我对位图使用还一无所知。
最好能给出一个vc6.0的实例,哪位大侠有使用getGlyphOutline的GGO_BITMAP,然后利用所得点阵输出字的例子请发给我,万分感激!保证给分!




答案1
int cbBuffer = dc.GetGlyphOutline(nChar,GGO_BITMAP,&gm,0L,NULL,&m2);
DWORD dwErr = GetLastError();
lpvBuffer=new char[cbBuffer];
cbBuffer=pdc->GetGlyphOutline(nChar,GGO_BITMAP,&gm,cbBuffer,lpvBuffer,&m2);
int nStride = cbBuffer / gm.gmBlackBoxY;
for(int y=0;y<gm.gmBlackBoxY;++y)
for(int x=0;x<nStride;++x)
for(int k=0;k<8;++k)
if((lpvBuffer[y*nStride+x]>>(7-k))&1)
pdc->SetPixel(8*x+k,y,RGB(255,0,0));


参见 http://community.csdn.net/Expert/topic/4182/4182636.xml?temp=.2751276

答案2
那篇文章我看过,但输出的点阵并不是你想要的.比方说我要16×16的点阵,gm.gmBlackBoxX
比16大,尽管设置字体是16×16的。

答案3
帮你google了一把
就找到这个资料

http://blog.csdn.net/hazy/archive/2005/06/22/400602.aspx

答案4
怎样确定合适的位置显示点阵啊?比如“日”字,32×32点阵,他的左边第一点总是(0,3),总是靠近左边框?字要居中才好看。那篇文章讲得不是很清楚


答案5
http://support.microsoft.com/kb/q97340/

答案6
试试如下代码
void CDlgDlg::OnButton2()
{
CDC *pDC = GetDC();
CFont font;
VERIFY(font.CreateFont(
72, // nHeight
0, // nWidth
0, // nEscapement
0, // nOrientation
FW_NORMAL, // nWeight
FALSE, // bItalic
FALSE, // bUnderline
0, // cStrikeOut
ANSI_CHARSET, // nCharSet ANSI_CHARSET DEFAULT_CHARSET
OUT_DEFAULT_PRECIS, // nOutPrecision
CLIP_DEFAULT_PRECIS, // nClipPrecision
DEFAULT_QUALITY, // nQuality
DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily
"宋体")); // lpszFacename
pDC->SelectObject(&font);

int c = 0xbbf0; //火

GLYPHMETRICS gm;
MAT2 mat2;
memset(&mat2,0,sizeof(mat2));
mat2.eM11.value = 1;
mat2.eM12.value = 0;
mat2.eM21.value = 0;
mat2.eM22.value = 1;
int len;
len = pDC->GetGlyphOutline(c,GGO_BITMAP,&gm,0,0,&mat2);
if(len == -1)return;
char *buf = new char[len];
pDC->GetGlyphOutline(c,GGO_BITMAP,&gm,len,buf,&mat2);

unsigned char *pData = (unsigned char*)buf;
unsigned int cnt = gm.gmBlackBoxX / 32 + (gm.gmCellIncX % 32 ? 1 : 0);
cnt *= 4;

int xoffset;
int yoffset;

OUTLINETEXTMETRIC otm;
memset(&otm,0,sizeof(otm));
otm.otmSize = sizeof(otm);
pDC->GetOutlineTextMetrics(sizeof(otm),&otm);

xoffset = gm.gmptGlyphOrigin.x; //x的偏移量
//y的偏移量 字的顶部 - y方向原点 都是相对于baseline
yoffset = otm.otmAscent - gm.gmptGlyphOrigin.y;

for(unsigned int row = 0; row < gm.gmBlackBoxY; row++)
{
for(unsigned int col = 0; col < cnt;col++)
{
for(unsigned int i = 0; i < 8; i++)
{
if((*pData) & (0x80 >> i))
{
pDC->SetPixel(xoffset + (col * 8 + i),yoffset + row,0);
}
}
pData++;
}
}

delete []buf;

ReleaseDC(pDC);
}


答案7
http://msdn.microsoft.com/library/en-us/dnvbdev00/html/rodfig3.jpg
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-5-6 14:28

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表