imghdr.py 3.9 KB

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