imghdr.py 2.77 KB
Newer Older
Guido van Rossum's avatar
Guido van Rossum committed
1 2 3 4
# Recognizing image files based on their first few bytes.


#-------------------------#
5
# Recognize image headers #
Guido van Rossum's avatar
Guido van Rossum committed
6 7
#-------------------------#

8
def what(file, h=None):
9
	if h is None:
10 11 12 13 14 15 16 17
		if type(file) == type(''):
			f = open(file, 'rb')
			h = f.read(32)
		else:
			location = file.tell()
			h = file.read(32)
			file.seek(location)
			f = None	
18 19 20 21 22 23 24 25 26
	else:
		f = None
	try:
		for tf in tests:
			res = tf(h, f)
			if res:
				return res
	finally:
		if f: f.close()
Guido van Rossum's avatar
Guido van Rossum committed
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
	return None


#---------------------------------#
# Subroutines per image file type #
#---------------------------------#

tests = []

def test_rgb(h, f):
	# SGI image library
	if h[:2] == '\001\332':
		return 'rgb'

tests.append(test_rgb)

def test_gif(h, f):
	# GIF ('87 and '89 variants)
	if h[:6] in ('GIF87a', 'GIF89a'):
		return 'gif'

tests.append(test_gif)

50 51
def test_pbm(h, f):
	# PBM (portable bitmap)
52
	if len(h) >= 3 and \
53 54
		h[0] == 'P' and h[1] in '14' and h[2] in ' \t\n\r':
		return 'pbm'
Guido van Rossum's avatar
Guido van Rossum committed
55

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
tests.append(test_pbm)

def test_pgm(h, f):
	# PGM (portable graymap)
	if len(h) >= 3 and \
		h[0] == 'P' and h[1] in '25' and h[2] in ' \t\n\r':
		return 'pgm'

tests.append(test_pgm)

def test_ppm(h, f):
	# PPM (portable pixmap)
	if len(h) >= 3 and \
		h[0] == 'P' and h[1] in '36' and h[2] in ' \t\n\r':
		return 'ppm'

tests.append(test_ppm)
Guido van Rossum's avatar
Guido van Rossum committed
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87

def test_tiff(h, f):
	# TIFF (can be in Motorola or Intel byte order)
	if h[:2] in ('MM', 'II'):
		return 'tiff'

tests.append(test_tiff)

def test_rast(h, f):
	# Sun raster file
	if h[:4] == '\x59\xA6\x6A\x95':
		return 'rast'

tests.append(test_rast)

88 89 90 91 92 93 94 95
def test_xbm(h, f):
	# X bitmap (X10 or X11)
	s = '#define '
	if h[:len(s)] == s:
		return 'xbm'

tests.append(test_xbm)

96 97 98 99 100 101
def test_jpeg(h, f):
	# JPEG data in JFIF format
	if h[6:10] == 'JFIF':
		return 'jpeg'

tests.append(test_jpeg)
Guido van Rossum's avatar
Guido van Rossum committed
102

103 104 105 106 107 108 109 110 111 112 113 114
def test_bmp(h, f):
	if h[:2] == 'BM':
		return 'bmp'
		
tests.append(test_bmp)

def test_png(h, f):
	if h[:8] == "\211PNG\r\n\032\n":
		return 'png'

tests.append(test_png)

Guido van Rossum's avatar
Guido van Rossum committed
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
#--------------------#
# Small test program #
#--------------------#

def test():
	import sys
	recursive = 0
	if sys.argv[1:] and sys.argv[1] == '-r':
		del sys.argv[1:2]
		recursive = 1
	try:
		if sys.argv[1:]:
			testall(sys.argv[1:], recursive, 1)
		else:
			testall(['.'], recursive, 1)
	except KeyboardInterrupt:
		sys.stderr.write('\n[Interrupted]\n')
		sys.exit(1)

def testall(list, recursive, toplevel):
	import sys
	import os
	for filename in list:
		if os.path.isdir(filename):
			print filename + '/:',
			if recursive or toplevel:
				print 'recursing down:'
				import glob
				names = glob.glob(os.path.join(filename, '*'))
				testall(names, recursive, 0)
			else:
				print '*** directory (use -r) ***'
		else:
			print filename + ':',
			sys.stdout.flush()
			try:
				print what(filename)
			except IOError:
				print '*** not found ***'