JPEG

Der /DCTDecode1) Filter für Streams nimmt ein JPEG, und wandelt es in ein PDF-kompatibles, binäres Bild. Wir können die Datei also direkt einbinden. Da es sich aber um ein Bildobjekt handelt, müssen wir immer noch die Breite, Höhe, Bittiefe und den Farbraum angeben. Diese Informationen müssen wir vorgängig aus dem JPEG ermitteln.

Dateiaufbau

JPEG Dateien entsprechen normalerweise dem JFIF oder EXIF Standard. Beide Standards verwenden dieselbe Struktur, so dass wir uns nicht mit den Differenzen befassen müssen.

Die Datei ist zweigeteilt in einen Metadatenteil, und einen Bilddatenteil. Der Metadatenteil kommt zuerst. Er enthält die Informationen, die wir suchen. Alle Zahlen in diesem Block, welche mehrere Bytes benötigen, sind in Big-Endian Anordnung. Folgende Datentypen kommen vor:

uint8 vorzeichenlose 8-Bit Zahl
uint16 vorzeichenlose 16-Bit Zahl

Die Metadaten sind in verschiedene Blöcke aufgeteilt, die direkt hintereinander in der Datei stehen. Jeder Block beginnt mit zwei Markerbytes. Davon ist das erste immer 0xFF, während das zweite den Blocktyp definiert.

Blocks mit einem Kennzeichen im Bereich 0xD0 - 0xD9 bestehen nur aus dem Marker. Bei allen anderen Blocks folgen nun 2 Bytes mit einer Zahl nach uint16. Diese Zahl enthält die Länge der Blockdaten in Byte. Die Angabe ist einschliesslich der Bytes für die Länge, aber ohne die Bytes für den Marker. Das heisst, die Längenangabe - 2 ergibt die noch zu lesenden Bytes für diesen Block. Mit diesem Wissen können wir nun für uns uninteressante Blocks überspringen.

Übrigens: Der erste Block in der Datei ist immer der „Start of Image“ Block. Er hat das Kennzeichen 0xD8, was einer der Blocks ohne weitere Daten ist. Die ersten drei Bytes einer JPEG-Datei sind folglich immer <FF D8 FF> (da der nächste Block direkt folgt). Diesen Umstand können wir nutzen, um JPEG-Dateien zu erkennen.

Der Block, der uns interessiert, ist der „Frame Header“. Dieser hat, je nach Kompressionsvariante, eines der Kennzeichen aus dem Bereich 0xC0 - 0xCF, mit Ausnahme der Kennzeichen 0xC4, 0xC8 und 0xCC. 0xC4 und 0xCC stehen für andere Blocks, 0xC8 ist unbenutzt. Ohne die Bytes für Marker und Längenangabe ist der Block zwischen 9 und 18 Bytes lang. Uns interessieren die ersten 6 Bytes.

Die ersten 6 Bytes des Frame Headers beinhalten:

Position Grösse Typ Inhalt
01 Byte uint8 Bittiefe
12 Byte uint16 Höhe in Pixeln
32 Byte uint16 Breite in Pixeln
51 Byte uint8 Farbraum

Die Bittiefe kann 8 oder 12 sein. PDF erlaubt nur 8 Bit.

Der Farbraum kann 1 oder 3 sein, wobei 1 für Graustufen und 3 für RGB2) steht. Es gibt eine von PDF unterstützte Adobe Erweiterung, welche zusätzlich den Wert 4 für CMYK zulässt.

Beispiel:

<FF C0 00 11 08 02 58 03 20 03 01 22 00 02 11 01 03 11 01>

Hier haben wir einen Block 0xC0, also einen Frame Header. Die Länge ist 0x11 (= 17), die Länge der Reindaten ist folglich 15 Byte. Aus den ersten 6 Byte können wir lesen, das die Bittiefe 8, die Höhe 0x258 (=600), die Breite 0x320 (=800), und der Farbraum 3 (also RGB) ist.

das Bildobjekt

Mit diesen Angaben können wir nun ein Bildobjekt erstellen. Da die Daten JPEG-komprimiert sind, müssen wir den /DCTDecode Filter angeben. Als Streaminhalt dient das unveränderte JPEG, allenfalls ASCII85 oder ASCIIHex kodiert.

Beispiel:

10 0 obj
<<
/Type /XObject
/Subtype /Image
/Width 800
/Height 600
/ColorSpace /DeviceRGB
/BitsPerComponent 8
/Interpolate true
/Filter [/ASCII85Decode /DCTDecode]
/Length 35654
>>
stream
...~>
endstream
endobj

Platz sparen

Oft enthalten JPEG Dateien viele Metadaten, die für die Dekompression unnötig sind. Wir können hier im PDF Platz sparen, indem wir nur die notwendigen Metadatenblöcke übernehmen. Folgende Regeln sind zu beachten:

  • Blöcke mit einem Kennzeichen 0xC0 - 0xDF sind für die Dekompression notwendig.
  • Blöcke mit einem Kennzeichen 0xE0 - 0xFE sind für die Dekompression nicht notwendig.
  • Blöcke mit anderen Kennzeichen sollten nicht vorkommen, und deuten auf eine beschädigte Datei hin.
  • Auf den Block mit Kennzeichen 0xDA folgen die Bilddaten.

Um wieder gültige JPEG Daten zu erhalten, schreibt man die übernommenen Metadatenblöcke und zum Schluss die Bilddaten direkt hintereinander.

1) JPEG verwendet eine auf „diskreter Cosinus Transformation“ basierende Kompression. Daher der Name des Filters.
2) Genaugenommen steht 3 für YCbCr, aber bei der Dekompression wird automatisch nach RGB umgerechnet.

Diskussion

Geben Sie Ihren Kommentar ein. Wiki-Syntax ist zugelassen:
I G J R V
 
grundlagen/dateien/bilder/jpeg.txt · Zuletzt geändert: 2012/08/23 11:42 (Externe Bearbeitung)
 
Falls nicht anders bezeichnet, ist der Inhalt dieses Wikis unter der folgenden Lizenz veröffentlicht: CC0 1.0 Universal
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki