Wie 2 JPEG-Dateien miteinander verbinden verlustlos ohne Dekodieren eines Hex-Editor?

StackOverflow https://stackoverflow.com/questions/609586

  •  03-07-2019
  •  | 
  •  

Frage

Ich versuche, ein Programm (prob in Java) zu schreiben, eine Reihe von JPEG-Dateien zusammen verlustlos zu verbinden, ohne sie zuerst decodiert werden.

Ich dachte, ich einfach anfangen würde und versuchen, und fügen Sie 2 JPEG-Dateien mit der gleichen Größe mit den gleichen Einstellungen komprimierte übereinander einen Hex-Editor.

Zuerst extrahieren I, die Bilddaten der JPEG-B und fügen sie in JPEG A. durch die Abmessungen in den Headern angegeben Modifizieren I eine neue erkennbares Bild (JPEG A + B JPEG in der y-Achse angehängt) erhalten, die diplayed werden kann. Obwohl jedoch die Bilddaten von JPEG-B deutlich zu erkennen ist, scheint es eine Menge Farbinformationen verloren zu haben und ist eindeutig falsch.

Also meine Frage ist, welche Schritte fehle ich hier draußen? Ich glaube nicht, gibt es keine andere Dimension spezifischen Header-Werte ich ändern müssen, vielleicht muss ich dekodieren, die Bilddaten von beiden JPEGs Huffman, dann fügen Sie sie zusammen und neu codieren dann das Los?

Ich habe einige Zeit damit verbracht auf JPEG-Spezifikationen lesen und Header usw., aber um ehrlich zu sein ich aus meiner Tiefe bin und mit einem Zeiger oder zwei wirklich tun könnte!

Vielen Dank für jede Hilfe.


Vielen Dank für alle Vorschläge. Ja, das ist auf jeden Fall möglich, die ich erwähnt habe sollte in meiner ursprünglichen Frage jpegtran. Ich versuche im Grunde diesen Aspekt der jpegtran Funktionalität zu replizieren, aber es in meinem eigenen Programm verwenden. Ich glaube, ich an der jpegtran Quelle aussehen soll, aber ich weiß nichts über C und nicht sehr viel über die Programmierung im Allgemeinen so Reverse Code Engineering Quelle ist leichter gesagt als getan!

War es hilfreich?

Lösung 2

Ok habe ich, wo ich falsch würde.

1) die Bildscandaten in Bytes gespeichert, aber die tatsächlichen wichtigen Informationen als variabler Länge Bitfolgen kodiert. Dies bedeutet, dass das Ende der eigentlichen Bilddaten nicht notwendigerweise auf einer Byte-Grenze fallen. Wenn die JPEG-Encoder muss polstern die Anzahl der Bits des Bytes machen Grenze es einfach eine Reihe von 1s erstellt.

2) die Art und Weise die tatsächlichen Pixel info gespeichert wird, ist ein wenig zu kompliziert (zumindest für mich) zu erklären, aber im Grunde ist alles innerhalb MCU, minimale Codierungseinheiten oder etwas codierte. Dies unterscheidet sich in der Größe in Abhängigkeit von dem Chroma-Subsampling, horizontale und vertikale Größen entweder 8 oder 16 Pixel. Für jede MCU gibt es DC- und AC-Komponenten, die eine einzelne Komponente von Luminanz, Y oder Chrominanz, Cb und Cr bilden. Das Problem war, dass die DC-Komponenten als Werte in Bezug auf den jeweiligen DC-Wert des vorhergehenden MCU gespeichert sind. Also, wenn ich die neuen Bilddaten von jpg B hinzugefügt, hatte es seine DC-Werte in Bezug auf 0 gespeichert (da es keine früheren MCUs waren), aber es benötigt von jpg A. die letzten DC-Werte der letzten MCU zu berücksichtigen (Hoffnung, die Sinn macht).

Die Lösung:

Sie müssen eine anfängliche decode (Huffman + Lauflängen-) der Bilddaten tun genau Enden, wo die Bilddaten, um herauszufinden, und dann die Hinter 1s abzustreifen. Sie müssen auch in geeigneter Weise der Anfangs-DC-Werte in der zweiten jpg ändern. Sie müssen dann die entsprechenden Bits encodieren, 1s summieren sich zu einem Byte-Grenze, et voila passen.

Wenn Sie in der x-Achse angehängt werden sollen, ist es ein wenig komplizierter. Sie haben die MCUs neu zu ordnen, so dass sie in der richtigen Reihenfolge zu scannen. Jpgs nach rechts scannen nach links, dann nach unten oben und dann in geeigneter Weise der DC-Werte einzustellen.

Bisher habe ich getestet nur diese auf einzelne MCU JPGs, aber theoretisch sollte es auch mit größeren arbeiten.

