2010-07-03 4 views
5

Ich kodiere eine Live Control/Remote-Desktop-Lösung mit dem kostenlosen Spiegeltreiber von DFMirage. Es gibt ein C# -Probe, wie der Spiegeltreiber here interagiert und gesteuert wird. Sie müssten den Spiegeltreiber zuerst installiert haben, natürlich here. Das Konzept besteht also darin, dass der Client (Helfer) eine Bildschirmaktualisierung anfordert und der Server (Opfer) einen sendet, der die rohe Pixelcodierung verwendet. Das Konzept eines Mirror-Treibers macht teure Änderungen an Bildschirmänderungen überflüssig, weil ein Mirror-Treiber in Echtzeit über alle Zeichenoperationen informiert wird. Der Spiegeltreiber empfängt den Ort und die Größe des Aktualisierungsrechtecks ​​und kann einfach den Speicher nach den neuen Pixelbytes abfragen und sie senden.Rohe Bitmap-Daten/Scan-Zeilen (Spiegel-Treiber-Rohdaten)?

Sollte einfach sein, außer dass ich nicht weiß, wie man das Teil, wo wir Speicher für die neuen Pixel Bytes abfragen. Das Beispiel zeigt, wie Speicher abfragen, um die Pixel des gesamten Bildschirm zu greifen, um etwas mit rohen Bitmap-Daten und Bildzeilen und schreiten und all das gute Zeug:

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; 

Das ist großartig und funktioniert gut. Das resultierende Bitmap Objekt hat jetzt die Pixel des gesamten Bildschirms. Aber wenn ich nur ein Rechteck von Pixeldaten extrahieren möchte, anstatt die Pixeldaten vom gesamten Bildschirm zu bekommen, wie könnte ich das tun? Ich denke, das ist eher eine Frage von rawbitmap-scan-stride, aber ich habe alles eingegeben, damit Sie wissen, woher das kommt. Also irgendwelche Erkenntnisse darüber, wie man nur einen Teil der Pixeldaten anstelle der gesamten Pixeldaten des Bildschirms erhält?

Update: Etwas gefunden interesting (nur Codeteil).

Antwort

0

Hier ist eine Funktion, um eine rechteckige Fläche von einem Quellbildpuffer auf eine Bitmap kopieren:

Rectangle roi = new Rectangle(100, 150, 200, 250); 
Bitmap result = ExtractImageRectangle(getChangesBuffer.UserBuffer, getChangesBuffer.Stride, getChangesBuffer.PixelFormat, roi); 

Dies setzt voraus, dass GetChangesBuffer Eigenschaften für:

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; 
} 

Sie dann wie folgt verwenden könnte das Schritt- und Pixelformat des Quellbildpuffers. Es ist höchstwahrscheinlich nicht, aber Sie sollten einige Mittel haben, um das Schritt- und Pixelformat Ihres Eingangsbildes zu bestimmen. In Ihrem Beispiel gehen Sie davon aus, dass der Schritt des Eingabebildes dem Schritt Ihres Ausgabebildes entspricht, was eine knifflige Annahme ist.