如果您使用的是 32bpp [P]ARGB 像素格式,则使用 LockBits/BitmapData 应该可以正常工作。诀窍是您必须一次复制一行数据,以便它在正确的位置对齐。您应该可以使用以下方式执行此操作:
Rectangle srcArea = new Rectangle(0, 0, srcBitmap.Width, srcBitmap.Height);
BitmapData srcData = srcBitmap.LockBits(srcArea, ImageLockMode.ReadOnly, destBitmap.PixelFormat);
Rectangle destArea = new Rectangle(25, 25, srcBitmap.Width, srcBitmap.Height);
BitmapData destData = destBitmap.LockBits(destArea, ImageLockMode.WriteOnly, destBitmap.PixelFormat);
IntPtr srcPtr = srcData.Scan0;
IntPtr destPtr = destData.Scan0;
byte[] buffer = new byte[srcData.Stride];
for (int i = 0; i < srcData.Height; ++i)
{
Marshal.Copy(srcPtr, buffer, 0, buffer.Length);
Marshal.Copy(buffer, 0, destPtr, buffer.Length);
srcPtr += srcData.Stride;
destPtr += destData.Stride;
}
srcBitmap.UnlockBits(srcData);
destBitmap.UnlockBits(destData);
作为警告,此代码不会按原样工作,因为我不确定增加 IntPtr 的正确咒语是什么。我以前做过同样类型的事情,但在 C++ 中。另外,不知道有没有办法直接复制数据而不是使用中间缓冲区。
另外一个警告:LockBits 调用 srcBitmap 和缓冲区的大小假定 srcBitmap 将完全包含在 destBitmap 中。如果不是这种情况(位图的某些部分将被裁剪掉),则需要调整锁定区域和缓冲区大小。
如果您不使用 32bpp 像素格式(即 24bpp),则会更加困难。源 BitmapData 的步幅可能包括一些不应复制的填充。您可以通过计算源行中的实际像素数据量来解决此问题,然后复制该数量。索引像素格式会更有效。