Screenshot anfertigen und zu Bytes "konvertieren" funktioniert nicht

  • VB.NET
  • .NET (FX) 4.0

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von Michdi.

    Screenshot anfertigen und zu Bytes "konvertieren" funktioniert nicht

    Guten Abend,
    ich versuche jetzt schon eine ganze Weile, einen Screenshot vom Bildschirm anzufertigen und dann in Bytes zu speichern, um diesen dann weiterzuverarbeiten. Meine Prozedur sieht bis jetzt dafür wie folgt aus:

    VB.NET-Quellcode

    1. Dim area As Rectangle
    2. Dim capture As System.Drawing.Bitmap
    3. Dim graph As Graphics
    4. area = Screen.PrimaryScreen.Bounds
    5. capture = New System.Drawing.Bitmap(area.Width, area.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
    6. graph = Graphics.FromImage(capture)
    7. graph.CopyFromScreen(area.X, area.Y, 0, 0, area.Size, CopyPixelOperation.SourceCopy)
    8. Dim abyt As Byte() = ImageToBytes(capture)

    Die Funktion ImageToBytes:

    VB.NET-Quellcode

    1. Private Function ImageToBytes(ByVal Image As Image) As Byte()
    2. Dim memImage As New System.IO.MemoryStream
    3. Dim bytImage() As Byte
    4. Image.Save(memImage, Image.RawFormat) 'Hier tritt der Fehler auf
    5. bytImage = memImage.GetBuffer()
    6. Return bytImage
    7. End Function

    Wenn ich das jetzt aber versuche kommt immer folgende Fehlermeldung:
    System.ArgumentNullException: 'Der Wert darf nicht NULL sein. Parametername: encoder'
    Ich habe schon viel gegoogelt und verschiedene Fehler bekommen. Wenn ich etwas anderes probiert habe, hat das auch nicht geklappt. Offenbar fehlt hier irgendwie der Parameter für den Encoder, wobei ich noch nicht ganz verstehe, was das bedeuten soll.

    Ich hoffe, dass ihr mir helfen könnt,

    Grüße
    Michdi
    Die beste maschinelle Übersetzung der Welt - DeepL Übersetzer
    Alle Zitate, die ich seit dem 1.9.2017 übersetzt habe, wurden vollautomatisch mit DeepL übersetzt.



    Willst du die Rohdaten sichern? Dann hohle dir mit LockBits die Bytes und schreibe dann auf die Platte, ansonsten nimm ein anderes ImageFormat, für Image.Save.
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin
    Ich will einfach nur die Bytes von dem Bild in "Byte-Form" haben, um diese dann per StreamWriter weiterzuverschiffen. (Ich nutze keinen MediaWriter weil ich keine weitere Verbindung öffnen möchte)
    Wie genau meinst du das mit ein anderes Format nehmen?
    Die beste maschinelle Übersetzung der Welt - DeepL Übersetzer
    Alle Zitate, die ich seit dem 1.9.2017 übersetzt habe, wurden vollautomatisch mit DeepL übersetzt.



    Michdi schrieb:

    Wie genau meinst du das mit ein anderes Format nehmen?


    Wie gesagt:

    VB.NET-Quellcode

    1. Private Function ImageToBytes(ByVal Image As Image) As Byte()
    2. Using memImage As New System.IO.MemoryStream
    3. Image.Save(memImage, ImageFormat.Png)
    4. Return memImage.ToArray()
    5. End Using
    6. End Function


    Edit:

    @Michdi Oder die Bilddaten in Roh-Form

    VB.NET-Quellcode

    1. Private Function GetBytes(ByVal img As Bitmap) As Byte()
    2. Dim bmpData As BitmapData = img.LockBits(New Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadOnly, img.PixelFormat)
    3. Dim ptr As IntPtr = bmpData.Scan0
    4. Dim bytes As Integer = Math.Abs(bmpData.Stride) * img.Height
    5. Dim rgbValues(bytes - 1) As Byte
    6. System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes)
    7. img.UnlockBits(bmpData)
    8. Return rgbValues
    9. End Function
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „NoIde“ ()

    @Michdi Dann hast Du offensichtlich mindestens zwei Probleme:
    • Image to Byte / Byte to Image
    • Senden von Bytes per TCP.
    Löse beide Teilprobleme unabhängig voneinander, und wenn Du sie gelöst hast, setze beide Teillösungen zu einem neuen Projekt zusammen.
    Die Teillösungen speichere in Deiner Snippet-Sammlung, Du wirst sie später gewiss noch brauchen. ;)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany Die Snippets für Image to Byte und Byte to Image habe ich schon fertig, jetzt bin ich dabei die Bytes über den Stream zu verschicken. Ich bin da aber noch nicht allzu weit, weil mir noch nicht ganz klar ist, wie ich die auf der Empfängerseite annehmen kann, da dort ja immer mit dem StreamReader alles gelesen wird.
    Die beste maschinelle Übersetzung der Welt - DeepL Übersetzer
    Alle Zitate, die ich seit dem 1.9.2017 übersetzt habe, wurden vollautomatisch mit DeepL übersetzt.



    Michdi schrieb:

    da dort ja immer mit dem StreamReader alles gelesen wird
    Dann musst Du zwei Programme zum Testen basteln: Eines sendet, das andere empfängt.
    Und es wäre gut, wenn Du die komplette Empfangsroutine hast.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Mein Code sieht zum Senden vom Client bis jetzt so aus:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private stream As NetworkStream
    3. Private streamw As StreamWriter
    4. Private streamr As StreamReader
    5. Private client As New TcpClient
    6. Private t As New Threading.Thread(AddressOf Listen)
    7. Private Delegate Sub DAddItem(ByVal s As String)
    8. Private Sub Listen()
    9. While client.Connected
    10. Try
    11. Me.Invoke(New DAddItem(AddressOf AddItem), streamr.ReadLine)
    12. Catch
    13. Application.Exit() 'Das Programm schließt sich sobald hier etwas nicht funktioniert, das ist so gewollt :)
    14. End Try
    15. End While
    16. End Sub
    17. Private Sub AddItem(ByVal s As String)
    18. 'Code gekürzt, hier werden alle Nachrichten empfangen und verarbeitet
    19. End Sub
    20. Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
    21. Try
    22. client.Connect(ip, 8001)
    23. If client.Connected Then
    24. stream = client.GetStream
    25. streamw = New StreamWriter(stream)
    26. streamr = New StreamReader(stream)
    27. streamw.WriteLine(nickName)
    28. streamw.Flush()
    29. t.Start()
    30. Else
    31. MsgBox(ex.Message, MsgBoxStyle.Critical, "Goodbye!")
    32. Application.Exit()
    33. End If
    34. Catch ex As Exception
    35. MsgBox(ex.Message, MsgBoxStyle.Critical, "Goodbye!")
    36. Application.Exit()
    37. End Try
    38. End Sub
    39. 'Der Code zum Senden von Nachrichten:
    40. streamw.WriteLine(cCrypt.EncryptedString)
    41. streamw.Flush()
    42. End Class


    Und der Server sieht wie folgt aus:

    VB.NET-Quellcode

    1. Module Server
    2. Private server As TcpListener
    3. Private client As New TcpClient
    4. Private ipendpoint As IPEndPoint = New IPEndPoint(IPAddress.Any, 8001)
    5. Private list As New List(Of Connection)
    6. Dim c As New Connection
    7. Private Structure Connection
    8. Dim stream As NetworkStream
    9. Dim streamw As StreamWriter
    10. Dim streamr As StreamReader
    11. Dim nick As String
    12. End Structure
    13. Sub Main()
    14. server = New TcpListener(ipendpoint)
    15. server.Start()
    16. Console.WriteLine("Listening on local port 8001")
    17. Try
    18. While True
    19. client = server.AcceptTcpClient
    20. c.stream = client.GetStream
    21. c.streamr = New StreamReader(c.stream)
    22. c.streamw = New StreamWriter(c.stream)
    23. c.nick = c.streamr.ReadLine
    24. list.Add(c)
    25. Dim t As New Threading.Thread(AddressOf ListenToConnection)
    26. t.Start(c)
    27. End While
    28. Catch ex As Exception
    29. MsgBox(ex.Message)
    30. End Try
    31. End Sub
    32. Private Sub ListenToConnection(ByVal con As Connection)
    33. Do
    34. Try
    35. Dim tmp As String = con.streamr.ReadLine
    36. Console.WriteLine(tmp)
    37. For Each c As Connection In list
    38. c.streamw.WriteLine(tmp)
    39. c.streamw.Flush()
    40. Next
    41. Catch
    42. Try
    43. list.Remove(con)
    44. Exit Do
    45. Catch ex As Exception
    46. con.stream.ReadByte()
    47. End Try
    48. End Try
    49. Loop
    50. End Sub


    Damit funktioniert auch alles so wie gewollt (Server mit mehreren Clients), jetzt muss ich beim Empfangen am Server (und dann beim Weiterleiten) es nur noch hinbekommen, dass er nicht die Bytes als String sendet, sondern falls es Bytes sind, auch Bytes sendet.
    Die beste maschinelle Übersetzung der Welt - DeepL Übersetzer
    Alle Zitate, die ich seit dem 1.9.2017 übersetzt habe, wurden vollautomatisch mit DeepL übersetzt.