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

创建新图像时,如何实现更快的位图数据复制?

图像操作类速度优化:替代g.DrawImage()的逐行像素复制方案

问题背景

  • 开发图像操作类时,g.DrawImage()调用耗时超出预期,无法达到处理速度要求
  • 此前使用LeadTools SDK时,通过逐行复制像素字节的方法获得了明显更快的处理效果
  • 已通过可靠的LogDebug()完成基准测试:
    • 当headerHeight = 0(不为原图顶部添加空白):处理3页图像总耗时约1.9秒
    • 当headerHeight = 100(添加100像素顶部空白):总耗时约3.6秒

优化方案:直接操作位图像素缓冲区

跳过g.DrawImage()的GDI+封装开销,直接通过锁定位图内存、逐行复制像素数据实现,和LeadTools的高效思路一致。

核心逻辑

  1. 锁定源位图与目标位图的像素缓冲区,获取直接内存访问权限
  2. 根据图像像素格式(如32位ARGB、24位RGB)计算每行字节数
  3. 若需添加顶部空白,从目标位图的headerHeight行开始,逐行复制源位图的像素数据
  4. 操作完成后解锁缓冲区,避免资源泄漏

代码示例

public Bitmap AddHeaderAndCopy(Bitmap sourceBmp, int headerHeight)
{
    // 创建目标位图,高度为原图高度加顶部空白高度
    Bitmap targetBmp = new Bitmap(sourceBmp.Width, sourceBmp.Height + headerHeight, sourceBmp.PixelFormat);
    
    // 定义源图和目标图的操作区域
    Rectangle sourceRect = new Rectangle(0, 0, sourceBmp.Width, sourceBmp.Height);
    Rectangle targetRect = new Rectangle(0, headerHeight, sourceBmp.Width, sourceBmp.Height);
    
    // 锁定位图像素数据,获取内存指针
    BitmapData sourceData = sourceBmp.LockBits(sourceRect, ImageLockMode.ReadOnly, sourceBmp.PixelFormat);
    BitmapData targetData = targetBmp.LockBits(targetRect, ImageLockMode.WriteOnly, targetBmp.PixelFormat);
    
    try
    {
        int rowByteCount = sourceData.Stride;
        IntPtr sourceRowPtr = sourceData.Scan0;
        IntPtr targetRowPtr = targetData.Scan0;
        
        // 逐行复制像素数据,规避内存对齐问题
        for (int y = 0; y < sourceBmp.Height; y++)
        {
            byte[] rowBuffer = new byte[rowByteCount];
            Marshal.Copy(sourceRowPtr, rowBuffer, 0, rowByteCount);
            Marshal.Copy(rowBuffer, 0, targetRowPtr, rowByteCount);
            
            // 移动指针到下一行
            sourceRowPtr = IntPtr.Add(sourceRowPtr, sourceData.Stride);
            targetRowPtr = IntPtr.Add(targetRowPtr, targetData.Stride);
        }
    }
    finally
    {
        // 必须解锁位图,否则会导致资源占用
        sourceBmp.UnlockBits(sourceData);
        targetBmp.UnlockBits(targetData);
    }
    
    return targetBmp;
}

性能优势说明

  • 直接操作内存避免了g.DrawImage()内置的坐标转换、格式兼容检查等额外开销
  • 逐行复制模式更适配CPU缓存机制,减少内存访问的延迟损耗
  • 添加顶部空白时仅需调整目标位图的起始复制行,无额外绘制逻辑,耗时增长远低于DrawImage()方案

内容的提问来源于stack exchange,提问作者Arvo Bowen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 15:46:06