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)}"