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