我试图比较截图并只写出差异。
这是我的代码
public Bitmap Difference(Bitmap bmp0, Bitmap bmp1)
{
Bitmap bmp2;
int Bpp = bmp0.PixelFormat == PixelFormat.Format24bppRgb ? 3 : 4;
bmp2 = new Bitmap(bmp0.Width, bmp0.Height, bmp0.PixelFormat);
var bmpData0 = bmp0.LockBits(
new Rectangle(0, 0, bmp0.Width, bmp0.Height),
ImageLockMode.ReadOnly, bmp0.PixelFormat);
var bmpData1 = bmp1.LockBits(
new Rectangle(0, 0, bmp1.Width, bmp1.Height),
ImageLockMode.ReadOnly, bmp1.PixelFormat);
var bmpData2 = bmp2.LockBits(
new Rectangle(0, 0, bmp2.Width, bmp2.Height),
ImageLockMode.ReadWrite, bmp2.PixelFormat);
// MessageBox.Show(bmpData0.Stride.ToString());
int len = bmpData0.Height * bmpData0.Stride;
// MessageBox.Show(bmpData0.Stride.ToString());
bool changed = false;
byte[] data0 = new byte[len];
byte[] data1 = new byte[len];
byte[] data2 = new byte[len];
Marshal.Copy(bmpData0.Scan0, data0, 0, len);
Marshal.Copy(bmpData1.Scan0, data1, 0, len);
Marshal.Copy(bmpData2.Scan0, data2, 0, len);
for (int i = 0; i < len; i += Bpp)
{
changed = ((data0[i] != data1[i])
|| (data0[i + 1] != data1[i + 1])
|| (data0[i + 2] != data1[i + 2]));
// this.Invoke(new Action(() => this.Text = changed.ToString()));
data2[i] = changed ? data1[i] : (byte)2; // special markers
data2[i + 1] = changed ? data1[i + 1] : (byte)3; // special markers
data2[i + 2] = changed ? data1[i + 2] : (byte)7; // special markers
if (Bpp == 4)
data2[i + 3] = changed ? (byte)255 : (byte)42; // special markers
}
// this.Invoke(new Action(() => this.Text = changed.ToString()));
Marshal.Copy(data2, 0, bmpData2.Scan0, len);
bmp0.UnlockBits(bmpData0);
bmp1.UnlockBits(bmpData1);
bmp2.UnlockBits(bmpData2);
return bmp2;
}
Bitmap shot = new Bitmap(SystemInformation.VirtualScreen.Width,
SystemInformation.VirtualScreen.Height,
PixelFormat.Format24bppRgb);
public Bitmap screenshot()
{
Graphics screenGraph = Graphics.FromImage(shot);
screenGraph.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0,
0,
SystemInformation.VirtualScreen.Size,
CopyPixelOperation.SourceCopy);
return shot;
}
我的电话:
private void Form1_Load(object sender, EventArgs e)
{
Bitmap prev = screenshot();
Thread.Sleep(1000);
Bitmap curr = screenshot();
pictureBox1.Image=Difference(prev,curr);
}
我在此行中获得Bitmap region is already locked.
错误
var bmpData1 = bmp1.LockBits(
new Rectangle(0, 0, bmp1.Width, bmp1.Height),
ImageLockMode.ReadOnly, bmp1.PixelFormat);
这是我的截图代码,一个简单的.net屏幕截图方法:
它真的很奇怪,因为我甚至没有在screenshot
方法中使用LockBits所以我不知道它为什么会抛出这个错误......
答案 0 :(得分:1)
如果您的位图是“自下而上”而不是“自上而下”,则Stride属性将为负值。
见这里: https://msdn.microsoft.com/en-us/library/system.drawing.imaging.bitmapdata.stride%28v=vs.110%29.aspx
从这篇文章:
“步幅是单行像素(扫描线)的宽度,四舍五入到四字节边界。如果步幅为正,则位图为自上而下。如果步幅为负,则位图为底部-up“。
使用
int len = bmpData0.Height * Math.Abs(bmpData0.Stride);
如果您使用的是自下而上的位图,则需要使用不同的机制将位图复制到缓冲区。关于如何在这个问题中处理这个问题有一些不同的建议,请参阅前三个答案:
How can I copy the pixel data from a Bitmap with negative stride?
从最新的编辑到您的问题,现在您的问题是您正在为截图使用相同的Bitmap实例。在screenshot()方法中移动'shot'声明,以便为每个屏幕截图使用不同的实例:
public Bitmap screenshot()
{
Bitmap shot = new Bitmap(SystemInformation.VirtualScreen.Width,
SystemInformation.VirtualScreen.Height,
PixelFormat.Format24bppRgb);
Graphics screenGraph = Graphics.FromImage(shot);
screenGraph.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0,
0,
SystemInformation.VirtualScreen.Size,
CopyPixelOperation.SourceCopy);
return shot;
}