BTW habe ich dies nur aus dank der Besitzer dieses ausgezeichnete jpg verwandte Ressource / blog

Andere Tipps

Das ist sehr viel machbar. Ich habe es auf einer Menge von Google Karte Bildkacheln die anschließen und Postergröße Bild zu erzeugen. Es ist ein Paket für Unix JPEG-Tools für genau das tun, um diesen genannt. Das Programm heißt jpegjoin . Pure-C-Quelle, mit Windows-Binaries zur Verfügung. Wenn kompiliert erstellt es eine Anwendung Befehlszeile, die bei der Ausführung zwei JPEG-Bilder loselessly unter vielen anderen Dingen verbindet. Es ist kein Bild de-komprimieren, verschmilzt nur die komprimierten Daten zusammen und fixiert den Kopf entsprechend. Ich benutzte es 100 Bilder zu fusionieren 50 Streifen zu erstellen und fusionierte dann diese Streifen wieder ein großes Bild zu erstellen.

Weitere Informationen finden Sie unter http://en.wikipedia.org/wiki/Lossy_compression finden #Lossless_editing

Der Quellcode

Der Quellcode für die zugrunde liegenden jpegtran Bibliothek hier . Ein Beispielskript zu imitieren jpegjoin hier .

jpeg ist - wie mp3 -. In der Regel stabil, wenn Sie es erneut komprimieren (mit dem gleichen Algorithmus)

so, wenn Sie die Bilder kommen und wieder komprimieren sie, nur sicherstellen, dass die neue Kompressionsrate zu den höchsten der zwei Bilder höher oder gleich ist. auf diese Weise Sie nicht wirklich Genauigkeit verlieren.

Zwei Ansätze:

1) dekodieren beide Quelle JPEG-Bilder, die resultierenden Bitmaps fusionieren und kodieren wieder als JPEG. Nachteilig ist hier die erneute Komprimierung.

2) Sicherstellen, dass die Quellbildbreite und -höhe sind Vielfache von 16, möglicherweise durch die Bilder zu beschneiden. Sie nicht die Bilder entschlüsseln, sondern das Ziel JPEG aus dem Quell MCU Blöcken (16 x 16 pixles Größe, damit das Beschneiden) zusammenzustellen.

Ich schlage vor, Sie die DRI und RSTN Marker zu betrachten, auch wenn dies viele Voraussetzungen erfordert, aber es funktioniert für mich: Anhängen eines PPM (ein Bitmap-Format) in eine jpeg, die DRI und RSTN codiert wird, verwendet wird, sind beide in gleiche Breite, und beide sind in Vielfachen von MCU.

ich nur die JPEG-Daten nach der letzten RSTN Markierung ausgeschnitten (falls vorhanden), dekodieren, dies zu PPM, und verbinden Sie die beiden PPMs zu einer einzigen MCU Linie, kodieren sie mit den gleichen Optionen mit dem Original-JPEG, ordnen Sie die RSTs in der resultierenden JPEG entsprechend die ursprünglichen JPEG- anhängt, dann das Ergebnis zu dem ursprünglichen JPEG. Mit dieser Methode ist es hindert mich daran, Dekodieren des gesamten ursprünglichen jpeg und kodieren Sie es erneut.

Als Decodierung und Encodierung Sachen, ich bin libjpeg verwenden.

Statt Bilder horizontal angehängt, ist es wahrscheinlich einfacher, jedes Bild um 90 Grad zu drehen, dann verbinden sie vertikal, dann drehen Sie das resultierende Bild zurück -90 Grad.

Lossless JPEG-Operationen sind so ziemlich ein Oxymoron. Sie können einige Tricks tun, wie drehen, aber das ist ziemlich viel es.

Ich würde vorschlagen, Sie lossless Quellbilder (TIFF oder PNG in den Sinn kommt) zu haben oder neu bewerten Ihre Bildqualitätsanforderungen - wieder einmal eine JPEG-Resampling, anständig ursprünglichen Dateien gegeben, nicht zu unterscheiden ist für die überwiegende Mehrheit der Menschen da draußen.

Was Sie versuchen zu, ist grundsätzlich nicht möglich.
Die Codierung der JPEG-Datei ist etwas komplex, und wenn Sie den Inhalt der Pixel sind zu ändern dann die Codierung wird sich ändern. Sie könnten mit einem Bild kleiner oder größer ist als die Summe der beiden Bilder beenden Sie kombinieren. Die einzigen Operationen, die möglich sind verlustlos sind diejenigen, die eine Eins-zu-Eins-Entsprechung mit den Pixeln des Originalbildes beizubehalten. Dies läuft darauf hinaus grundsätzlich auf 90-Grad-Drehungen nach unten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top