Análisis Profundos

¿Qué es HEIC? Una inmersión técnica profunda en firmas de archivos, detección y conversión

koboshiCo-founder
·6 min de lectura
¿Qué es HEIC? Una inmersión técnica profunda en firmas de archivos, detección y conversión
Resumen

HEIC no es solo un JPEG más pequeño. Es un formato contenedor basado en ISO Base Media File Format con imágenes codificadas en HEVC en su interior. Aquí te explicamos cómo funciona, cómo detectarlo leyendo bytes brutos, y cómo convertirlo cuando la compatibilidad falla.

Abre un archivo HEIC en un editor hexadecimal. Los primeros doce bytes:

00 00 00 18 66 74 79 70 68 65 69 63

Eso es ISOBMFF — el mismo estándar de contenedor que usa MP4. 0x18 (24 bytes) es el tamaño de la caja, ftyp es la caja de tipo de archivo, heic es la marca principal. Un archivo HEIC no es una codificación de imagen. Es un contenedor con un marcador de marca, que alberga imágenes codificadas en HEVC.

Qué es realmente HEIC

HEIC = High Efficiency Image Container. La implementación con marca de Apple de HEIF, estandarizado por MPEG como ISO/IEC 23008-12 en 2015. JPEG es tanto un algoritmo de compresión como un formato de archivo. HEIC es solo un contenedor. La compresión interna es HEVC (H.265), el mismo códec utilizado para video 4K.

Un solo archivo HEIC puede almacenar:

  • Una imagen principal
  • Múltiples imágenes alternativas (fotos en ráfaga)
  • Secuencias de imágenes (Live Photos: imagen fija + video de 3 segundos)
  • Canales alfa y mapas de profundidad
  • Profundidad de color de 16 bits por canal (JPEG está limitado a 8 bits)

El contenedor usa una estructura de cajas — exactamente como MP4:

BoxPropósito
ftypTipo de archivo y marcas compatibles
metaMetadatos y propiedades del elemento
mdatDatos de imagen codificados en bruto (flujo de bits HEVC)
ilocUbicaciones de elementos dentro de mdat

Esta extensibilidad permite a HEIC hacer cosas que JPEG nunca pudo hacer. Analizarlo requiere entender la jerarquía de cajas, no solo leer un flujo de bits en bruto.

Por qué Apple cambió

Apple no inventó HEIC. MPEG publicó HEIF en 2015. Apple lo adoptó como formato de cámara predeterminado del iPhone en iOS 11 (2017).

El cambio fue aritmético, no marketing. Una foto típica de iPhone de 12 MP en JPEG es ~3,5 MB. En HEIC, ~1,8 MB. Con 50 GB de nivel gratuito de almacenamiento iCloud, esa diferencia significa aproximadamente 14.000 fotos adicionales. Apple vende niveles de almacenamiento. La cuenta se hace sola.

También hubo alineación del ecosistema. Apple ya había adoptado HEVC para video (H.265 en iOS 11). Reutilizar el mismo códec para imágenes fijas significaba bloques de decodificación de hardware compartidos en los chips de la serie A, menor consumo de energía y un único camino de licenciamiento.

Los pros y los contras

HEIC es superior a JPEG en casi todas las métricas, excepto la compatibilidad.

AspectoHEICJPEG
Eficiencia de compresión~40–50% más pequeño a igual calidadLínea de base
Profundidad de colorHasta 16 bits8 bits
TransparenciaNo
Múltiples imágenes por archivoNo
Reedicionesin pérdidaNo
Soporte nativo de WindowsRequiere extensión HEIFUniversal
Soporte de navegadores webSolo SafariUniversal
Soporte de AndroidNativo en 9+Universal
Licenciamiento de patentesPool de patentes HEVCJPEG es libre de regalías

El HEVC está cubierto por múltiples pools de patentes (MPEG LA, Access Advance). Apple cubre las tarifas para los usuarios de iOS. Los terceros no tienen ese lujo. Esa incertidumbre es gran parte de la razón por la que la adopción fuera del ecosistema de Apple se estancó.

Detectar HEIC leyendo la firma del archivo

No confíes en la extensión .heic. Lee los primeros 32 bytes y analiza la caja ftyp.

Diseño exacto de bytes del encabezado de un archivo HEIC válido:

Bytes 0–3:   Tamaño de la caja (uint32 big-endian)
Bytes 4–7:   Tipo de caja: "ftyp" (0x66 0x74 0x79 0x70)
Bytes 8–11:  Marca principal: "heic" o "heif" o "mif1"
Bytes 12–15: Versión menor (generalmente 0x00000000)
Bytes 16+:   Lista de marcas compatibles (ej. "mif1", "heic", "MiHE")

TypeScript del lado del 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)
}

Nuestro convertidor ejecuta esta verificación antes de intentar la decodificación. Marca incorrecta = rechazo inmediato, sin ciclos de CPU desperdiciados.

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"}

Verificación de nivel superior con filetype:

import filetype

kind = filetype.guess("photo.heic")
if kind and kind.extension in ("heic", "heif"):
    print(kind.mime)  # image/heic

O con pillow-heif:

from pillow_heif import is_heif

if is_heif("photo.heic"):
    # contenedor 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);
}

Con fileinfo:

$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file('photo.heic');
// image/heic o image/heif

ImageMagick CLI

ImageMagick 7+ admite HEIC si se compiló con libheif:

magick identify -verbose photo.heic | grep "Format:"
# Format: HEIC (High Efficiency Image Container)

Sin libheif: no decode delegate for this image format. En la mayoría de las distribuciones de Linux, libheif-examples proporciona heif-convert como alternativa.

La ruta de conversión

Saber que un archivo es HEIC no lo abre. Windows necesita las HEIF Image Extensions. La mayoría de los navegadores se niegan a renderizar HEIC en etiquetas <img>. Android 9+ lo maneja nativamente; los dispositivos más antiguos no.

La solución: convertir. Nuestro convertidor de HEIC a JPG maneja todo el pipeline en tu navegador:

  1. Soltar archivos — fotos individuales o carpetas enteras, el procesamiento por lotes es automático.
  2. Validación de firma — la verificación exacta de bytes de arriba se ejecuta en cada archivo. Los archivos que no son HEIC se rechazan inmediatamente con un mensaje claro.
  3. Decodificación del lado del cliente — una compilación WebAssembly de libheif se ejecuta localmente. Sin subidas. Sin servidores.
  4. Salida que preserva la calidad — JPG al 90% de calidad conserva la resolución y la precisión del color originales.
  5. Descarga por lotes — archivos individuales o un único archivo ZIP.

Para salida sin pérdida con transparencia: HEIC a PNG. Para tamaños optimizados para web: HEIC a WebP.

Tus archivos nunca abandonan tu dispositivo. De eso se trata.

Más publicaciones del blog para leer