blob: 76e8abb2d5833d487ba94e9ebe31f66e1fb9df0c [file] [log] [blame]
Guido van Rossum54f22ed2000-02-04 15:10:34 +00001"""Recognize image file formats based on their first few bytes."""
Guido van Rossum1c34fc71992-05-27 14:06:59 +00002
Berker Peksagef223a12016-10-01 05:01:54 +03003from os import PathLike
4
Skip Montanaro17ab1232001-01-24 06:27:27 +00005__all__ = ["what"]
Guido van Rossum1c34fc71992-05-27 14:06:59 +00006
7#-------------------------#
Guido van Rossum45ac47c1997-10-08 15:22:32 +00008# Recognize image headers #
Guido van Rossum1c34fc71992-05-27 14:06:59 +00009#-------------------------#
10
Guido van Rossum45ac47c1997-10-08 15:22:32 +000011def what(file, h=None):
Serhiy Storchaka91b0bc22014-01-25 19:43:02 +020012 f = None
Guido van Rossum54f22ed2000-02-04 15:10:34 +000013 try:
Serhiy Storchaka91b0bc22014-01-25 19:43:02 +020014 if h is None:
Berker Peksagef223a12016-10-01 05:01:54 +030015 if isinstance(file, (str, PathLike)):
Serhiy Storchaka91b0bc22014-01-25 19:43:02 +020016 f = open(file, 'rb')
17 h = f.read(32)
18 else:
19 location = file.tell()
20 h = file.read(32)
21 file.seek(location)
Guido van Rossum54f22ed2000-02-04 15:10:34 +000022 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
Guido van Rossum1c34fc71992-05-27 14:06:59 +000029
30
31#---------------------------------#
32# Subroutines per image file type #
33#---------------------------------#
34
35tests = []
36
Benjamin Peterson0b952902008-08-16 16:48:16 +000037def test_jpeg(h, f):
38 """JPEG data in JFIF or Exif format"""
39 if h[6:10] in (b'JFIF', b'Exif'):
40 return 'jpeg'
Guido van Rossum1c34fc71992-05-27 14:06:59 +000041
Benjamin Peterson0b952902008-08-16 16:48:16 +000042tests.append(test_jpeg)
43
44def test_png(h, f):
45 if h.startswith(b'\211PNG\r\n\032\n'):
46 return 'png'
47
48tests.append(test_png)
Guido van Rossum1c34fc71992-05-27 14:06:59 +000049
50def test_gif(h, f):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000051 """GIF ('87 and '89 variants)"""
Barry Warsaw72937f32007-08-12 14:37:20 +000052 if h[:6] in (b'GIF87a', b'GIF89a'):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000053 return 'gif'
Guido van Rossum1c34fc71992-05-27 14:06:59 +000054
55tests.append(test_gif)
56
Benjamin Peterson0b952902008-08-16 16:48:16 +000057def test_tiff(h, f):
58 """TIFF (can be in Motorola or Intel byte order)"""
59 if h[:2] in (b'MM', b'II'):
60 return 'tiff'
61
62tests.append(test_tiff)
63
64def test_rgb(h, f):
65 """SGI image library"""
66 if h.startswith(b'\001\332'):
67 return 'rgb'
68
69tests.append(test_rgb)
70
Guido van Rossum2db91351992-10-18 17:09:59 +000071def test_pbm(h, f):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000072 """PBM (portable bitmap)"""
73 if len(h) >= 3 and \
Guido van Rossumc9341282007-08-13 17:50:00 +000074 h[0] == ord(b'P') and h[1] in b'14' and h[2] in b' \t\n\r':
Guido van Rossum54f22ed2000-02-04 15:10:34 +000075 return 'pbm'
Guido van Rossum1c34fc71992-05-27 14:06:59 +000076
Guido van Rossum2db91351992-10-18 17:09:59 +000077tests.append(test_pbm)
78
79def test_pgm(h, f):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000080 """PGM (portable graymap)"""
81 if len(h) >= 3 and \
Guido van Rossumc9341282007-08-13 17:50:00 +000082 h[0] == ord(b'P') and h[1] in b'25' and h[2] in b' \t\n\r':
Guido van Rossum54f22ed2000-02-04 15:10:34 +000083 return 'pgm'
Guido van Rossum2db91351992-10-18 17:09:59 +000084
85tests.append(test_pgm)
86
87def test_ppm(h, f):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000088 """PPM (portable pixmap)"""
89 if len(h) >= 3 and \
Guido van Rossumc9341282007-08-13 17:50:00 +000090 h[0] == ord(b'P') and h[1] in b'36' and h[2] in b' \t\n\r':
Guido van Rossum54f22ed2000-02-04 15:10:34 +000091 return 'ppm'
Guido van Rossum2db91351992-10-18 17:09:59 +000092
93tests.append(test_ppm)
Guido van Rossum1c34fc71992-05-27 14:06:59 +000094
Guido van Rossum1c34fc71992-05-27 14:06:59 +000095def test_rast(h, f):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000096 """Sun raster file"""
Guido van Rossumc9341282007-08-13 17:50:00 +000097 if h.startswith(b'\x59\xA6\x6A\x95'):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000098 return 'rast'
Guido van Rossum1c34fc71992-05-27 14:06:59 +000099
100tests.append(test_rast)
101
Guido van Rossum05b55e71992-06-03 16:48:44 +0000102def test_xbm(h, f):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000103 """X bitmap (X10 or X11)"""
Guido van Rossumc9341282007-08-13 17:50:00 +0000104 if h.startswith(b'#define '):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000105 return 'xbm'
Guido van Rossum05b55e71992-06-03 16:48:44 +0000106
107tests.append(test_xbm)
108
Guido van Rossum9e330741997-04-11 18:59:38 +0000109def test_bmp(h, f):
Guido van Rossumc9341282007-08-13 17:50:00 +0000110 if h.startswith(b'BM'):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000111 return 'bmp'
Tim Peters07e99cb2001-01-14 23:47:14 +0000112
Guido van Rossum9e330741997-04-11 18:59:38 +0000113tests.append(test_bmp)
114
Serhiy Storchaka2f8dca72014-05-25 11:45:37 +0300115def test_webp(h, f):
116 if h.startswith(b'RIFF') and h[8:12] == b'WEBP':
117 return 'webp'
118
119tests.append(test_webp)
120
R David Murray2f608202014-06-26 12:27:57 -0400121def test_exr(h, f):
122 if h.startswith(b'\x76\x2f\x31\x01'):
123 return 'exr'
124
125tests.append(test_exr)
126
Guido van Rossum1c34fc71992-05-27 14:06:59 +0000127#--------------------#
128# Small test program #
129#--------------------#
130
131def test():
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000132 import sys
133 recursive = 0
134 if sys.argv[1:] and sys.argv[1] == '-r':
135 del sys.argv[1:2]
136 recursive = 1
137 try:
138 if sys.argv[1:]:
139 testall(sys.argv[1:], recursive, 1)
140 else:
141 testall(['.'], recursive, 1)
142 except KeyboardInterrupt:
143 sys.stderr.write('\n[Interrupted]\n')
144 sys.exit(1)
Guido van Rossum1c34fc71992-05-27 14:06:59 +0000145
146def testall(list, recursive, toplevel):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000147 import sys
148 import os
149 for filename in list:
150 if os.path.isdir(filename):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000151 print(filename + '/:', end=' ')
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000152 if recursive or toplevel:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000153 print('recursing down:')
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000154 import glob
155 names = glob.glob(os.path.join(filename, '*'))
156 testall(names, recursive, 0)
157 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000158 print('*** directory (use -r) ***')
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000159 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000160 print(filename + ':', end=' ')
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000161 sys.stdout.flush()
162 try:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000163 print(what(filename))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200164 except OSError:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000165 print('*** not found ***')
Barry Warsaw72937f32007-08-12 14:37:20 +0000166
167if __name__ == '__main__':
168 test()