我正在使用DFMirage的免费镜像驱动程序编写实时控件/远程桌面解决方案。有关如何连接和控制镜像驱动程序here的C#示例。首先需要安装镜像驱动程序,here。因此,概念是,客户端(帮助者)请求屏幕更新,服务器(受害者)使用原始像素编码发送一个。镜像驱动程序的概念消除了对屏幕更改进行昂贵轮询的需要,因为镜像驱动程序会实时通知所有屏幕绘制操作。镜像驱动程序接收更新矩形的位置和大小,并且可以简单地查询内存以获取新的像素字节并发送它们。
应该很简单,除了我不知道如何做查询内存以获取新像素字节的部分。该示例演示了如何使用原始位图数据和扫描线以及所有优点来查询内存以获取整个屏幕的像素:
Bitmap result = new Bitmap(_bitmapWidth, _bitmapHeight, format);
Rectangle rect = new Rectangle(0, 0, _bitmapWidth, _bitmapHeight);
BitmapData bmpData = result.LockBits(rect, ImageLockMode.WriteOnly, format);
// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;
// Declare an array to hold the bytes of the bitmap.
int bytes = bmpData.Stride * _bitmapHeight;
var getChangesBuffer = (GetChangesBuffer)Marshal
.PtrToStructure(_getChangesBuffer, typeof (GetChangesBuffer));
var data = new byte[bytes];
Marshal.Copy(getChangesBuffer.UserBuffer, data, 0, bytes);
// Copy the RGB values into the bitmap.
Marshal.Copy(data, 0, ptr, bytes);
result.UnlockBits(bmpData);
return result;
这很好,工作正常。生成的Bitmap
对象现在具有整个屏幕的像素。但是,如果我只想提取像素数据的矩形而不是从整个屏幕获取像素数据,我将如何做到这一点?我想这更像是一个rawbitmap-scan-stride问题,但我输入了所有这些,所以你可能知道它来自哪里。那么有关如何获得一部分像素数据而不是整个屏幕的像素数据的任何见解?
更新:发现了一些interesting(仅限代码部分)。
答案 0 :(得分:0)
这是一个将矩形区域从某个源图像缓冲区复制到Bitmap
的功能:
private static Bitmap ExtractImageRectangle(byte[] sourceBuffer, int sourceStride, PixelFormat sourcePixelFormat, Rectangle rectangle)
{
Bitmap result = new Bitmap(rectangle.Width, rectangle.Height, sourcePixelFormat);
BitmapData resultData = result.LockBits(new Rectangle(0, 0, result.Width, result.Height), ImageLockMode.WriteOnly, result.PixelFormat);
int bytesPerPixel = GetBytesPerPixel(sourcePixelFormat); // Left as an exercise for the reader
try
{
// Bounds checking omitted for brevity
for (int rowIndex = 0; rowIndex < rectangle.Height; ++rowIndex)
{
// The address of the start of this row in the destination image
IntPtr destinationLineStart = resultData.Scan0 + resultData.Stride * rowIndex;
// The index at which the current row of our rectangle starts in the source image
int sourceIndex = sourceStride * (rowIndex + rectangle.Top) + rectangle.Left * bytesPerPixel;
// Copy the row from the source to the destination
Marshal.Copy(sourceBuffer, sourceIndex, destinationLineStart, rectangle.Width * bytesPerPixel);
}
}
finally
{
result.UnlockBits(resultData);
}
return result;
}
然后您可以像这样使用它:
Rectangle roi = new Rectangle(100, 150, 200, 250);
Bitmap result = ExtractImageRectangle(getChangesBuffer.UserBuffer, getChangesBuffer.Stride, getChangesBuffer.PixelFormat, roi);
这假定GetChangesBuffer
具有源图像缓冲区的步幅和像素格式的属性。它很可能没有,但您应该有一些方法来确定输入图像的步幅和像素格式。在您的示例中,您假设输入图像的步幅等于输出图像的步幅,这是一个棘手的假设。