整理文件夹结构
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
# pyheic_struct/inspect_heic.py
|
||||
|
||||
import sys
|
||||
import pprint # 用于漂亮地打印字典
|
||||
|
||||
from pyheic_struct import HEICFile
|
||||
|
||||
def inspect_file(filename: str):
|
||||
print(f"--- 正在侦察: {filename} ---")
|
||||
|
||||
try:
|
||||
heic_file = HEICFile(filename)
|
||||
except Exception as e:
|
||||
print(f"CRITICAL: 文件解析失败: {e}")
|
||||
return
|
||||
|
||||
# 1. 打印厂商信息 (ftyp)
|
||||
if heic_file._ftyp_box:
|
||||
print(f"\n[ftyp] 厂商信息:")
|
||||
print(f" {heic_file._ftyp_box.raw_data}")
|
||||
|
||||
# 2. 打印主图像 ID (pitm)
|
||||
primary_id = heic_file.get_primary_item_id()
|
||||
print(f"\n[pitm] 主图像 Item ID:")
|
||||
print(f" {primary_id}")
|
||||
|
||||
# 3. 打印所有项目 (iinf)
|
||||
print(f"\n[iinf] 文件中的所有项目:")
|
||||
heic_file.list_items() # 这个方法会自己打印
|
||||
|
||||
# 4. 打印项目位置 (iloc) - 这是我们调试的关键! (已修改)
|
||||
if heic_file._iloc_box:
|
||||
print(f"\n[iloc] 项目位置 (片段) - 包含绝对偏移量:")
|
||||
locations = heic_file._iloc_box.locations
|
||||
|
||||
# 打印所有位置及其详细的 extents
|
||||
for loc in locations:
|
||||
# 打印摘要
|
||||
print(f" {loc}")
|
||||
# 打印关键的 extents (偏移量, 长度)
|
||||
if loc.extents:
|
||||
for extent in loc.extents:
|
||||
print(f" -> (offset={extent[0]}, length={extent[1]})")
|
||||
else:
|
||||
print(" -> (No extents found)")
|
||||
|
||||
# 5. 打印项目关联 (iref)
|
||||
if heic_file._iref_box:
|
||||
print(f"\n[iref] 项目关联:")
|
||||
pprint.pprint(heic_file._iref_box.references)
|
||||
|
||||
# 6. 查找 'mpvd' 盒 (三星特定)
|
||||
mpvd_box = heic_file.find_box('mpvd') #
|
||||
if mpvd_box:
|
||||
print(f"\n[mpvd] 动态照片盒 (三星):")
|
||||
print(f" 找到了 'mpvd' 盒,位于偏移量: {mpvd_box.offset}")
|
||||
else:
|
||||
print(f"\n[mpvd] 未找到 'mpvd' 盒 (这是 Apple 文件的预期行为)")
|
||||
|
||||
# --- START NEW INSPECTION ---
|
||||
# 7. 打印项目属性 (iprp / ipma) - 这是我们缺失的知识!
|
||||
if heic_file._iprp_box and heic_file._iprp_box.ipma:
|
||||
print(f"\n[ipma] 项目属性关联:")
|
||||
|
||||
ipma = heic_file._iprp_box.ipma
|
||||
|
||||
# 打印主 ID 的属性
|
||||
if primary_id and primary_id in ipma.entries:
|
||||
print(f" 主 ID ({primary_id}) 关联的属性索引:")
|
||||
pprint.pprint(ipma.entries[primary_id].associations)
|
||||
|
||||
# 尝试打印 "shifted" ID (三星)
|
||||
if primary_id:
|
||||
shifted_id = primary_id << 16
|
||||
if shifted_id in ipma.entries:
|
||||
print(f" 三星 Shifted ID ({shifted_id}) 关联的属性索引:")
|
||||
pprint.pprint(ipma.entries[shifted_id].associations)
|
||||
|
||||
print(f"\n (ipma 完整转储 - 前 5 项):")
|
||||
count = 0
|
||||
for item_id, entry in ipma.entries.items():
|
||||
if count >= 5:
|
||||
print(" ...")
|
||||
break
|
||||
print(f" - Item {item_id}: {entry.associations}")
|
||||
count += 1
|
||||
else:
|
||||
print(f"\n[ipma] 未找到 'ipma' 盒。")
|
||||
|
||||
if heic_file._iprp_box and heic_file._iprp_box.ipco:
|
||||
print(f"\n[ipco] 属性容器 (前 10 个属性盒):")
|
||||
count = 0
|
||||
for prop_box in heic_file._iprp_box.ipco.children:
|
||||
if count >= 10:
|
||||
print(" ...")
|
||||
break
|
||||
print(f" - (索引 {count+1}) : {prop_box}") # 索引是 1-based
|
||||
count += 1
|
||||
else:
|
||||
print(f"\n[ipco] 未找到 'ipco' 盒。")
|
||||
# --- END NEW INSPECTION ---
|
||||
|
||||
print(f"\n--- 侦察完毕: {filename} ---")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("用法: python scripts/inspect_heic.py <文件名>")
|
||||
print("例如: python scripts/inspect_heic.py examples/samsung.heic")
|
||||
else:
|
||||
inspect_file(sys.argv[1])
|
||||
@@ -0,0 +1,4 @@
|
||||
from pyheic_struct.cli import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,46 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT_DIR = Path(__file__).resolve().parents[1]
|
||||
DEFAULT_EXAMPLE = ROOT_DIR / "examples" / "samsung_apple_compatible.HEIC"
|
||||
|
||||
# --- Hex Dump Utility ---
|
||||
def hexdump(data, length=16):
|
||||
"""Creates a formatted hex dump of a byte string."""
|
||||
results = []
|
||||
for i in range(0, len(data), length):
|
||||
chunk = data[i:i + length]
|
||||
|
||||
# 1. Offset
|
||||
offset = f"{i:08x} "
|
||||
|
||||
# 2. Hex values
|
||||
hex_part = " ".join(f"{b:02x}" for b in chunk)
|
||||
hex_part = hex_part.ljust(length * 3 - 1) # Pad to align
|
||||
|
||||
# 3. ASCII representation
|
||||
ascii_part = "".join(chr(b) if 32 <= b <= 126 else "." for b in chunk)
|
||||
|
||||
results.append(f"{offset}{hex_part} |{ascii_part}|")
|
||||
return "\n".join(results)
|
||||
# --- End Utility ---
|
||||
|
||||
|
||||
filename = os.environ.get("HEIC_SAMPLE", str(DEFAULT_EXAMPLE))
|
||||
|
||||
if not os.path.exists(filename):
|
||||
print(f"Error: File not found: {filename}")
|
||||
print("Set HEIC_SAMPLE environment variable or place the sample under examples/.")
|
||||
else:
|
||||
try:
|
||||
with open(filename, 'rb') as f:
|
||||
# Read the first 512 bytes (enough to see the ftyp and meta headers)
|
||||
file_header_data = f.read(512)
|
||||
|
||||
print(f"--- Hex Dump for {filename} (First 512 Bytes) ---")
|
||||
print(hexdump(file_header_data))
|
||||
print("="*60)
|
||||
|
||||
except Exception as e:
|
||||
print(f"An error occurred while reading the file: {e}")
|
||||
Reference in New Issue
Block a user