双缓冲绘图,是指先在内存中进行各种绘图操作,在将内存中绘制好的图形取出显示在控件上,这样可以避免窗口闪烁的现象。

根据上述原理,我们可以自行实现双缓冲绘图,示例代码如下:

private void Paint()
{
    // tempImage -> 临时位图
    // tempGraphics -> 临时位图的绘图对象
    // viewGraphics -> 显示控件的绘图对象
    using (Bitmap tempImage = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height))
    using (Graphics tempGraphics = Graphics.FromImage(tempImage))
    using (Graphics viewGraphics = pictureBox1.CreateGraphics())
    {
        // 步骤一:在临时位图上绘图
        tempGraphics.Clear(Color.Black); // 使用黑色填充
        if (MainImage != null)
            tempGraphics.DrawImage(MainImage, 0, 0, pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height); // 绘制图像

        // 步骤二:将位图取出,绘制到显示控件上
        viewGraphics.DrawImage(tempImage, 0, 0);
    }
}

但是该方法有个缺点,就是 Graphics.DrawImage() 这个函数的执行效率比较差,在绘制一些分辨率较大的图像时会显得力不从心,这对于在毫秒必争的图像处理领域显然无法接受。

所以就有了另外的双缓冲绘图的实现方法,就是将所有绘图操作都放到显示控件的 Paint 事件中去执行,然后我们仅需要执行 Control.Invalidate() 即可刷新显示控件。也就是说,我们将耗时操作都放在另外的线程中执行了,我们的绘图操作便不再占用时间了。示例代码如下:

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    // 这些事为了提高 Graphics 的执行效率
    e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
    e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
    e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;

    // 绘图
    if (MainImage != null)
        e.Graphics.DrawImage(MainImage, 0, 0, pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
}

private void Paint()
{
    pictureBox1.Invalidate();
}
01-22 23:30