Posts mit dem Label Struktur werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Struktur werden angezeigt. Alle Posts anzeigen

Dienstag, 27. August 2013

baseline TIFF – Versuch einer Rekonstruktion, Teil1

Vorwort

Im Artikel »baseline TIFF« bin ich auf den Aufbau des TIFF-Formates eingegangen. Um die Eignung von TIFF-Dateien als Bildformat für die Langzeitverfügbarkeit (bzw. Langzeitarchivierung) zu testen, habe ich das Bild aus dem Beitrag genommen, leicht geändert und mit einem Fuzzing-Tool bitweise zerstört.

Als Werkzeug habe ich zzuf genutzt, welches ich angewiesen habe, 1‰ aller Bits des Original-Bildes zufällig zu verändern.
$> zzuf -c -s87423 -r0.001 <example_tiff.tiff >fuzzy-0.001.tiff
$> display fuzzy-0.001.tiff
 
display.im6: fuzzy-0.001.tiff: invalid TIFF directory; tags are not sorted in ascending order. `TIFFReadDirectory' @ warning/tiff.c/TIFFWarnings/768.
display.im6: fuzzy-0.001.tiff: unknown field with tag 275 (0x113) encountered. `TIFFReadDirectory' @ warning/tiff.c/TIFFWarnings/768.
display.im6: fuzzy-0.001.tiff: unknown field with tag 16663 (0x4117) encountered. `TIFFReadDirectory' @ warning/tiff.c/TIFFWarnings/768.
display.im6: fuzzy-0.001.tiff: TIFF directory is missing required "StripOffsets" field. `MissingRequired' @ error/tiff.c/TIFFErrors/508.

Versuch einer Rekonstruktion des Image File Directory (IFD)

