Bild zoomen ohne Qualitätsverlust

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

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von SidezockingLP.

    Bild zoomen ohne Qualitätsverlust

    Hey,

    Ich probiere ein sehr kleines Bild (16x16) zu zoomen (Also zoom um so auf 1500%). Mache ich das mit dem 'Strechimage' der Picturebox oder dem Code darunter wird das Bild sehr verschwommen. Photoshop und auch Paint bekommen es aber hin ohne Qualitätsverlust. Habt ihr vielleicht eine Idee mit welchem Ansatz man das lösen kann?

    Der Code:

    VB.NET-Quellcode

    1. Public Sub ZoomImage(ByRef ZoomValue As Int32)
    2. If original Is Nothing Then
    3. Exit Sub
    4. End If
    5. Dim zoomImage As New Bitmap(original,
    6. (Convert.ToInt32(original.Width * (ZoomValue) / 100)),
    7. (Convert.ToInt32(original.Height * (ZoomValue / 100))))
    8. Dim converted As Graphics = Graphics.FromImage(zoomImage)
    9. converted.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
    10. Pic.Image = Nothing 'Display PicBox
    11. Pic.Image = zoomImage
    12. End Sub


    Noch etwas: Bei Bild Photoshop sieht man weiße Streifen die die 'einzelnen' Pixel abgrenzen. Wie geht denn sowas?
    Hoffe ihr wisst Rat :)
    Bilder
    • paint.PNG

      65,69 kB, 570×634, 92 mal angesehen
    • photoshop.PNG

      21,89 kB, 650×660, 81 mal angesehen
    • prog.PNG

      49,36 kB, 428×341, 81 mal angesehen
    Definiere "Qualitätsverlust". Für die meisten ist das gezeigte Photoshop-/Paint-Ergebnis Qualitätsverlust, da alles pixelig aussieht.
    Dein Resultat ergibt sich durch Deine Zeile converted.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic. Ändere den Interpolationsmodus ab (probier mal System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic.Default), dann sollte es passen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Ich kenne mich mit den Interpolationsmöglichkeiten von .NET nicht aus, aber bei 8-Bit Bildern verwendet man normal NearestNeighbor Interpolation. So werden nebeneinander stehende Pixel einfach dupliziert beim Skalieren. Bei Bilinear oder Bicubic wird eine 2D-lineare oder 2D-kubische Funktion beim Skalieren auf die Pixel angewendet um einen "smoothen" Übergang zu bekommen, was normalerweise als qualitativer angesehen wird (außer halt bei Pixel-Art).


    LG

    EDIT: Habe nochmal geschaut, es gibt tatsächlich den Modus: Drawing2D.InterpolationMode.NearestNeighbor
    @VaporiZed
    Für die meisten ist das gezeigte Photoshop-/Paint-Ergebnis Qualitätsverlust, da alles pixelig aussieht.
    Das bild ist ja nur 16x16 Pixel groß. Ob das jetzt Q-Verlust ist oder nicht weiß ich nicht, es währe aber schöner wenn es wie im Photoshop-/Paint-Ergebnis aussieht. Denn möchte man es bearbeiten, will man dieses ganze 'Rechteck', diesen 'einen' Pixel gleich einfärben, dafür ist es besser wenn man die Rechtecke erkennen kann als wie bei meinem Ergebnissen wo die Farben übergängig sind.
    @xd-franky-5
    Danke für die Erklärung.
    Mit

    Quellcode

    1. HighQualityBicubic.Default
    oder

    Quellcode

    1. InterpolationMode.NearestNeighbor
    ist kein unterschied erkennbar.

    VB.NET-Quellcode

    1. Public Sub ZoomImage(ByRef ZoomValue As Int32)
    2. If original Is Nothing Then
    3. Exit Sub
    4. End If
    5. Dim zoomImage As New Bitmap(original,
    6. (Convert.ToInt32(original.Width * (ZoomValue) / 100)),
    7. (Convert.ToInt32(original.Height * (ZoomValue / 100))))
    8. Dim converted As Graphics = Graphics.FromImage(zoomImage)
    9. converted.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor
    10. Pic.Image = Nothing 'Display PicBox
    11. Pic.Image = zoomImage
    12. End Sub
    Du verwendest schließlich das graphics Objekt auch nicht zum skalieren. Verwende die Bitmap Überladung die nur width und height nimmt und zeichne dein bild über Graphics.DrawImage
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @jvbsl Danke für die Idee :)
    So gehts:

    VB.NET-Quellcode

    1. Public Sub ZoomImage(ByRef ZoomValue As Int32)
    2. If original Is Nothing Then
    3. Exit Sub
    4. End If
    5. Dim newwidth As Integer = original.Width * (ZoomValue) / 100
    6. Dim newheight As Integer = original.Height * (ZoomValue / 100)
    7. Dim oImage As New Bitmap(newwidth, newheight)
    8. Using g As Graphics = Graphics.FromImage(oImage)
    9. g.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
    10. g.DrawImage(original, New Rectangle(0, 0, newwidth, newheight))
    11. End Using
    12. Pic.Image = Nothing 'Display PicBox
    13. Pic.Image = oImage
    14. End Sub


    Noch Verbesserungsvorschläge ?
    Ahhh, ich werde wahnsinnig :/ Ich habe ja gesagt "es geht", naja nur so halb wie ich gerade festgestellt habe. Links unten im Bild wird einfach was abgeschnitten ???! Habe im Anhang ein Vergleichsbild zwischen meinem Programm und einem anderen. Wo die Pfeile sind ist der Fehler.

    Hier ist der Code:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    3. Me.Load_Pic("nepng")
    4. End Sub
    5. Public original As Bitmap
    6. Public akt_zoom As Integer
    7. Public Sub Load_Pic(file As String)
    8. Me.Show()
    9. If Not (Pic.Image Is Nothing) Then
    10. Pic.Image.Dispose()
    11. Pic.Image = Nothing
    12. End If
    13. Dim myStream As System.IO.FileStream = New System.IO.FileStream(file, IO.FileMode.Open)
    14. Dim myImage As Bitmap = Image.FromStream(myStream)
    15. myStream.Close()
    16. original = myImage
    17. Pic.Image = original
    18. End Sub
    19. Public Sub ZoomImage(ByRef ZoomValue As Int32)
    20. If original Is Nothing Then
    21. Exit Sub
    22. End If
    23. Dim newwidth As Integer = original.Width * (ZoomValue) / 100
    24. Dim newheight As Integer = original.Height * (ZoomValue / 100)
    25. Dim oImage As New Bitmap(newwidth, newheight)
    26. Using g As Graphics = Graphics.FromImage(oImage)
    27. g.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
    28. g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed
    29. g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality
    30. g.DrawImage(original, New Rectangle(0, 0, newwidth, newheight))
    31. End Using
    32. Pic.Image = Nothing 'Display PicBox
    33. Pic.Image = oImage
    34. akt_zoom = ZoomValue
    35. End Sub
    36. Private Sub Pic_MouseWheel(sender As Object, e As MouseEventArgs) Handles Pic.MouseWheel
    37. If e.Delta > -1 Then
    38. If akt_zoom < 2000 Then
    39. ZoomImage(akt_zoom + 100)
    40. End If
    41. Else
    42. If akt_zoom > 100 Then
    43. ZoomImage(akt_zoom - 100)
    44. ElseIf akt_zoom > 10 Then
    45. ZoomImage(akt_zoom - 10)
    46. End If
    47. End If
    48. End Sub
    49. End Class


    Weiß jemand was da Falsch läuft?
    Im Anhang auch noch das Bild das ich Laden möchte falls es jemand Debuggen möchte.
    PS: Die Picturebox ist Centerimage falls das wichtig ist.

    LG
    Bilder
    • Fehler.PNG

      53,33 kB, 1.181×508, 71 mal angesehen
    • diamond_sword.png

      344 Byte, 16×16, 268 mal angesehen
    Jetzt mal kurz so vor'm Einschlafen:

    VB.NET-Quellcode

    1. Dim oImage As New Bitmap(newwidth, newheight)
    2. [...]
    3. g.DrawImage(original, New Rectangle(0, 0, newwidth, newheight))
    Das passt m.E. nicht. Wenn newWidth = 1 wäre, dann ginge das Bild bei der X-Koordinate von 0 bis 0.
    Aber in der g.DrawImage-Zeile gehst Du von 0 bis newWidth, also von 0 bis 1, was einer Breite von 2 Pixeln entspricht. Die deklarierte Breite ist m.E. falsch.
    Und Höhe genauso.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @SidezockingLP Wenn Du Manipulationen am Bild (Größe, ...) vornimmst, speichere es ab, solange Du darqan entwickelst und überzeuge Dich, dass das, was da rauskommt, das ist, was rauskommen soll.
    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!
    @VaporiZed Meinst du so:?

    VB.NET-Quellcode

    1. Dim oImage As New Bitmap(newwidth + 1, newheight + 1)

    So ändert sich leider nichts :/

    @RodFromGermany Hab das Bild jetzt immer gespeichert und angeschaut. Laden tut es richtig, ab dem ersten Zoomvorgang besteht der Fehler durchgehend

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

    @SidezockingLP Mach mal ein neues kleines Projekt, das den Effekt reproduziert und hänge es an.
    ZIP, bereinigt - ohne bin- und obj-Verzeichnis.
    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!