imghdr.py 3.7 KB

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