Max: JPEG-Bilder verlustfrei drehen (on-the-fly)

Hallo,

gibt es eine Möglichkeit, dass man Bilder im JPEG-Format mit PHP verlustfrei dreht? Also direkt über PHP aufrufen, dann drehen (immer nur 90-Grad-Winkel) und wieder abspeichern? Die Abmessung der Bilder sind immer ein Vielfaches von 16 Pixeln, was ja aufgrund des Kompressionsalgorhythmus von JPEG notwendig ist.

Die Offline-Lösungen, siehe http://sylvana.net/jpegcrop/losslessapps.html, sind mir soweit bekannt.

Danke,
Max

  1. Die Abmessung der Bilder sind immer ein Vielfaches von 16 Pixeln, was ja aufgrund des Kompressionsalgorhythmus von JPEG notwendig ist.

    Nein - JFIF bzw. JPEG nutzt 8x8 große Blöcke - notwendig ist das aber nicht, ausser man will verlustfrei in 90°-Winkeln drehen.

    imagerotate() schon versucht?

    1. Die Abmessung der Bilder sind immer ein Vielfaches von 16 Pixeln, was ja aufgrund des Kompressionsalgorhythmus von JPEG notwendig ist.

      Nein - JFIF bzw. JPEG nutzt 8x8 große Blöcke - notwendig ist das aber nicht, ausser man will verlustfrei in 90°-Winkeln drehen.

      imagerotate() schon versucht?

      Ja, aber ich würde jetzt sagen, dass es nicht verlustfrei arbeitet? Wenn ich die Datei speichere, dann ist die Größe schonmal ganz anders als vorher. OK, ich kann da die Qualität bei imagejpeg() einstellen, aber genau da zeigt es ja eigentlich, dass die Variante nicht ganz richtig sein kann, weil die Datei neu komprimiert wird.

      Any other ideas?

      Max

      PS: "man will verlustfrei in 90°-Winkeln drehen" <- genau das will ich btw.

      1. Ja, aber ich würde jetzt sagen, dass es nicht verlustfrei arbeitet?

        imagerotate() arbeitet defintiv verlustfrei - deine Verluste entstehen ggf. durchs ausgeben mittels (zum Beispiel) imagejpeg().

        Speichere das neue Bild in ein verlustfreies Format - z.B. PNG und vergleiche das Ergebnis mit der gedrehten Quelle - es müsste 1:1 ident sein.

        1. Hallo,

          imagerotate() arbeitet defintiv verlustfrei - deine Verluste entstehen ggf. durchs ausgeben mittels (zum Beispiel) imagejpeg().

          ja, das ist genaugenommen korrekt.

          Speichere das neue Bild in ein verlustfreies Format - z.B. PNG und vergleiche das Ergebnis mit der gedrehten Quelle - es müsste 1:1 ident sein.

          Bestimmt. Aber wenn ich "JPEG-Bilder verlustfrei drehen" möchte, dann will ich hinterher wieder ein JPEG, das mit dem Original (bis auf die geänderte Orientierung) pixel-identisch ist.
          Eine Umwandlung in ein verlustfreies Format ist Schummelei!

          Ah ja, die gdlib arbeitet grundsätzlich so: Das Bild laden, dekomprimieren, bearbeiten, dann neu komprimieren. Erfüllt also nicht die Anforderungen des OP.

          So long,
           Martin

          --
          F: Was ist ekliger als ein angebissener Apfel mit einem Wurm drin?
          A: Ein angebissener Apfel mit einem halben Wurm.
          1. Ah ja, die gdlib arbeitet grundsätzlich so: Das Bild laden, dekomprimieren, bearbeiten, dann neu komprimieren. Erfüllt also nicht die Anforderungen des OP.

            Danke für Deine Anmerkung, hätte es wohl nicht ganz so genau ausdrücken können.

            Aktuell gebe ich mich damit zufrieden, dass ich on-the-fly imagerotate verwende. Wenn aber jemand die Bilder unterladen will (ist ein Fotoalbum), dann bekommt er das nicht gedrehte Original. Dem Fotodienst oder Drucker dürfte es egal sein, der passt es wohl automatisch ans Papierformat an.

            Vielleicht hat ja noch jemand einen Vorschlag. Meine Idee/Wunsch ist, dass der user ein Bild sieht, welches gedreht werden muß, dieses dreht und ich es entsprechend gleich zurückspeichere. Wenn dabei (weitere) Verluste auftreten, dann kann es ja theoretisch sein, dass ein nicht ganz eindeutiges Bild noch X-mal drehen deutlich schlechter aussieht als am Anfang. Deswegen die Frage nach der verlustfreien Drehung.

            MfG, Max

          2. Ah ja, die gdlib arbeitet grundsätzlich so: Das Bild laden, dekomprimieren, bearbeiten, dann neu komprimieren. Erfüllt also nicht die Anforderungen des OP.

            Bist du da sicher - bzw. was verstehst du unter dekomprimieren?

            Um ein JPEG verlustfrei zu drehen ist es erforderlich, die Kompression rückgängig zu machen (sprich den exakten Algorithmus verkehrt herum auszuführen) - das JPEG einfach in eine Rastergrafik lesen führt ggf. zu einem abweichenen Ergebnis.

            1. Hi,

              Ah ja, die gdlib arbeitet grundsätzlich so: Das Bild laden, dekomprimieren, bearbeiten, dann neu komprimieren. Erfüllt also nicht die Anforderungen des OP.
              Bist du da sicher - bzw. was verstehst du unter dekomprimieren?

              ja, bin ich. Die gdlib arbeitet intern immer mit unkomprimierten Bilddaten, ganz ähnlich wie ein Windows-BMP, so dass jedes Pixel einzeln adressiert und manipuliert werden kann. Das heißt, komprimierte Formate wie GIF, PNG oder JPEG werden komplett decodiert und stehen erst dann zur Bearbeitung zur Verfügung. Daher braucht beispielsweise ein JPEG mit 400x300 Pixel Größe auch 400*300*3 Bytes im Speicher (also knapp 400kB), auch wenn die JPEG-Datei nur 21kB groß ist.

              Um ein JPEG verlustfrei zu drehen ist es erforderlich, die Kompression rückgängig zu machen (sprich den exakten Algorithmus verkehrt herum auszuführen)

              Nicht ganz. Ich habe den JPEG-Kompressionsalgorithmus noch nicht in allen Einzelheiten verstanden, aber die Bildinformation *innerhalb* eines 8x8 großen Blocks lässt sich AFAIK tatsächlich verlustfrei decodieren und wieder neu codieren. Der Informationsverlust findet bei der Erzeugung der 8x8-Blöcke statt.
              Verlustfreies Drehen heißt also:
               * Jeden 8x8-Block in sich drehen, das geht verlustfrei
               * Die Gesamtanordnung der Blöcke drehen, geht auch verlustfrei

              das JPEG einfach in eine Rastergrafik lesen führt ggf. zu einem abweichenen Ergebnis.

              Abweichend wovon? - Bei JPEG gilt dasselbe wie bei MPEG (und davon abgeleitet auch bei mp3-Audio): Die Decodierung bzw. Dekompression einer vorliegenden Datenmenge ist ein mathematisch exakter Vorgang und muss unabhängig vom verwendeten Weg immer dasselbe Ergebnis liefern, sonst ist der Algorithmus fehlerhaft.

              So long,
               Martin

              --
              Auch mit eckigen Radios kann man Rundfunk hören.
              1. ja, bin ich. Die gdlib arbeitet intern immer mit unkomprimierten Bilddaten, ganz ähnlich wie ein Windows-BMP, so dass jedes Pixel einzeln adressiert und manipuliert werden kann.

                das ist mir klar :)

                Abweichend wovon? - Bei JPEG gilt dasselbe wie bei MPEG (und davon abgeleitet auch bei mp3-Audio): Die Decodierung bzw. Dekompression einer vorliegenden Datenmenge ist ein mathematisch exakter Vorgang und muss unabhängig vom verwendeten Weg immer dasselbe Ergebnis liefern, sonst ist der Algorithmus fehlerhaft.

                Das schon - aber man kann mit derselben Rastergrafik mit verschiedenen Algorithmen komprimieren und dann zu unterschiedlichen Ergebnissen kommen.

                Wenn man also mit GD die JPEG-Datei liest muss sie nach dem Drehen exakt so komprimieren, wie auch das original Komprimiert wurde um wieder zum Ergebnis vor der Drehung zu kommen bzw. keinen Verlust zu haben.

                Dafür darf die Grafik eben nicht einfach als Rastergrafik eingelesen werden - es müssen auch die Komressionsschritte "rückgängig" gemacht werden (um das Muster zu lesen).

                1. Hallo,

                  man kann mit derselben Rastergrafik mit verschiedenen Algorithmen komprimieren und dann zu unterschiedlichen Ergebnissen kommen.

                  zweifellos, deswegen gibt's ja beim Erzeugen einer JPEG-Grafik so große Qualitätsunterschiede zwischen verschiedenen Programmen - auch bei nahezu gleicher resultierender Dateigröße.

                  Wenn man also mit GD die JPEG-Datei liest muss sie nach dem Drehen exakt so komprimieren, wie auch das original Komprimiert wurde um wieder zum Ergebnis vor der Drehung zu kommen bzw. keinen Verlust zu haben.

                  Hier liegt dein Denkfehler: Es ist nicht möglich, sie exakt so zu komprimieren, wie das Original, weil du im Gegensatz zum Original mit Daten arbeitest, die schon einmal verlustbehaftet komprimiert wurden (es sind also bereits Informationen unwiederbringlich verlorengegangen).

                  Dafür darf die Grafik eben nicht einfach als Rastergrafik eingelesen werden - es müssen auch die Komressionsschritte "rückgängig" gemacht werden (um das Muster zu lesen).

                  Genau das ist nicht möglich, ebensowenig wie man die Kompression eines MPEG-Videos oder eines mp3-Audioclips exakt rückgängig machen kann, weil einfach nicht mehr die exakte Information vorliegt. Anders bei GIF und PNG, die verlustlos komprimieren; hier kann ich das Ausgangsmaterial *exakt* bis aufs Pixel rekonstruieren.
                  Wenn bei der Verarbeitung von Daten Informationen verlorengehen, ist es prinzipiell unmöglich, aus den verbleibenden Daten die Gesamtinformation exakt zu rekonstruieren, es bleibt immer nur eine fehlerbehaftete Näherung.

                  Bye,
                   Martin

                  --
                  Verliebt:    Er spricht, sie lauscht.
                  Verlobt:     Sie spricht, er lauscht.
                  Verheiratet: Beide sprechen, und die Nachbarn lauschen.
                  1. Genau das ist nicht möglich
                    Wenn bei der Verarbeitung von Daten Informationen verlorengehen, ist es prinzipiell unmöglich, aus den verbleibenden Daten die Gesamtinformation exakt zu rekonstruieren, es bleibt immer nur eine fehlerbehaftete Näherung.

                    Ich hab' mich unglücklich ausgedrückt - natürlich können die Verloren Bildinformationen nicht wieder rekonstrukiert werden - jedoch, wenn bereits 8x8-Blöcke komprmiert wurden und man diese nochmal mit demselben Algorithmus komprimiert, wird das bild nicht mehr verändert

                    In JPEG sieht ein 8x8-Block, egal wie er gedreht ist immer wieder gleich aus, wenn derselbe Algorithmus angewandt wird.

                    12345678
                    12345678
                    12345678
                    12345678
                    12345678
                    12345678
                    12345678
                    12345678

                    entspricht

                    11111111
                    22222222
                    33333333
                    44444444
                    55555555
                    66666666
                    77777777
                    88888888

                    Man muss nur darauf achten, dass nicht sowas passiert - hier würde Information fehlen:

                    11111111
                    11111111
                    33333333
                    33333333
                    55555555
                    55555555
                    77777777
                    77777777

              2. aber die Bildinformation *innerhalb* eines 8x8 großen Blocks lässt sich AFAIK tatsächlich verlustfrei decodieren und wieder neu codieren.

                Ich nehme an hier ist gemeint, dass man die bestehenden Daten (bei denen vorher vielleicht schon was verloren ging) verlustfrei hin und her komprimieren kann? Das ist zumindest mathematisch gesehen richtig. Rundungsfehler gibts vielleicht trotzdem.

                Der Informationsverlust findet bei der Erzeugung der 8x8-Blöcke statt.

                Wie meinst du das genau? Die Blöcke werden ja nicht irgendwie erzeugt, die werden durch das Bild vorgegeben.
                Genau genommen entsteht der Verlust erst dann, wenn ein Block codiert wurde und wenn dann darauf die Komprimierung angewendet wurde.

                * Jeden 8x8-Block in sich drehen, das geht verlustfrei

                Irgendwas geht bei jpg schon mit verlustfrei drehen, das hab ich auch schon gehört. Ich weiß allerdings nicht wie das genau geht. Ob man wirklich die Blöcke drehen kann?
                Sinnvoll wär ja eigentlich wenn man im Bild einfach die gewünschte Ausrichtung speichert. Dann würden die Daten bleiben wie sie sind und die Darstellung ist dann so rum oder anders rum ...

                1. Der Informationsverlust findet bei der Erzeugung der 8x8-Blöcke statt.
                  Wie meinst du das genau? Die Blöcke werden ja nicht irgendwie erzeugt, die werden durch das Bild vorgegeben.

                  Ja, aber auch nur wenn das Bild in seinen Dimensionen durch 8 Teilbar ist - sonst entsteht bei drehen ein anderes 8x8-Raster.

                  Genau genommen entsteht der Verlust erst dann, wenn ein Block codiert wurde und wenn dann darauf die Komprimierung angewendet wurde.

                  Jein, wenn auf den Block ein anderer Algorithmus angewendet wird. Ein bestimmtes Muster wird zwangsläufig schlechter wenn man dieses Muster nochmal drüberjagt.

                  Genaugenommen kann man JPEG aber nur _sicher_ verlustfrei bearbeiten, wenn man es NICHT in eine Rastergrafik konvertiert sondern nur die bereits bodierten Blöcke umsortiert bzw dreht.

                  1. Hallo,

                    Genaugenommen kann man JPEG aber nur _sicher_ verlustfrei bearbeiten, wenn man es NICHT in eine Rastergrafik konvertiert sondern nur die bereits bodierten Blöcke umsortiert bzw dreht.

                    sag ich doch ...

                    Aber Wikipedia erklärt das alles eigentlich viel besser und ausführlicher. :-)

                    Schönen Tag noch,
                     Martin

                    --
                    Kleine Geschenke erhalten die Freundschaft.
                    Große verderben sie aber meist auch nicht.
                    1. sag ich doch ...

                      Ja ich weiß :D Aber auch eine Bereits mit Artefakten belastete Rastergrafik lässt sich ggf. verlustfrei in JPEG übertragen wenn man die Algorithmen kennt (oder "ausprobieren" kann) :)

              3. Moin!

                Um ein JPEG verlustfrei zu drehen ist es erforderlich, die Kompression rückgängig zu machen (sprich den exakten Algorithmus verkehrt herum auszuführen)

                Nicht ganz. Ich habe den JPEG-Kompressionsalgorithmus noch nicht in allen Einzelheiten verstanden, aber die Bildinformation *innerhalb* eines 8x8 großen Blocks lässt sich AFAIK tatsächlich verlustfrei decodieren und wieder neu codieren. Der Informationsverlust findet bei der Erzeugung der 8x8-Blöcke statt.

                Nein, nicht so ganz.

                Das Bild wird in 8x8-Blöcke unterteilt. Dann werden die drei Farbkanäle der Pixel jeweils als Welle aufgefaßt und mit Fouriertransformation in Ortsfrequenzen umgesetzt. Diese Ortsfrequenzmatrix kriegt dann noch konstante Faktoren draufmultipliziert, so dass am Ende sehr viele Nullen entstanden sind (oder durch Rundung entstehen - das ist dann der Informationsverlust!). Viele Nullen auf einmal lassen sich prima komprimieren - fertig ist die Bildkompression.

                Verlustfreies Drehen heißt also:
                * Jeden 8x8-Block in sich drehen, das geht verlustfrei
                * Die Gesamtanordnung der Blöcke drehen, geht auch verlustfrei

                Exakt. Der Trick ist, die Daten im JPEG nicht wieder komplett zu Pixeln zurückzurechnen, sondern nur soweit, dass das Drehen möglich wird. Das erfordert lediglich ein Umsortieren der fertigen Ortsfrequenzmatrix (Zeilen zu Spalten und Umgekehrt, ggf. spiegeln), ohne aber an den Zahlenwerten etwas zu verändern.

                - Sven Rautenberg

  2. @@Max:

    nuqneH

    gibt es eine Möglichkeit, dass man Bilder im JPEG-Format mit PHP verlustfrei dreht?

    Muss es denn PHP sein?

    Im Abschnitt Verlustfreie Nachbearbeitung von JPEG [Wikipedia] wird 'jpegtran' genannt. Vielleicht kannst du das auf deinem Server laufen lassen?

    Qapla'

    --
    Alle Menschen sind klug. Die einen vorher, die anderen nachher. (John Steinbeck)
    1. gibt es eine Möglichkeit, dass man Bilder im JPEG-Format mit PHP verlustfrei dreht?

      Muss es denn PHP sein?

      leider ja bzw. ein anderes Programm, was schon auf dem Server installiert ist.

      Im Abschnitt Verlustfreie Nachbearbeitung von JPEG [Wikipedia] wird 'jpegtran' genannt. Vielleicht kannst du das auf deinem Server laufen lassen?

      Geht leider nicht, ist ein Webhosting-Paket bei all-inkl.com und nicht mein eigener Server, d.h. ich kann da nix installieren.

      Trotzdem danke für den Tipp,
      Max

      1. Hallo Max,

        gibt es eine Möglichkeit, dass man Bilder im JPEG-Format mit PHP verlustfrei dreht?

        Im Abschnitt Verlustfreie Nachbearbeitung von JPEG [Wikipedia] wird 'jpegtran' genannt. Vielleicht kannst du das auf deinem Server laufen lassen?

        Geht leider nicht, ist ein Webhosting-Paket bei all-inkl.com und nicht mein eigener Server, d.h. ich kann da nix installieren.

        jpegtran ist Open Source. Du könntest die für Dich interessante Funktionalität in PHP umsetzen :-)

        Freundliche Grüße

        Vinzenz