Mittwoch, 31. Juli 2013

baseline TIFF

Da gerade im Umfeld von OCR Projekten oft TIFF eingesetzt wird, kaum aber einer weiß, was die Besonderheiten des Bildformates sind, habe ich mich entschlossen in diesem Post die Grundlagen kurz vorzustellen.

Es hat sich für mich bewährt, Protokolle oder Dateiformate von Hand auseinanderzunehmen. So habe ich ein baseline TIFF erzeugt, welches im folgenden als Beispiel dienen soll. Die Datei ist 20x10 Pixel groß, s/w und gut geeignet die Besonderheiten kennenzulernen.



Beispiel-TIFF (hier als PNG)

Kurzinfo zu 'Tagged Image File Format' (TIFF)

Magic Byte

"II" (little-endian): 0x49492a00
"MM" (big-endian): 0x4d4d002a

Dateiendung

 .TIF bzw. .TIFF

MimeType

 image/tiff

Spezifikation

ftp://ftp.adobe.com/pub/adobe/devrelations/devtechnotes/pdffiles/tiff6.pdf bzw. http://partners.adobe.com/public/developer/tiff/index.html

Geschichte

Ursprünglich entwickelt von Aldus und Microsoft. 1994 wurde Aldus von Adobe übernommen.

Die aktuelle Version von TIFF ist 6.0 (1992) und wird moderat durch TIFF Technical Notes, zB. zu 'deflate'-Kompression ergänzt.


Aufbau

Eine TIFF-Datei ist im Wesentlich wie folgt aufgebaut:
Aufbau TIFF Datei

Sie besteht aus Header, Image File Directories und Streams.

