龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > asp.net编程 >

C#实现获取屏幕图像差异效果

时间:2009-12-21 11:47来源:未知 作者:admin 点击:
分享到:
先帖几张效果图 软件界面 差异结果 我们对两幅图像的比较,可以逐个像素比较,也可以先把图像分块,然后比较对应块中的数据。那么,到底分块是什么个概念,又该如何分块,分块

先帖几张效果图

软件界面

差异结果

我们对两幅图像的比较,可以逐个像素比较,也可以先把图像分块,然后比较对应块中的数据。那么,到底分块是什么个概念,又该如何分块,分块后的数据如何比较呢?下面我将逐一进行介绍。

     分块也就是说把图片分成“几乘几”的小块,如图1所示一幅200*80的图像。按横向划分4块,纵向划分2块的方式,可以画出一个二行四列的网格,其中每一格就是分块数据。

screenshare-v2-1 图1

      看起来似乎很简单,其实实现上也很简单,^_^。在Dot Net中,Bitmap类有一个很好用的方法就是Clone,该方法的其中一个重载方法为:public Bitmap Clone(Rectangle rect, PixelFormat format); 怎么样?知道怎么做了吧。你只需要建立一个图像数组用于存储所有块数据,然后其中的每一个块数据均通过Clone方法从母图像中获取。

      分块后的数据其实仍然是一个图像,怎么比较这个图像呢?我第一次接触到分块算法的时候,就愣住了,难道对于分块数据仍然采用像素扫描的方式?研究了DG的算法后才发现自己太天真了。对于分块数据,可以直接在内存中进行比较,这种比较方式速度最快。说到这里,不知道是否有朋友会有疑问:“既然内存中比较速度最快,那为什么还要搞隔行、分块呢?”,答案很简单,因为我们不止是要比较出不同,更重要的是要把不同的部分加以利用。不管是隔行还是分块,目的都是为了能最小化变化的区域,只有这样才能有效降低网络负载。

      如果对上述内容理解清楚了,那接下来就来看下分块的思路。这个思路主要还要感谢DG的算法。

      首先对原图进行分块的初始化,经过这步之后会得到一个最原始的分块数组。然后拿该分块数组与第二张图片进行内存比较。比较的时候,并非逐个分块进行比较,而是有选择的进行比较,这种选择建立在三种假设的基础上:

     1. 鼠标所在的块会发生变化;

     2. 当一个块变化的时候,该块周围的块也会发生变化;

     3. 图片第一行和最后一行会发生变化;

     当比较出不同的时候,即可以采取我们想要的一些行为。另外,要注意的就是选择一个合适分块粒度(即你要把图像分成“几乘几”)。如果分块多,则每一个分块的数据量就小,但是比较的次数就会变多。如果分块少,则每一个分块的数据量较多,但是比较次数就会变少。因此选择一个合适的粒度会影响程序的性能,据文献资料的记载和他人的尝试,一般认为把屏幕分成16*8块最为合适。

      说了这么多,下面来看下关键代码吧:

C# Code [http://www.xueit.com]
/// <summary>
/// 初始化所有分块的数据
/// </summary>
public void InitializeBlocks()
{
    int top = 0;
    int left = 0;

    _blocks = new List<Bitmap>(_blocksInColumn * _blocksInRow);
    _isSupposedChanged = new List<bool>(_blocks.Capacity);
    _isScanned = new List<bool>(_blocks.Capacity);

    _blockWidth = (_oldBmp.Width   _blocksInRow - 1) / _blocksInRow;
    _blockHeight = (_oldBmp.Height   _blocksInColumn - 1) / _blocksInColumn;

    for (int i = 1; i <= _blocks.Capacity; i  )
    {
        top = ((i   _blocksInRow - 1) / _blocksInRow) - 1;
        left = i - _blocksInRow * top - 1;

        _blocks.Add(_oldBmp.Clone(new Rectangle(left * _blockWidth, top * _blockHeight, _blockWidth, _blockHeight), _oldBmp.PixelFormat));
        if (i <= _blocksInRow || _blocks.Capacity - i - 1 < _blocksInRow)
        {
            _isSupposedChanged.Add(true);
        }
        else
        {
            _isSupposedChanged.Add(false);
        }
        _isScanned.Add(false);
    }
}


精彩图集

赞助商链接