小妹现在急着出结果,但问题迟迟不能解决,希望好心人帮我指点迷津啊,分数不够可以再加。
我要把两张的bmp叠加在一起,透明度可调,调节过程中会有渐显的结果。
在网上也查了很多,但都没有把问题解决,失望的不行,之前发过一次,没效果,只能再发一次了。如果有源码的话发在我邮箱,感谢。[email protected],我的qq:310731218.其实我的VC++基础不好的,但是因为老师要做这课题,就硬着头皮接下来了,到现在都快到尾声了,我还没搞出来,郁闷的很,我好爱埋怨啊!下面是我用slider控制图像叠加时透明度的代码 。
hDIB和hDIBSrc是成员变量,分别是图1和图2的句柄(已经在别的函数中得到)。IDC_PICCOMP是picture控件,我想让叠加后的图像在它里面显示。 
编译过了,但运行不了,调试时到
int  cxSrc=lpbmifh->biWidth;  //  源图象宽度  
int  cySrc=lpbmifh->biHeight;  //  源图象高度
这个位置就出错了。中间叠加的代码是在网上查的) 
void CMy2009Dlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 

// TODO: Add your message handler code here and/or call default 
CSliderCtrl* slider=(CSliderCtrl*) pScrollBar; 
if (slider==&m_slider) 

m_Alpha=slider->GetPos(); 
int alpha=m_Alpha; // BOOL  CompoundDIB(HANDLE  hDIB,HANDLE  hDIBSrc,int  alpha)  
//{  
LPVOID  lpvBuf=NULL;  //  目标图象数据指针  
LPVOID  lpvBufSrc=NULL;  //  源图数据指针  //  //  源图象信息  //    
LPBITMAPINFO  lpbmif=(LPBITMAPINFO)hDIBSrc;    
LPBITMAPINFOHEADER  lpbmifh=(LPBITMAPINFOHEADER)lpbmif;  
//  计算图象数据偏移量  
UINT  nColors=lpbmifh->biClrUsed  ?  lpbmifh->biClrUsed  :  1 < <lpbmifh->biBitCount;  
if  (  nColors  >256  )  
nColors=0;  //  如果颜色数大于256色,则没有调色板  
lpvBufSrc=(LPVOID)((LPBYTE)lpbmif->bmiColors+nColors*sizeof(RGBQUAD));    
int  cxSrc=lpbmifh->biWidth;  //  源图象宽度  
int  cySrc=lpbmifh->biHeight;  //  源图象高度  
//  计算图象每行的字节数(图象位数  x  图象宽度,如果不能被2整除则在每行后面添加一个0字节)  
int  nBytesPerLineSrc=((cxSrc*lpbmifh->biBitCount+31)&~31)/8;    //  //  目标图象信息  //  
lpbmif=(LPBITMAPINFO)hDIB;  
lpbmifh=(LPBITMAPINFOHEADER)lpbmif;  
nColors=lpbmifh->biClrUsed  ?  lpbmifh->biClrUsed  :  1 < <lpbmifh->biBitCount;  
if  (  nColors  >256  )  
nColors=0;  
lpvBuf=(LPVOID)((LPBYTE)lpbmif->bmiColors+nColors*sizeof(RGBQUAD));  
int  cx=lpbmifh->biWidth;  
int  cy=lpbmifh->biHeight;  
int  nBytesPerLine=((cx*lpbmifh->biBitCount+31)&~31)/8;  LPBYTE  lpbPnt=NULL;  
LPBYTE  lpbPntSrc=NULL;  
//  //  通过alpha值合并两张图象的像素值  //  
//  这里假设是24位真彩色图象,其他深度的图象处理方法可以以次类推  
for  (  int  y=(cy <cySrc  ?  cy  :  cySrc);  y>0  ;y--  )  
{  
lpbPnt=(LPBYTE)lpvBuf+nBytesPerLine*(y-1);  
lpbPntSrc=(LPBYTE)lpvBufSrc+nBytesPerLineSrc*(y-1);  
for  (  int  x=0;  x <(cx <cxSrc  ?  cx  :  cxSrc);  x++  )  
{  
for  (  int  i=0  ;i <3  ;i++  )  
*lpbPnt++=(*lpbPnt*(255-alpha)+*(lpbPntSrc++)*alpha)/255;  }  } CStatic*  pPic=(CStatic*)GetDlgItem(IDC_PICCOMP); ASSERT(pPic);  
pPic->SetBitmap((HBITMAP)hDIB);  Invalidate(); 

