やりたいこと
画像ファイルが JPEG 2000 形式かどうかを判別したい。本来は JPEG 2000 形式の画像ファイルは拡張子が .jp2 である。しかし、拡張子が .jpg だったり MIME タイプが image/jpeg だったりしても、実際は JPEG 2000 形式である場合がある。そこで、バイナリデータを確認して判断する。
方法
マジックナンバー (フォーマット識別子) で判断する。RFC 3745 - MIME Type Registrations for JPEG 2000 (ISO/IEC 15444) には
Magic number(s): 12 byte string: X'0000 000C 6A50 2020 0D0A 870A' (for all JPEG-2000 family files)
と記載されているので、それに則る。
Ruby
def jpeg_2000?(binary_string)
magic_number = %w(00 00 00 0C 6A 50 20 20 0D 0A 87 0A).join
binary_string[0...12].unpack1('H*').upcase == magic_number
end
require 'pathname'
# ~/Downloads/JPEG.jpg は JPEG 形式。
jpeg_image = Pathname(Dir.home).join('Downloads/JPEG.jpg')
jpeg_2000?(jpeg_image.binread)
#=> false
# ~/Downloads/JPEG_2000.jpg は JPEG 2000 形式 (だが拡張子は .jpg) 。
jpeg_2000_image = Pathname(Dir.home).join('Downloads/JPEG_2000.jpg')
jpeg_2000?(jpeg_2000_image.binread)
#=> true
Python
import binascii
def is_jpeg_2000(bytes):
magic_number = '00 00 00 0C 6A 50 20 20 0D 0A 87 0A'
return binascii.hexlify(bytes[0:12]).decode('utf-8').upper() == ''.join(magic_number.split())
import os
# ~/Downloads/JPEG.jpg は JPEG 形式。
jpeg_image = os.path.join(os.environ['HOME'], 'Downloads/JPEG.jpg')
with open(jpeg_image, 'rb') as f:
is_jpeg_2000(f.read()) # False
# ~/Downloads/JPEG_2000.jpg は JPEG 2000 形式 (だが拡張子は .jpg) 。
jpeg_2000_image = os.path.join(os.environ['HOME'], 'Downloads/JPEG_2000.jpg')
with open(jpeg_2000_image, 'rb') as f:
is_jpeg_2000(f.read()) # True
バージョン情報
$ ruby -v
ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [arm64-darwin21]
$ python --version
Python 3.10.2