blog

枪手亨利

博客园 首页 新随笔 联系 订阅 管理
  在实际工作中,有时候我们会遇到将两幅图像相融合的问题。比如书法作品从白纸上抠出,放到特定背景上去等等。由于数字图像本身几乎都是用矩形存放的,如果直接将前景图像贴到背景图像上去,看起来是背景图里面包含了一个矩形的前景图,这样并没有达到两幅图融为一体的效果(图1)。如果此时将前景图部分区域设置为透明,这个问题就解决了。

  例如将图1书法图片的白色部分设置为透明色,再贴到背景图上。看起来这些字就好像直接在背景图片写的一样(见图2)。另外,如果感觉到字的位置不合适,还可以自由拖动它。

  当然,这些工作用Photoshop之类的软件可以实现。本文就如何用VC 编程来实现显示透明位图以及如何自由拖动透明位图作了说明并给出了源代码。





图1


图2

 一、透明位图的显示:

  首先我们要学会使用一个SDK函数TransparentBlt,其原型如下:

BOOL TransparentBlt(
 HDC hdcDest, // 目标DC句柄
 int nXOriginDest, // 目标左上角X坐标
 int nYOriginDest, // 目标左上角Y坐标
 int nWidthDest, // 目标矩形宽度
 int hHeightDest, // 目标矩形高度
 HDC hdcSrc, // 源DC句柄
 int nXOriginSrc, // 源左上角X坐标
 int nYOriginSrc, // 源左上角Y坐标
 int nWidthSrc, // 源矩形宽度
 int nHeightSrc, // 源矩形高度
 UINT crTransparent // 要置为透明的颜色
);

  如同StretchBlt 函数,该函数也可以缩放显示位图。

  此函数在Win98以后的windows操作系统中均可使用,但使用此函数要包含静态链接库Msimg32.lib,方法是:在VC集成开发环境中,Project->Setting->Link页,在Object/libray modules 下填入:Msimg32.lib即可。

  透明位图显示方法如下:

  从Visual C++ 6.0 集成开发环境中将背景图片和书法图片导入资源中,ID标识分别为IDB_BJ, IDB_SHUFA.,然后重写其视图类的OnDraw函数:

void CTransparentBltView::OnDraw(CDC* pDC)
{
CTransparentBltDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CBitmap bj;
CBitmap shufa;
bj.LoadBitmap(IDB_BJ);
shufa.LoadBitmap(IDB_SHUFA);
BITMAP BT;
bj.GetBitmap(&BT);//获得bj位图信息
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap* poldbitmap=memDC.SelectObject(&bj);
//先显示背景图
pDC->BitBlt(0,0, BT.bmWidth,BT.bmHeight,&memDC,0,0,SRCCOPY);
shufa.GetBitmap(&BT);//获得shufa位图信息
memDC.SelectObject(&shufa); //选入前景图
//透明位图显示,将前景图画到pDC中,指定RGB(255,255,255)为透明掩码。即此//处只显示背景图,从前景图看起来这块好像透明一样。
TransparentBlt(pDC->m_hDC,0,0, BT.bmWidth,BT.bmHeight, memDC.m_hDC,
0,0,BT.bmWidth,BT.bmHeight,RGB(255,255,255));
memDC.SelectObject(poldbitmap);
}

  二、实现透明位图拖动

  这里要使用跟踪器类CrectTracker。简单来说这个类的对象代表一个矩形,这个矩形可以被拖动,改变大小,显示不同的外形。类似于在Word中插入一个对象,选定该对象后会出现一个矩形,有8个拖动点,该矩形能缩放,移动。

  首先,在视图类中添加成员变量:CRectTracker m_tracker;在构造函数中设置跟踪器矩形初始大小为书法图片的大小。

SHUFA.GetBitmap(&BT);
m_tracker.m_rect.SetRect(0,0,BT.bmWidth,BT.bmHeight);

  然后,捕获LbuttonDown消息:

void CTransparentBltView::OnLButtonDown(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 if(m_tracker.Track(this,point))//拖动跟踪器时,刷新屏幕
  Invalidate(false);
  CView::OnLButtonDown(nFlags, point);
}

  再重写OnDraw函数:

void CTransparentBltView::OnDraw(CDC* pDC)
{
 CTransparentBltDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);
 // TODO: add draw code for native data here
 CDC memDC;
 memDC.CreateCompatibleDC(pDC);
 CBitmap* poldbitmap=memDC.SelectObject(&bj);
 pDC->BitBlt(0,0,640,480,&memDC,0,0,SRCCOPY);//先显示背景图
 memDC.SelectObject(&shufa); //选入前景图,
 TransparentBlt(pDC->m_hDC,
 m_tracker.m_rect.TopLeft().x,m_tracker.m_rect.TopLeft().y,
 BT.bmWidth,BT.bmHeight,
 memDC.m_hDC,0,0,BT.bmWidth,BT.bmHeight,RGB(255,255,255));
 memDC.SelectObject(poldbitmap);

}

  锦上添花,再捕获视图类的OnSetCursor消息:

BOOL CTransparentBltView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
 // TODO: Add your message handler code here and/or call default
 //鼠标移动到跟踪器范围内时,改变鼠标指针形状,指示可以拖动图片
 if(m_tracker.SetCursor(pWnd,nHitTest)) /
  return true;
  return CView::OnSetCursor(pWnd, nHitTest, message);
}

  这样就可以将书法图片在背景图片上来自由拖动到自己满意的位置为止。
posted on 2005-12-18 11:52  henry  阅读(841)  评论(0)    收藏  举报