InDesign関連ファイルは下記の4つある:
- indd(ドキュメント)
- indt(テンプレート)
- indb(ブック)(>=InDesign2.0)
- indl(ライブラリ)(>=InDesign2.0)
これらのファイル内部、バージョン情報が保存されている。下記の青枠はメジャーバージョン、緑枠はマイナーバージョンで、16進数の表記。よって、バイナリデータから直接バージョン情報の取得が可能だ。
コードはシンプルで、各バージョン其々のサンプルファイルまた使い方は:https://github.com/mlove4u/InDesignFileVersion
class InDesignFile():
def __init__(self):
# 構造について、XMPSpecificationPart3.pdfのP36に書いてある
# https://github.com/adobe/xmp-docs/blob/master/XMPSpecifications/XMPSpecificationPart3.pdf
#
# 16 byte:ファイルのGUID
# 基本は:0606EDF5-D81D-46e5-BD31-EFE7FE74B71D --> InDesign >= 2.0
# 但し、一番最初のv1.0と1.5は例外(GUIDが定義されていなかった?)
self.fGUID = "0606edf5d81d46e5bd31efe7fe74b71d"
#
# 8 bytes: ファイルの種類(拡張子が間違っても、この情報からファイル種類がわかる)
self.database = (
"444f43554d454e54", # DOCUMENT: .indd/indt
"424f4f4b424f4f4b", # BOOKBOOK: .indb
"4c49425241525934", # LIBRARY4: .indl
"4c49425241525932", # LIBRARY2: old version: InDesign2.0 / CS
)
# Adobe InDesignの名前
self.names = {
# (major version, minor version), app name
(1, 0): "1.0",
(1, 5): "1.5",
(2, 0): "2.0",
(3, 0): "CS",
(4, 0): "CS2",
(5, 0): "CS3",
(6, 0): "CS4",
(7, 0): "CS5",
(7, 5): "CS5.5",
(8, 0): "CS6",
(9, 0): "CC",
(10, 0): "CC 2014",
(11, 0): "CC 2015",
(12, 0): "CC 2017", # NOTE: CC 2016 does not exists
(13, 0): "CC 2018",
(14, 0): "CC 2019",
# >=InDesign 2020: 2005 + major_version
}
def get_version(self, file: str, check_fGUID=True) -> tuple:
# return: ((major version[int], minor_version[int]), app_name)
# Example: ((18, 0), 'Adobe InDesign 2023')
with open(file, "rb") as f:
fGUID = f.read(16).hex()
if fGUID != self.fGUID:
if check_fGUID:
return None, "Not a InDesign file"
else: # maybe V1.0/1.5
f.seek(92) # go to the position of database
b = f.read(24)
fMagicBytes = b[:8].hex()
if fMagicBytes not in self.database:
return None, "Not a InDesign file."
# Endian of object streams, 1=little endian, 2=big endian
fObjectStreamEndian = b[8]
if fObjectStreamEndian == 1:
major_version, minor_version = b[13], b[17]
elif fObjectStreamEndian == 2:
major_version, minor_version = b[16], b[20]
else:
raise f"Invalid endian of object streams: {fObjectStreamEndian}"
#
app_name = self.__get_app_name(major_version, minor_version)
return (major_version, minor_version), app_name
def __get_app_name(self, major_version, minor_version):
# get InDesign app str name
v = 0
if major_version in (1, 7) and minor_version == 5: # v1.5/7.5
v = 5
return f"Adobe InDesign {self.names.get((major_version, v), 2005 + major_version)}"
