代码中有一些根本性的错误,我不敢相信我直到现在才注意到。
byte* destRowPtr = (byte*)destbtmpdata.Scan0 + (destRow * destbtmpdata.Stride);
这会获取指向目标行的指针,但不会获取要复制到的列,这在旧代码中是在 rowSize 循环内完成的。现在看起来像:
byte* destRowPtr = (byte*)destbtmpdata.Scan0 + (destRow * destbtmpdata.Stride) + pointX * 3;
现在我们有了目标数据的正确指针。现在我们可以摆脱 for 循环了。使用来自的建议Vilx- https://stackoverflow.com/questions/740555/lockbits-performance-critical-code/857480#857480 and Rob https://stackoverflow.com/questions/740555/lockbits-performance-critical-code/857932#857932代码现在看起来像:
private static unsafe void CopyBitmapToDestSuperFast(BitmapData sourcebtmpdata, BitmapData destbtmpdata, Point point)
{
//calculate total number of rows to copy.
//using ternary operator instead of Math.Min, few ms faster
int totalRows = (destbtmpdata.Height - point.Y < sourcebtmpdata.Height) ? destbtmpdata.Height - point.Y : sourcebtmpdata.Height;
//calculate the width of the image to draw, this cuts off the image
//if it goes past the width of the destination image
int rowWidth = (destbtmpdata.Width - point.X < sourcebtmpdata.Width) ? destbtmpdata.Width - point.X : sourcebtmpdata.Width;
//loop through each row on the source bitmap and get mem pointers
//to the source bitmap and dest bitmap
for (int i = 0; i < totalRows; i++)
{
int destRow = point.Y + i;
//get the pointer to the start of the current pixel "row" and column on the output image
byte* destRowPtr = (byte*)destbtmpdata.Scan0 + (destRow * destbtmpdata.Stride) + point.X * 3;
//get the pointer to the start of the FIRST pixel row on the source image
byte* srcRowPtr = (byte*)sourcebtmpdata.Scan0 + (i * sourcebtmpdata.Stride);
//RtlMoveMemory function
CopyMemory(new IntPtr(destRowPtr), new IntPtr(srcRowPtr), (uint)rowWidth * 3);
}
}
将 500x500 图像复制到网格中的 5000x5000 图像 50 次所用时间:00:00:07.9948993 秒。现在,经过上述更改,需要 00:00:01.8714263 秒。好多了。