Exifを一度削除して入れたい情報を新たに追加する。基本的に入れて有効なのは「アーティスト情報」「著作権」「編集日時」と思う。以下にコードで、その後に解説。
FIELDS = [
{'tag': b'\x01\x3b', 'type': ['ASCII', b'\x00\x02'], 'count': 0, 'offset': b'',
'name': 'アーティスト', 'value': b'Ibuki SHITORI\x00'},
{'tag': b'\x82\x98', 'type': ['ASCII', b'\x00\x02'], 'count': 0, 'offset': b'',
'name': '撮影著作権者/編集著作権者', 'value': b'Copyright 2023 Ibuki SHITORI\x00'},
{'tag': b'\x01\x32', 'type': ['ASCII', b'\x00\x02'], 'count': 0, 'offset': b'',
'name': 'ファイル変更日時', 'value': b'yyyy:mm:dd hh:mm:ss\x00'}
]
def simple_new_add_exif(file_name, new_file_name, fields):
simple_delete_exif(file_name, new_file_name)
app_marker = b'\xff\xe1'
app_length = 18
app_label = b'Exif\x00\x00MM\x00\x2a\x00\x00\x00\x08'
app_field_num = len(fields)
app_offset = 10 + app_field_num * 12
app_fields = b''
app_value = b''
for field in fields:
if field['tag'] == b'\x01\x32':
field['value'] = datetime.datetime.now().strftime('%Y:%m:%d %H:%M:%S').encode()+b'\x00'
add_field = b''
if field['type'][0] in ['ASCII']:
value_length = len(field['value'])
if value_length > 4 and field['value'][-1] == 0:
add_field = field['tag'] + field['type'][1] + value_length.to_bytes(4, 'big') + app_offset.to_bytes(4, 'big')
app_offset += value_length
app_value += field['value']
elif value_length == 4 and field['value'][-1] == 0:
add_field = field['tag'] + field['type'][1] + value_length.to_bytes(4, 'big') + field['value']
app_fields += add_field
app_length += app_field_num * 12 + len(app_value)
app_data = app_marker + app_length.to_bytes(2, 'big') + app_label + app_field_num.to_bytes(2, 'big') + app_fields + app_value
with open(new_file_name, 'rb') as f:
new_data = f.read()
start_of_image_index = new_data.index(b'\xff\xd8')
new_data = new_data[start_of_image_index:start_of_image_index + 2] + app_data + new_data[start_of_image_index + 2:]
with open(new_file_name, 'wb') as f:
f.write(new_data)
def simple_delete_exif(file_name, new_file_name):
with open(file_name, 'rb') as f:
data = f.read()
start_of_image_index = data.index(b'\xff\xd8')
start_of_scan_index = data.index(b'\xff\xda')
application_segment_marker = []
for header in range(start_of_image_index, start_of_scan_index, 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]
tag_length = int.from_bytes(data[header + 2:header + 4], 'big')
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)
フィールドは「Tag」「Type」「Count」「Offset」に加えてフィールド名とその値をキーにした辞書のリスト。「Count」「Offset」はフィールドの値によって変わるので後から変更するという方針で辞書を作成する。