imghdr.py 4.3 KB

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