Image file types

Microdoft BMP

The header is divided into two parts:

  1. First 14 bytes (0-13) is the file header
  2. The following 40 bytes (14-53) is the information header
Bytes Information Description
00-01 Signature 42 4D
02-05 File size in bytes
06-09 Reserved zeros
10-13 Data offset
14-17 Size of information header 40 bytes
18-21 Width in pixels
22-25 Height in pixels
26-27 Planes 1
28-29 Bit count 1-24 for bit depth
30-33 Compression 0 for no compression, 1 for 8-bit RLE, 2 for 4-bit RLE
34-37 Image size
38-41 Horizontal reolution in pixels per meter
42-45 Vertical resolution in pixels per meter
46-49 Colors used if zero then 2^BitsCount
50-53 Important colors zero if all important

If BitCount is less than or equal to 8, after the header comes the color table, which uses 4 times ColorsUsed. BMP format uses little endian convention for byte ordering: in each word of 4 bytes the least valued byte comes first. More about BMP at Wikipedia.

hexdump('images/sample.bmp', 128)
000000: 424d 8a7b 0c00 0000 0000 8a00 0000 7c00 |BM.{..........|.|
000010: 0000 8002 0000 aa01 0000 0100 1800 0000 |................|
000020: 0000 007b 0c00 0000 0000 0000 0000 0000 |...{............|
000030: 0000 0000 0000 0000 ff00 00ff 0000 ff00 |................|
000040: 0000 0000 00ff 4247 5273 80c2 f528 60b8 |......BGRs...(`.|
000050: 1e15 2085 eb01 4033 3313 8066 6626 4066 |.. [email protected]&@f|
000060: 6606 a099 9909 3c0a d703 245c 8f32 0000 |f.....<...$\.2..|
000070: 0000 0000 0000 0000 0000 0400 0000 0000 |................|
8002 0000 -> 0000 0280 -> 640
aa01 0000 -> 0000 01aa -> 426

PNG

PNG format header information is encoded in four-letter chunks: IHDR for image resolution and depth, PLTE for color palette, IDAT for image data, and IEND marks the end of file. There may be other chunks describing data.

hexdump('images/cameraman.png',128)
000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 |.PNG........IHDR|
000010: 0000 0200 0000 0200 0803 0000 00c3 a624 |...............$|
000020: c800 0000 0467 414d 4100 00b1 8f0b fc61 |.....gAMA......a|
000030: 0500 0000 0173 5247 4200 aece 1ce9 0000 |.....sRGB.......|
000040: 0180 504c 5445 0c0c 0ca1 a1a1 a9a9 a99f |..PLTE..........|
000050: 9f9f 0a0a 0aa7 a7a7 0808 080e 0e0e a3a3 |................|
000060: a3a5 a5a5 abab abb5 b5b5 adad adb3 b3b3 |................|
000070: 9d9d 9db1 b1b1 afaf afb7 b7b7 9b9b 9b97 |................|

Hexdump function

from math import ceil
def hexdump(file, n):
    f = open(file, 'rb')
    h = f.read(n)
    hl = [hex(c)[2:].zfill(2) for c in h] # all the bytes as 2 character hex strings
    hl2 = hl + (-len(hl)%16)*['  '] # fill up to a multiple of width 16
    asc = ['.']*n
    for i in range(n): # create ascii values (if printable) of bytes
        ii = int(hl[i], 16)
        if ii >= 32 and ii <= 126:
            asc[i] = chr(ii)
    asc = asc + (-len(hl)%16)*[' '] # fill up to a multiple of width 16
    for i in range(int(ceil(n/16))):
        print(hex(i*16)[2:].zfill(6) + ': ' + \
              ' '.join([hl2[16*i+2*j]+hl2[16*i+2*j+1] for j in range(8)]) + \
              ' |' + ''.join([asc[16*i+j] for j in range(16)]) + '|')