"""Recognize image file formats based on their first few bytes.""" | |
__all__ = ["what"] | |
#-------------------------# | |
# Recognize image headers # | |
#-------------------------# | |
def what(file, h=None): | |
if h is None: | |
if isinstance(file, basestring): | |
f = open(file, 'rb') | |
h = f.read(32) | |
else: | |
location = file.tell() | |
h = file.read(32) | |
file.seek(location) | |
f = None | |
else: | |
f = None | |
try: | |
for tf in tests: | |
res = tf(h, f) | |
if res: | |
return res | |
finally: | |
if f: f.close() | |
return None | |
#---------------------------------# | |
# Subroutines per image file type # | |
#---------------------------------# | |
tests = [] | |
def test_jpeg(h, f): | |
"""JPEG data in JFIF format""" | |
if h[6:10] == 'JFIF': | |
return 'jpeg' | |
tests.append(test_jpeg) | |
def test_exif(h, f): | |
"""JPEG data in Exif format""" | |
if h[6:10] == 'Exif': | |
return 'jpeg' | |
tests.append(test_exif) | |
def test_png(h, f): | |
if h[:8] == "\211PNG\r\n\032\n": | |
return 'png' | |
tests.append(test_png) | |
def test_gif(h, f): | |
"""GIF ('87 and '89 variants)""" | |
if h[:6] in ('GIF87a', 'GIF89a'): | |
return 'gif' | |
tests.append(test_gif) | |
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_rgb(h, f): | |
"""SGI image library""" | |
if h[:2] == '\001\332': | |
return 'rgb' | |
tests.append(test_rgb) | |
def test_pbm(h, f): | |
"""PBM (portable bitmap)""" | |
if len(h) >= 3 and \ | |
h[0] == 'P' and h[1] in '14' and h[2] in ' \t\n\r': | |
return 'pbm' | |
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) | |
def test_rast(h, f): | |
"""Sun raster file""" | |
if h[:4] == '\x59\xA6\x6A\x95': | |
return 'rast' | |
tests.append(test_rast) | |
def test_xbm(h, f): | |
"""X bitmap (X10 or X11)""" | |
s = '#define ' | |
if h[:len(s)] == s: | |
return 'xbm' | |
tests.append(test_xbm) | |
def test_bmp(h, f): | |
if h[:2] == 'BM': | |
return 'bmp' | |
tests.append(test_bmp) | |
#--------------------# | |
# 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 ***' |