You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现将pictureBox1图像逐像素/逐段缓慢绘制到pictureBox2?

实现从pictureBox1逐步绘制图像到pictureBox2的正确方法

需求

将pictureBox1中的图像以逐像素或逐组像素的方式缓慢绘制到pictureBox2,呈现从空白开始逐步涂色的效果,而非一次性完成。

现有代码问题分析

你当前的代码逻辑完全搞反了:

  • 修改后的Paint事件中,你创建了原图像的副本,然后用空的rgbValues数组覆盖原图像的字节数据,这相当于逐步擦除原图像,所以会出现图像从上到下消失的效果。
  • 当你把Bitmap初始化为new Bitmap(512,512)时,这个空白Bitmap没有任何原图像的数据,自然不会显示任何内容。

正确实现思路

核心是维护一个空白的目标Bitmap,每次Timer触发时,从原图像中复制一部分像素到目标Bitmap中,然后刷新pictureBox2显示这个目标Bitmap,直到整个图像绘制完成。

步骤说明

  1. 定义全局变量存储原图像Bitmap、目标Bitmap,以及当前绘制的进度(比如当前已绘制的行数)。
  2. 在窗体加载时初始化目标Bitmap为空白(和原图像同尺寸),并复制原图像到全局变量(避免重复创建)。
  3. Timer的Tick事件中,每次处理一行或多行像素,将原图像对应区域的像素复制到目标Bitmap,然后刷新pictureBox2。
  4. pictureBox2的Paint事件直接绘制目标Bitmap,无需每次操作LockBits,提升效率。

完整代码示例

// 全局变量
private Bitmap _sourceBitmap;
private Bitmap _targetBitmap;
private int _currentRow = 0;

private void Form1_Load(object sender, EventArgs e)
{
    // 初始化原图像Bitmap(确保pictureBox1已加载图像)
    if (pictureBox1.Image != null)
    {
        _sourceBitmap = new Bitmap(pictureBox1.Image);
        // 创建空白目标Bitmap,尺寸和原图像一致
        _targetBitmap = new Bitmap(_sourceBitmap.Width, _sourceBitmap.Height);
        // 初始化目标Bitmap为白色空白(也可以用透明,根据需求调整)
        using (Graphics g = Graphics.FromImage(_targetBitmap))
        {
            g.Clear(Color.White);
        }
    }
    // 设置Timer间隔,控制绘制速度(单位:毫秒)
    timer1.Interval = 50;
}

private void timer1_Tick(object sender, EventArgs e)
{
    if (_sourceBitmap == null || _targetBitmap == null) return;

    // 每次绘制一行,也可以改成绘制多行或固定数量像素,调整速度
    if (_currentRow < _sourceBitmap.Height)
    {
        // 锁定原图像和目标图像的当前行
        Rectangle rowRect = new Rectangle(0, _currentRow, _sourceBitmap.Width, 1);
        BitmapData sourceData = _sourceBitmap.LockBits(rowRect, ImageLockMode.ReadOnly, _sourceBitmap.PixelFormat);
        BitmapData targetData = _targetBitmap.LockBits(rowRect, ImageLockMode.WriteOnly, _targetBitmap.PixelFormat);

        // 复制一行的像素数据
        int bytesPerRow = Math.Abs(sourceData.Stride);
        byte[] rowBytes = new byte[bytesPerRow];
        System.Runtime.InteropServices.Marshal.Copy(sourceData.Scan0, rowBytes, 0, bytesPerRow);
        System.Runtime.InteropServices.Marshal.Copy(rowBytes, 0, targetData.Scan0, bytesPerRow);

        // 解锁Bitmap
        _sourceBitmap.UnlockBits(sourceData);
        _targetBitmap.UnlockBits(targetData);

        _currentRow++;
        // 刷新pictureBox2
        pictureBox2.Invalidate();
    }
    else
    {
        // 绘制完成,停止Timer
        timer1.Stop();
    }
}

private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
    if (_targetBitmap != null)
    {
        e.Graphics.DrawImage(_targetBitmap, 0, 0);
    }
}

// 窗体关闭时释放Bitmap资源,避免内存泄漏
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    _sourceBitmap?.Dispose();
    _targetBitmap?.Dispose();
}

可选优化

  • 如果想要逐像素绘制而非逐行,可以修改Tick事件中的逻辑,每次复制一个像素的字节数据,调整Timer间隔控制速度。
  • 可以随机绘制像素,实现类似“泼墨”的涂色效果,只需将_currentRow改为随机坐标即可。

内容的提问来源于stack exchange,提问作者Daniel Lip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 17:11:17