public static class BitmapHelper {
public static Bitmap Clone(Bitmap bmp) {
var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
Bitmap newbmp = new Bitmap(rect.Width, rect.Height);
using (Graphics gfx = Graphics.FromImage(newbmp)) {
gfx.InterpolationMode = InterpolationMode.High;
gfx.PixelOffsetMode = PixelOffsetMode.None;
gfx.DrawImage(bmp, rect, rect, GraphicsUnit.Pixel);
}
return newbmp;
}
}
大多数情况下,这会创建一个相同的副本,但如果传递给Clone的原始位图是通过从较大的位图绘制一个部分来创建的,其中该部分扩展到较大位图的最右边,则我得到的副本会在最右边的边缘略微改变像素。
我做错了什么?
创建原始代码的代码如下所示:
var SmallerImage = new Bitmap(_sqSize, _sqSize);
using (var gfx = Graphics.FromImage(SmallerImage)) {
gfx.InterpolationMode = InterpolationMode.High;
gfx.PixelOffsetMode = PixelOffsetMode.None;
gfx.DrawImage(LargerImage,
new Rectangle(0, 0, _sqSize, _sqSize),
new Rectangle(p.X, p.Y, _sqSize, _sqSize),
GraphicsUnit.Pixel);
}
重要的是要知道Point p和_sqSize是这样的,因为源矩形(DrawImage调用中的第二个矩形)直到LargerImage的最右边。
当Point p和_sqSize使得源矩形没有与LargerImage的右边缘对接时,同样的代码会创建一个相同的副本。
有谁能告诉我为什么会这样?
或者,有人可以告诉我如何可靠地创建一个像素的精确像素复制吗?看起来它应该很容易,但我似乎无法做到。
new Bitmap(bmp)
与我的克隆方法存在同样的问题。 bmp.Clone()
似乎确实有效,但它有问题(有些不是深层复制 - 与原始文件共享数据),使用它会在很多方面破坏我的代码。
答案 0 :(得分:0)
首先,检查图像在克隆之前是否已经存在这些工件。
使用Clone()
确实只是一个浅层副本,但我相信Clone(Rectangle, PixelFormat)
是一个深层克隆:
public static Bitmap Clone(Bitmap bmp) {
var newbmp = bmp.Clone(new Rectangle(0, 0, bmp.Width, bmp.Height), bmp.PixelFormat);
return newbmp;
}
如果这不起作用,请尝试复制原始数据:
[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
public static Bitmap Clone(Bitmap bmp) {
var oldData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
var newBmp = new Bitmap(bmp.Width, bmp.Height, oldData.PixelFormat);
var newData = newBmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat);
CopyMemory(newData.Scan0, oldData.Scan0, (uint)(Math.Abs(oldData.Stride) * oldData.Height));
newBmp.UnlockBits(newData);
bmp.UnlockBits(oldData);
return newBmp;
}