Abra um arquivo HEIC em um editor hexadecimal. Os primeiros doze bytes:
00 00 00 18 66 74 79 70 68 65 69 63
Isso é ISOBMFF — o mesmo padrão de contêiner que o MP4 usa. 0x18 (24 bytes) é o tamanho da caixa, ftyp é a caixa de tipo de arquivo, heic é a marca principal. Um arquivo HEIC não é uma codificação de imagem. É um contêiner com um marcador de marca, abrigando imagens codificadas em HEVC.
O que HEIC realmente é
HEIC = High Efficiency Image Container. A implementação com marca da Apple do HEIF, padronizado pelo MPEG como ISO/IEC 23008-12 em 2015. JPEG é tanto um algoritmo de compressão quanto um formato de arquivo. HEIC é apenas um contêiner. A compressão interna é HEVC (H.265), o mesmo codec usado para vídeo 4K.
Um único arquivo HEIC pode armazenar:
- Uma imagem principal
- Múltiplas imagens alternativas (fotos em sequência)
- Sequências de imagens (Live Photos: imagem estática + vídeo de 3 segundos)
- Canais alfa e mapas de profundidade
- Profundidade de cor de 16 bits por canal (JPEG é limitado a 8 bits)
O contêiner usa uma estrutura de caixas — exatamente como o MP4:
| Box | Propósito |
|---|---|
ftyp | Tipo de arquivo e marcas compatíveis |
meta | Metadados e propriedades do item |
mdat | Dados de imagem codificados brutos (bitstream HEVC) |
iloc | Localizações de itens dentro de mdat |
Essa extensibilidade permite que o HEIC faça coisas que o JPEG nunca pôde fazer. Analisá-lo requer entender a hierarquia de caixas, não apenas ler um bitstream bruto.
Por que a Apple mudou
A Apple não inventou o HEIC. O MPEG publicou o HEIF em 2015. A Apple o adotou como formato de câmera padrão do iPhone no iOS 11 (2017).
A mudança foi aritmética, não marketing. Uma foto típica de iPhone de 12 MP em JPEG é ~3,5 MB. Em HEIC, ~1,8 MB. Com 50 GB do nível gratuito de armazenamento do iCloud, essa diferença significa aproximadamente 14.000 fotos adicionais. A Apple vende níveis de armazenamento. A conta se faz sozinha.
Houve também o alinhamento do ecossistema. A Apple já havia adotado o HEVC para vídeo (H.265 no iOS 11). Reutilizar o mesmo codec para imagens estáticas significava blocos de decodificação de hardware compartilhados nos chips da série A, menor consumo de energia e um único caminho de licenciamento.
Os prós e contras
O HEIC é superior ao JPEG em quase todas as métricas, exceto a compatibilidade.
| Aspecto | HEIC | JPEG |
|---|---|---|
| Eficiência de compressão | ~40–50% menor na mesma qualidade | Linha de base |
| Profundidade de cor | Até 16 bits | 8 bits |
| Transparência | Sim | Não |
| Múltiplas imagens por arquivo | Sim | Não |
| Reedição sem perda | Sim | Não |
| Suporte nativo do Windows | Requer extensão HEIF | Universal |
| Suporte de navegadores web | Apenas Safari | Universal |
| Suporte do Android | Nativo em 9+ | Universal |
| Licenciamento de patentes | Pool de patentes HEVC | JPEG é isento de royalties |
O HEVC é coberto por múltiplos pools de patentes (MPEG LA, Access Advance). A Apple cobre as taxas para os usuários do iOS. Terceiros não têm esse privilégio. Essa incerteza é grande parte da razão pela qual a adoção fora do ecossistema da Apple estagnou.
Detectando HEIC lendo a assinatura do arquivo
Não confie na extensão .heic. Leia os primeiros 32 bytes e analise a caixa ftyp.
Layout exato de bytes do cabeçalho de um arquivo HEIC válido:
Bytes 0–3: Tamanho da caixa (uint32 big-endian)
Bytes 4–7: Tipo da caixa: "ftyp" (0x66 0x74 0x79 0x70)
Bytes 8–11: Marca principal: "heic" ou "heif" ou "mif1"
Bytes 12–15: Versão menor (geralmente 0x00000000)
Bytes 16+: Lista de marcas compatíveis (ex. "mif1", "heic", "MiHE")
TypeScript do lado do navegador:
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)
}
Nosso conversor executa essa verificação antes de tentar a decodificação. Marca errada = rejeição imediata, sem ciclos de CPU desperdiçados.
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"}
Verificação de nível superior com filetype:
import filetype
kind = filetype.guess("photo.heic")
if kind and kind.extension in ("heic", "heif"):
print(kind.mime) # image/heic
Ou com pillow-heif:
from pillow_heif import is_heif
if is_heif("photo.heic"):
# contêiner válido
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);
}
Com fileinfo:
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file('photo.heic');
// image/heic ou image/heif
ImageMagick CLI
ImageMagick 7+ suporta HEIC se compilado com libheif:
magick identify -verbose photo.heic | grep "Format:"
# Format: HEIC (High Efficiency Image Container)
Sem libheif: no decode delegate for this image format. Na maioria das distribuições Linux, libheif-examples fornece heif-convert como alternativa.
O caminho da conversão
Saber que um arquivo é HEIC não significa que você pode abri-lo. O Windows exige as HEIF Image Extensions. A maioria dos navegadores ainda se recusa a renderizar HEIC em tags <img>. O Android 9+ lida com isso nativamente; dispositivos mais antigos não.
A solução: converter. Nosso conversor de HEIC para JPG lida com todo o pipeline no seu navegador:
- Soltar arquivos — fotos individuais ou pastas inteiras, o processamento em lote é automático.
- Validação de assinatura — a verificação exata de bytes acima é executada em cada arquivo. Arquivos que não são HEIC são imediatamente rejeitados com uma mensagem clara.
- Decodificação do lado do cliente — uma compilação WebAssembly do libheif é executada localmente. Sem uploads. Sem servidores.
- Saída que preserva a qualidade — JPG com 90% de qualidade preserva a resolução e a precisão de cor originais.
- Download em lote — arquivos individuais ou um único arquivo ZIP.
Para saída sem perda com transparência: HEIC para PNG. Para tamanhos otimizados para web: HEIC para WebP.
Seus arquivos nunca deixam seu dispositivo. É disso que se trata.