Ich beziehe mich auf oben gezeigte mini TIFF-Datei (Ist mittlerweile unter https://github.com/SLUB-digitalpreservation/fixit_tiff/tree/master/examples zu finden) . Im folgenden ist die Datei als Hex-Dump zu sehen:

Tabelle 1. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
00000000
4949 2a00 2600 0000
0000 0000 0000 fd1e
II*.&...........
00000010
f011 1080 111c e011
1080 1110 8011 1080
................
00000020
0000 0000 0000 1000
fe00 0400 0100 0000
................
00000030
0000 0000 0001 0300
0100 0000 1400 0000
................
00000040
0101 0300 0100 0000
0a00 0000 0201 0300
................
00000050
0100 0000 0100 0000
0301 0300 0100 0000
................
00000060
0100 0000 0601 0300
0100 0000 0000 0000
................
00000070
0d01 0200 2500 0000
ec00 0000 1101 0400
....%...........
00000080
0100 0000 0800 0000
1201 0300 0100 0000
................
00000090
0100 0000 1501 0300
0100 0000 0100 0000
................
000000a0
1601 0300 0100 0000
4000 0000 1701 0400
........@.......
000000b0
0100 0000 1e00 0000
1a01 0500 0100 0000
................
000000c0
1201 0000 1b01 0500
0100 0000 1a01 0000
................
000000d0
1c01 0300 0100 0000
0100 0000 2801 0300
............(...
000000e0
0100 0000 0200 0000
0000 0000 2f68 6f6d
............/hom
000000f0
652f 726f 6d65 796b
652f 7469 6666 2f65
e/romeyke/tiff/e
00000100
7861 6d70 6c65 5f74
6966 662e 7469 6666
xample_tiff.tiff
00000110
0000 0000 0048 0000
0001 0000 0048 0000
.....H.......H..
00000120
0001
..

Header

Der Header einer TIFF-Datei ist
  • 8 Byte groß
  • enthält Magic Bytes
  • und Offset des ersten IFD 
Die ersten zwei Bytes (0x00-0x01) beschreiben die byte-order: 
  • 0x4949 little endian (least significant to most significant byte) 
  • 0x4d4d big endian (most significant to least significant byte)
Die byte-order ist wichtig und zieht sich durch die gesamte TIFF-Datei. 
Die nächsten zwei Bytes enthalten die Antwort auf den Sinn des Lebens und entsprechen der Zahl 42 (ebenfalls abhängig von der byte order).

Die Bytes 4-7 zeigen auf das erste Image File Directory (IFD), hier die Adresse 0x0000 0026. Baseline TIFFs enthalten nur ein IFD, mehr dazu später.

Image File Directory

Aufbau Image File Directory (IFD) in TIFF-Datei
Im Kopf des IFDs wird in ersten 2 Bytes wird die Anzahl der Tags festgelegt. Da so eine sehr variable Länge des IFDs entsteht muss am Ende der Speicherort des nächsten IFDs angegeben sein.

Das letzte IFD enthält als Offset den Wert 0x0000 0000 0000 0000.

Wenn wir den Hex-Dump einfärben, so daß die Tags abwechselnd gelb oder silber hinterlegt sind, wird die Struktur deutlicher:

Tabelle 2. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
00000000
4949 2a00 2600 0000
0000 0000 0000 fd1e
II*.&...........
00000010
f011 1080 111c e011
1080 1110 8011 1080
................
00000020
0000 0000 0000 1000
fe00 0400 0100 0000
................
00000030
0000 0000 0001 0300
0100 0000 1400 0000
................
00000040
0101 0300 0100 0000
0a00 0000 0201 0300
................
00000050
0100 0000 0100 0000
0301 0300 0100 0000
................
00000060
0100 0000 0601 0300
0100 0000 0000 0000
................
00000070
0d01 0200 2500 0000
ec00 0000 1101 0400
....%...........
00000080
0100 0000 0800 0000
1201 0300 0100 0000
................
00000090
0100 0000 1501 0300
0100 0000 0100 0000
................
000000a0
1601 0300 0100 0000
4000 0000 1701 0400
........@.......
000000b0
0100 0000 1e00 0000
1a01 0500 0100 0000
................
000000c0
1201 0000 1b01 0500
0100 0000 1a01 0000
................
000000d0
1c01 0300 0100 0000
0100 0000 2801 0300
............(...
000000e0
0100 0000 0200 0000
0000 0000 2f68 6f6d
............/hom
000000f0
652f 726f 6d65 796b
652f 7469 6666 2f65
e/romeyke/tiff/e
00000100
7861 6d70 6c65 5f74
6966 662e 7469 6666
xample_tiff.tiff
00000110
0000 0000 0048 0000
0001 0000 0048 0000
.....H.......H..
00000120
0001
..

Im Beispiel enthält die Adresse 0x00000026 den Wert 1000, sprich: das IFD enthält 16 Einträge. Da jeder Eintrag 12 Bytes enhält geht das IFD bis zur Adresse 0x00000026 + 2 + 16*12 + 4 = 38 + 2 + 192 + 4 = 236 = 0x0000 00ec.

IFD - Entries (Tags)


Ein IFD-Tageintrag beschreibt verschiedene Attribute eines Bildes oder der Kompressionsmethode. Es gibt viele verschiedene Tags die nicht alle verwendet werden müssen. Durch diese IFD-Einträge, kurz Tags, hat TIFF seinen Namen.

Die Tag-Einträge in der IFD sind alle 12 Bytes groß und wie folgt aufgebaut:
IFD Eintrag bzw Tag eines TIFFs
Innerhalb eines Image File Directories müssen die IFD-Tags nach ihrer 'Tag ID' aufsteigend sortiert vorliegen.
Dabei gelten die Bereiche 0x8000-0xfde7 als "private" und 0xfde8-0xffff als "reusable". Für spezielle Anwendungen kann man von Adobe die Vergabe eine "private" Tag-ID anfordern. "reusable" Tags können frei verwendet werden.

Allerdings können zukünftige Versionen von TIFF die beiden Bereiche neu definieren.

'Field Type' beschreibt den Datentyp der Werte. Zur Zeit sind ff. definiert:
  • 1 = BYTE (8-bit unsigned integer)
  • 2 = ASCII (7-bit ASCII code, null-terminiert).
  • 3 = SHORT (16-bit unsigned integer)
  • 4 = LONG (32-bit unsigned integer)
  • 5 = RATIONAL (Zähler und Nenner, je ein LONG)
  • 6 = SBYTE (8-bit signed integer, 2-er Kompl.)
  • 7 = UNDEFINED (8-bit, feldabhängig)
  • 8 = SSHORT (16-bit signed integer, 2-er Kompl.)
  • 9 = SLONG (32-bit signed integer, 2-er Kompl.)
  • 10 = SRATIONAL (Zähler und Nenner, je ein SLONG)
  • 11 = FLOAT (32-bit, single precision IEEE)
  • 12 = DOUBLE (64-bit, double precision IEEE)
 'Count' gibt an, wieviele Werte (nicht Bytes!) vom Typ 'Field Type' gespeichert werden. 

Wenn Werte eines IFD-Eintrages zusammen (Count mal FieldType) 4 Bytes nicht übersteigen, werden diese direkt im Value/Offset-Bereich gespeichert. Andernfalls gibt Value/Offset die Adresse innerhalb der TIFF-Datei an.

Gehen wir nun mal die einzelnen IFD-Einträge, die im Beispiel verwendet werden, durch.

IFD Entry - 0x28 

Der erste IFD-Eintrag an Adresse 0x28 sieht wie folgt aus:

Tabelle 3. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
00000020
0000 0000 0000 1000
fe00 0400 0100 0000
................
00000030
0000 0000 0001 0300
0100 0000 1400 0000
................

Die Tag-ID lautet 0x00fe und bedeutet TIFFTAG_SUBFILETYPE (Die jeweils aktuellen Werte, kann man sich aus der Header-Datei der libtiff heraussuchen, meist in /usr/include/tiff/tiff.h). Der Field Type lautet 0x0004 und bedeutet 32-Bit unsigned integer. Count steht auf 0x0000 0001. Da ein 32-Bit unsigned integer in 4 Bytes passt, handelt es sich um den Value 0x0000 0000.

IFD Entry - 0x34

Der IFD-Eintrag an Adresse 0x34 sieht wie folgt aus:

Tabelle 4. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
00000030
0000 0000 0001 0300
0100 0000 1400 0000
................

ergibt Tag-ID 0x0100, der für TIFFTAG_IMAGEWIDTH steht. Field Type ist 0x0003, also short 16-Bit unsigned integer. Count ist 0x0000 0001. Der Wert lautet damit 0x0014, welches 20 Pixel entspricht.

IFD Entry - 0x40

Der IFD-Eintrag an Adresse 0x40 sieht wie folgt aus:

Tabelle 5. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
00000040
0101 0300 0100 0000
0a00 0000 0201 0300
................

steht für Tag-ID 0x0101 = TIFFTAG_IMAGELENGTH. Field Type ist ebenfalls 0x0003 und Count ebenso 1. Der Wert beträgt demnach 0x000a, also 10 Pixel.

IFD Entry - 0x4c

Der IFD-Eintrag an Adresse 0x4c sieht wie folgt aus:

Tabelle 6. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
00000040
0101 0300 0100 0000
0a00 0000 0201 0300
................
00000050
0100 0000 0100 0000
0301 0300 0100 0000
................

steht für Tag-ID 0x0102 = BITS_PER_SAMPLE, Field Type ist 0x0003, Count ist 1. Der Wert ist dann 0x00000001, also 1.

IFD Entry - 0x58

Der IFD-Eintrag an Adresse 0x58 sieht wie folgt aus:

Tabelle 7. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
00000050
0100 0000 0100 0000
0301 0300 0100 0000
................
00000060
0100 0000 0601 0300
0100 0000 0000 0000
................

steht für Tag-ID 0x0103 = TIFFTAG_COMPRESSION, Field-Type und Count wie oben. Der Wert lautet 0x0000 0001 und bedeutet No Compression.

IFD Entry - 0x64

Der IFD-Eintrag an Adresse 0x64 sieht wie folgt aus:


Tabelle 8. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
00000060
0100 0000 0601 0300
0100 0000 0000 0000
................

steht für Tag-ID 0x0106 = TIFFTAG_PHOTOMETRIC. Der Field Type lautet 0x0003, also 16-Bit short unsigned integer. Count ist 0x0000 0001, also 1 und der Wert ist 0x0000 0000, also 'PHOTOMETRIC_MINISWHITE", sprich das nicht gesetzte Bit entspricht der Farbe Weiß.

IFD-Entry - 0x70


Tabelle 9. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
00000070
0d01 0200 2500 0000
ec00 0000 1101 0400
....%...........

steht für Tag-ID 0x010d = TIFFTAG_DOCUMENTNAME. Field Type lautet 0x0002, also 7-Bit ASCII Code in 8 Bit. Count ist 0x0000 0025, dh. inklusive Null-Byte ist der String 37 Zeichen lang. Da dies nicht in 4 Bytes passt, handelt es sich bei 0x000000ec nicht um einen Wert, sondern um eine Adresse im File.


Tabelle 10. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
00000070
0d01 0200 2500 0000
ec00 0000 1101 0400
....%...........
:
:
:
:
000000e0
0100 0000 0200 0000
0000 0000 2f68 6f6d
............/hom
000000f0
652f 726f 6d65 796b
652f 7469 6666 2f65
e/romeyke/tiff/e
00000100
7861 6d70 6c65 5f74
6966 662e 7469 6666
xample_tiff.tiff
00000110
0000 0000 0048 0000
0001 0000 0048 0000
.....H.......H..
00000120
0001
..

Der Wert lautet also /home/romeyke/tiff/example_tiff.tiff.

IFD-Entry - 0x7c


Tabelle 11. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
00000070
0d01 0200 2500 0000
ec00 0000 1101 0400
....%...........
00000080
0100 0000 0800 0000
1201 0300 0100 0000
................

steht für Tag-ID 0x0111 = TIFFTAG_STRIPOFFSETS. Field Type lautet 0x0004, also 32 Bit unsigned integer. Count ist 0x0000 0001, und der Wert = 0x00000008, dh. die Bilddaten liegen auf Adresse 0x08:


Tabelle 12. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
00000000
4949 2a00 2600 0000
0000 0000 0000 fd1e
II*.&...........
00000010
f011 1080 111c e011
1080 1110 8011 1080
................
00000020
0000 0000 0000 1000
fe00 0400 0100 0000
................
:
:
:
:
00000070
0d01 0200 2500 0000
ec00 0000 1101 0400
....%...........
00000080
0100 0000 0800 0000
1201 0300 0100 0000
................
:
:
:
:

IFD-Entry - 0x88


Tabelle 13. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
00000080
0100 0000 0800 0000
1201 0300 0100 0000
................
00000090
0100 0000 1501 0300
0100 0000 0100 0000
................

steht für Tag-ID 0x0112 = TIFFTAG_ORIENTATION, Field Type lautet 0x0003 = 16 Bit unsigned integer. Count beträgt 0x0000 0001 und der Wert 0x0000 0001, was "row 0 top, col 0 lhs", also von Oben Links beginnend bedeutet.

IFD-Entry - 0x94


Tabelle 14. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
00000090
0100 0000 1501 0300
0100 0000 0100 0000
................

steht für Tag-ID 0x0115 = TIFFTAG_SAMPLESPERPIXEL, Field Type lautet 0x0003 = 16 Bit unsigned integer. Count beträgt 0x0000 0001 und Wert 0x0000 0001, also 1.

IFD-Entry - 0xa0


Tabelle 15. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
000000a0
1601 0300 0100 0000
4000 0000 1701 0400
........@.......

steht für Tag-ID 0x0116 = TIFFTAG_ROWSPERSTRIP, Field Type 0x0003 = 16 Bit unsigned integer. Count beträgt 0x0000 0001 und Wert 0x0000 0004, also 4 Reihen pro Streifen.

IFD-Entry - 0xac


Tabelle 16. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
000000a0
1601 0300 0100 0000
4000 0000 1701 0400
........@.......
000000b0
0100 0000 1e00 0000
1a01 0500 0100 0000
................

steht für Tag-ID 0x0117 = TIFFTAG_STRIPBYTECOUNTS, Field Type 0x0004 = 32 Bit unsigned integer. Count beträgt 0x0000 0001 und Wert 0x0000 001e = 30, dh. 30 Bytes pro Streifen.

IFD-Entry - 0xb8


Tabelle 17. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
000000b0
0100 0000 1e00 0000
1a01 0500 0100 0000
................
000000c0
1201 0000 1b01 0500
0100 0000 1a01 0000
................

steht für Tag-ID 0x011a = TIFFTAG_XRESOLUTION, Field Type 0x0005 = RATIONAL (2x 32 Bit unsigned integer), Count beträgt 0x0000 0001. Da Wert nicht in 4 Byte passt, handelt es sich um Adresse im File, dh. 0x0000 0112:


Tabelle 18. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
000000b0
0100 0000 1e00 0000
1a01 0500 0100 0000
................
000000c0
1201 0000 1b01 0500
0100 0000 1a01 0000
................
:
:
:
:
00000110
0000 0000 0048 0000
0001 0000 0048 0000
.....H.......H..

Der Zähler beträgt 0x4800 0000 = 1207959552 und der Nenner 0x0100 0000 = 16777216. Damit beträgt die X-Auflösung 1207959552/16777216 = 72 dots pro Einheit

IFD-Entry - 0xc4


Tabelle 19. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
000000c0
1201 0000 1b01 0500
0100 0000 1a01 0000
................

steht für Tag-ID 0x011b = TIFFTAG_YRESOLUTION, Field Type 0x0005 = RATIONAL (2x 32 Bit unsigned integer), Count beträgt 0x0000 0001. Da Wert nicht in 4 Byte passt, handelt es sich um Adresse im File, dh. 0x0000 011a:


Tabelle 20. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
000000c0
1201 0000 1b01 0500
0100 0000 1a01 0000
................
:
:
:
00000110
0000 0000 0048 0000
0001 0000 0048 0000
.....H.......H..
00000120

Der Zähler beträgt 0x4800 0000 = 1207959552 und der Nenner 0x0100 0000 = 16777216. Damit beträgt die Y-Auflösung 1207959552/16777216 = 72 dots pro Einheit.

IFD-Entry - 0xd0


Tabelle 21. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
000000d0
1c01 0300 0100 0000
0100 0000 2801 0300
............(...

steht für Tag-ID 0x011c = TIFFTAG_PLANARCONFIG, Field Type 0x0003 für 16 Bit unsigned integer, Count 0x0000 0001 und Wert 0x0001, was "single image plane" bedeutet.

IFD-Entry - 0xdc


Tabelle 22. Beispiel:
Byte Hex (8 Byte) (8 Byte) ASCII
000000d0
1c01 0300 0100 0000
0100 0000 2801 0300
............(...
000000e0
0100 0000 0200 0000
0000 0000 2f68 6f6d
............/hom

steht für Tag-ID 0x0128 = TIFFTAG_RESOLUTIONUNIT, Field Type 0x0003 für 16 Bit unsigned integer, Count 0x0000 0001 und Wert 0x0000 0002, was für INCH steht. Die unter TIFFTAG_XRESOLUTION und TIFFTAG_YRESOLUTION gemachten Angaben beziehen sich also auf inch.

Fazit

TIFF ist eigentlich relativ simple. Durch das Image File Directory (IFD) werden die Tags verwaltet, die die Datei beschreiben. Der Hauptunterschied zwischen baseline TIFFs und erweiterten ist, daß letztere mehrere Image File Directories enthalten können.

Die Informationen aus dem TIFF kann man schneller mit dem der libtiff beiliegenden Werkzeug tiffinfo herausholen:

$ tiffinfo example_tiff.tiff 
  TIFF Directory at offset 0x26 (38)
  Subfile Type: (0 = 0x0)
  Image Width: 20 Image Length: 10
  Resolution: 72, 72 pixels/inch
  Bits/Sample: 1
  Compression Scheme: None
  Photometric Interpretation: min-is-white
  Orientation: row 0 top, col 0 lhs
  Samples/Pixel: 1
  Rows/Strip: 64
  Planar Configuration: single image plane
  DocumentName: /home/romeyke/tiff/example_tiff.tiff

Im Beispiel wurden nur Stripes verwendet, TIFF unterstützt aber auch Kacheln. Für tiefergehende Beschäftigung mit TIFF sei nochmal auf die sehr gute Dokumentation unter ftp://ftp.adobe.com/pub/adobe/devrelations/devtechnotes/pdffiles/tiff6.pdf verwiesen.

Die einzelnen Tags, die in baseline TIFF erlaubt sind, sind unter http://www.awaresystems.be/imaging/tiff/tifftags/baseline.html aufgelistet.