PicScrub logoPicScrub
Quay lại danh sách định dạng

Định dạng HEIC

High Efficiency Image Container

Container ISOBMFF

Nếu từng làm việc với file video MP4, bạn sẽ thấy HEIC rất quen thuộc. Apple chọn ISO Base Media File Format (ISOBMFF) làm container cho HEIC, nghĩa là nó cùng dòng máu với các định dạng video hơn là với những định dạng ảnh truyền thống như JPEG hay PNG.

File gồm các "box" (còn gọi là atom) lồng nhau, mỗi box có mã kiểu 4 ký tự. Đây là một thiết kế thanh thoát đến bất ngờ, cho phép dựng những cây dữ liệu phức tạp mà vẫn khá dễ đọc một khi bạn đã nắm được phần căn bản.

Cấu trúc file HEIC

ftyp
meta
mdat
ftyp
24 byte
Loại file và các brand
meta
1000 byte
Nơi chứa siêu dữ liệu
mdat
Độ dài thay đổi
Dữ liệu media (HEVC)

Phần đầu file HEIC (box ftyp)

Kích thước box (24)
Kiểu box (ftyp)
Brand chính (heic)
Phiên bản phụ
Brand tương thích (mif1)
Brand tương thích (heic)
OffsetHexASCII
0000
000000186674797068656963
....ftypheic
000C
000000006D69663168656963
....mif1heic

Cấu trúc một box

Kích thướcKiểuDữ liệu
4 byte (BE)4 byteKích thước trừ 8

Nếu kích thước bằng 1 thì ngay sau phần kiểu là một trường kích thước mở rộng 8 byte. Nếu bằng 0 thì box kéo dài tới hết file.

Những box quan trọng

Cây box trong file HEIC có thể lồng khá sâu. Khác với JPEG, nơi siêu dữ liệu nằm ở những vị trí đoán được, HEIC chôn siêu dữ liệu xuống vài tầng trong một cấu trúc lồng nhau. Đây là cách các mảnh chính ghép lại với nhau.

ftyp:loại file

Box đầu tiên của file. Chứa brand chính và các brand tương thích. Bắt buộc phải có để nhận diện định dạng.

Các brand tương thích: heic heix hevc hevx heim heis hevm hevs mif1 msf1

meta:nơi chứa siêu dữ liệu

Chứa toàn bộ siêu dữ liệu, gồm vị trí các item, thuộc tính và liên kết giữa chúng. Đây là chỗ dữ liệu EXIF/XMP nằm.

meta (nơi chứa siêu dữ liệu)
├── hdlr  (tham chiếu handler)
├── pitm  (ID của item chính)
├── iloc  (vị trí item → offset vào mdat)
│   └── các mục [item_id, offset, length]
├── iinf  (thông tin item → tìm item 'Exif')
│   └── các mục infe kèm kiểu item
├── iprp  (thuộc tính item)
│   ├── ipco (nơi chứa thuộc tính)
│   │   ├── hvcC  (cấu hình bộ giải mã HEVC)
│   │   ├── ispe  (kích thước ảnh)
│   │   ├── colr  (hồ sơ ICC, offset+12)
│   │   ├── Exif  (EXIF ở dạng TIFF)
│   │   └── pixi  (thông tin điểm ảnh)
│   └── ipma (liên kết thuộc tính)
└── iref  (tham chiếu giữa các item)

mdat:dữ liệu media

Chứa dữ liệu ảnh thật đã mã hóa bằng HEVC. Box iloc trong meta cho biết offset trỏ vào mdat.

Siêu dữ liệu trong HEIC

Nếu bạn quen với các marker APP của JPEG thì HEIC làm khác hẳn. Thay vì các marker xếp nối tiếp ở đầu file, siêu dữ liệu ở đây tồn tại dưới dạng "thuộc tính item" nằm trong box meta. Dữ liệu EXIF vẫn ở đúng dạng TIFF quen thuộc, nhưng muốn tìm được nó thì phải lần qua cây box trước đã.

Thuộc tính EXIF

Nằm trong ipco (nơi chứa thuộc tính item) với kiểu "Exif". Chứa dữ liệu EXIF chuẩn ở dạng TIFF, giống hệt JPEG.

Thuộc tính XMP

Siêu dữ liệu dựa trên XML, lưu dưới dạng thuộc tính kiểu "mime" với content-type là "application/rdf+xml".

Hồ sơ ICC

Hồ sơ màu nằm trong box "colr" với kiểu "prof".

Vì sao offset lại quan trọng

Box iloc chứa các offset byte chính xác trỏ vào mdat. Nếu kích thước của bất kỳ box nào thay đổi (chẳng hạn do xóa siêu dữ liệu) thì phải tính lại toàn bộ offset, nếu không file sẽ không đọc được nữa.

Ẩn danh hóa không mất chất lượng

Đây là chỗ HEIC trở nên rắc rối. Định dạng này sinh ra để lưu trữ ảnh và video thật hiệu quả, chứ không phải để dễ chỉnh sửa siêu dữ liệu.

Vấn đề nằm ở đâu

Cấu trúc dựa trên offset của HEIC khiến việc bỏ bớt byte trở nên rủi ro. Box iloc chứa các offset byte chính xác trỏ vào mdat. Chỉ cần xóa một box thôi là những offset đó sai hết, và ảnh sẽ không mở được nữa.

Cách ghi đè bằng số 0

Thay vì xóa hẳn các box siêu dữ liệu, PicScrub ghi đè nội dung bên trong bằng số 0 và giữ nguyên cấu trúc lẫn kích thước box.

Trước: [Exif][Dữ liệu GPS: 37.7749, -122.4194][Máy: iPhone]
Sau:  [Exif][0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00...]

Vì sao lại ghi đè bằng số 0?

  • • Giữ file nguyên vẹn:mọi offset vẫn đúng
  • • Không nén lại:dữ liệu ảnh không bị đụng tới
  • • Siêu dữ liệu bị phá hủy:số 0 thì chẳng mang thông tin gì
  • • Khôi phục được không?:Không, dữ liệu đã bị ghi đè là mất hẳn

PicScrub xử lý HEIC như thế nào

1

Đọc cấu trúc box

Duyệt đệ quy ftyp, meta và nhận diện toàn bộ các box

2

Định vị siêu dữ liệu

Tìm các thuộc tính Exif và XMP trong container ipco

3

Ghi đè nội dung siêu dữ liệu

Ghi đè nội dung các box siêu dữ liệu bằng số 0

4

Giữ nguyên cấu trúc

Giữ nguyên phần đầu box, kích thước và toàn bộ offset

Một lưu ý về dung lượng file

Vì PicScrub ghi đè bằng số 0 thay vì xóa hẳn, file kết quả sẽ nặng đúng bằng file đầu vào. Phần chỗ dành cho siêu dữ liệu vẫn còn đó, chỉ là được lấp đầy bằng số 0.

Đầu vào: 2,5 MB (kèm 50KB EXIF)
Đầu ra: 2,5 MB (50KB toàn số 0)

HEIC, HEIF và AVIF

Cách đặt tên khá dễ nhầm, nên hãy làm rõ luôn. HEIF là định dạng container, còn HEIC và AVIF nói về codec dùng để nén ảnh nằm bên trong container đó.

Định dạngContainerCodecAi dùng
HEICHEIFHEVC (H.265)Thiết bị Apple
HEIFHEIFNhiều loạiContainer dùng chung
AVIFHEIFAV1Web (miễn phí bản quyền)

Cả ba đều dùng chung cấu trúc container ISOBMFF/HEIF, nên cách làm của PicScrub áp dụng được cho tất cả.