Bild zu Bytes

  • VB.NET
  • .NET 5–6

Es gibt 44 Antworten in diesem Thema. Der letzte Beitrag () ist von -Franky-.

    Bild zu Bytes

    Hallo,

    wie kann man eine Bilddatei In ihre Pixel zerlegen? Und als was wäre so ein Pixel zu repräsentieren in einem Programm?
    Ich möchte eine Bilddatei einlesen und eine Textdatei daraus schreiben, wobei ein Pixel zu einem String wird. Ist der Pixel weiß, dann "0", sonst "1"

    Viele Grüße
    Hi
    Am schnellsten get das über LockBits/UnlockBits. Nach dem LockBits kopierst entweder jedes Pixel einzeln raus, oder Du kopierst alles komplett in ein ByteArray das Du dann durchlaufen kannst. Achtung: Je nach Pixelformat des Originals werden etwas andere Berechnungen benötigt um an den einzelnen Pixel zu kommen bzw dem Pixel im ByteArray. Oder Du sagst LockBits das das Original mit 32bppARGB verwendet werden soll. Dann braucht nur eine Formel für die Pixelposition.
    Mfg -Franky-
    @Haudruferzappeltnoch Kommt darauf an, was Du machen willst:

    VB.NET-Quellcode

    1. Dim col As Color = myBitmap.GetPixel(x, y)
    funktioniert sehr gut aber ist auch sehr gemütlich.
    Sieh mal hier vorbei: stackoverflow.com/questions/17…onverting-image-to-base64
    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!
    Danke euch, ich habs jetzt mit den LockBits probiert.
    Hab bisher nur kleine .png Bilder probiert. Aber damit geht es schonmal.

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. Dim img1 As New Bitmap(".png")
    3. IO.File.WriteAllText(".txt", BitsOf(img1))
    4. img1.Dispose
    5. End Sub
    6. Private Function BitsOf(bmp As Bitmap) As String
    7. Dim LockedBits = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), Imaging.ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb)
    8. Dim rawdata = BytesFrom(LockedBitsImg1)
    9. Dim PixelsSet As New List(Of Boolean)
    10. For i = 0 To rawdataImg1.Count - 1 Step 3
    11. PixelsSet.Add(Not (rawdata(i) = 255 AndAlso rawdata(i + 1) = 255 AndAlso rawdata(i + 2) = 255))
    12. Next i
    13. Dim strbBits As New Text.StringBuilder("")
    14. Dim addendum = 8 - bmp.Width Mod 8
    15. For i = 0 To PixelsSet.Count - 1 Step bmp.Width
    16. For k = i To bmp.Width + i - 1
    17. If PixelsSet(k) Then
    18. strbBits.Append("1"c)
    19. Else
    20. strbBits.Append("0"c)
    21. End If
    22. Next
    23. strbBits.Append(String.Empty.PadLeft(addendum, "0"c))
    24. strbBits.Append(vbCrLf)
    25. Next
    26. Return strbBits.ToString
    27. End Function
    28. Private Function BytesFrom(bmpDat As BitmapData) As Byte()
    29. Dim ptr As IntPtr = bmpDat.Scan0
    30. Dim bytes As Integer = Math.Abs(bmpDat.Stride) * bmpDat.Height
    31. Dim rgbValues(bytes - 1) As Byte
    32. System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes)
    33. Return rgbValues
    34. End Function
    35. End Class

    Edit: Jetzt ohne Pixel Klasse, die bräuchte ich ja nur wenn ich damit noch was machen möchte.

    Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    @Haudruferzappeltnoch Was soll denn passieren?
    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!
    Na hab ich doch geschrieben am Anfang. Bild geht rein. Text kommt raus.
    Jede Pixelreihe wird eine Textzeile.
    Jeder Pixel wird eine Zahl. 0 wenn Pixel weiß, sonst 1

    (Und ich hab noch die Reihe aufgefüllt mit "0" bis die Bits durch 8 teilbar sind)
    Die Textdatei, die geschrieben wird, ist quasi eine bitartige Repräsentation der Schwarzweiß-Version des Bildes.
    @Haudruferzappeltnoch Dann ist aber die Base64String-Variante etwas eleganter.
    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 schrieb:

    Dann ist aber die Base64String-Variante etwas eleganter

    Inwiefern denn? Der will scheinbar einfach eine Farbe auf ein char/string mappen, base64 würde doch in diesem Falle gar nichts nützen?
    Und Gott alleine weiß alles am allerbesten und besser.
    Hi

    Das PixelFormat ist relativ egal. Klar, das 1bppIndexed hat einen Vorteil, der auch gleichzeitig ein Nachteil sein kann. Wer sagt denn das in der Palette Schwarz und Weiß vorhanden sein müssen und vor allem an welcher Position? Gibt es eigentlich immer noch den Bug das man von Indexed-Formaten kein Graphics-Objekt erstellen kann?

    Ich würde nach Möglichkeit und in diesem Fall auch, immer im 32bppARGB arbeiten. Selbst wenn man den AlphaChannel nicht benötigt. Die Formel für die Berechnung der Pixelposition ab Scan0 oder im ByteArray ist sehr einfach.
    Mfg -Franky-

    φConst schrieb:

    Inwiefern denn?
    Es ist kürzer.
    @Haudruferzappeltnoch Was soll mit dem String passieren?
    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!
    @Haudruferzappeltnoch
    Irgendwie vermisse ich ein UnlockBits in Deinem Code und wozu brauch man die PadBytes des Bildes?

    Ich schließe mich mal der Frage von RodFromGermany an. Wozu brauch man ein S/W-Bild als String?
    Mfg -Franky-
    @Haudruferzappeltnoch @-Franky- kleine Anmerkung zu Bildern in Base64Strings:
    Macht eine Form mit einer PictureBox und ladet in diese ein Bild als lokale Ressource.
    Nach dem Speichern seht Euch die FormX.resx an, da ist das Bild als Base64String codieret abgelegt.
    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
    Das schon klar was ein Base64-String ist. Pack ein S/W-Bild in die PB und enthält der Base64-String ausschließlich 0 und 1?

    Denke es macht mehr Sinn sich weitere Gedanken zu machen wenn Haudruferzappeltnoch sagt, wozu das ganze am Ende dienen soll / gebraucht wird.
    Mfg -Franky-

    -Franky- schrieb:

    enthält der Base64-String ausschließlich 0 und 1?
    Nein.
    Eine 7 ist letzten Endes 0111 binär.
    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!
    @Haudruferzappeltnoch

    Ich habe auch schon mal sowas gemacht. Dazu habe ich folgenden Algo genommen, denn der Konvertiert Bilder zu SchwarzWeiss-Bilder. Musst den Algo ein bisschen anpassen, dann kannst du entscheiden, ab wann "0" oder "1" geschrieben wird.

    Fehlt bei dir ein UnlockBits? Der muss unbedingt noch gesetzt werden.

    EDIT: Gefunden ist von hier. Hab mich schon gefragt woher ich das habe.
    Color Matrix zum Ersetzen von Farben ?


    Freundliche Grüsse

    exc-jdbi

    VB.NET-Quellcode

    1. '"bgra" ist die Byte-Array die aus deiner Image gemacht worden ist, wenn mit LockBits/UnlockBits gearbeitet wird.
    2. '"BGRAValues" ist die neue Array die die SW-Convertierung enthält.
    3. '"whiteborder" (z.B. TrackBar) ist ein Wert 0 - 255 der die Skalierung angibt, ab wann die Schwarzweiss-Konvertierung anfangen soll.
    4. Dim b, g, r, a As Byte
    5. Dim blnremove As Boolean
    6. 'black = rgb(0,0,0)
    7. 'white = rgb(255,255,255)
    8. For i = 0 To bgra.Length - 3 Step 4
    9. b = bgra(i) : g = bgra(i + 1)
    10. r = bgra(i + 2) : a = bgra(i + 3)
    11. blnremove = False
    12. If r < whiteborder OrElse g < whiteborder OrElse
    13. b < whiteborder OrElse a < whiteborder Then blnremove = True
    14. If blnremove Then
    15. Me.BGRAValues(i) = 0 : Me.BGRAValues(i + 1) = 0
    16. Me.BGRAValues(i + 2) = 0 : Me.BGRAValues(i + 3) = 255
    17. End If
    18. Next

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    @RodFromGermany
    Jau, und dann must das ganze ja doch aufdröseln um dann einen String mit 0 und 1 zu erhalten.

    Wie geschrieben, mal schauen wozu Haudruferzappeltnoch das ganze braucht.

    @exc-jdbi
    Ich glaub es geht gar nicht so sehr um das konvertieren von einem Pixelformat in ein anderes oder wie man ein Farbbild in ein S/W-Bild konvertiert. Da gibt es zig Möglichkeiten.
    Mfg -Franky-

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „-Franky-“ ()

    Soll es doch ja auch nicht. Wollte nur ein kleines Verständnisproblem klären.

    Die Konvertierung in 0 oder 1 ist ja wirklich sehr einfach. Und mit obigen Algo wird sogar gezeigt, dass es skalierbar ist, und man nicht unbedingt mit 0 oder 255 angefangen werden muss. Es kann auch irgendwo zwischen diesen zwei Werten angefangen werden.

    Für was auch immer @Haudruferzappeltnoch das schlussendlich braucht. Es kann nie schaden, mehr darüber zu wissen.

    Freundliche grüsse

    exc-jdbi