Versuchen wir das Bild zu rekonstruieren. Zur Erinnerung hier nochmal der Aufbau eines TIFFs:
Aufbau TIFF
Das kaputte TIFF-Bild sieht als Hexdump so aus:
00000000  49 49 2a 00 28 03 00 00  00 00 00 00 00 00 00 00  |II*.(...........|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000050  00 00 00 00 00 00 00 00  00 00 00 0c 00 00 00 0c  |................|
00000060  00 00 00 0c 00 00 00 0c  00 00 00 0c 00 00 00 0c  |................|
00000070  00 00 00 01 00 00 00 09  00 00 00 04 00 00 00 00  |................|
00000080  00 00 00 05 00 00 00 0c  00 00 00 0c 00 00 00 0c  |................|
00000090  00 00 00 0c 00 00 00 00  00 00 00 0c 00 00 00 0c  |................|
000000a0  00 00 00 0c 00 00 00 0c  00 00 00 f6 00 00 00 f6  |................|
000000b0  00 00 00 fa 00 00 00 ff  00 00 00 f6 00 00 00 f6  |................|
000000c0  00 00 00 1a 00 00 00 d5  00 00 00 54 00 00 00 00  |...........T....|
000000d0  00 00 00 75 00 00 00 ff  00 00 00 f5 00 00 00 f5  |...u............|
000000e0  00 00 00 ef 00 00 00 00  00 00 00 ff 00 00 00 f4  |................|
000000f0  00 00 00 f5 00 00 00 f5  00 00 00 00 00 00 00 00  |................|
00000100  10 00 00 28 00 00 00 e3  00 00 00 00 00 00 00 00  |...(............|
00000110  00 00 00 00 00 00 00 cb  00 00 00 51 00 00 00 00  |...........Q....|
00000120  00 00 00 70 00 00 00 af  00 00 00 01 00 00 00 01  |...p............|
00000130  00 00 00 00 00 00 00 00  00 00 00 ff 00 00 00 00  |................|
00000140  00 00 00 01 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000150  00 00 00 34 00 00 00 e4  00 00 00 00 00 00 00 00  |...4............|
00000160  00 00 00 00 00 00 00 cb  00 00 00 51 00 00 00 00  |...........Q....|
00000170  10 00 00 70 00 00 00 da  00 00 00 8b 00 00 00 8c  |...p............|
00000180  00 00 00 00 00 00 00 00  00 00 00 ff 00 00 00 88  |................|
00000190  00 00 00 8b 00 00 00 3d  00 00 00 00 00 00 00 00  |.......=........|
000001a0  00 00 00 34 00 00 00 e4  00 00 00 00 00 00 00 00  |...4............|
000001b0  00 00 00 00 00 00 00 cb  00 00 00 51 00 00 00 00  |...........Q....|
000001c0  00 00 00 70 00 00 00 ce  00 00 00 63 00 00 00 63  |...p.......c...c|
000001d0  00 00 00 00 00 00 00 00  00 00 00 ff 00 00 00 5f  |..............._|
000001e0  00 00 00 63 00 00 00 2b  00 00 00 00 00 00 00 00  |...c...+........|
000001f0  00 00 00 35 00 00 00 e8  00 00 00 00 00 00 00 00  |...5............|
00000200  00 00 00 00 00 00 00 cf  00 00 00 52 00 00 00 00  |...........R....|
00000210  00 00 00 72 00 00 00 af  00 00 00 00 00 00 00 00  |...r............|
00000220  00 00 00 00 00 00 01 00  20 00 00 ff 00 00 00 00  |........ .......|
00000230  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000240  00 00 00 2c 00 00 00 c2  00 00 00 00 00 00 00 00  |...,............|
00000250  00 00 00 00 00 00 00 ad  00 00 00 44 00 00 00 00  |...........D....|
00000260  00 00 00 5f 00 00 00 94  00 00 00 00 00 00 00 00  |..._............|
00000270  00 00 00 00 00 00 00 00  00 00 00 e7 00 00 00 00  |................|
00000280  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000290  00 00 00 0e 00 00 00 3c  00 00 00 00 00 00 00 00  |.......<........|
000002a0  00 00 00 00 00 00 00 35  00 00 00 15 00 00 00 00  |.......5........|
000003b0  00 00 00 1d 00 00 00 2e  00 00 00 00 00 00 00 00  |................|
000002c0  00 00 00 00 00 00 00 00  00 00 00 47 00 00 00 00  |...........G....|
000002d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000310  00 08 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000320  00 00 00 00 00 00 00 00  12 00 fe 00 04 00 01 00  |................|
00000330  00 00 00 00 00 00 00 01  03 00 01 00 00 00 14 00  |................|
00000340  00 00 01 01 03 00 01 00  00 00 0a 00 00 00 02 01  |................|
00000350  03 00 04 00 00 00 06 04  00 00 03 01 03 00 01 00  |................|
00000360  00 00 01 00 00 00 06 01  03 00 01 00 00 00 02 00  |................|
00000370  00 00 0d 01 02 00 2a 00  00 00 0e 04 00 00 06 01  |......*.........|
00000380  02 00 0e 00 00 00 38 04  00 00 13 01 04 00 01 00  |......8.........|
00000390  00 00 08 00 00 00 12 01  03 00 01 00 00 00 01 00  |................|
000003a0  00 00 15 01 03 00 01 00  00 00 04 00 00 00 16 01  |................|
000003b0  03 00 01 00 00 00 40 00  00 00 17 41 04 00 01 00  |......@....A....|
000003c0  00 00 20 03 00 00 1a 01  05 00 01 00 00 00 46 04  |.. ...........F.|
000003d0  00 00 1b 01 05 00 01 00  00 00 4e 04 00 00 1c 01  |..........N.....|
000003e0  03 00 01 00 00 00 01 00  00 00 28 01 03 00 01 00  |..........(.....|
000003f0  00 00 02 00 00 00 52 01  03 00 01 00 00 00 01 00  |......R.........|
00000400  00 00 00 00 00 00 08 00  08 00 08 00 08 00 2f 68  |............../h|
00000410  6f 6d 65 2f 72 6f 6d 65  79 6b 65 2f 44 6f 6b 75  |ome/romeyke/Doku|
00000420  6d 65 6e 74 65 2f 65 78  61 6d 70 6c 65 5f 74 69  |mente/example_ti|
00000430  66 66 2e 74 69 66 66 00  54 65 73 74 62 69 6c 64  |ff.tiff.Testbild|
00000440  20 54 49 46 46 00 00 00  00 48 00 00 00 01 00 00  | TIFF....H......|
00000450  00 48 00 00 00 01                                 |.H....|
00000456

Schauen wir uns zu erst die 8 Bytes des Headers an. Das einzig Kritische könnte ein zerstörter Offset zum IFD sein:

00000000  49 49 2a 00 28 03 00 00  00 00 00 00 00 00 00 00  |II*.(...........|

Die ersten zwei Bytes sind in Ordnung, da sie nur zwei Werte annehmen können:
0x4949 little endian (least significant to most significant byte) 
0x4d4d big endian (most significant to least significant byte)

Die nächsten zwei Bytes stellen die Zahl 42 in jeweiliger Endianess dar: 2a 00 ist also auch in Ordnung.

Die Bytes 4-7 zeigen auf das erste Image File Directory (IFD), hier die Adresse 0x0000 0328
Kann dieser Wert stimmen?

Von IFDs wissen wir, daß diese wie folgt aufgebaut sind:
Aufbau Image File Directory (IFD) in TIFF-Datei
An der Adresse 0x0328 stehen ff. Werte: 
00000320  00 00 00 00 00 00 00 00  12 00 fe 00 04 00 01 00  |................|
00000330  00 00 00 00 00 00 00 01  03 00 01 00 00 00 14 00  |................|
00000340  00 00 01 01 03 00 01 00  00 00 0a 00 00 00 02 01  |................|
00000350  03 00 04 00 00 00 06 04  00 00 03 01 03 00 01 00  |................|
00000360  00 00 01 00 00 00 06 01  03 00 01 00 00 00 02 00  |................|
00000370  00 00 0d 01 02 00 2a 00  00 00 0e 04 00 00 06 01  |......*.........|
00000380  02 00 0e 00 00 00 38 04  00 00 13 01 04 00 01 00  |......8.........|
00000390  00 00 08 00 00 00 12 01  03 00 01 00 00 00 01 00  |................|
000003a0  00 00 15 01 03 00 01 00  00 00 04 00 00 00 16 01  |................|
000003b0  03 00 01 00 00 00 40 00  00 00 17 41 04 00 01 00  |......@....A....|
000003c0  00 00 20 03 00 00 1a 01  05 00 01 00 00 00 46 04  |.. ...........F.|
000003d0  00 00 1b 01 05 00 01 00  00 00 4e 04 00 00 1c 01  |..........N.....|
000003e0  03 00 01 00 00 00 01 00  00 00 28 01 03 00 01 00  |..........(.....|
000003f0  00 00 02 00 00 00 52 01  03 00 01 00 00 00 01 00  |......R.........|
00000400  00 00 00 00 00 00 08 00  08 00 08 00 08 00 2f 68  |............../h|
00000410  6f 6d 65 2f 72 6f 6d 65  79 6b 65 2f 44 6f 6b 75  |ome/romeyke/Doku|
00000420  6d 65 6e 74 65 2f 65 78  61 6d 70 6c 65 5f 74 69  |mente/example_ti|
00000430  66 66 2e 74 69 66 66 00  54 65 73 74 62 69 6c 64  |ff.tiff.Testbild|
00000440  20 54 49 46 46 00 00 00  00 48 00 00 00 01 00 00  | TIFF....H......|
00000450  00 48 00 00 00 01                                 |.H....|
00000456

Die Anzahl der Tags ergibt sich aus den Bytes 0x0328 und 0x0329 mit Wert 0x12 und 0x00, was für  18 Einträge steht. Dieser Wert klingt erstmal plausibel. Wir wissen, daß jedes Tag 12 Byte groß ist und im baseline-TIFF der nextIFD-Eintrag aus 4Bytes mit dem Wert 0x00 besteht. Schauen wir also an die Adresse 0x0328+2+12*18 = 0x402. Dort stehen 4 mal die Werte 0x00. Sieht erst einmal korrekt aus.

Wir können also annehmen, daß das IFD korrekt ist. Jeder Eintrag im IFD besteht ja aus 12 Bytes und ist wie folgt aufgebaut:
Tag-Eintrag
Aus dem Artikel zu baseline TIFF wissen wir, daß die Tags in ihrer Nummer (ID) aufsteigend sortiert sind. Lesen wir dazu jeweils die 2 Bytes mit Offset n*12:
  • 1. 0x32a: 0xfe 0x00 -> 254
  • 2. 0x336: 0x00 0x01 -> 64
  • 3. 0x342: 0x01 0x01 -> 257
  • 4. 0x34e: 0x02 0x01 -> 258
  • 5. 0x35a: 0x03 0x01 -> 259
  • 6. 0x366: 0x06 0x01 -> 262
  • 7. 0x372: 0x0d 0x01 -> 269
  • 8. 0x37e: 0x06 0x01 -> 262
  • 9. 0x38a: 0x13 0x01 -> 275
  • 10.0x396: 0x12 0x01 -> 274
  • 11.0x3a2: 0x15 0x01 -> 277
  • 12.0x3ae: 0x16 0x01 -> 278
  • 13.0x3ba: 0x17 0x41 -> 16663
  • 14.0x3c6: 0x1a 0x01 -> 282
  • 15.0x3d2: 0x1b 0x01 -> 283
  • 16.0x3de: 0x1c 0x01 -> 284
  • 17.0x3ea: 0x28 0x01 -> 296
  • 18.0x3f6: 0x52 0x01 -> 338

Ins Auge fallen die Tags 2, 6, 8, 13 u. 18. Insbesondere Tag 2 und 13 können nicht stimmen, da sie krass die Sortierung verletzten. Eventuell müssen wir die Tags 6-10 nochmal prüfen.

Der Tag 2 an Adresse 0x336 müsste einen Wert um die 250 enthalten.Sehr wahrscheinlich ist, daß er statt 0x00 0x01 die Folge 0x01 0x00 enthält, was dem Wert 256 entspräche.

Der Tag 13 an Adresse 0x3ba hat wahrscheinlich im zweiten Byte nur einen Bit-Fehler und sollte statt 0x17 0x41 die Folge 0x17 0x01 enthalten. Das ergebe dann den Wert 279.

Tragen wir die Tag-Bezeichner und die vorläufig korrigierten Tags des IFD ein:
  • 1. 0x32a: 0xfe 0x00 -> 254 -> TIFFTAG_SUBFILETYPE
  • 2. 0x336: 0x00 0x01 -> 256 -> TIFFTAG_IMAGEWIDTH
  • 3. 0x342: 0x01 0x01 -> 257 -> TIFFTAG_IMAGELENGTH
  • 4. 0x34e: 0x02 0x01 -> 258 -> TIFFTAG_BITSPERSAMPLE
  • 5. 0x35a: 0x03 0x01 -> 259 -> TIFFTAG_COMPRESSION
  • 6. 0x366: 0x06 0x01 -> 262 -> TIFFTAG_PHOTOMETRIC
  • 7. 0x372: 0x0d 0x01 -> 269 -> TIFFTAG_DOCUMENTNAME
  • 8. 0x37e: 0x06 0x01 -> 262 -> TIFFTAG_PHOTOMETRIC
  • 9. 0x38a: 0x13 0x01 -> 275 ->  (nicht existent)
  • 10.0x396: 0x12 0x01 -> 274 -> TIFFTAG_ORIENTATION
  • 11.0x3a2: 0x15 0x01 -> 277 -> TIFFTAG_SAMPLESPERPIXEL
  • 12.0x3ae: 0x16 0x01 -> 278 -> TIFFTAG_ROWSPERSTRIP
  • 13.0x3ba: 0x17 0x01 -> 279 -> TIFFTAG_STRIPBYTECOUNTS
  • 14.0x3c6: 0x1a 0x01 -> 282 -> TIFFTAG_XRESOLUTION
  • 15.0x3d2: 0x1b 0x01 -> 283 -> TIFFTAG_YRESOLUTION
  • 16.0x3de: 0x1c 0x01 -> 284 -> TIFFTAG_PLANARCONFIG
  • 17.0x3ea: 0x28 0x01 -> 296 -> TIFFTAG_RESOLUTIONUNIT
  • 18.0x3f6: 0x52 0x01 -> 338 -> TIFFTAG_EXTRASAMPLES
Bis auf Eintrag 9 und eventuell Eintrag 18 klingen die Tags so sinnvoll, daß sie richtig sein könnten. Tag 9 muß dann zwischen 262 und 274 liegen und könnte ff. Tags enthalten:
  • TIFFTAG_THRESHHOLDING           263 
  • TIFFTAG_CELLWIDTH               264
  • TIFFTAG_CELLLENGTH              265
  • TIFFTAG_FILLORDER               266
  • TIFFTAG_DOCUMENTNAME            269
  • TIFFTAG_IMAGEDESCRIPTION        270
  • TIFFTAG_MAKE                    271
  • TIFFTAG_MODEL                   272
  • TIFFTAG_STRIPOFFSETS            273
Wenn wir tiffinfo (Teil der libtiff) zur Hilfe nehmen, bekommen wir ff. Ausgabe:

$> tiffinfo fuzzy-0.001.tiff
TIFFReadDirectoryCheckOrder: Warning, Invalid TIFF directory; tags are not sorted in ascending order.
TIFFReadDirectory: Warning, Unknown field with tag 275 (0x113) encountered.
TIFFReadDirectory: Warning, Unknown field with tag 16663 (0x4117) encountered.
MissingRequired: TIFF directory is missing required "StripOffsets" field.


Also ist Eintrag 9 mit hoher Wahrscheinlichkeit das Tag TIFFTAG_STRIPOFFSETS mit ID 273.

Ende Teil1


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.