
簡(jiǎn)介ISO/IEC 23008-12:2017 是高效編碼與異構(gòu)環(huán)境媒體交付系列標(biāo)準(zhǔn)的第 12 部分正式定義 HEIF/HEIC 圖像文件格式面向多媒體開發(fā)人員、移動(dòng)端圖像處理工程師、流媒體系統(tǒng)設(shè)計(jì)者以及關(guān)注圖像格式演進(jìn)的技術(shù)人員。資源為官方發(fā)布的 PDF 原版標(biāo)準(zhǔn)僅 1 個(gè)文件壓縮包約 906KB正文內(nèi)容覆蓋范圍、規(guī)范性引用文件、術(shù)語與定義、縮略語、總覽和通用要求等章節(jié)便于按章節(jié)查閱和引用標(biāo)準(zhǔn)原文。該格式基于 HEVC 高效視頻編碼不僅支持單張圖像與圖像序列還能封裝元數(shù)據(jù)與派生圖像為不同設(shè)備、軟件平臺(tái)之間的互操作性及格式轉(zhuǎn)換提供統(tǒng)一規(guī)范。已有 259 人學(xué)習(xí)下載適合希望深入理解 HEIF/HEIC 容器結(jié)構(gòu)、自行實(shí)現(xiàn)編碼器或解碼器、排查媒體播放兼容性問題的技術(shù)工程師作為標(biāo)準(zhǔn)依據(jù)參考。1. HEIC 的真相它贏在文件組織方式而不是壓縮算法同樣一張 1024×1024 的照片HEIC 文件里可能根本沒有保存一張完整的主圖而是存了 4 塊 512×512 的瓦片外加一條把它們拼成 2×2 網(wǎng)格的表達(dá)式。真正決定畫面如何呈現(xiàn)的不是某個(gè)像素壓縮算法而是一套盒子Box組織規(guī)則。這就是 ISO/IEC 23008-12:2017HEIF/HEIC 背后的規(guī)范與 JPEG 最本質(zhì)的區(qū)別它不定義圖像內(nèi)容的編碼方式只定義圖像如何被組織、如何被引用、如何被派生出新圖像。搞懂這套組織規(guī)則你才能解釋為什么 HEIC 能被裁剪、旋轉(zhuǎn)、疊加輔助圖卻幾乎不損失畫質(zhì)也才能理解為什么同樣一個(gè) HEIC 文件在某些解碼器上正常、在另一些上直接翻車。這篇從文件骨架拆到條目、屬性、派生與序列再落到常見排查方法。2. 從 ISOBMFF 派生為什么是盒子樹而不是新容器標(biāo)準(zhǔn)正文 6.2 和 7.2 都寫著一句話Derivation from the ISO base media file format從 ISO 基礎(chǔ)媒體文件格式派生。這句話是整個(gè) HEIF 架構(gòu)的根它沒有發(fā)明新容器而是直接復(fù)用了 MP4 家族那套經(jīng)過二十年驗(yàn)證的盒子模型。理解這一點(diǎn)你就理解了一半的設(shè)計(jì)動(dòng)機(jī)——圖像格式的容錯(cuò)性、擴(kuò)展性、流式友好性都來自這套樹狀結(jié)構(gòu)而不是來自某個(gè)更聰明的壓縮算法。2.1 盒子Box的自我描述size type 構(gòu)成的一切HEIF 文件就是一串首尾相接的盒子。每個(gè)盒子的前 8 個(gè)字節(jié)是固定的前 4 字節(jié)是 big-endian 的長(zhǎng)度含這 8 字節(jié)頭部后 4 字節(jié)是 ASCII 類型標(biāo)識(shí)。一個(gè)盒子可以包含子盒子于是整份文件天然變成一棵樹。下面這個(gè)遞歸解析邏輯是所有 HEIF 解碼器地基def walk_boxes(data, offset0, depth0): while offset 8 len(data): size int.from_bytes(data[offset:offset4], big) btype data[offset4:offset8].decode(latin1) if size 1: # 32 位長(zhǎng)度不夠用擴(kuò)展為 64 位長(zhǎng)度 size int.from_bytes(data[offset8:offset16], big) header 16 elif size 0: # 0 表示盒子一直延伸到文件末尾 size len(data) - offset header 8 else: header 8 payload data[offsetheader:offsetsize] print( * depth f{btype} {offset}: {size} bytes) if btype meta: # meta 盒內(nèi)部通常嵌套完整子盒序列 walk_boxes(payload, 0, depth 1) offset size這段代碼的關(guān)鍵在于解析器可以不認(rèn)識(shí)某個(gè)盒子只靠 size 字段就能跳到下一個(gè)盒子繼續(xù)讀。所以未來新增任何屬性盒舊解碼器都能安全跳過絕不會(huì)因?yàn)橐粋€(gè)未知類型就整體崩潰——這就是向前兼容在文件格式層面的具體落地。三種長(zhǎng)度語義也很講究size0 只允許出現(xiàn)在文件最后一個(gè)盒子用來兜底size1 是給大文件準(zhǔn)備的 64 位擴(kuò)展普通手機(jī)照片用不上但專業(yè)相機(jī)和長(zhǎng)圖像序列必須靠它。2.2 ftyp / meta / mdat三個(gè)盒子的分工與邊界HEIF 文件骨架可以簡(jiǎn)化成三種角色文件頭、元數(shù)據(jù)島、原始數(shù)據(jù)池。典型的頂層結(jié)構(gòu)是 ftyp、meta、mdat 三個(gè)盒子各司其職。ftyp 在最前面聲明這個(gè)文件屬于哪個(gè)品牌brand以及兼容哪些品牌。解碼器先看它決定能否繼續(xù)。meta 盒是所有描述信息的家條目清單、屬性定義、條目與屬性的映射、圖像角色全在這里。mdat 盒則是完全不解釋內(nèi)容的字節(jié)池——主圖像、縮略圖、輔助圖像、元數(shù)據(jù)的原始字節(jié)都平鋪在里面靠偏移量和長(zhǎng)度被 meta 里的條目引用。這種元數(shù)據(jù)與像素?cái)?shù)據(jù)分離的設(shè)計(jì)對(duì)整個(gè)生態(tài)是決定性的。JPEG 的做法是文件頭擠著一堆分段、文件尾再掛 EXIF數(shù)據(jù)和管理信息耦合在同一個(gè)流里而 HEIF 的做法更像文件系統(tǒng)meta 是目錄項(xiàng)mdat 是數(shù)據(jù)塊。目錄項(xiàng)壞了最多損失索引數(shù)據(jù)塊還能搶救回來反過來想替換一個(gè)條目里的圖像內(nèi)容只需要改 mdat 中對(duì)應(yīng)區(qū)段的指針和長(zhǎng)度不需要重寫整個(gè)文件。2.3 兼容紅利為什么不多發(fā)明一個(gè)容器從設(shè)計(jì)取舍看從 ISOBMFF 派生帶來的最大紅利是解析器現(xiàn)成。MP4 家族的容器解析已經(jīng)在播放器、瀏覽器、嵌入式設(shè)備里被驗(yàn)證過無數(shù)遍隨機(jī)訪問、字節(jié)序、嵌套深度限制、損壞恢復(fù)策略這些都是血淚經(jīng)驗(yàn)換來的。HEIF 直接繼承這些經(jīng)驗(yàn)而不是像某些格式那樣從頭定義一套二進(jìn)制結(jié)構(gòu)再花五年踩坑。我一般這么理解這個(gè)決策標(biāo)準(zhǔn)委員會(huì)把賭注壓在圖像未來一定會(huì)越來越像媒體上——靜態(tài)圖像、圖像序列、分層編碼、派生關(guān)系本質(zhì)上都是多個(gè)數(shù)據(jù)對(duì)象 它們之間的引用關(guān)系。用一套為多媒體設(shè)計(jì)的容器來裝圖像比讓圖像格式守著單幀單文件的舊模型更符合演進(jìn)方向。所以標(biāo)準(zhǔn)第 9 章才敢放心地?cái)U(kuò)展 ItemInfoEntry 和 Item Properties Box因?yàn)槿萜鞴羌軟]動(dòng)只是在 meta 這個(gè)目錄區(qū)里加字段舊解析器依舊能跳過。3. 圖像條目與屬性把像素和對(duì)像素的解釋徹底拆開HEIF 對(duì)傳統(tǒng)圖像格式最狠的一次重構(gòu)是把一幅圖像從單一像素塊拆成了兩個(gè)概念圖像條目Image Item和圖像屬性Image Property。條目是一段數(shù)據(jù)屬性是這段數(shù)據(jù)如何被解釋。同一個(gè)條目可以掛多個(gè)屬性同一個(gè)屬性也可以被多個(gè)條目共享。這一層設(shè)計(jì)直接決定了 HEIC 文件能同時(shí)承載主圖、縮略圖、深度圖、旋轉(zhuǎn)信息、色彩信息而不互相干擾。3.1 ItemInfoEntry圖像條目的身份證每個(gè)圖像條目都有一個(gè) infeItemInfoEntry作為身份證。它記錄條目 ID、條目類型和條目名稱。標(biāo)準(zhǔn)第 9.2 節(jié)專門為它定義了擴(kuò)展語法原因是舊版 ISOBMFF 里條目信息分散在不同盒中2017 版把它們統(tǒng)一進(jìn)一個(gè)可擴(kuò)展結(jié)構(gòu)def parse_infe(payload): version payload[0] flags int.from_bytes(payload[1:4], big) p 4 if version 2: item_ID int.from_bytes(payload[p:p2], big); p 2 item_protection_index int.from_bytes(payload[p:p2], big); p 2 item_type payload[p:p4].decode(latin1); p 4 end payload.index(b\x00, p) item_name payload[p:end].decode(utf-8) return { item_ID: item_ID, item_type: item_type, item_name: item_name, protection_index: item_protection_index, }item_type 是四個(gè)字符的代碼它決定了解碼器把這條數(shù)據(jù)當(dāng)什么比如 hvc1 表示 HEVC 編碼的主圖像auxl 表示輔助圖像具體輔助用途由屬性進(jìn)一步說明grid 表示瓦片拼接圖像iovl 表示疊加圖像。item_ID 在文件內(nèi)唯一所有引用關(guān)系——無論是屬性映射、派生源引用還是角色指派——都靠這個(gè)數(shù)字串起來。注意 parse 結(jié)束后item_name 只是給人看的名字解碼器不應(yīng)該依賴它做邏輯判斷否則換個(gè)名字就會(huì)翻車。3.2 屬性池與映射ipco / ipma 的雙層結(jié)構(gòu)圖像屬性不是直接寫死在條目里的而是集中在 iprpItem Properties Box中內(nèi)部再分 ipco屬性定義池和 ipma條目到屬性的映射表。這種雙層結(jié)構(gòu)很像數(shù)據(jù)庫的表設(shè)計(jì)屬性定義只存一份多個(gè)條目通過 ipma 映射到同一條定義省空間也省一致性維護(hù)成本。ipma 里每條關(guān)聯(lián)還帶一個(gè) essential 標(biāo)志——標(biāo)記這個(gè)屬性是不是解碼必不可少的如果解碼器不認(rèn)識(shí)一個(gè) essential 屬性必須拒絕解碼而不是忽略它。屬性 Box設(shè)計(jì)作用關(guān)鍵取值ispe圖像空間范圍寬、高解碼前必須知道irot90° 倍數(shù)的旋轉(zhuǎn)0/90/180/270imir水平或垂直鏡像軸方向clap清潔孔徑從解碼畫面裁剪出有效區(qū)colr色彩信息色彩原色、傳輸特性、矩陣系數(shù)pixi像素信息每分量位深、通道數(shù)pasp像素寬高比非正方形像素的修正rloc相對(duì)位置條目在畫布上的偏移auxC輔助圖像類型深度圖、alpha、色度圖等解碼器要正確顯示一張 HEIC不是解完像素就行而是要按順序把這一串屬性應(yīng)用上去先用 ispe 確定畫布按 irot/imir 做幾何變換用 clap 決定最終顯示窗口用 colr 把像素轉(zhuǎn)換到目標(biāo)色彩空間。任何一個(gè)屬性被遺漏輕則方向不對(duì)重則顏色整個(gè)偏掉。這就是為什么 HEIF 解碼比 JPEG 解碼更依賴完整實(shí)現(xiàn)而不是能出圖就行。3.3 派生圖像不存像素的 grid / iovl / iden最反直覺的部分在這里一個(gè)圖像條目可以完全沒有自己的像素?cái)?shù)據(jù)它的 content 是對(duì)其他條目的引用。標(biāo)準(zhǔn) 6.6 節(jié)定義了派生圖像Derived Images常見類型包括 grid網(wǎng)格拼接、iovl疊加合成和 iden恒等變換。grid 的思想很直白把一張大圖切成若干瓦片每個(gè)瓦片是獨(dú)立編碼的 hvc1 條目再建立一個(gè) grid 條目聲明按 2×3 拼接即可。解碼時(shí)不需要同時(shí)解出整張大圖而是按需解出可視區(qū)域的瓦片——這對(duì)超大分辨率的全景圖、衛(wèi)星圖意義重大。iovl 則是把多個(gè)條目按坐標(biāo)疊加前景圖、背景圖、alpha 圖分開存需要合成時(shí)才疊加。派生關(guān)系可以鏈?zhǔn)角短滓粋€(gè) iovl 的輸入本身可以是一個(gè) grid 條目。解碼器像做深度優(yōu)先遍歷一樣遞歸求值所以標(biāo)準(zhǔn)要求解碼器必須能檢測(cè)循環(huán)引用否則一條A 派生自 BB 又派生自 A的惡意文件就能讓解碼線程死循環(huán)。3.4 圖像角色隱藏圖、封面圖、縮略圖、輔助圖如何分工條目類型說了數(shù)據(jù)是什么圖像角色再說這張圖在文件里干什么。標(biāo)準(zhǔn) 6.4 節(jié)定義了隱藏圖、封面圖、縮略圖、輔助圖和主圖主圖是默認(rèn)展示的封面圖用于某些交互場(chǎng)景優(yōu)先顯示縮略圖用小尺寸快速預(yù)覽輔助圖不直接顯示它給主圖提供深度、alpha、色彩校正所需的數(shù)據(jù)隱藏圖存在但不參與任何正常呈現(xiàn)。這五個(gè)角色都通過關(guān)聯(lián)屬性標(biāo)記而不是靠文件內(nèi)的順序推斷。我見過某項(xiàng)目用第一個(gè)條目就是主圖的假設(shè)去寫解碼器結(jié)果遇到輔助圖排在前面就直接把深度圖當(dāng)照片顯示。正確的做法永遠(yuǎn)是先解析 meta 里的角色映射再?zèng)Q定哪些條目進(jìn)渲染管線、哪些只做后臺(tái)附屬。4. 圖像序列一段沒有聲音的視頻軌道是怎么組織的HEIF 不只是單張圖片的容器標(biāo)準(zhǔn)第 7 章完整定義了圖像序列Image Sequence。一個(gè)序列被組織成一條軌道track軌道里的每一幀是一個(gè)樣本sample。從容器角度看它幾乎就是一段沒有音頻、沒有 B 幀復(fù)雜度約束的視頻軌道。連拍、動(dòng)態(tài)照片、延時(shí)攝影、分層的 HDR 靜態(tài)圖像都可以靠這條軌道在同一個(gè)文件里表達(dá)。4.1 軌道的皮膚Track Header 里的 handler 與尺寸軌道在容器層必須有 Track Header 盒聲明基本參數(shù)還要用 handler 盒聲明軌道類型。HEIF 圖像序列的 handler 類型被定義為 pict這樣播放器一看就能把它歸類為圖像軌道而非普通視頻軌從而用圖像解碼管線而不是完整視頻播放管線處理它。這個(gè)區(qū)分很重要圖像序列強(qiáng)調(diào)逐幀可編輯、可替換而不是像視頻那樣強(qiáng)調(diào)連續(xù)回放。標(biāo)準(zhǔn) 7.2.3 還定義了一個(gè)專門的 Coding Constraints 盒ccst用來聲明這軌圖像的解碼約束。它的位域設(shè)計(jì)很緊湊def parse_ccst(payload): # payload 前 4 字節(jié)是 version flags第 5 字節(jié)是約束位域 flags_byte payload[4] all_ref_pics_intra (flags_byte 7) 1 # 所有幀是否都為幀內(nèi)編碼 intra_pred_used (flags_byte 6) 1 # 幀內(nèi)預(yù)測(cè)是否被啟用 max_ref_per_pic flags_byte 0x3F # 每幀最多引用幾個(gè)參考幀 return { all_ref_pics_intra: all_ref_pics_intra, intra_pred_used: intra_pred_used, max_ref_per_pic: max_ref_per_pic, }這三個(gè)字段的價(jià)值在于讓解碼器在解碼前就拿到策略而不是逐幀試探。如果 all_ref_pics_intra 為 1說明每一幀都不依賴其他幀解碼器就可以做完全隨機(jī)訪問編輯時(shí)可以放心插入、刪除任何一幀而不用重新編碼后續(xù)幀。max_ref_per_pic 則告訴解碼器內(nèi)存窗口要開多大。很多 HEIF 解碼翻車就是因?yàn)閷?shí)現(xiàn)方無視 ccst默認(rèn)按普通視頻 B 幀處理結(jié)果遇到全幀內(nèi)序列時(shí)白白多做了一個(gè)完整的幀重排流程。4.2 refs 樣本組記錄幀之間的直接引用關(guān)系即便有 ccst 聲明HEVC 編碼的圖像序列還是可能出現(xiàn)幀間引用比如某些幀參考前一幀做預(yù)測(cè)編碼。問題在于解碼器想隨機(jī)訪問第 n 幀時(shí)怎么知道該回溯到哪一幀標(biāo)準(zhǔn) 7.4.1 給出了答案直接引用樣本列表Direct Reference Samples List用 refs 樣本組記錄每個(gè)樣本直接引用了哪些樣本。引用關(guān)系清晰后隨機(jī)訪問點(diǎn)推導(dǎo)就變成一個(gè)簡(jiǎn)單的圖遍歷# 根據(jù) refs 樣本組推導(dǎo)每個(gè)樣本是否可獨(dú)立解碼 def find_random_access_points(refs_group, total_samples): independent set() for sample_id in range(1, total_samples 1): refs refs_group.get(sample_id, []) if not refs: independent.add(sample_id) # 不引用任何幀天然隨機(jī)訪問點(diǎn) elif all(r in independent for r in refs): independent.add(sample_id) # 依賴的都是獨(dú)立幀也隨機(jī)可達(dá) return sorted(independent)這里的關(guān)鍵洞察是直接引用和間接引用的區(qū)分。一個(gè)樣本可能間接依賴前面十九幀但 refs 只記錄直接依賴的那幾幀。解碼器靠這個(gè)映射回溯時(shí)不需要把整段歷史都解碼出來而是可以沿著依賴鏈只解必要幀代價(jià)是多次跳轉(zhuǎn)。誤用 refs 的典型錯(cuò)誤是拿關(guān)鍵幀類型去猜比如認(rèn)為所有不包含 IDR 的幀都依賴前面最近的一個(gè) IDR——這在參考關(guān)系不連續(xù)時(shí)是錯(cuò)的解碼結(jié)果就是花屏或者綠屏。4.3 縮略圖軌道、輔助軌道與 eqiv 實(shí)體組序列不止一條。標(biāo)準(zhǔn) 7.5 節(jié)規(guī)定了縮略圖序列軌道和輔助圖像序列軌道縮略圖軌道通過 thmb 軌道引用關(guān)聯(lián)到主軌道解碼器需要快速預(yù)覽時(shí)直接讀縮略軌道不必解碼全分辨率主序列輔助軌道保存深度、alpha、HDR 信息它們和主序列通過引用關(guān)系一一對(duì)應(yīng)但又獨(dú)立編碼、獨(dú)立可替換。6.8 節(jié)的 eqiv 機(jī)制打通了靜態(tài)圖和動(dòng)態(tài)序列的邊界。一個(gè)未定時(shí)的圖像條目比如封面圖通過 eqiv 實(shí)體組關(guān)聯(lián)到某條軌道的某個(gè)時(shí)間段或者說某個(gè) sample group 把 timed sequence 里的一段樣本與 untimed item 等價(jià)起來。實(shí)際價(jià)值很直接相冊(cè)封面既可以是縮略圖條目也可以指到視頻軌道里的某一幀播放器在展示時(shí)就不用關(guān)心數(shù)據(jù)的物理存放形態(tài)只看邏輯等價(jià)關(guān)系。5. HEIF/HEIC 排查指南常見問題、踩坑與驗(yàn)證方法容器設(shè)計(jì)再優(yōu)雅實(shí)現(xiàn)時(shí)該踩的坑一個(gè)都不會(huì)少。下面這五類問題是我在實(shí)際項(xiàng)目中見過最多的 HEIF/HEIC 解碼故障每條都按現(xiàn)象、原因、解決拆開?,F(xiàn)象不支持該條目類型——解碼器直接拒絕打開或者只顯示黑屏。原因很多實(shí)現(xiàn)只認(rèn)得 hvc1 主圖像遇到 grid、iovl 派生條目或者 auxl 輔助條目要么直接報(bào)錯(cuò)要么把輔助圖像當(dāng)主圖渲染。更深層的原因是這類解碼器沒有實(shí)現(xiàn) ipma 里的 essential 標(biāo)志邏輯不知道哪些條目必須支持、哪些可以安全跳過。解決先解析 meta 里的所有 infe打印 item_type 清單確認(rèn)文件里到底有哪些類型的條目。遇到派生條目如果實(shí)現(xiàn)不支持就沿派生樹的引用關(guān)系找到最底層的 hvc1 真實(shí)像素條目。遇到輔助條目按角色映射過濾掉不要進(jìn)渲染管線?,F(xiàn)象圖像顯示方向不對(duì)但 EXIF 里明明寫著正確的旋轉(zhuǎn)角度。原因HEIF 的方向不依賴 EXIF而是靠 irot / imir 屬性。很多移植的解碼器沿用了 JPEG 時(shí)代讀 EXIF Orientation的習(xí)慣完全無視這兩個(gè)屬性盒于是畫面沒有被旋轉(zhuǎn)或鏡像。更隱蔽的是 irot 只支持 90° 的整數(shù)倍如果原圖是任意角度就必須靠 clap 先裁剪再旋轉(zhuǎn)處理順序錯(cuò)了也會(huì)偏。解決解碼完像素后先查 ipma 里有沒有掛 irot 和 imir再查 clap 是否定義了裁剪區(qū)。應(yīng)用順序固定為先裁 clap再鏡像 imir再旋轉(zhuǎn) irot最后才是色彩轉(zhuǎn)換。順序顛倒就會(huì)得到既偏又花的畫面?,F(xiàn)象封面圖不是想要的畫面顯示成了白場(chǎng)或深度圖。原因封面條目的選擇邏輯寫死了用第一個(gè)條目。前面說過條目在文件里的物理順序與角色無關(guān)輔助條目、隱藏條目可能排在主圖前面。有的文件里封面由 cover 角色顯式指定有的靠 primary item 指定兩者優(yōu)先級(jí)還不同。解決先查 eqiv 實(shí)體組或樣本組看封面是否關(guān)聯(lián)到某個(gè)時(shí)間點(diǎn)的序列幀如果沒有再查角色映射里 cover 標(biāo)記者都查不到才回退到 primary item。不要信任第 0 個(gè) item這種假設(shè)。現(xiàn)象動(dòng)態(tài)照片/連拍序列只有第一幀能顯示后續(xù)幀花屏或綠屏。原因解碼器沒有讀 refs 樣本組把 HEVC 幀間預(yù)測(cè)幀當(dāng)獨(dú)立幀直接解碼或者解析了 refs 但是沒有按依賴鏈回溯解碼。還有一類原因是 ccst 里 max_ref_per_pic 聲明了較大窗口但解碼器內(nèi)部參考幀緩存開小了。解決逐幀打印 refs 映射確認(rèn)當(dāng)前幀的直接引用樣本列表在解碼順序上強(qiáng)制按依賴拓?fù)渑判虮WC每一幀解碼前它的所有引用都已解碼。同時(shí)把參考幀緩存大小對(duì)齊到 ccst 的 max_ref_per_pic。現(xiàn)象文件完整性校驗(yàn)失敗但圖像能正常打開。原因標(biāo)準(zhǔn) 8.4 節(jié)定義的完整性檢查是對(duì)條目數(shù)據(jù)做摘要校驗(yàn)值存在 meta 中。如果某個(gè)工具在保存時(shí)重寫了 mdat 里的字節(jié)比如歸一化、重壓縮卻沒有同步更新摘要校驗(yàn)必然失敗。反過來有的流式寫入器在文件未完全落盤時(shí)提前計(jì)算摘要也會(huì)得到不匹配的結(jié)果。解決拿到文件先確認(rèn)完整性校驗(yàn)的覆蓋范圍——是覆蓋整個(gè) mdat還是覆蓋單個(gè)條目數(shù)據(jù)。校驗(yàn)失敗時(shí)不要直接丟棄文件打印摘要算法標(biāo)識(shí)和預(yù)期值對(duì)比原始數(shù)據(jù)區(qū)有沒有被改動(dòng)。很多官方工具打不開但自家?guī)炷荛_的疑難雜癥最后都?xì)w因到這里。6. 設(shè)計(jì)取舍為什么標(biāo)準(zhǔn)押注在組織規(guī)則而不是編碼器上ISO/IEC 23008-12:2017 通篇沒有規(guī)定圖像必須用某種編碼它只規(guī)定條目怎么聲明、屬性怎么掛、派生怎么引用、序列怎么組織。真正的壓縮效率來自 HEVC未來換成更激進(jìn)的編碼器容器依舊成立。這個(gè)取舍的背后是一種判斷編碼技術(shù)的迭代周期是五年一代而文件格式一旦鋪開生命周期是二十年起步。把如何組織和如何編碼解耦才能讓格式活得比任何一代編碼器都長(zhǎng)。代價(jià)同樣清晰。解碼器的復(fù)雜度從讀像素流升級(jí)為先解析盒子樹再沿著條目、屬性、引用關(guān)系求值軟件棧整體變重。一個(gè)小設(shè)備上的 HEIF 解碼器光處理 grid 瓦片和 iovl 疊加就要維護(hù)一個(gè)遞歸求值器服務(wù)端生成 HEIC 時(shí)還要維護(hù) ipco 屬性池的去重與 ipma 映射的一致性。這些成本 JPEG 時(shí)代是完全沒有的。所以標(biāo)準(zhǔn)選了多層抽象屬性可擴(kuò)展essential 標(biāo)志讓不認(rèn)識(shí)新屬性的解碼器顯式失敗而非默默出錯(cuò)refs 樣本組讓隨機(jī)訪問從猜幀類型變成查依賴圖。這些設(shè)計(jì)本質(zhì)上都是在給組織規(guī)則兜底——用更精確的元數(shù)據(jù)換取更寬容的擴(kuò)展空間。從那以后我每次拿到一個(gè)新的圖像容器或打包格式都會(huì)先強(qiáng)制自己畫一遍盒子樹列出所有條目、所有屬性、所有引用關(guān)系再談解碼??床欢藐P(guān)系的解碼器寫出來也是脆的。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取