heic重构建

This commit is contained in:
Nymiro
2025-10-20 20:14:58 +13:00
parent 366e2f7c82
commit 70130d9e6b
25 changed files with 1504 additions and 255 deletions
+37 -8
View File
@@ -1,12 +1,14 @@
# pyheic_struct/parser.py
import struct
from typing import List, BinaryIO
from io import BytesIO
from base import Box
from base import Box, FullBox
from heic_types import (
ItemLocationBox, PrimaryItemBox, ItemInfoBox, ItemPropertiesBox,
ItemPropertyContainerBox, ItemPropertyAssociationBox, ImageSpatialExtentsBox,
ItemReferenceBox # <-- Import the new class
ItemReferenceBox, ItemInfoEntryBox # <-- 导入新的 'infe' 盒
)
BOX_TYPE_MAP = {
@@ -17,12 +19,15 @@ BOX_TYPE_MAP = {
'ipco': ItemPropertyContainerBox,
'ipma': ItemPropertyAssociationBox,
'ispe': ImageSpatialExtentsBox,
'iref': ItemReferenceBox, # <-- Register the new class
'iref': ItemReferenceBox,
'infe': ItemInfoEntryBox, # <-- 注册新的 'infe' 盒
}
# 'iref' is also a container.
# 'iinf' IS a container (它包含 'infe' 盒)
CONTAINER_BOXES = {'meta', 'moov', 'trak', 'iprp', 'ipco', 'dinf', 'fiinf', 'ipro', 'iinf', 'iref'}
FULL_BOXES = {'meta', 'hdlr', 'pitm', 'iinf', 'iloc', 'ipma', 'ispe', 'iref'}
# 几乎所有语义盒都是 FullBox
FULL_BOXES = {'meta', 'hdlr', 'pitm', 'iinf', 'iloc', 'ipma', 'ispe', 'iref', 'infe'}
def parse_boxes(stream: BinaryIO, max_size: int) -> List[Box]:
"""
@@ -59,16 +64,40 @@ def parse_boxes(stream: BinaryIO, max_size: int) -> List[Box]:
if len(raw_data) < content_size: break
box_class = BOX_TYPE_MAP.get(box_type, Box)
if box_class == Box and box_type in FULL_BOXES:
box_class = FullBox
box = box_class(size, box_type, current_offset_in_stream, raw_data)
if box.type in CONTAINER_BOXES:
child_stream = BytesIO(box.raw_data)
parse_size = len(box.raw_data)
if box.type in FULL_BOXES:
# Skip version/flags from the beginning of the raw_data
child_stream.read(4)
parse_size -= 4
if box.is_full_box:
# 跳过 4 字节的 version/flags
if parse_size >= 4:
child_stream.read(4)
parse_size -= 4
# --- START FIX ---
# 'iinf' 盒在 version/flags 之后还有一个 item_count 字段
# 我们必须在解析它的子盒之前跳过它
if box.type == 'iinf':
if box.version == 0:
if parse_size >= 2:
child_stream.read(2) # 跳过 16-bit item_count
parse_size -= 2
else:
if parse_size >= 4:
child_stream.read(4) # 跳过 32-bit item_count
parse_size -= 4
# --- END FIX ---
box.children = parse_boxes(child_stream, parse_size)
# 调用钩子
box._post_parse_initialization()
boxes.append(box)
stream.seek(current_offset_in_stream + size)