Откройте файл HEIC в шестнадцатеричном редакторе. Первые двенадцать байтов:
00 00 00 18 66 74 79 70 68 65 69 63
Это ISOBMFF — тот же контейнерный стандарт, который использует MP4. 0x18 (24 байта) — размер бокса, ftyp — бокс типа файла, heic — основной бренд. Файл HEIC — это не кодирование изображения. Это контейнер с маркером бренда, содержащий HEVC-кодированные изображения.
Что на самом деле представляет собой HEIC
HEIC = High Efficiency Image Container. Брендированная реализация Apple формата HEIF, стандартизированного MPEG как ISO/IEC 23008-12 в 2015 году. JPEG — это и алгоритм сжатия, и формат файла. HEIC — это только контейнер. Внутреннее сжатие — HEVC (H.265), тот же кодек, что используется для 4K-видео.
Один файл HEIC может хранить:
- Одно основное изображение
- Несколько альтернативных изображений (серийная съёмка)
- Последовательности изображений (Live Photos: статичное фото + 3-секундное видео)
- Альфа-каналы и карты глубины
- 16-битную глубину цвета на канал (JPEG ограничен 8 битами)
Контейнер использует структуру боксов — точно так же, как MP4:
| Box | Назначение |
|---|---|
ftyp | Тип файла и совместимые бренды |
meta | Метаданные и свойства элементов |
mdat | Сырые закодированные данные изображения (HEVC-битстрим) |
iloc | Расположение элементов внутри mdat |
Именно эта расширяемость позволяет HEIC делать то, на что JPEG никогда не был способен. Парсинг требует понимания иерархии боксов, а не простого чтения сырого битстрима.
Почему Apple перешла
Apple не изобрела HEIC. MPEG опубликовал HEIF в 2015 году. Apple приняла его как формат камеры iPhone по умолчанию в iOS 11 (2017).
Переход был арифметическим, а не маркетинговым. Фото iPhone 12 МП в JPEG занимает ~3,5 МБ. В HEIC — ~1,8 МБ. При 50 ГБ бесплатного тарифа iCloud этот разрыв означает примерно 14 000 дополнительных фотографий. Apple продаёт тарифы хранилища. Счёт очевиден.
Было и выравнивание экосистемы. Apple уже внедрила HEVC для видео (H.265 в iOS 11). Повторное использование того же кодека для статичных изображений означало совместные аппаратные блоки декодирования на чипах серии A, меньшее энергопотребление и единый путь лицензирования.
Компромиссы
HEIC технически превосходит JPEG почти по всем метрикам, кроме совместимости.
| Аспект | HEIC | JPEG |
|---|---|---|
| Эффективность сжатия | ~40–50% меньше при том же качестве | Базовый уровень |
| Глубина цвета | До 16 бит | 8 бит |
| Прозрачность | Да | Нет |
| Несколько изображений в файле | Да | Нет |
| Неразрушающее редактирование | Да | Нет |
| Нативная поддержка Windows | Требуется расширение HEIF | Универсальная |
| Поддержка веб-браузеров | Только Safari | Универсальная |
| Поддержка Android | Нативная с 9+ | Универсальная |
| Патентное лицензирование | Пул патентов HEVC | JPEG без лицензионных отчислений |
HEVC покрывается несколькими патентными пулами (MPEG LA, Access Advance). Apple оплачивает сборы за пользователей iOS. Сторонние производители этого преимущества не имеют. Эта неопределённость — большая часть причины, почему внедрение за пределами экосистемы Apple застопорилось.
Детектирование HEIC чтением сигнатуры файла
Не доверяйте расширению .heic. Прочитайте первые 32 байта и распарсите бокс ftyp.
Точная байтовая раскладка заголовка валидного файла HEIC:
Bytes 0–3: Размер бокса (big-endian uint32)
Bytes 4–7: Тип бокса: "ftyp" (0x66 0x74 0x79 0x70)
Bytes 8–11: Основной бренд: "heic" или "heif" или "mif1"
Bytes 12–15: Минорная версия (обычно 0x00000000)
Bytes 16+: Список совместимых брендов (напр. "mif1", "heic", "MiHE")
TypeScript в браузере:
async function isHeic(file: File): Promise<boolean> {
const buffer = await file.slice(0, 32).arrayBuffer()
const bytes = new Uint8Array(buffer)
if (String.fromCharCode(...bytes.slice(4, 8)) !== "ftyp") return false
const brand = String.fromCharCode(...bytes.slice(8, 12))
return ["heic", "heif", "mif1", "msf1"].includes(brand)
}
Наш конвертер выполняет эту проверку перед попыткой декодирования. Неправильный бренд = немедленный отказ. CPU не тратится впустую.
Python
def is_heic(path: str) -> bool:
with open(path, "rb") as f:
header = f.read(32)
if len(header) < 12:
return False
if header[4:8].decode("ascii", errors="ignore") != "ftyp":
return False
return header[8:12].decode("ascii", errors="ignore") in {"heic", "heif", "mif1", "msf1"}
Проверка более высокого уровня с filetype:
import filetype
kind = filetype.guess("photo.heic")
if kind and kind.extension in ("heic", "heif"):
print(kind.mime) # image/heic
Или с pillow-heif:
from pillow_heif import is_heif
if is_heif("photo.heic"):
# действительный контейнер
pass
Go
func isHeic(path string) bool {
f, err := os.Open(path)
if err != nil {
return false
}
defer f.Close()
buf := make([]byte, 32)
if _, err := f.Read(buf); err != nil {
return false
}
if string(buf[4:8]) != "ftyp" {
return false
}
brand := string(buf[8:12])
return brand == "heic" || brand == "heif" || brand == "mif1" || brand == "msf1"
}
PHP
function isHeic(string $path): bool {
$header = file_get_contents($path, false, null, 0, 32);
if (strlen($header) < 12) return false;
if (substr($header, 4, 4) !== 'ftyp') return false;
return in_array(substr($header, 8, 4), ['heic', 'heif', 'mif1', 'msf1'], true);
}
С fileinfo:
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file('photo.heic');
// image/heic или image/heif
ImageMagick CLI
ImageMagick 7+ поддерживает HEIC при компиляции с libheif:
magick identify -verbose photo.heic | grep "Format:"
# Format: HEIC (High Efficiency Image Container)
Без libheif: no decode delegate for this image format. В большинстве дистрибутивов Linux установка libheif-examples предоставляет утилиту heif-convert в качестве альтернативы.
Путь конвертации
Знание того, что файл — HEIC, не означает, что вы можете его открыть. Windows требует HEIF Image Extensions. Большинство браузеров по-прежнему отказываются рендерить HEIC в тегах <img>. Android 9+ обрабатывает его нативно; старые устройства — нет.
Решение: конвертировать. Наш конвертер HEIC в JPG обрабатывает весь конвейер в вашем браузере:
- Перетащить файлы — отдельные фото или целые папки, пакетная обработка автоматическая.
- Валидация сигнатуры — точная байтовая проверка выше выполняется для каждого файла. Не-HEIC файлы немедленно отклоняются с чётким сообщением.
- Клиентское декодирование — сборка WebAssembly libheif выполняется локально. Никаких загрузок. Никакого взаимодействия с сервером.
- Сохранение качества — JPG с качеством 90% сохраняет исходное разрешение и точность цвета.
- Пакетная загрузка — отдельные файлы или один ZIP-архив.
Для вывода без потерь с прозрачностью: HEIC в PNG. Для оптимизированных для веб размеров: HEIC в WebP.
Ваши файлы никогда не покидают ваше устройство. В этом весь смысл.


