好的,只是在一天结束时很快就完成了,所以可能会有一些错误,但在我测试的图像中,它似乎工作正常。
private static void CopyBmpRegion(Bitmap image, Rectangle srcRect, Point destLocation)
{
//do some argument sanitising.
if (!((srcRect.X >= 0 && srcRect.Y >= 0) && ((srcRect.X + srcRect.Width) <= image.Width) && ((srcRect.Y + srcRect.Height) <= image.Height)))
throw new ArgumentException("Source rectangle isn't within the image bounds.");
if ((destLocation.X < 0 || destLocation.X > image.Width) || (destLocation.Y < 0 || destLocation.Y > image.Height))
throw new ArgumentException("Destination must be within the image.");
// Lock the bits into memory
BitmapData bmpData = image.LockBits(new Rectangle(Point.Empty, image.Size), ImageLockMode.ReadWrite, image.PixelFormat);
int pxlSize = (bmpData.Stride / bmpData.Width); //calculate the pixel width (in bytes) of the current image.
int src = 0; int dest = 0; //source/destination pixels.
//account for the fact that not all of the source rectangle may be able to copy into the destination:
int width = (destLocation.X + srcRect.Width) <= image.Width ? srcRect.Width : (image.Width - (destLocation.X + srcRect.Width));
int height = (destLocation.Y + srcRect.Height) <= image.Height ? srcRect.Height : (image.Height - (destLocation.Y + srcRect.Height));
//managed buffer to hold the current pixel data.
byte[] buffer = new byte[pxlSize];
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
//calculate the start of the current source pixel and destination pixel.
src = ((srcRect.Y + y) * bmpData.Stride) + ((srcRect.X + x) * pxlSize);
dest = ((destLocation.Y + y) * bmpData.Stride) + ((destLocation.X + x) * pxlSize);
// Can replace this with unsafe code, but that's up to you.
Marshal.Copy(new IntPtr(bmpData.Scan0.ToInt32() + src), buffer, 0, pxlSize);
Marshal.Copy(buffer, 0, new IntPtr(bmpData.Scan0.ToInt32() + dest), pxlSize);
}
}
image.UnlockBits(bmpData); //unlock the data.
}
本质上,您描述了您希望复制的区域的源矩形(以像素为单位,而不是以字节为单位),即 Rectangle(0, 0, 100, 100) 将描述从图像左上角开始的 100x100 像素宽的块。
接下来,描述目标矩形的左上角。尽可能多的源矩形将被复制到目标,但如果图像不够宽/高以容纳整个矩形,它将被剪裁。
使用示例如下:
Image img = Image.FromFile(@"C:\Users\254288b\Downloads\mozodojo-original-image.jpg");
CopyBmpRegion((Bitmap)img, new Rectangle(5, 5, 100, 100), new Point(100, 100));
img.Save(@"C:\Users\254288b\Downloads\mozodojo-new-image.jpg", ImageFormat.Jpeg);
结果如下:
mozodojo-原始图像.jpg
mozodojo-new-image.jpg
看看情况如何。