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