概要
Pythonのimghdrモジュールを使って画像ファイルの形式を判定する。
バージョン情報
- Python 3.7.6
参考ページ
https://docs.python.org/ja/3/library/imghdr.html
ファイル名を指定して判定
pngファイルをimghdrで判定してみる。
test.pngというファイル名で何か適当なpngファイルを保存し、下記のコードを実行する。
imghdr.what('test.png') #=> png
pngという文字列が返ってきた。jpegファイルならjpeg、gifファイルならgifという文字列が返る。
上記で使った test.png のファイル名だけ test.jpg に変更して判定してみる。
imghdr.what('test.jpg') #=> png
ちゃんとファイルの中身を見て判定しているので、拡張子が変わっても判定結果が変わることはない。
既に開いているファイルの判定
openしたファイルについても引数に渡せる。
with open('test.png', 'rb') as fp: print( imghdr.what(fp) ) #=> png
3系の場合、開く時は rb で開かないとエラーになるので注意。
with open('test.png') as fp: print( imghdr.what(fp) ) #=> UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte
imghdrの仕組み
imghdrはファイルの冒頭32byteを読み込んでマジックナンバー等を確認している。
下記はpngチェックの実装。
def test_png(h, f): if h.startswith(b'\211PNG\r\n\032\n'): return 'png'
pngのシグネチャは 89 50 4E 47 0D 0A 1A 0A で、これをbytesで表すとこうなるらしい。
こちらはjpeg。
def test_jpeg(h, f): """JPEG data in JFIF or Exif format""" if h[6:10] in (b'JFIF', b'Exif'): return 'jpeg'
jpegのチェックは見ての通り、適当に書いたテキストでも通過してしまうケースはある。
例えば下記のテキストを保存したファイルはjpegと判定される。
hoge AJFIF fuga
この実装を読むと画像ファイルのシグネチャについて詳しくなれそう。
https://github.com/python/cpython/blob/3.8/Lib/imghdr.py
判定可能なファイル形式
値 | Image format |
---|---|
rgb | SGI ImgLib Files |
gif | GIF 87a and 89a Files |
pbm | Portable Bitmap Files |
pgm | Portable Graymap Files |
ppm | Portable Pixmap Files |
tiff | TIFF Files |
rast | Sun Raster Files |
xbm | X Bitmap Files |
jpeg | JPEG data in JFIF or Exif formats |
bmp | BMP files |
png | Portable Network Graphics |
webp | WebP files |
exr | OpenEXR Files |
改定履歴
Author: Masato Watanabe, Date: 2020-01-25, 記事投稿