解决方案 »

  1.   

    是必须用GDI来做图像处理完成么? 如果不是 那个可以使用GDI+ 只要设定ColorMatrix就可以实现图像透明效果 两个图片都透明就相当于叠加了。
      

  2.   


    我不太有时间再熟悉GDI+的环境了。
      

  3.   

    lpbmif=(LPBITMAPINFO)hDIB;
    ??这样强转没戏吧?
    BITMAPINFO 可以自己写的
      

  4.   

    有必要自己计算吗?先把图片1绘制到DC上,然后把图片2通过AlphaBlend()绘制到DC的相同区域即可。
      

  5.   

    你的方法我没仔细看,只说思路。1, 你可以考虑用GDI+,如果没有时间看,就算了。
    2, 自己混合两张图片的算法,这个算法其实很简单。大致过程如下:1, 定义一个混合的比例,比如1%~99%,这个值可以使用滚动条控制。
    2, 做一个嵌套循环,循环计算每个像素点的值
    for(int i=0; i<w1; i++)
    for(int j=0; j<h1; j++)
    {
       pixel(i, j);
    }3  像素点值的计算方法:
       A图点的像素颜色值: r1, g1, b1
       B图点的像素值颜色: r2, g2, b2
       混合alpha的值,范围(0.01~0.99)   则最后的目标值为
       r = r1 * alpha + r2 * (1 - alpha);
      g = g1 * alpha + g2 * ( 1 - alpha);
      b = b1 * alpha + b2 * (1 - alpha);   把最重点的颜色值就为 RGB(r, g, b)4  你使用static作为显示区域,这个地方可能不是很好,应该使用图像缓冲技术,不然你的速度会很慢。
       直接创建一个 虚拟DC,把两幅图片合并后的效果画在这张图上,然后把这个虚拟图绘在你要的任何一个窗口上面即可。5   如果你使用的两张图片大小不一样,可能比较麻烦,可以考虑先做两张图片大小一样的叠加,做好了,再考虑图片大小不一样的算法。
      

  6.   

    我觉得可以设置图片的alpha达到效果.
      

  7.   

    to coyer:谢谢,你将的思路我很清楚,其实上面我的程序的思想就是这个意思,但是程序到前面就卡住了。
      

  8.   

    VC提供现成的Alpha混合函数阿.
    摘自MSDNBOOL AlphaBlend(
      HDC hdcDest,                 // handle to destination DC
      int nXOriginDest,            // x-coord of upper-left corner
      int nYOriginDest,            // y-coord of upper-left corner
      int nWidthDest,              // destination width
      int nHeightDest,             // destination height
      HDC hdcSrc,                  // handle to source DC
      int nXOriginSrc,             // x-coord of upper-left corner
      int nYOriginSrc,             // y-coord of upper-left corner
      int nWidthSrc,               // source width
      int nHeightSrc,              // source height
      BLENDFUNCTION blendFunction  // alpha-blending function
    );
      

  9.   

    算法基本是对的,但是你可能对于位图句柄、DDB、DIB的意义不太清楚,类型不是可以随意强制转换的,比如:
    LPBITMAPINFO  lpbmif=(LPBITMAPINFO)hDIBSrc;    
    LPBITMAPINFOHEADER  lpbmifh=(LPBITMAPINFOHEADER)lpbmif; 
    第二个有点道理,如果lpbmif真的是一个BITMAPINFO结构指针的话;但是第一个就不知道怎么来的了,有什么依据?另外,这种图形处理的方式,最好直接绘图而不要用控件来显示,基于你这里:
    pPic->SetBitmap((HBITMAP)hDIB);
    我对你这个hDIB是什么类型不清楚。
      

  10.   

    是闪烁还是效果消失啊?闪烁的话是你双缓冲没有做好
    在操作时只用给内存DC上绘图,在OnDraw里面在把内存DC复制到当前DC,这样就避免了闪烁,或者试试OnEraseBkgnd()返回TRUE 。是因为窗口变大变小,移动时等等画面会重绘,以前的就没有了。要随时调用Invalidate() ,它会调用OnDraw(),同时使用双缓冲避免闪烁。