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