1"""Recognize image file formats based on their first few bytes."""
2
3__all__ = ["what"]
4
5#-------------------------#
6# Recognize image headers #
7#-------------------------#
8
9def what(file, h=None):
10    if h is None:
11        if isinstance(file, basestring):
12            f = open(file, 'rb')
13            h = f.read(32)
14        else:
15            location = file.tell()
16            h = file.read(32)
17            file.seek(location)
18            f = None
19    else:
20        f = None
21    try:
22        for tf in tests:
23            res = tf(h, f)
24            if res:
25                return res
26    finally:
27        if f: f.close()
28    return None
29
30
31#---------------------------------#
32# Subroutines per image file type #
33#---------------------------------#
34
35tests = []
36
37def test_jpeg(h, f):
38    """JPEG data in JFIF format"""
39    if h[6:10] == 'JFIF':
40        return 'jpeg'
41
42tests.append(test_jpeg)
43
44def test_exif(h, f):
45    """JPEG data in Exif format"""
46    if h[6:10] == 'Exif':
47        return 'jpeg'
48
49tests.append(test_exif)
50
51def test_png(h, f):
52    if h[:8] == "\211PNG\r\n\032\n":
53        return 'png'
54
55tests.append(test_png)
56
57def test_gif(h, f):
58    """GIF ('87 and '89 variants)"""
59    if h[:6] in ('GIF87a', 'GIF89a'):
60        return 'gif'
61
62tests.append(test_gif)
63
64def test_tiff(h, f):
65    """TIFF (can be in Motorola or Intel byte order)"""
66    if h[:2] in ('MM', 'II'):
67        return 'tiff'
68
69tests.append(test_tiff)
70
71def test_rgb(h, f):
72    """SGI image library"""
73    if h[:2] == '\001\332':
74        return 'rgb'
75
76tests.append(test_rgb)
77
78def test_pbm(h, f):
79    """PBM (portable bitmap)"""
80    if len(h) >= 3 and \
81        h[0] == 'P' and h[1] in '14' and h[2] in ' \t\n\r':
82        return 'pbm'
83
84tests.append(test_pbm)
85
86def test_pgm(h, f):
87    """PGM (portable graymap)"""
88    if len(h) >= 3 and \
89        h[0] == 'P' and h[1] in '25' and h[2] in ' \t\n\r':
90        return 'pgm'
91
92tests.append(test_pgm)
93
94def test_ppm(h, f):
95    """PPM (portable pixmap)"""
96    if len(h) >= 3 and \
97        h[0] == 'P' and h[1] in '36' and h[2] in ' \t\n\r':
98        return 'ppm'
99
100tests.append(test_ppm)
101
102def test_rast(h, f):
103    """Sun raster file"""
104    if h[:4] == '\x59\xA6\x6A\x95':
105        return 'rast'
106
107tests.append(test_rast)
108
109def test_xbm(h, f):
110    """X bitmap (X10 or X11)"""
111    s = '#define '
112    if h[:len(s)] == s:
113        return 'xbm'
114
115tests.append(test_xbm)
116
117def test_bmp(h, f):
118    if h[:2] == 'BM':
119        return 'bmp'
120
121tests.append(test_bmp)
122
123#--------------------#
124# Small test program #
125#--------------------#
126
127def test():
128    import sys
129    recursive = 0
130    if sys.argv[1:] and sys.argv[1] == '-r':
131        del sys.argv[1:2]
132        recursive = 1
133    try:
134        if sys.argv[1:]:
135            testall(sys.argv[1:], recursive, 1)
136        else:
137            testall(['.'], recursive, 1)
138    except KeyboardInterrupt:
139        sys.stderr.write('\n[Interrupted]\n')
140        sys.exit(1)
141
142def testall(list, recursive, toplevel):
143    import sys
144    import os
145    for filename in list:
146        if os.path.isdir(filename):
147            print filename + '/:',
148            if recursive or toplevel:
149                print 'recursing down:'
150                import glob
151                names = glob.glob(os.path.join(filename, '*'))
152                testall(names, recursive, 0)
153            else:
154                print '*** directory (use -r) ***'
155        else:
156            print filename + ':',
157            sys.stdout.flush()
158            try:
159                print what(filename)
160            except IOError:
161                print '*** not found ***'
162