HEIC and HEIF: Apple's Modern Image Format Explained
Since iOS 11 launched in 2017, every iPhone shooting in default mode has been creating HEIC files. Hundreds of millions of users now accumulate libraries of .heic images — and routinely run into the problem that Windows, older Android phones, and many web services cannot handle them without conversion. Understanding what HEIC and HEIF are, how they work, and how to convert them efficiently solves one of the most common format headaches in personal computing.
HEIF vs HEIC: Clearing Up the Confusion
The naming is genuinely confusing. Here is the precise distinction:
| Term | Full Name | Meaning |
|---|---|---|
| HEIF | High Efficiency Image File Format | The container format (MPEG/ISO standard) |
| HEIC | High Efficiency Image Container | A HEIF file using HEVC (H.265) compression |
| AVIF | AV1 Image File Format | A HEIF file using AV1 compression |
.heif |
File extension | Generic HEIF, may use any codec |
.heic |
File extension | Apple-specific; always HEVC-compressed |
So: HEIF is the box, HEVC is what Apple puts in the box, and .heic is the label Apple chose. When people say "HEIF" they almost always mean what Apple calls HEIC. This guide uses HEIC to refer to Apple's implementation.
Why HEIC Exists: The Compression Advantage
HEIC achieves roughly twice the compression of JPEG at equivalent visual quality. A photo that takes 3 MB as JPEG might be 1.4 MB as HEIC with no perceptible quality difference on a calibrated display.
The compression gain comes from HEVC's more sophisticated prediction coding (larger transform blocks, better intra-prediction, improved entropy coding) applied to still images. HEVC was designed for video, but its per-frame coding is dramatically better than JPEG's DCT algorithm from 1992.
Additional capabilities that JPEG lacks:
- 10-bit color depth — smoother gradients, less banding in skies and skin tones
- Wide color gamut (Display P3) — used by all iPhone cameras since iPhone 7
- HDR (Dolby Vision / HDR10) — iPhone 12+ captures HDR photos
- Alpha channel — transparency support (HEVC Profile: Main Still Picture + alpha)
- Image sequences — Live Photos store the still frame and the 1.5-second video clip in a single HEIC file
- Depth maps — Portrait mode depth data embedded in the container
- Auxiliary images — Gain map for HDR → SDR tonemapping (Apple Adaptive HDR)
- Lossless — HEVC supports lossless coding for archival use
HEIF Container Structure
HEIF is based on ISOBMFF (ISO Base Media File Format, ISO/IEC 14496-12) — the same container used by MP4 and MOV. Instead of being a time-based sequence of samples, a HEIF file organizes images as items:
HEIC File (ISOBMFF)
├── ftyp box ← File type declaration: brand = 'heic', compatible_brands = ['mif1','hevc']
├── meta box ← All metadata and item references
│ ├── hdlr ← Handler type: 'pict'
│ ├── pitm ← Primary item ID (which item is the main image)
│ ├── iloc ← Item location: byte offset + length for each item's data
│ ├── iinf ← Item information: type (hvc1/av01), content type, name
│ ├── iref ← Item references: 'auxl' (auxiliary), 'thmb' (thumbnail), 'cdsc' (description)
│ ├── iprp ← Item properties
│ │ ├── ispe (image spatial extents: width × height)
│ │ ├── colr (colour information: nclx for P3/BT.2020 or prof for ICC profile)
│ │ ├── pixi (pixel information: bit depth per channel)
│ │ ├── hvcC (HEVC decoder configuration record)
│ │ └── Exif/XMP metadata property
│ └── grpl ← Group lists (stereo pair, alpha associations)
├── mdat box ← Compressed image bitstream(s)
└── [moov box] ← Present in Live Photos: the embedded video track
The iloc box is the index: it maps item IDs to byte ranges within mdat, enabling efficient random access to any image in a multi-image HEIC without reading the whole file.
Compatibility Landscape
| Platform | HEIC Support | Notes |
|---|---|---|
| iOS 11+ | Native read/write | Default camera format |
| macOS 10.13+ | Native read/write | Preview, Photos, Quick Look |
| Windows 10/11 | Requires codec pack | Free "HEIF Image Extensions" from Microsoft Store |
| Windows Photos app | With codec | Installs automatically on modern Windows |
| Android 9+ | Partial read | HEIF decode support in MediaCodec API |
| Android 12+ | Better support | Camera HEIF capture on some OEMs |
| Chrome 85+ | AVIF only | HEIC not natively supported |
| Firefox | AVIF only | HEIC blocked (no HEVC license) |
| Safari | Full HEIC/HEIF | macOS and iOS native |
| Photoshop | With HEIF plugin | Adobe Camera Raw 13.2+ |
| GIMP | libheif plugin | Install via package manager |
The core compatibility problem is HEVC licensing: browser vendors and Linux distributions resist shipping HEVC decoders due to patent royalty concerns. This is why AVIF (AV1-in-HEIF) was developed as a royalty-free alternative.
Converting HEIC with FFmpeg
FFmpeg supports HEIC decode via libheif on systems where it is compiled in:
# Check if FFmpeg has HEIF support
ffmpeg -decoders 2>/dev/null | grep heif
# Convert single HEIC to JPEG (quality 95)
ffmpeg -i photo.heic -q:v 1 output.jpg
# Convert to PNG (lossless)
ffmpeg -i photo.heic output.png
# Batch convert all HEIC to JPEG
for f in *.heic; do
ffmpeg -i "$f" -q:v 2 "${f%.heic}.jpg"
done
# Preserve EXIF metadata (requires exiftool after conversion)
ffmpeg -i photo.heic -q:v 1 output.jpg
exiftool -TagsFromFile photo.heic -all:all output.jpg
Converting HEIC with Python (pillow-heif)
The pillow-heif library integrates HEIF support into Pillow:
from PIL import Image
import pillow_heif
# Register HEIF opener with Pillow
pillow_heif.register_heif_opener()
# Open and convert HEIC to JPEG
with Image.open('photo.heic') as img:
# Convert to sRGB if wide-gamut P3
if img.mode in ('RGB', 'RGBA'):
img = img.convert('RGB')
img.save('output.jpg', 'JPEG', quality=92, optimize=True)
print(f"Size: {img.size}, Mode: {img.mode}")
# Access HEIF-specific metadata
heif_file = pillow_heif.read_heif('photo.heic')
print(f"Images in file: {len(heif_file)}") # >1 for Live Photos
print(f"Bit depth: {heif_file.bit_depth}")
print(f"Has alpha: {heif_file.has_alpha}")
# Batch convert preserving EXIF
import os
from pathlib import Path
pillow_heif.register_heif_opener()
for heic_path in Path('.').glob('*.heic'):
with Image.open(heic_path) as img:
exif_data = img.info.get('exif')
out = heic_path.with_suffix('.jpg')
save_kwargs = {'quality': 92}
if exif_data:
save_kwargs['exif'] = exif_data
img.convert('RGB').save(out, 'JPEG', **save_kwargs)
print(f"Converted: {out}")
Using libheif Directly (C API)
For maximum control, libheif provides the reference HEIC decoder:
#include <libheif/heif.h>
struct heif_context* ctx = heif_context_alloc();
heif_context_read_from_file(ctx, "photo.heic", NULL);
struct heif_image_handle* handle;
heif_context_get_primary_image_handle(ctx, &handle);
int width = heif_image_handle_get_width(handle);
int height = heif_image_handle_get_height(handle);
int bit_depth = heif_image_handle_get_luma_bits_per_pixel(handle);
struct heif_image* image;
heif_decode_image(handle,
&image,
heif_colorspace_RGB,
heif_chroma_interleaved_RGB,
NULL);
int stride;
const uint8_t* pixels = heif_image_get_plane_readonly(image,
heif_channel_interleaved,
&stride);
// pixels now contains raw RGB bytes, stride bytes per row
heif_image_release(image);
heif_image_handle_release(handle);
heif_context_free(ctx);
HEIC vs JPEG vs WebP vs AVIF Comparison
| Feature | JPEG | WebP | HEIC | AVIF |
|---|---|---|---|---|
| Compression efficiency | Baseline | +30% vs JPEG | +50% vs JPEG | +50% vs JPEG |
| Bit depth | 8-bit | 8/10-bit | 8/10/12-bit | 8/10/12-bit |
| Alpha channel | No | Yes | Yes | Yes |
| HDR | No | No | Yes | Yes |
| Wide color (P3) | No | No | Yes | Yes |
| Lossless | No | Yes | Yes | Yes |
| Image sequences | No | Yes (WebP anim) | Yes (HEIF seq) | Yes |
| Browser support | Universal | Universal | Safari only | Chrome/Firefox/Safari |
| Patent status | Free (expired) | Royalty-free | HEVC royalties | Royalty-free |
| Encode speed | Fast | Medium | Slow | Very slow |
| Decode speed | Fast | Fast | Medium | Medium |
When to Convert HEIC
Convert HEIC to JPEG or PNG when:
- Sharing with Windows users who lack the HEVC codec pack
- Uploading to web services or social media that reject HEIC
- Attaching to email for recipients on non-Apple platforms
- Processing in software that does not support HEIC (older Photoshop, GIMP without plugin)
- Publishing web images (use WebP or AVIF instead for better browser support)
Keep HEIC when:
- Archiving in Apple ecosystem (iCloud, Photos)
- Storage space is constrained and quality must be preserved
- HDR content will be viewed on Apple devices
Summary
HEIC is a technically superior image format that Apple chose for good reasons: 50% smaller files with equivalent quality, HDR support, wide color, and flexible multi-image containers. The compatibility friction with non-Apple platforms is real but shrinking as Windows adds codec support and Android improves HEIF decode. For archival and Apple-to-Apple sharing, keep HEIC. For cross-platform distribution, converting to JPEG or WebP remains the practical choice.
Related conversions
Most teams that read this guide convert images in one of these directions: