科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件VC数字图像处理编程讲座之五

VC数字图像处理编程讲座之五

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本期讲座继续介绍BMP图像特效效果。

作者:刘涛 来源:作者授权转载 2007年10月21日

关键字: VC 数字图像处理 编程

  • 评论
  • 分享微博
  • 分享邮件
第四节 BMP图像操作的补充篇

  上一讲中我们介绍了图像特效显示操作的实现方法,如随机显示效果、马赛克效果、拉幕显示效果等,由于篇幅的限制,还有许多效果没有介绍;本期讲座将接着上一讲的内容,继续介绍一些图像特效显示效果。

  另外,我们前面的学习都是针对现成的BMP图像,在实际工作学习中,绝大部分处理图像过程都是在一个系统环境中,也就是说需要和图像数据的获取设备直接打交道,一般情况下,计算机图像处理系统从系统层次上可分为高、中、低档三个层次,目前比较普及的是低档次的系统,该系统由CCD(摄像头)、图像采集卡、计算机三个部分组成,其结构简单,应用方便,效果也比较不错,得到的图像较清晰,所以目前在工程应用中采用的比较多。这就给开发人员带来一个现实的问题,如何使用图像采集卡呢?目前虽然各种编程资源中基于VC开发经验的文章不少,但是关于如何在VC开发平台上使用图像采集卡的文章的确没发现,笔者借这期讲座的宝贵机会,补充介绍一下如何在程序中编写自己的代码来操作图像采集卡,从而搭建一个完整的图像处理系统。希望通过这部分内容的学习,在读者的脑海里就可以建立一个完整的图像操作系统概念;同时也能够给目前正需要利用图像采集卡开发自己的图像处理系统的朋友有所帮助。

  1. 抖动图像

  在上一节讲座中,我们讲到了如何实现图象的"雕刻"和"浮雕"效果,它们的实现思想是通过求取"没有处理过的相邻两个像素之间的差值"来实现的。如果没有限制"以前没有处理过的两个像素之间的操作",取而代之的是"处理以前已经操作过的像素",那末就可以将一个像素的灰度值传递到与其相邻的若干像素。事实上,有时后我们必须通过上述的约定才能实现一些效果,如图像的抖动效果。例如,为了使图象看起来好象从左上角向右下角扫过,以产生运动的感觉,必须要反复拷贝左上方的那些像素的灰度值,逐步把它们融合在一起,看起来好象图像后边有一些颜色在逐渐的消失,这就是我们要讲的图象的抖动效果。下面给出了该效果的实现代码:

void CDibView::OnDouDongImage() //产生"抖动"效果图函数
{
 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);//显示图像
}

  对于比较复杂的图像,计算当前像素的灰度和斜上方像素的均值产生的抖动效果可能不明显,为了解决这个问题,笔者的解决办法是隔行隔列的计算,比如说计算当前位置(i j)的灰度值,我取(i,j)和(i-2,j-2)两个位置的像素的灰度值的平均。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章