【问题标题】:Raw bitmap data/scan lines (mirror driver raw data)?原始位图数据/扫描线(镜像驱动程序原始数据)?
【发布时间】:2010-07-03 17:32:56
【问题描述】:

我正在使用 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(仅代码部分)。

【问题讨论】:

    标签: c# driver remote-desktop


    【解决方案1】:

    这是一个将矩形区域从某个源图像缓冲区复制到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 具有源图像缓冲区的步幅和像素格式的属性。它很可能没有,但您应该有一些方法来确定输入图像的步幅和像素格式。在您的示例中,您假设输入图像的步幅等于输出图像的步幅,这是一个棘手的假设。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-06
      • 2017-09-10
      • 2015-12-22
      • 2013-06-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多