Boolean(,) to Byte() / 2-dim Array in 1-dim Array konvertieren

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 24 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Boolean(,) to Byte() / 2-dim Array in 1-dim Array konvertieren

    Hallo!
    Ich bearbeite Bilder und konvertiere diese von Bitmap zu Byte() und speichere dann alles in einer .XML-Datei ab!
    Nun habe ich das Problem das ich eine Funktion hab die mit einem Boolean(,) Array funktioniert..d.H. ich brauche eine Funktion, bzw. zwei, mit denen ich von Byte() zu Boolean(,) konvertieren kann!

    Hmm, meine versuche dazu funktionieren iwie nicht! Wenn ich das Array zurück inn Bitmap verwandel sehe ich nur paar Bildpunkte in der ersten Zeile tanzen..

    Spoiler anzeigen

    Quellcode

    1. Private Function _boolToByte(ByVal _Bool As Boolean(,)) As Byte()
    2. Dim _byte(_Bool.Length) As Byte
    3. 'Dim _stride As Integer = 20
    4. Dim _loop As Integer = 0
    5. For x As Integer = 0 To _Bool.GetUpperBound(0) - 1
    6. For y As Integer = 0 To _Bool.GetUpperBound(1) - 1
    7. If _Bool(x, y) = True Then
    8. _byte(x + y) = 0
    9. Else
    10. _byte(x + y) = 255
    11. End If
    12. ' Debug.WriteLine("x:" & x & "-y:" & y & "--" & _byte(x + y).ToString)
    13. Next
    14. Next
    15. Return _byte
    16. End Function
    17. Private Function _byteToBool(ByVal _Byte As Byte()) As Boolean(,)
    18. Dim _bool(20, 20) As Boolean
    19. Debug.WriteLine(_Byte.Length)
    20. For x = 0 To 19
    21. For y = 0 To 19
    22. If _Byte(x + y) < 127 Then
    23. _bool(x, y) = False
    24. Else
    25. _bool(x, y) = True
    26. End If
    27. Next
    28. Next
    29. Return _bool
    30. End Function

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

    Hi
    Bilder gehören i.A. nicht in eine Datenbank.
    Was zudem nicht passt: Es müsste wohl x + _stride sein. Aber ehrlich gesagt passt das Hinten und Vorne nicht. Byte() ist wesentlich eleganter, als Boolean(,) (und in diesem Fall auch eleganter, als BitArray()).
    Speichere das Bild in eine Datei auf dem Server ab und wähle für die Datei einen eindeutigen Namen. Anschließend lässt du die Datenbank auf die Datei verweisen.

    Viele Grüße
    ~blaze~
    0 1 2 3 4 5
    6 7 8 9 10 11
    12 13 14 15 16 17
    18 19 20 21 22 23
    24 25 26 27 28 29

    wie könnte man da nur das Mapping von 2D auf 1D machen?

    x+y geht schonmal nicht: max(x+y) = 9 und wir müssen bis mind. 29 kommen
    also eine einfache Multiplikation muss her

    y*6+x -> max(y*6+x)=29

    und außerdem bildet jedes (x,y) paar auf nur einen index Wert ab.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Naja, Datenbank = DataTable

    ..also das soll ein Bitmap von 20*20 px sein!
    Bei _Array.UpperLength bekomm ich 401.

    ..dann ist das ja auch schon Falsch:

    Spoiler anzeigen

    Quellcode

    1. Public Shared Function getBinaryTiles(ByVal bmp As Bitmap, ByVal iRowCount As Integer, ByVal iColumnCount As Integer, ByVal iPercentNeeded As Integer) As Byte()
    2. Dim iTileWidth As Integer = CInt(bmp.Width / iColumnCount)
    3. Dim iTileHeight As Integer = CInt(bmp.Height / iRowCount)
    4. Dim iPixelsInTile As Integer = iTileHeight * iTileWidth
    5. Dim bBinary(401) As Byte
    6. Dim iTileX As Integer = 0
    7. Dim iTileY As Integer = 0
    8. Dim _lbBitmap As New LockBits(bmp)
    9. _lbBitmap.LockBits()
    10. For iX = 0 To _lbBitmap.Width - 1 Step iTileWidth
    11. For iY = 0 To _lbBitmap.Height - 1 Step iTileHeight
    12. Dim iCountMarkedPixelsInTile As Integer = 0
    13. For x = iX To iX + iTileWidth - 1
    14. For y = iY To iY + iTileHeight - 1
    15. If _lbBitmap.GetPixel(x, y).GetBrightness = 0 Then
    16. iCountMarkedPixelsInTile += 1
    17. End If
    18. Next
    19. Next
    20. Dim iPercent As Integer = CInt(Math.Round(100 / iPixelsInTile * iCountMarkedPixelsInTile, 0))
    21. If iPercent >= iPercentNeeded Then
    22. bBinary(iTileX + iTileY) = 255
    23. Else
    24. bBinary(iTileX + iTileY) = 0
    25. End If
    26. iTileY += 1
    27. Next
    28. iTileX += 1
    29. iTileY = 0
    30. Next
    31. _lbBitmap.UnlockBits()
    32. Return bBinary
    33. End Function

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

    ich verstehe das Problem nicht.
    Bitmap nach Byte() konvertieren kann ich.
    Bilder in Db speichern finde ich auch i.O., je nach Anforderung.
    Weil eine Db, die nur Dateipfade verwaltet, ist anfällig dagegen, dass jemand im Dateisystem rumpfuscht - und kleine Bildle eh noProblem.

    Aber warum man Byte() nach Boolean(,) konvertieren will, ist mir unerfindlich, und es scheint ja auch iwas mit Tile-Generierung zu tun haben - aber was?

    Also meine Lieblings-Gegenfrage/Bitte: Erklär mal, was du eiglich beabsichtigst.
    Hehe, nunja..ich habe eine Bitmap von der ich die Pixeldaten mit LockBits auslese um diese als Byte() zu speichern. Soweit alles i.O.!
    Dann habe ich eine Funktion (nicht von mir) die mir von dem Bitmap, wie oben erwähnt, Tiles generiert..aber nur Boolean(,) akzeptiert..

    ..deswegen das hin und her! Hab schon versucht die Funktion umzuschreiben..aber da kommt nur murks bei rum..

    ..grml..und die Funktion klappt auch nicht:

    Spoiler anzeigen

    Quellcode

    1. [vbnet] Private Function _pixelate(ByVal _bmp As Bitmap) As Bitmap
    2. Dim bmOut As Bitmap = New Bitmap(_bmp.Width, _bmp.Height, _bmp.PixelFormat)
    3. Dim pixelationAmount As Integer = 10
    4. ' store average of rgb
    5. Dim pixel As Color
    6. Dim x As Integer = 0
    7. Dim iPixelsInTile As Integer = pixelationAmount * pixelationAmount
    8. While x < Width
    9. Dim y As Integer = 0
    10. While y < Height
    11. Dim bx As Integer = x + pixelationAmount
    12. Dim by As Integer = y + pixelationAmount
    13. If by >= Height Then
    14. by = Height
    15. End If
    16. If bx >= _bmp.Width Then
    17. bx = _bmp.Width
    18. End If
    19. Dim iCountMarkedPixelsInTile As Integer = 0
    20. For xx As Integer = x To bx - 1
    21. For yy As Integer = y To by - 1
    22. pixel = _bmp.GetPixel(xx, yy)
    23. If pixel.GetBrightness = 0 Then
    24. iCountMarkedPixelsInTile += 1
    25. End If
    26. Next
    27. Next
    28. Dim iPercent As Integer = CInt(Math.Round(100 / iPixelsInTile * iCountMarkedPixelsInTile, 0))
    29. For xx As Integer = x To bx - 1
    30. For yy As Integer = y To by - 1
    31. If iPercent >= 1 Then
    32. bmOut.SetPixel(xx, yy, Color.Black)
    33. Else
    34. bmOut.SetPixel(xx, yy, Color.White)
    35. End If
    36. Next
    37. Next
    38. y += pixelationAmount
    39. End While
    40. x += pixelationAmount
    41. End While
    42. Return bmOut
    43. End Function
    44. [/vbnet]


    Also eine Funktion die alle 20px die Quersumme der Farbwerte(bzw. S/W) nimmt und entweder schwarz oder weiß überwiegt!

    Hier das Original:

    Spoiler anzeigen

    Quellcode

    1. Public Shared Function getBinaryTiles(ByVal bmp As Bitmap, ByVal iRowCount As Integer, ByVal iColumnCount As Integer, ByVal iPercentNeeded As Integer) As Boolean(,)
    2. Dim iTileWidth As Integer = CInt(bmp.Width / iColumnCount)
    3. Dim iTileHeight As Integer = CInt(bmp.Height / iRowCount)
    4. Dim iPixelsInTile As Integer = iTileHeight * iTileWidth
    5. Dim bBinary(iColumnCount - 1, iRowCount - 1) As Boolean
    6. Dim iTileX As Integer = 0
    7. Dim iTileY As Integer = 0
    8. For iX = 0 To bmp.Width - 1 Step iTileWidth
    9. For iY = 0 To bmp.Height - 1 Step iTileHeight
    10. Dim iCountMarkedPixelsInTile As Integer = 0
    11. For x = iX To iX + iTileWidth - 1
    12. For y = iY To iY + iTileHeight - 1
    13. If bmp.GetPixel(x, y).GetBrightness = 0 Then
    14. iCountMarkedPixelsInTile += 1
    15. End If
    16. Next
    17. Next
    18. Dim iPercent As Integer = CInt(Math.Round(100 / iPixelsInTile * iCountMarkedPixelsInTile, 0))
    19. If iPercent >= iPercentNeeded Then
    20. bBinary(iTileX, iTileY) = True
    21. Else
    22. bBinary(iTileX, iTileY) = False
    23. End If
    24. iTileY += 1
    25. Next
    26. iTileX += 1
    27. iTileY = 0
    28. Next
    29. Return bBinary
    30. End Function

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

    Morrison schrieb:

    ...Tiles generiert..aber nur Boolean(,) akzeptiert.
    Solch scheint mir abstrus.
    Sieh besser zu, dass du eine vernünftige Tiles-Generier-Funktion zustande bringst.
    Oder zeig die Methode mal - ich kann mir kaum vorstellen, dass jmd sowas komisches veröffentlicht.

    Morrison schrieb:

    Also eine Funktion die alle 20px die Quersumme der Farbwerte(bzw. S/W) nimmt und entweder schwarz oder weiß überwiegt!
    Sowas ist nicht wirklich eine Tiles-Generierung.
    Das wäre eher eine Rasterung, aber auch nicht wirklich, denn bei einer Rasterung stellt man aus den Bool-Informationen dann eine Schwarz-Weiß-Bitmap her.

    Aber ist mir immer noch nicht klar, was du damit vor hast - was willst du mit dem Bool(,)?
    OK, also diese Funktion funktioniert (lol):

    Spoiler anzeigen

    Quellcode

    1. Private Function _BMPpixel(ByVal _bmp As Bitmap) As Bitmap
    2. Dim bmOut As Bitmap = New Bitmap(_bmp.Width, _bmp.Height, _bmp.PixelFormat)
    3. Dim pixelationAmount As Integer = 8
    4. ' store average of rgb
    5. Dim pixel As Color
    6. Dim x As Integer = 0
    7. Dim iPixelsInTile As Integer = pixelationAmount * pixelationAmount
    8. While x < _bmp.Width
    9. Dim y As Integer = 0
    10. While y < _bmp.Height
    11. Dim bx As Integer = x + pixelationAmount
    12. Dim by As Integer = y + pixelationAmount
    13. If by >= _bmp.Height Then
    14. by = _bmp.Height
    15. End If
    16. If bx >= _bmp.Width Then
    17. bx = _bmp.Width
    18. End If
    19. Dim iCountMarkedPixelsInTile As Integer = 0
    20. For xx As Integer = x To bx - 1
    21. For yy As Integer = y To by - 1
    22. pixel = _bmp.GetPixel(xx, yy)
    23. If pixel.GetBrightness = 0 Then
    24. iCountMarkedPixelsInTile += 1
    25. End If
    26. Next
    27. Next
    28. Dim iPercent As Integer = CInt(Math.Round(100 / iPixelsInTile * iCountMarkedPixelsInTile, 0))
    29. For xx As Integer = x To bx - 1
    30. For yy As Integer = y To by - 1
    31. If iPercent >= 1 Then
    32. bmOut.SetPixel(xx, yy, Color.Black)
    33. Else
    34. bmOut.SetPixel(xx, yy, Color.White)
    35. End If
    36. Next
    37. Next
    38. y += pixelationAmount
    39. End While
    40. x += pixelationAmount
    41. End While
    42. Return bmOut
    43. End Function

    Nur brauch ich jetzt als Rückgabewert dein Byte()! (*lol*)

    ​Edit:
    ..natürlich "ein" Byte()-Array..als Rückgabewert, kein Bitmap.
    Ich weiß nur leider nicht wie das mit dem "Stride" funktioniert!

    Wenn ich die Bitmap mit Schleifen durchlaufe habe ich die x und y Werte..wie mache ich daraus die Position des Bytes im Array?

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

    Morrison schrieb:

    Wenn ich die Bitmap mit Schleifen durchlaufe habe ich die x und y Werte..wie mache ich daraus die Position des Bytes im Array?
    Das ist jetzt wieder was ganz anderes, als was du je gefragt hast, in diesem Thread.
    Aber es ist verständlich - ich hoffe nur, es ist wirklich, was du wissen willst.

    Ich formuliere dein Anliegen nochmal um, und du sagst mir, ob ich richtig verstanden habe:
    Du möchtest das Byte-Array erhalten mit den Pixel-Daten der Bitmap.

    Dabei meint "Pixel-Daten" die Farb-Kanäle rgb, (rot grün blau).

    Dazu ist zu sagen, dass hauptsächlich zweierlei Bitmapse üblich sind: Manche Bitmaps haben 3 Bytes per Pixel, andere haben 4 Bytes per Pixel, nämlich zusätzlich den Alpha-Kanal ("argb" -> alpha red green blue) . Man notiert diese Einstellung aber nicht "Bytes per Pixel", sondern Bitweise.
    Also
    System.Drawing.Imaging.PixelFormat.Format24bppRgb bedeutet, diese Bitmap hat 3 Bytes per Pixel, und
    System.Drawing.Imaging.PixelFormat.Format32bppArgb bedeutet, die Bitmap hat 4 Bytes per Pixel

    Also je nachdem, aus welcher Art Bitmap deine Pixeldaten sind, musst du in 3er-Schritten durch die Pixel iterieren oder in 4ern.

    Und Stride gibt die Anzahl der Bytes pro Bildzeile an - ist also abhängig sowohl von Höhe, Breite des Bildes, sowie vom Pixelformat.

    Ist es das, womit du arbeiten willst?
    @EdR: Jup, damit will/muss ich arbeiten!!

    Jetzt habe ich zwei Funktionen, die eine macht mir ein Byte() zum speichern der Daten, die andere soll des Array wieder zu nem Bild machen

    Bitmap to Byte (mit Tiles):
    Spoiler anzeigen

    Quellcode

    1. Private Function _BMPtoByte(ByVal _bmp As Bitmap) As Byte()
    2. ' Dim bmOut As Bitmap = New Bitmap(_bmp.Width, _bmp.Height, _bmp.PixelFormat)
    3. Dim pixelationAmount As Integer = 8
    4. ' store average of rgb
    5. Dim pixel As Color
    6. Dim x As Integer = 0
    7. Dim iPixelsInTile As Integer = pixelationAmount * pixelationAmount
    8. Dim _lbBMP As New LockBits(_bmp)
    9. _lbBMP.LockBits()
    10. Dim _byte(40000) As Byte
    11. While x < _lbBMP.Width
    12. Dim y As Integer = 0
    13. While y < _lbBMP.Height
    14. Dim bx As Integer = x + pixelationAmount
    15. Dim by As Integer = y + pixelationAmount
    16. If by >= _lbBMP.Height Then
    17. by = _lbBMP.Height
    18. End If
    19. If bx >= _lbBMP.Width Then
    20. bx = _lbBMP.Width
    21. End If
    22. Dim iCountMarkedPixelsInTile As Integer = 0
    23. For xx As Integer = x To bx - 1
    24. For yy As Integer = y To by - 1
    25. pixel = _lbBMP.GetPixel(xx, yy)
    26. If pixel.GetBrightness = 0 Then
    27. iCountMarkedPixelsInTile += 1
    28. End If
    29. Next
    30. Next
    31. Dim iPercent As Integer = CInt(Math.Round(100 / iPixelsInTile * iCountMarkedPixelsInTile, 0))
    32. For xx As Integer = x To bx - 1
    33. For yy As Integer = y To by - 1
    34. If iPercent >= 1 Then
    35. _byte(yy * _lbBMP.Width + xx) = 0
    36. Else
    37. _byte(yy * _lbBMP.Width + xx) = 255
    38. End If
    39. Next
    40. Next
    41. y += pixelationAmount
    42. End While
    43. x += pixelationAmount
    44. End While
    45. _lbBMP.UnlockBits()
    46. Return _byte
    47. End Function


    Byte to Bitmap:
    Spoiler anzeigen

    Quellcode

    1. Private Function _ByteToBMP(ByVal bytes As Byte()) As Bitmap
    2. Dim memStream As MemoryStream = New MemoryStream(bytes)
    3. Dim _bmp As Bitmap = New Bitmap(Image.FromStream(memStream))
    4. Return _bmp
    5. End Function



    Nur gibt die zweite Funktion den Fehler: Ungültiger Parameter

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

    Nee, bin nich zufrieden...
    ...ich kann ja auch nicht prüfen ob das Byte-Array korrekt ist weil die ByteToBitmap-Funktion ja nicht funktioniert!

    Die erste Funktion soll mir die Bytes auslesen und gleichzeitig das Bitmap "pixelieren", also in inem Rechteck von 8px den Schwarzwert messen und wenn Schwarz überwiegt die 8*8px schwarz machen!
    och die 2. Methode funktioniert. Man muss ihr nur ein Byte geben, aus einer Bitmap, die regulär in einen Stream abgespeichert wurde - dann kann sie das auch lesen.

    Aber ich hab eine neue Idee, was du wohl wollen magst:
    Du möchtest eine Bitmap rastern, und zwar in 8*8 - Raster.
    Da solltest du besser nicht von Tiles reden, denn Tiles sind was ganz anderes - das sind Teil-Ausschnitte einer Bitmap de.wikipedia.org/wiki/Kachelgrafik.

    Ich find, du hast ein erhebliches Problem, zu erklären, was du eiglich machen willst - seit drei tagen versuche ich das nun herauszubekommen, und sicher bin ich immer noch nicht.
    Hier habe ich jetzt etwas was funktioniert!

    Ich habe eine Form mit zwei PictureBoxes und einem Button:
    Spoiler anzeigen

    Quellcode

    1. ​Option Strict On
    2. Imports System.Drawing.Text
    3. Public Class Form1
    4. Dim _Pattern As String = "abcdefghijklmnopqrstuvwxyzäöüßABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ1234567890"
    5. Dim _FontCollection As New InstalledFontCollection() 'Installierte Fonts
    6. Dim sf As New StringFormat With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center} 'PictureBox Ausrichtug mittig setzen
    7. Dim middleBox As Size
    8. Private Sub bGO_Click(sender As Object, e As EventArgs) Handles bGO.Click
    9. _getFontCharBitmaps()
    10. End Sub
    11. Private Sub _getFontCharBitmaps()
    12. For Each _font As FontFamily In _FontCollection.Families
    13. Application.DoEvents()
    14. Dim tempFont As Font = Nothing
    15. If _font.IsStyleAvailable(FontStyle.Regular) Then
    16. tempFont = New Font(_font, 64, FontStyle.Regular)
    17. ElseIf _font.IsStyleAvailable(FontStyle.Bold) Then
    18. tempFont = New Font(_font, 64, FontStyle.Bold)
    19. ElseIf _font.IsStyleAvailable(FontStyle.Italic) Then
    20. tempFont = New Font(_font, 64, FontStyle.Italic)
    21. End If
    22. For Each _char As Char In _Pattern
    23. Application.DoEvents()
    24. If tempFont IsNot Nothing Then
    25. Dim _bmp As Bitmap = _draw(PictureBox1, _char, tempFont)
    26. PictureBox1.Image = _bmp
    27. PictureBox1.Refresh()
    28. PictureBox2.Image = _BMPpixel(_bmp)
    29. PictureBox2.Refresh()
    30. End If
    31. Next
    32. Next
    33. End Sub
    34. Public Function _draw(ByVal _pb1 As PictureBox, ByVal _string As String, ByVal _actFont As Font) As Bitmap
    35. Dim img = New Bitmap(_pb1.Width, _pb1.Height, Imaging.PixelFormat.Format32bppArgb)
    36. Dim gr As Graphics = Graphics.FromImage(img)
    37. middleBox = New Size(CInt(_pb1.Width / 2), CInt(_pb1.Height / 2))
    38. gr.Clear(Color.White) '(_pb1.BackColor)
    39. Try
    40. gr.DrawString(_string, _actFont, Brushes.Black, middleBox.Width, middleBox.Height, sf)
    41. Catch ex As Exception
    42. End Try
    43. gr.Dispose()
    44. Return img
    45. End Function
    46. Private Function _BMPpixel(ByVal _bmp As Bitmap) As Bitmap
    47. Dim bmOut As Bitmap = New Bitmap(_bmp.Width, _bmp.Height, _bmp.PixelFormat)
    48. Dim pixelationAmount As Integer = 8
    49. Dim pixel As Color
    50. Dim x As Integer = 0
    51. Dim iPixelsInTile As Integer = pixelationAmount * pixelationAmount
    52. While x < _bmp.Width
    53. Dim y As Integer = 0
    54. While y < _bmp.Height
    55. Dim bx As Integer = x + pixelationAmount
    56. Dim by As Integer = y + pixelationAmount
    57. If by >= _bmp.Height Then
    58. by = _bmp.Height
    59. End If
    60. If bx >= _bmp.Width Then
    61. bx = _bmp.Width
    62. End If
    63. Dim iCountMarkedPixelsInTile As Integer = 0
    64. For xx As Integer = x To bx - 1
    65. For yy As Integer = y To by - 1
    66. pixel = _bmp.GetPixel(xx, yy)
    67. If pixel.GetBrightness = 0 Then
    68. iCountMarkedPixelsInTile += 1
    69. End If
    70. Next
    71. Next
    72. Dim iPercent As Integer = CInt(Math.Round(100 / iPixelsInTile * iCountMarkedPixelsInTile, 0))
    73. For xx As Integer = x To bx - 1
    74. For yy As Integer = y To by - 1
    75. If iPercent >= 1 Then
    76. bmOut.SetPixel(xx, yy, Color.Black)
    77. Else
    78. bmOut.SetPixel(xx, yy, Color.White)
    79. End If
    80. Next
    81. Next
    82. y += pixelationAmount
    83. End While
    84. x += pixelationAmount
    85. End While
    86. Return bmOut
    87. End Function
    88. End Class


    In der ersten PB ist das Originalbild und in PB2 das Ergebnis!
    Nur möchte ich als Ausgabe kein Bitmap haben sondern ein Byte()!
    Also so sollte das eigentlich aussehen...nun feil ich das nochn bissl Rund!!

    Spoiler anzeigen

    VB.NET-Quellcode

    1. ​Option Strict On
    2. Imports System.Drawing.Imaging
    3. Imports System.Drawing.Text
    4. Public Class Form1
    5. Dim _Pattern As String = "abcdefghijklmnopqrstuvwxyzäöüßABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ1234567890"
    6. Dim _FontCollection As New InstalledFontCollection() 'Installierte Fonts
    7. Dim sf As New StringFormat With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center} 'PictureBox Ausrichtug mittig setzen
    8. Dim middleBox As Size
    9. Private Sub bGO_Click(sender As Object, e As EventArgs) Handles bGO.Click
    10. _getFontCharBitmaps()
    11. End Sub
    12. Private Sub _getFontCharBitmaps()
    13. For Each _font As FontFamily In _FontCollection.Families
    14. Application.DoEvents()
    15. Dim tempFont As Font = Nothing
    16. If _font.IsStyleAvailable(FontStyle.Regular) Then
    17. tempFont = New Font(_font, 72, FontStyle.Regular)
    18. ElseIf _font.IsStyleAvailable(FontStyle.Bold) Then
    19. tempFont = New Font(_font, 72, FontStyle.Bold)
    20. ElseIf _font.IsStyleAvailable(FontStyle.Italic) Then
    21. tempFont = New Font(_font, 72, FontStyle.Italic)
    22. End If
    23. For Each _char As Char In _Pattern
    24. Application.DoEvents()
    25. If tempFont IsNot Nothing Then
    26. Dim _bmp As Bitmap = _draw(PictureBox1, _char, tempFont)
    27. PictureBox1.Image = _getRect(_bmp)
    28. PictureBox1.Refresh()
    29. Dim _bool As Boolean()() = Image2Bool(_bmp)
    30. Dim _bbmp As Bitmap = CType(Bool2Image(ZhangSuenThinning(_bool)), Bitmap) '_BMPpixel(CType(Bool2Image(ZhangSuenThinning(_bool)), Bitmap))
    31. PictureBox2.Image = _getRect(_bbmp)
    32. PictureBox2.Refresh()
    33. End If
    34. Next
    35. Next
    36. End Sub
    37. Public Function _draw(ByVal _pb1 As PictureBox, ByVal _string As String, ByVal _actFont As Font) As Bitmap
    38. Dim img = New Bitmap(_pb1.Width, _pb1.Height, Imaging.PixelFormat.Format32bppArgb)
    39. Dim gr As Graphics = Graphics.FromImage(img)
    40. middleBox = New Size(CInt(_pb1.Width / 2), CInt(_pb1.Height / 2))
    41. gr.Clear(Color.White) '(_pb1.BackColor)
    42. Try
    43. gr.DrawString(_string, _actFont, Brushes.Black, middleBox.Width, middleBox.Height, sf)
    44. Catch ex As Exception
    45. End Try
    46. gr.Dispose()
    47. Return img
    48. End Function
    49. Private Function _BMPpixel(ByVal _bmp As Bitmap) As Bitmap
    50. Dim bmOut As Bitmap = New Bitmap(_bmp.Width, _bmp.Height, _bmp.PixelFormat)
    51. Dim pixelationAmount As Integer = 4
    52. Dim pixel As Color
    53. Dim x As Integer = 0
    54. Dim iPixelsInTile As Integer = pixelationAmount * pixelationAmount
    55. Dim _lbIn As New LockBits(_bmp)
    56. Dim _lbOut As New LockBits(bmOut)
    57. _lbIn.LockBits()
    58. _lbOut.LockBits()
    59. While x < _lbIn.Width
    60. Dim y As Integer = 0
    61. While y < _lbIn.Height
    62. Dim bx As Integer = x + pixelationAmount
    63. Dim by As Integer = y + pixelationAmount
    64. If by >= _lbIn.Height Then
    65. by = _lbIn.Height
    66. End If
    67. If bx >= _lbIn.Width Then
    68. bx = _lbIn.Width
    69. End If
    70. Dim iCountMarkedPixelsInTile As Integer = 0
    71. For xx As Integer = x To bx - 1
    72. For yy As Integer = y To by - 1
    73. pixel = _lbIn.GetPixel(xx, yy)
    74. If pixel.GetBrightness = 0 Then
    75. iCountMarkedPixelsInTile += 1
    76. End If
    77. Next
    78. Next
    79. Dim iPercent As Integer = CInt(Math.Round(100 / iPixelsInTile * iCountMarkedPixelsInTile, 0))
    80. For xx As Integer = x To bx - 1
    81. For yy As Integer = y To by - 1
    82. If iPercent >= 1 Then
    83. _lbOut.SetPixel(xx, yy, Color.Black)
    84. Else
    85. _lbOut.SetPixel(xx, yy, Color.White)
    86. End If
    87. Next
    88. Next
    89. y += pixelationAmount
    90. End While
    91. x += pixelationAmount
    92. End While
    93. _lbIn.UnlockBits()
    94. _lbOut.UnlockBits()
    95. Return bmOut
    96. End Function
    97. Public Shared Function _getRect(ByVal bmp As Bitmap) As Bitmap
    98. Dim xCropLeft As Integer = -1
    99. Dim xCropRight As Integer = -1
    100. Dim yCropTop As Integer = -1
    101. Dim yCropBottom As Integer = -1
    102. Dim bEnd As Boolean = False
    103. Dim _lbBMP As New LockBits(bmp)
    104. _lbBMP.LockBits()
    105. For x = 0 To _lbBMP.Width - 1
    106. For y = 0 To _lbBMP.Height - 1
    107. If _lbBMP.GetPixel(x, y).GetBrightness = 0 Then 'Erstes schwarz von links
    108. If xCropLeft = -1 Then
    109. xCropLeft = x
    110. bEnd = True
    111. Exit For
    112. End If
    113. End If
    114. Next
    115. If bEnd = True Then
    116. Exit For
    117. End If
    118. Next
    119. bEnd = False
    120. For x = _lbBMP.Width - 1 To 0 Step -1
    121. For y = 0 To _lbBMP.Height - 1
    122. If _lbBMP.GetPixel(x, y).GetBrightness = 0 Then 'Erstes schwarz von rechts
    123. If xCropRight = -1 Then
    124. xCropRight = x
    125. bEnd = True
    126. Exit For
    127. End If
    128. End If
    129. Next
    130. If bEnd = True Then
    131. Exit For
    132. End If
    133. Next
    134. bEnd = False
    135. For y = 0 To _lbBMP.Height - 1
    136. For x = 0 To _lbBMP.Width - 1
    137. If _lbBMP.GetPixel(x, y).GetBrightness = 0 Then 'Erstes schwarz von oben
    138. If yCropTop = -1 Then
    139. yCropTop = y
    140. bEnd = True
    141. Exit For
    142. End If
    143. End If
    144. Next
    145. If bEnd = True Then
    146. Exit For
    147. End If
    148. Next
    149. bEnd = False
    150. For y = _lbBMP.Height - 1 To 0 Step -1
    151. For x = 0 To _lbBMP.Width - 1
    152. If _lbBMP.GetPixel(x, y).GetBrightness = 0 Then 'Erstes schwarz von unten
    153. If yCropBottom = -1 Then
    154. yCropBottom = y
    155. bEnd = True
    156. Exit For
    157. End If
    158. End If
    159. Next
    160. If bEnd = True Then
    161. Exit For
    162. End If
    163. Next
    164. Dim _rect As New Rectangle(xCropLeft, yCropTop, xCropRight - xCropLeft + 0, yCropBottom - yCropTop + 0)
    165. _lbBMP.UnlockBits()
    166. Dim bmpScaled As Bitmap = New Bitmap(150, 150) '' Wenn gezeichnetes Bitmap gleich null tritt exeption auf!!!
    167. Using grp = Graphics.FromImage(bmpScaled)
    168. grp.DrawImage(bmp, New Rectangle(0, 0, 150, 150), _rect, GraphicsUnit.Pixel)
    169. End Using
    170. Return bmpScaled
    171. End Function
    172. Public Shared Function Image2Bool(img As Image) As Boolean()()
    173. 'Dim bmp As New Bitmap(img)
    174. Dim bmp As New LockBits(CType(img, Bitmap))
    175. bmp.LockBits()
    176. Dim s As Boolean()() = New Boolean(bmp.Height - 1)() {}
    177. For y As Integer = 0 To bmp.Height - 1
    178. s(y) = New Boolean(bmp.Width - 1) {}
    179. For x As Integer = 0 To bmp.Width - 1
    180. s(y)(x) = bmp.GetPixel(x, y).GetBrightness() < 0.3
    181. Next
    182. Next
    183. bmp.UnlockBits()
    184. Return s
    185. End Function
    186. Public Shared Function Bool2Image(s As Boolean()()) As Image
    187. Dim bmp As New Bitmap(s(0).Length, s.Length)
    188. Using g As Graphics = Graphics.FromImage(bmp)
    189. g.Clear(Color.White)
    190. End Using
    191. Dim _LB As New LockBits(bmp)
    192. _LB.LockBits()
    193. For y As Integer = 0 To _LB.Height - 1
    194. For x As Integer = 0 To _LB.Width - 1
    195. If s(y)(x) Then
    196. _LB.SetPixel(x, y, Color.Black)
    197. End If
    198. Next
    199. Next
    200. _LB.UnlockBits()
    201. Return DirectCast(bmp, Bitmap)
    202. End Function
    203. Public Shared Function ZhangSuenThinning(s As Boolean()()) As Boolean()()
    204. Dim temp As Boolean()() = ArrayClone(s)
    205. ' make a deep copy to start..
    206. Dim count As Integer = 0
    207. Do
    208. ' the missing iteration
    209. count = [step](1, temp, s)
    210. temp = ArrayClone(s)
    211. ' ..and on each..
    212. count += [step](2, temp, s)
    213. ' ..call!
    214. temp = ArrayClone(s)
    215. Loop While count > 0
    216. Return s
    217. End Function
    218. Private Shared Function [step](stepNo As Integer, temp As Boolean()(), s As Boolean()()) As Integer
    219. Dim count As Integer = 0
    220. For a As Integer = 1 To temp.Length - 2
    221. For b As Integer = 1 To temp(0).Length - 2
    222. If SuenThinningAlg(a, b, temp, stepNo = 2) Then
    223. ' still changes happening?
    224. If s(a)(b) Then
    225. count += 1
    226. End If
    227. s(a)(b) = False
    228. End If
    229. Next
    230. Next
    231. Return count
    232. End Function
    233. Private Shared Function SuenThinningAlg(x As Integer, y As Integer, s As Boolean()(), even As Boolean) As Boolean
    234. Dim p2 As Boolean = s(x)(y - 1)
    235. Dim p3 As Boolean = s(x + 1)(y - 1)
    236. Dim p4 As Boolean = s(x + 1)(y)
    237. Dim p5 As Boolean = s(x + 1)(y + 1)
    238. Dim p6 As Boolean = s(x)(y + 1)
    239. Dim p7 As Boolean = s(x - 1)(y + 1)
    240. Dim p8 As Boolean = s(x - 1)(y)
    241. Dim p9 As Boolean = s(x - 1)(y - 1)
    242. Dim bp1 As Integer = NumberOfNonZeroNeighbors(x, y, s)
    243. If bp1 >= 2 AndAlso bp1 <= 6 Then
    244. '2nd condition
    245. If NumberOfZeroToOneTransitionFromP9(x, y, s) = 1 Then
    246. If even Then
    247. If Not ((p2 AndAlso p4) AndAlso p8) Then
    248. If Not ((p2 AndAlso p6) AndAlso p8) Then
    249. Return True
    250. End If
    251. End If
    252. Else
    253. If Not ((p2 AndAlso p4) AndAlso p6) Then
    254. If Not ((p4 AndAlso p6) AndAlso p8) Then
    255. Return True
    256. End If
    257. End If
    258. End If
    259. End If
    260. End If
    261. Return False
    262. End Function
    263. Private Shared Function NumberOfZeroToOneTransitionFromP9(x As Integer, y As Integer, s As Boolean()()) As Integer
    264. Dim p2 As Boolean = s(x)(y - 1)
    265. Dim p3 As Boolean = s(x + 1)(y - 1)
    266. Dim p4 As Boolean = s(x + 1)(y)
    267. Dim p5 As Boolean = s(x + 1)(y + 1)
    268. Dim p6 As Boolean = s(x)(y + 1)
    269. Dim p7 As Boolean = s(x - 1)(y + 1)
    270. Dim p8 As Boolean = s(x - 1)(y)
    271. Dim p9 As Boolean = s(x - 1)(y - 1)
    272. Dim A As Integer = Convert.ToInt32((Not p2 AndAlso p3)) + Convert.ToInt32((Not p3 AndAlso p4)) + Convert.ToInt32((Not p4 AndAlso p5)) + Convert.ToInt32((Not p5 AndAlso p6)) + Convert.ToInt32((Not p6 AndAlso p7)) + Convert.ToInt32((Not p7 AndAlso p8)) + Convert.ToInt32((Not p8 AndAlso p9)) + Convert.ToInt32((Not p9 AndAlso p2))
    273. Return A
    274. End Function
    275. Private Shared Function NumberOfNonZeroNeighbors(x As Integer, y As Integer, s As Boolean()()) As Integer
    276. Dim count As Integer = 0
    277. If s(x - 1)(y) Then
    278. count += 1
    279. End If
    280. If s(x - 1)(y + 1) Then
    281. count += 1
    282. End If
    283. If s(x - 1)(y - 1) Then
    284. count += 1
    285. End If
    286. If s(x)(y + 1) Then
    287. count += 1
    288. End If
    289. If s(x)(y - 1) Then
    290. count += 1
    291. End If
    292. If s(x + 1)(y) Then
    293. count += 1
    294. End If
    295. If s(x + 1)(y + 1) Then
    296. count += 1
    297. End If
    298. If s(x + 1)(y - 1) Then
    299. count += 1
    300. End If
    301. Return count
    302. End Function
    303. Public Shared Function ArrayClone(Of T)(A__1 As T()()) As T()()
    304. Return A__1.[Select](Function(a__2) a__2.ToArray()).ToArray()
    305. End Function
    306. Public Function getPointerTo(ByRef obj As Object) As Object
    307. Return obj
    308. End Function
    309. End Class


    LockBits-Klasse:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Drawing.Imaging
    2. Imports System.Runtime.InteropServices
    3. Public Class LockBits
    4. Implements IDisposable
    5. Private source As Bitmap = Nothing
    6. Private Iptr As IntPtr = IntPtr.Zero
    7. Private bitmapData As BitmapData = Nothing
    8. Private m_Pixels As Byte()
    9. Private m_Depth As Integer
    10. Private m_Width As Integer
    11. Private m_Height As Integer
    12. Public Property Pixels() As Byte()
    13. Get
    14. Return m_Pixels
    15. End Get
    16. Set(value As Byte())
    17. m_Pixels = value
    18. End Set
    19. End Property
    20. Public Property _BitmapData() As BitmapData
    21. Get
    22. Return bitmapData
    23. End Get
    24. Set(value As BitmapData)
    25. bitmapData = value
    26. End Set
    27. End Property
    28. Private Property Depth() As Integer
    29. Get
    30. Return m_Depth
    31. End Get
    32. Set(value As Integer)
    33. m_Depth = value
    34. End Set
    35. End Property
    36. Public Property Width() As Integer
    37. Get
    38. Return m_Width
    39. End Get
    40. Set(value As Integer)
    41. m_Width = value
    42. End Set
    43. End Property
    44. Public Property Height() As Integer
    45. Get
    46. Return m_Height
    47. End Get
    48. Set(value As Integer)
    49. m_Height = value
    50. End Set
    51. End Property
    52. Public ReadOnly Property Bitmap() As Bitmap
    53. Get
    54. Return source
    55. End Get
    56. End Property
    57. Public Sub New(source As Bitmap)
    58. Me.source = source
    59. End Sub
    60. ''' <summary>
    61. ''' Lock bitmap data
    62. ''' </summary>
    63. Public Sub LockBits()
    64. Try
    65. ' Get width and height of bitmap
    66. Width = source.Width
    67. Height = source.Height
    68. ' get total locked pixels count
    69. Dim PixelCount As Integer = Width * Height
    70. ' Create rectangle to lock
    71. Dim rect As New Rectangle(0, 0, Width, Height)
    72. ' get source bitmap pixel format size
    73. Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat)
    74. ' Check if bpp (Bits Per Pixel) is 8, 24, or 32
    75. If Depth <> 8 AndAlso Depth <> 24 AndAlso Depth <> 32 Then
    76. Throw New ArgumentException("Only 8, 24 and 32 bpp images are supported.")
    77. End If
    78. ' Lock bitmap and return bitmap data
    79. bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite, source.PixelFormat)
    80. 'Debug.WriteLine(bitmapData.Stride)
    81. ' create byte array to copy pixel values
    82. Dim [step] As Integer = Depth \ 8
    83. Pixels = New Byte(PixelCount * [step] - 1) {}
    84. Iptr = bitmapData.Scan0
    85. ' Copy data from pointer to array
    86. Marshal.Copy(Iptr, Pixels, 0, Pixels.Length)
    87. Catch ex As Exception
    88. Debug.WriteLine(ex.Message)
    89. End Try
    90. End Sub
    91. ''' <summary>
    92. ''' Unlock bitmap data
    93. ''' </summary>
    94. Public Sub UnlockBits()
    95. Try
    96. ' Copy data from byte array to pointer
    97. Marshal.Copy(Pixels, 0, Iptr, Pixels.Length)
    98. ' Unlock bitmap data
    99. source.UnlockBits(bitmapData)
    100. Catch ex As Exception
    101. Debug.WriteLine(ex.Message)
    102. End Try
    103. End Sub
    104. ''' <summary>
    105. ''' Get the color of the specified pixel
    106. ''' </summary>
    107. ''' <param name="x"></param>
    108. ''' <param name="y"></param>
    109. ''' <returns></returns>
    110. Public Function GetPixel(x As Integer, y As Integer) As Color
    111. Dim clr As Color = Color.Empty
    112. ' Get color components count
    113. Dim cCount As Integer = Depth \ 8
    114. ' Get start index of the specified pixel
    115. Dim i As Integer = ((y * Width) + x) * cCount
    116. If i > Pixels.Length - cCount Then
    117. Throw New IndexOutOfRangeException()
    118. End If
    119. If Depth = 32 Then
    120. ' For 32 bpp get Red, Green, Blue and Alpha
    121. Dim b As Byte = Pixels(i)
    122. Dim g As Byte = Pixels(i + 1)
    123. Dim r As Byte = Pixels(i + 2)
    124. Dim a As Byte = Pixels(i + 3)
    125. ' a
    126. clr = Color.FromArgb(a, r, g, b)
    127. End If
    128. If Depth = 24 Then
    129. ' For 24 bpp get Red, Green and Blue
    130. Dim b As Byte = Pixels(i)
    131. Dim g As Byte = Pixels(i + 1)
    132. Dim r As Byte = Pixels(i + 2)
    133. clr = Color.FromArgb(r, g, b)
    134. End If
    135. If Depth = 8 Then
    136. ' For 8 bpp get color value (Red, Green and Blue values are the same)
    137. Dim c As Byte = Pixels(i)
    138. clr = Color.FromArgb(c, c, c)
    139. End If
    140. Return clr
    141. End Function
    142. ''' <summary>
    143. ''' Set the color of the specified pixel
    144. ''' </summary>
    145. ''' <param name="x"></param>
    146. ''' <param name="y"></param>
    147. ''' <param name="color"></param>
    148. Public Sub SetPixel(x As Integer, y As Integer, color As Color)
    149. ' Get color components count
    150. Dim cCount As Integer = Depth \ 8
    151. ' Get start index of the specified pixel
    152. Dim i As Integer = ((y * Width) + x) * cCount
    153. If Depth = 32 Then
    154. ' For 32 bpp set Red, Green, Blue and Alpha
    155. Pixels(i) = color.B
    156. Pixels(i + 1) = color.G
    157. Pixels(i + 2) = color.R
    158. Pixels(i + 3) = color.A
    159. End If
    160. If Depth = 24 Then
    161. ' For 24 bpp set Red, Green and Blue
    162. Pixels(i) = color.B
    163. Pixels(i + 1) = color.G
    164. Pixels(i + 2) = color.R
    165. End If
    166. If Depth = 8 Then
    167. ' For 8 bpp set color value (Red, Green and Blue values are the same)
    168. Pixels(i) = color.B
    169. End If
    170. End Sub
    171. #Region "IDisposable Support"
    172. Private disposedValue As Boolean ' So ermitteln Sie überflüssige Aufrufe
    173. ' IDisposable
    174. Protected Overridable Sub Dispose(disposing As Boolean)
    175. If Not Me.disposedValue Then
    176. If disposing Then
    177. ' TODO: Verwalteten Zustand löschen (verwaltete Objekte).
    178. End If
    179. ' TODO: Nicht verwaltete Ressourcen (nicht verwaltete Objekte) freigeben und Finalize() unten überschreiben.
    180. ' TODO: Große Felder auf NULL festlegen.
    181. End If
    182. Me.disposedValue = True
    183. End Sub
    184. ' TODO: Finalize() nur überschreiben, wenn Dispose(ByVal disposing As Boolean) oben über Code zum Freigeben von nicht verwalteten Ressourcen verfügt.
    185. 'Protected Overrides Sub Finalize()
    186. ' ' Ändern Sie diesen Code nicht. Fügen Sie oben in Dispose(ByVal disposing As Boolean) Bereinigungscode ein.
    187. ' Dispose(False)
    188. ' MyBase.Finalize()
    189. 'End Sub
    190. ' Dieser Code wird von Visual Basic hinzugefügt, um das Dispose-Muster richtig zu implementieren.
    191. Public Sub Dispose() Implements IDisposable.Dispose
    192. ' Ändern Sie diesen Code nicht. Fügen Sie oben in Dispose(disposing As Boolean) Bereinigungscode ein.
    193. Dispose(True)
    194. GC.SuppressFinalize(Me)
    195. End Sub
    196. #End Region
    197. End Class

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