.jpg Bild spiegeln

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

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von Peter329.

    .jpg Bild spiegeln

    Hi,

    aus irgendeinem Grund krieg ich immer wieder von Leuten .jpg Dateien geschickt, die "seitenverkehrt" sind. Warum auch immer das so ist.

    Natürlich kann ich die Bildchen mit meinem Grafik Editor spiegeln. Aber das ist halt auf Dauer ziemlich lästig.

    Weiß jemand, wie man mit VB auf einfache Weise in einer .jpg Datei links und rechts vertauschen kann ?

    LG
    Peter

    *Topic verschoben*

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Yeeeehhhaaaaa ... ! Danke!

    Das ist ja wunderbar ... damit kann ich die pics nicht nur spiegeln, sondern auch drehen ... Und das ist eine Funktionalität, die ich durchaus auch benötige, obwohl ich das bisher noch gar nicht angesprochen habe.

    So sieht mein Coding jetzt aus:

    VB.NET-Quellcode

    1. Private Sub cmdLoad2_Click(sender As Object, e As EventArgs) Handles cmdLoad2.Click
    2. lblMessage.Text = ""
    3. If Not File.Exists(strObject) Then
    4. lblMessage.Text = strObject & " does not exist"
    5. Exit Sub
    6. End If
    7. Try
    8. bitmap1 = CType(Bitmap.FromFile(strObject), Bitmap)
    9. PictureBox1.SizeMode = PictureBoxSizeMode.Zoom
    10. PictureBox1.Image = bitmap1
    11. Catch ex As System.IO.FileNotFoundException
    12. MessageBox.Show("Load failed: " & ex.Message)
    13. Exit Sub
    14. End Try
    15. End Sub
    16. Private Sub cmdRotateRight_Click(sender As Object, e As EventArgs) Handles cmdRotateRight.Click
    17. lblMessage.Text = ""
    18. If bitmap1 IsNot Nothing Then
    19. bitmap1.RotateFlip(RotateFlipType.Rotate90FlipNone)
    20. PictureBox1.Image = bitmap1
    21. Else
    22. lblMessage.Text = "BITMAP1 does not exist"
    23. End If
    24. End Sub
    25. Private Sub cmdRotateLeft_Click(sender As Object, e As EventArgs) Handles cmdRotateLeft.Click
    26. lblMessage.Text = ""
    27. If bitmap1 IsNot Nothing Then
    28. bitmap1.RotateFlip(RotateFlipType.Rotate270FlipNone)
    29. PictureBox1.Image = bitmap1
    30. Else
    31. lblMessage.Text = "BITMAP1 does not exist"
    32. End If
    33. End Sub
    34. Private Sub cmdFlip_Click(sender As Object, e As EventArgs) Handles cmdFlip.Click
    35. lblMessage.Text = ""
    36. If bitmap1 IsNot Nothing Then
    37. bitmap1.RotateFlip(RotateFlipType.Rotate180FlipY)
    38. PictureBox1.Image = bitmap1
    39. Else
    40. lblMessage.Text = "BITMAP1 does not exist"
    41. End If
    42. End Sub
    43. Private Sub cmdSave_Click(sender As Object, e As EventArgs) Handles cmdSave.Click
    44. lblMessage.Text = "SAVE not implemented"
    45. End Sub


    Natürlich kann man den Code noch optimieren - aber das ist ja auch nur ein Test. Ansonsten klappt im Display alles soweit ganz prima! Die Speicherung habe ich bisher noch nicht in Angriff genommen.

    Bevor ich jetzt in dieser Richtung weiterarbeite: das Verfahren verlangt, dass ich meinen .jpg File in eine Bitmap konvertiere ... und dann muss ich das Dingens nach der Drehung/Spiegelung wieder in einen .jpg File zurück konvertieren. Wie sieht denn das mit Verlusten der Qualität aus ... ? Ist das zu vernachlässigen?

    Na, ich wäre gespannt auf eure Einschätzung. Oder auf Hinweise, wie man das Problem alternativ lösen kann.

    LG
    Peter

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

    Peter329 schrieb:

    das Verfahren verlangt, dass ich meinen .jpg File in eine Bitmap konvertiere

    Falls Du damit bitmap1 = CType(Bitmap.FromFile(strObject), Bitmap) meinst: Das passt schon so. "Bitmap" bedeutet einfach "ein 2-dimensionales Array von Pixeln". JPEG ist auch nur eines von vielen Bitmap-Formaten, so wie TGA, PNG, oder eben, und da wird die Verwirrung herkommen, BMP. "BMP" ist das "Microsoft Bitmap"-Fromat: de.wikipedia.org/wiki/Windows_Bitmap
    Das ist ein von Microsoft entwickeltes Bitmap-Fromat, und die haben es "Bitmap" genannt. Das ist, als würde man eine Programmiersprache entwickeln und sie "Programmiersprache" nennen. Bitmap.FromFile lädt einfach ein beliebiges Bitmap-Format und gibt Dir die Möglichkeit, mit den Rohdaten zu arbeiten.

    Jetzt sei aber folgendes gesagt: Wann immer Du Bilder als JPEG encodierst (das passiert, wenn Du bitmap1.Save("Datei.jpeg", ImageFormats.JPEG) aufrufst), dann gehen Daten verloren, weil JPEG eben ein verlustbehaftetes Format ist. Das heißt, da die Dateien ursprünglich schon mal als JPEG gespeichert wurden, ist damals auch Qualität verloren gegangen. Wenn Du jetzt nochmal als JPEG speicherst, dann geht wieder etwas Qualität verloren. Das macht bei Fotos üblicherweise nichts aus, aber es ist trotzdem gut, wenn man weiß, was passiert.
    Wenn Du nicht möchtest, dass noch mehr Qualität verloren geht, dann musst Du ein verlustfreies Format verwenden. Ich empfehle dazu generell PNG.

    Eine Sache noch: Es ist in .NET nicht üblich, Hungarian Notation zu verwenden. Meiner Meinung nach sieht es auch nicht schön aus.
    Gib Deinen Variablen/Methoden/Klassen stattdessen möglichst aussagekräftige Namen. Wenn man zum Beispiel strObject liest, weiß man nicht, wofür die Variable überhaupt gut sein soll. Stattdessen könnte man zum Beispiel ImageFilePath verwenden. Dann weiß man sofort, dass es sich um einen Dateipfad zu einem Bild handelt.

    Ah, und noch eine Sache: Statt Image.FromFile kannst Du New Bitmap verwenden. Warum das eine gute Idee ist, ist hier erklärt: GDI+ Bitmap Vergrößern -> Bitmap wird abgeschnitten
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Noch eine Anmerkung: Man kann JPEGs auch verlustfrei spiegeln und drehen. Wie das programmiertechnisch geht, kann ich euch nicht sagen, aber Programme wie z. B. IrfanView können das, also muss es irgendwie gehen. ;)
    Besucht auch mein anderes Forum:
    Das Amateurfilm-Forum

    Marcus Gräfe schrieb:

    Man kann JPEGs auch verlustfrei spiegeln und drehen.
    Das ist so nicht ganz korrekt.
    Eine JPG ist bereits verlustbehaftet komprimiert worden. Und man kann den Komprimierungsgrad vorgeben.
    Wenn so ein Bild im RAM ist, ist es bereits verlustbehaftet, allerdings ist die Weiterbearbeitung bis zum erneuten ggf. verlustbehafteten Abspeichern verlustfrei.
    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!
    Doch es ist wohl korrekt.
    Wie du bereits bemerkt hast bekommt man beim primitiven Spiegeln das Problem, dass beim erneuten Abspeichern als jpeg noch mehr vom Original verloren geht und bei primitiven Transformationen wie Rotationen um 90°*n oder Spiegelungen kann man dies verhindern, dazu muss man aber das ganze selbst in die Hand nehmen und die DCT Koeffizienten(sind bei JPEG mW auf 8x8 Pixel) selbst auslesen ohne, das Komplette Bild jemals Komplett zu decodieren. Diese muss man dann spiegeln und ebenfalls die Anordnung der einzelnen DCTs und neu abspeichern, dadurch erhält man komplett dieselben Pixelwerte als beim ursprünglichen Bild ohne durch Zusätzliche Kompression Informationen zu verlieren(schließlich wendet man keine Kompression mehr an, sondern arbeitet nur auf der bereits ursprünglich vorhandenen)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Es gibt auch noch die Möglichkeit, einfach die Metadaten des Bildes zu verändern.
    bitmap1.GetPropertyItem(274).Value(0) ist ein Wert, der angibt, wie das Bild gedreht ist.

    Quellcode

    1. 1 => RotateFlipType.RotateNoneFlipNone
    2. 2 => RotateFlipType.RotateNoneFlipX
    3. 3 => RotateFlipType.Rotate180FlipNone
    4. 4 => RotateFlipType.Rotate180FlipX
    5. 5 => RotateFlipType.Rotate90FlipX
    6. 6 => RotateFlipType.Rotate90FlipNone
    7. 7 => RotateFlipType.Rotate270FlipX

    Die Tabelle gilt beim Dekodieren. Das lässt sich sicher auch umdrehen. Aber ob Bitmap.Save die Daten nicht nochmal neu encodiert, sondern wirklich nur die Metadaten verändert, kann ich nicht sagen.
    Ich würde auch generell davon abraten, Bilder so zu drehen. Viele Programme beachten diese Metadaten nicht und dann wird das Bild plötzlich falsch rum angezeigt. Das passiert mir ständig, wenn ich Bilder anschaue, die ich mit meinem Handy gemacht habe.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Vielen Dank erst mal an die Ratgeber.

    Ich hab den Save jetzt so programmiert, dass man die "Quality" mit einem NumericUpDown einstellen kann:

    VB.NET-Quellcode

    1. Dim QualityLevel As Integer = NumericUpDown1.Value
    2. myEncoderParameter = New EncoderParameter(myEncoder, QualityLevel)
    3. myEncoderParameters.Param(0) = myEncoderParameter
    4. bitmap1.Save(strObject2, myImageCodecInfo, myEncoderParameters)


    Mit QualityLevel = 95 bleibt die Größe meiner .jpg Files in etwa erhalten ... Für andere Werte wird der File sehr viel kleiner bzw. sehr viel größer als der ursprüngliche File. Mit diesem Wert ist dann eigentlich auch mit heftigem Zoom kein Unterschied in der Qualität zwischen Original und der gedrehten / gespiegelten Version für mich ersichtlich. Selbst wenn man den Vorgang ein Dutzend Mal wiederholt (also den jeweils neuen File erneut in Folge weiterverarbeitet).

    Ich bin mit der Lösung jetzt sehr zufrieden. Deshalb werde ich wegen der damit verbundenen Risiken auch davon absehen, mit den Metadaten zu experimentieren.

    LG
    Peter