BMP图像操作的补充篇
上一讲中我们介绍了图像特效显示操作的实现方法,如随机显示效果、马赛克效果、拉幕显示效果等,由于篇幅的限制,还有许多效果没有介绍;本期讲座将接着上一讲的内容,继续介绍一些图像特效显示效果。
另外,我们前面的学习都是针对现成的BMP图像,在实际工作学习中,绝大部分处理图像过程都是在一个系统环境中,也就是说需要和图像数据的获取设备直接打交道,一般情况下,计算机图像处理系统从系统层次上可分为高、中、低档三个层次,目前比较普及的是低档次的系统,该系统由CCD(摄像头)、图像采集卡、计算机三个部分组成,其结构简单,应用方便,效果也比较不错,得到的图像较清晰,所以目前在工程应用中采用的比较多。这就给开发人员带来一个现实的问题,如何使用图像采集卡呢?目前虽然各种编程资源中基于VC开发经验的文章不少,但是关于如何在VC开发平台上使用图像采集卡的文章的确没发现,笔者借这期讲座的宝贵机会,补充介绍一下如何在程序中编写自己的代码来操作图像采集卡,从而搭建一个完整的图像处理系统。希望通过这部分内容的学习,在读者的脑海里就可以建立一个完整的图像操作系统概念;同时也能够给目前正需要利用图像采集卡开发自己的图像处理系统的朋友有所帮助。
1. 抖动图像
在上一节讲座中,我们讲到了如何实现图象的"雕刻"和"浮雕"效果,它们的实现思想是通过求取"没有处理过的相邻两个像素之间的差值"来实现的。如果没有限制"以前没有处理过的两个像素之间的操作",取而代之的是"处理以前已经操作过的像素",那末就可以将一个像素的灰度值传递到与其相邻的若干像素。事实上,有时后我们必须通过上述的约定才能实现一些效果,如图像的抖动效果。例如,为了使图象看起来好象从左上角向右下角扫过,以产生运动的感觉,必须要反复拷贝左上方的那些像素的灰度值,逐步把它们融合在一起,看起来好象图像后边有一些颜色在逐渐的消失,这就是我们要讲的图象的抖动效果。下面给出了该效果的实现代码:
{
HANDLE data1handle;//用来存放图像数据的句柄;
LPBITMAPINFOHEADER lpBi;//图像的信息头结构;
CDibDoc *pDoc=GetDocument();//得到文挡指针;
HDIB hdib;//用来存放图像数据的句柄;
unsigned char *pData;//指向原始图像数据的指针;
unsigned char *data;//指向处理后图像数据的指针;
hdib=pDoc->m_hDIB;//拷贝存放已经读取的图像文件数据句柄;
lpBi=(LPBITMAPINFOHEADER)GlobalLock((HGLOBAL)hdib);//获取图像信息头;
pData=(unsigned char*)FindDIBBits((LPSTR)lpBi);
//FindDIBBits是我定义的一个函数,根据图像的结构得到位图的灰度值数据;
pDoc->SetModifiedFlag(TRUE);
//设置文档修改标志为"真",为后续的修改存盘作准备;
data1handle=GlobalAlloc(GMEM_SHARE,WIDTHBYTES(lpBi->biWidth*8)*lpBi->biHeight); //声明一个缓冲区用来暂存处理后的图像数据;
data=(unsigned char*)GlobalLock((HGLOBAL)data1handle);//得到该缓冲区的指针;
AfxGetApp()->BeginWaitCursor();
int i,j,buf;
for( i=lpBi->biHeight; i>=2; i--)//从图像右下角开始对图像的各个像素进行"抖动"处理;
for( j=lpBi->biWidth; j>=2; j--)
{
//抖动处理、从图像的右下角开始计算图像斜上方相邻像素的均值;
buf=(*(pData+(lpBi->biHeight-i)*WIDTHBYTES(lpBi->biWidth*8)+j)+*(pData+(lpBi->biHeight-i+1)*WIDTHBYTES(lpBi->biWidth*8)+j-1))/2;
if(buf>255) buf=255;//限制像素点的灰度范围为0-255;
if(buf<0)buf=0; *(data+(lpBi->biHeight-i)*WIDTHBYTES(lpBi->biWidth*8)+j)=(BYTE)buf;
}
for( j=0; j<biHeight; j++)
for( i=0; i<biWidth; i++)
//重新写回原始图像的数据缓冲区;
*(pData+i*WIDTHBYTES(lpBi->biWidth*8)+j)=*(data+i*WIDTHBYTES(lpBi->biWidth*8)+j); AfxGetApp()->EndWaitCursor();
pDoc->m_hDIB =hdib//将处理过的图像数据写回pDoc中的图像缓冲区;
GlobalUnlock((HGLOBAL)hdib);//解锁、释放缓冲区;
GlobalUnlock((HGLOBAL)data1handle);
GlobalFree((HGLOBAL)hdib);
GlobalFree((HGLOBAL)data1handle);
Invalidate(TRUE);//显示图像
}
2.图像合成技术
图像合成技术很重要,其实质是操作将两幅或两幅以上的图像,将它们的信息融合在一起,产生1+1>2的效果。我们在进行图像合成的时候可以采用Alpha值的方法,下面来看一下如何利用Alpha值来合成两张图片。
采用Alpha图象合成的方法,就是最终合成的图象的各点像素值是由用来制作合成图的两张图片的相应点的像素值按一定比例混合而成的,这个比例由Alpha值决定,具体算式如下:
// Alpha取值范围从0到255
{
BYTE lpData1,lpData2;
// 源图象2的信息
//由于待合成的两个图象的格式、大小是一样的,所以我只获取一个图像文件的图像信息就可以了。
LPBITMAPINFO lpBi=(LPBITMAPINFO)HDib2;
// 计算图象数据偏移量
lpData2=(LPVOID)((LPBYTE)lpBi->bmiColors+256*sizeof(RGBQUAD));
//获取源图像2的图像数据;
lpBi=(LPBITMAPINFO)HDib1;
lpData1=(LPVOID)((LPBYTE)lpBi->bmiColors+256*sizeof(RGBQUAD));
//通过alpha值合并两张图象的像素值
for ( int i=0;i< lpBi->biWidth; i++ )
for(int j=0;j< lpBi->biHeight;j++ )
{
//套用alpha图像混合公式;
*(lpData1+i*WIDTHBYTES(lpBi->biWidth*8)+j)=(*(lpData1+i*WIDTHBYTES(lpBi->biWidth*8)+j)*(255-alpha)+ *(lpData2+i*WIDTHBYTES(lpBi->biWidth*8)+j)*alpha)/255;
}
return lpData1;
}
