HEIC ファイルを十六進エディタで開く。先頭の 12 バイト:
00 00 00 18 66 74 79 70 68 65 69 63
これは ISOBMFF —— MP4 が使うのと同じコンテナ標準だ。0x18(24 バイト)は box サイズ、ftyp はファイルタイプ box、heic はメジャーブランド。HEIC ファイルは画像エンコードではない。特定のブランドマーカーを持つコンテナで、内部に HEVC エンコード画像を封入している。
HEIC とは何か
HEIC = High Efficiency Image Container。Apple がブランド化した HEIF の実装で、MPEG によって 2015 年に ISO/IEC 23008-12 として標準化された。JPEG は圧縮アルゴリズムとファイルフォーマットの両方だが、HEIC はコンテナに過ぎない。内部の圧縮は HEVC(H.265)、4K 動画と同じコーデックだ。
1 つの HEIC ファイルは以下を格納できる:
- 1 枚のプライマリ画像
- 複数の代替画像(バースト撮影)
- 画像シーケンス(Live Photo:静止画 + 3 秒動画)
- アルファチャンネルと深度マップ
- チャンネルあたり 16 ビット色深度(JPEG は 8 ビットに制限される)
コンテナは box 構造を使う —— MP4 とまったく同じだ:
| Box | 用途 |
|---|---|
ftyp | ファイルタイプと互換ブランド |
meta | アイテムメタデータとプロパティ |
mdat | 生のエンコード画像データ(HEVC ビットストリーム) |
iloc | mdat 内のアイテム位置 |
この拡張性こそが、HEIC に JPEG では決して不可能なことをさせている。解析するには box 階層を理解する必要があり、生のビットストリームを読むだけでは足りない。
Apple が切り替えた理由
Apple は HEIC を発明していない。MPEG は 2015 年に HEIF を公開し、Apple は 2017 年の iOS 11 で iPhone のデフォルトカメラフォーマットとして採用した。
推進力はマーケティングではなく、算術だった。iPhone の 1200 万画素写真は JPEG で約 3.5 MB、HEIC で約 1.8 MB だ。50 GB の無料 iCloud ティアでは、この差は約 14,000 枚の追加写真を意味する。ストレージティアを販売する Apple にとって、この計算は自明だ。
もう 1 つの要因はエコシステムの整合性だ。Apple はすでに動画で HEVC を採用していた(iOS 11 の H.265)。静止画に同じコーデックを再利用することは、A シリーズチップ上でハードウェアデコードブロックを共有し、消費電力を低下させ、単一のライセンスパスを維持することを意味した。
トレードオフ
HEIC は互換性という 1 つの点を除いて、ほぼすべての面で JPEG を凌駕している。
| 側面 | HEIC | JPEG |
|---|---|---|
| 圧縮効率 | 同等画質で約 40–50% 小型 | ベースライン |
| 色深度 | 最大 16 ビット | 8 ビット |
| 透明度 | あり | なし |
| 1 ファイル複数画像 | あり | なし |
| 非破壊再編集 | あり | なし |
| Windows ネイティブサポート | HEIF 拡張機能が必要 | 普遍的 |
| Web ブラウザサポート | Safari のみ | 普遍的 |
| Android サポート | 9 以降でネイティブ | 普遍的 |
| 特許ライセンス | HEVC 特許プール | JPEG はロイヤリティフリー |
HEVC は複数の特許プール(MPEG LA、Access Advance)によってカバーされている。Apple は iOS ユーザーに代わってライセンス料を支払っているが、サードパーティベンダーにはその特典はない。この不確実性が、Apple エコシステム外での採用が停滞した大きな理由だ。
ファイルシグネチャ読み取りによる HEIC 検出
.heic 拡張子は信じるな。先頭 32 バイトを読み、ftyp box をパースする。
有効な HEIC ファイルヘッダーの正確なバイトレイアウト:
Bytes 0–3: Box サイズ(ビッグエンディアン uint32)
Bytes 4–7: Box タイプ: "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+ は libheif でコンパイルされていれば HEIC をサポートする:
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 には Microsoft Store の HEIF Image Extensions が必要だ。ほとんどのブラウザは <img> タグでの HEIC レンダリングを拒否する。Android 9+ はネイティブに処理するが、古いデバイスはそうではない。
解決策:変換する。私たちの HEIC to JPG コンバーター はブラウザ内でパイプライン全体を処理する:
- ファイルをドロップ — 単一写真またはフォルダ全体、バッチ処理は自動的だ。
- シグネチャ検証 — 上記のバイトチェックが各ファイルに対して実行される。HEIC でないファイルは明確な不一致メッセージと共に直ちに拒否される。
- クライアントサイドデコード — libheif の WebAssembly ビルドがローカルで実行される。アップロードなし。サーバーに触れない。
- 品質保持出力 — 90% 品質の JPG は元の解像度と色精度を維持する。
- バッチダウンロード — 個別ファイルまたは単一の ZIP アーカイブ。
透明度付きのロスレス出力が必要な場合:HEIC to PNG。Web 最適化サイズが必要な場合:HEIC to WebP。
あなたのファイルはデバイスから離れない。それが重要な点だ。


