Last modified: Tue Dec 6 13:44:52 UTC+0100 2016 © A. Tarpai
TIFF decoder
I did not plan to display TIFF images in my homebrew OS. The only reason was to test the LZW-decompressor for the TIFF LZW-variant.
Test TIFF image from Pixar:
probably not displayed by the browser
TIFF converted to PNG and the BPM output of the decoder:
Image data decompression succeeds, but obviously TIFF used transparency for those black background pixels - not supported at the moment.
Lets look at decoder's output:
Opening strike.tif
Header: big-endian
IFD: 16 entries:
IFD-Entry: 256
ImageWidth: 256
IFD-Entry: 257
ImageLength: 200
IFD-Entry: 258
4 x BitsPerSample: 8 8 8 8
IFD-Entry: 259
Compression: 5 (LZW)
IFD-Entry: 262
IFD-Entry: 273
Number of Strips: 25
IFD-Entry: 277
SamplesPerPixel: 4
IFD-Entry: 278
RowsPerStrip: 8
IFD-Entry: 279
IFD-Entry: 282
IFD-Entry: 283
IFD-Entry: 284
IFD-Entry: 286
IFD-Entry: 287
IFD-Entry: 296
IFD-Entry: 338
Decoding...
00000008: strip 1 (compressed data of 147 bytes)
0000009b: strip 2 (compressed data of 147 bytes)
0000012e: strip 3 (compressed data of 814 bytes)
0000045c: strip 4 (compressed data of 2634 bytes)
00000ea6: strip 5 (compressed data of 3637 bytes)
00001cdb: strip 6 (compressed data of 3454 bytes)
00002a59: strip 7 (compressed data of 3262 bytes)
00003717: strip 8 (compressed data of 4095 bytes)
00004716: strip 9 (compressed data of 4714 bytes)
00005980: strip 10 (compressed data of 5226 bytes)
00006dea: strip 11 (compressed data of 5571 bytes)
000083ad: strip 12 (compressed data of 6633 bytes)
00009d96: strip 13 (compressed data of 6565 bytes)
0000b73b: strip 14 (compressed data of 6082 bytes)
0000cefd: strip 15 (compressed data of 5717 bytes)
0000e552: strip 16 (compressed data of 5884 bytes)
0000fc4e: strip 17 (compressed data of 6288 bytes)
000114de: strip 18 (compressed data of 6128 bytes)
00012cce: strip 19 (compressed data of 5211 bytes)
00014129: strip 20 (compressed data of 4903 bytes)
00015450: strip 21 (compressed data of 5064 bytes)
00016818: strip 22 (compressed data of 5200 bytes)
00017c68: strip 23 (compressed data of 5265 bytes)
000190f9: strip 24 (compressed data of 5398 bytes)
0001a60f: strip 25 (compressed data of 2159 bytes)
Writing strike.bmp.
The image is 256 x 200 pixels. 4 samples per pixel, some form of RGBA. 25 strips, 8 rows each strip = 200. LZW compression.
When LZW writes directly into BMP pixel data, the image showed up like this:
This is because there are a few possibilities how to store packed RGBA pixels, and it varies from standard to platform and software:
A R G B .. R G B A .. A B G R .. B G R A .. (BM format)
The decoder, being a dummy TIFF reader, simply ignores the alpha component (it seems like this TIFF used alpha for transparency only).
TIFF structure
TIFF image data is compressed in units of strips, located anywhere in the TIFF file. Each strip covers RowsPerStrip of image data:
+-------------------------------------+ | | | STRIP | | | +-------------------------------------+ | ............................... | | ..........RowsPerStrip..... | | ...................... | +-------------------------------------+ | | | | | | +-------------------------------------+ | | | | | | +-------------------------------------+ | | | | | | +-------------------------------------+
Indeed, for the first strip: 8 + 147 = 155 (9Bhex), the start offset of the next strip.
TIFF LZW-variant
LZW data per Strip.
- CodeSize always starts with 9-bits
- first CodeWord is CLR
- increase CodeSize after writing Directory Entry #510, #1022, #2046 and #4094
- after writing Directory Entry #4094 we expect CLR (as the last 12-bit code for 4095)
TIFF pixel structure
- Bilevel
- Grayscale
- Palette-color
- RGB Full Color
TIFF compression
- no compression
- Huffman
- PackBits
- LZW
- LZW + Differencing Predictor
20120410 A. Tarpai


