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