プログラミング > Python >

Exifの削除

2023-04-01
   pythonによるexifの削除について。解説はコードの後に。
                    
def simple_delete_exif(file_name, new_file_name):
	with open(file_name, 'rb') as f:
		data = f.read()
		start_of_image = data.index(b'\xff\xd8')
		start_of_scan = data.index(b'\xff\xda')
		application_segment_marker = []
		for header in range(start_of_image, start_of_scan, 2):
			tag = data[header:header + 2]
			if b'\xff\xe0' <= tag <= b'\xff\xef':
				tag_length = struct.unpack('>H', data[header + 2:header + 4])[0]
				application_segment_marker.append(data[header:header + tag_length + 2])
		with open(new_file_name, 'wb') as g:
			new_data = data
			for marker in application_segment_marker:
				new_data = new_data.replace(marker, b'')
			g.write(new_data)
                

目次

画像データを開く

   画像データを読み込むにはopenを使い、開くモードとして読み取り専用の'r'、書き込み専用の'w'、追記専用の'a'がある。また'b'はバイナリデータの読み込みモードを表している。テキスト形式なら't'を選ぶ。

exifの削除

   ExifはJPEGデータの始まりSOI (start of image) と画像データの始まりSOS (start of scan) の間に存在する。そのためSOIを表すマーカ「b'\xff\xd8'」とSOSを表すマーカ「b'\xff\xda'」の位置をindexメソッドによって取得している。シングルクォーテーションの前にある「b」はバイナリデータで表すための表記。
   Exifが埋め込まれるのはAPP (application segment marker) がb'\xff\xe0'からb'\xff\xef'。2バイト区切りで進めて埋め込まれていたらAPPマーカの次の2バイトでデータの長さが記されているのでその分を足して一つのExifデータとして保存している。
   struct.unpackはバイナリデータを数字に変換する。第一引数はエンディアンと呼ばれるものでCPUに依存して、バイナリデータの読む向きが変化する。「\x00 \x01」を数字にしたとき1と読み込むのはビッグエンディアン、逆さまにして「\x01 \x00」として257と読むのがリトルエンディアン。
   最後に書き込みをする前にExifのデータ列を空白に置き換えることで削除している。