I420(YUV420P)完全ガイド:データレイアウト・サイズ計算・色空間・変換の実務ポイント

I420とは(概要)

I420(アイフォートゥエンティ)とは、8ビットのYUV 4:2:0平面フォーマットの一つで、画像・映像処理やビデオコーデック、ストリーミングなどで広く使われています。別名で IYUV や YUV420P(FFmpegでのAV_PIX_FMT_YUV420Pに相当)とも呼ばれ、メモリ上では平面(planar)レイアウトで Y(輝度)プレーンの後に U(Cb)プレーン、V(Cr)プレーンが続く配置が特徴です。各成分は1バイト(8ビット)で表現されますが、色差成分(U/V)は水平方向・垂直方向ともに2分の1にサンプリングされます。

データレイアウトとサイズ計算

I420の基本的なレイアウトは次の通りです。

  • Yプレーン:幅W、高さH、サイズ = W × H バイト
  • Uプレーン:幅 = ceil(W/2)、高さ = ceil(H/2)、サイズ = ceil(W/2) × ceil(H/2) バイト
  • Vプレーン:Uと同じサイズ、順序は U の後に V

幅・高さが偶数の場合は簡単に計算でき、UとVの合計は (W × H) / 2 となるため、合計バッファサイズは 1.5 × W × H バイトになります(例えば 1920×1080 だと 1920×1080×1.5 = 3110400 バイト)。幅・高さが奇数の場合は多くの実装で ceil を用いて切り上げるため、実際のバッファサイズは若干大きくなります。一般的なサイズ式は:

  • 総バイト数 = W × H + 2 × ceil(W/2) × ceil(H/2)

行単位のパディング(stride、linesize)を持つことが多く、ピクセル幅と行のバイト幅が一致しない場合は各行末に余分なバイトが入ります。特にハードウェアやライブラリ(FFmpeg, libyuv, Androidなど)ではパフォーマンスのために行境界を 16/32 バイト境界に合わせることがあり、これを考慮してメモリ計算を行う必要があります。

I420 と他フォーマット(NV12, NV21, YV12 など)の違い

YUV420のサブサンプリング自体は同じでも、メモリ上の配置が異なるフォーマットが複数存在します。代表的なものを挙げます。

  • I420 / YUV420P / IYUV:Y, U, V の順で平面を並べる(I420とFFmpegのAV_PIX_FMT_YUV420P相当)。
  • YV12:Y, V, U の順(UとVの平面が入れ替わっている)。しばしば YV12 と表記されたり、V と U の順序ミスで色が反転するトラブルが起きる。
  • NV12:Yプレーンの後に U と V が交互にインターリーブされたセミプラン(UVUV...)。Intel のハードウェアや多くのGPUでサポートされている。
  • NV21:NV12 と同じだがインターリーブ順が VU(VUVU...)。Android の一部APIやカメラ出力で使われることがある。

上記の違いは単純にメモリの並び方の違いですが、U/Vの順序やインターリーブの有無を間違えると色が大きく変わるため注意が必要です。

色空間・レンジ・クロマサンプリングの位置(siting)について

I420自体は「どの色空間(BT.601, BT.709, BT.2020など)を使っているか」や「リミテッドレンジ(テレビ)かフルレンジ(コンピュータ)か」といったメタ情報を含みません。したがって、YUVデータをRGBに変換する際は、正しい色空間・レンジ・クロマサンプリング位置(クロマのサンプリングがどのピクセルに対応するか)を外部で指定する必要があります。

クロマのサンプリング位置(chroma siting)は縦横2分の1でサンプリングされるU/VがどのYピクセルに属するかを決めるもので、実装によって「ピクセルの中心に対応する」場合や「ピクセルの左上角に対応する」場合があります(ITU-R BT.601 と MPEG 系で扱いが違うことがある)。この違いは映像のエッジやサブピクセルの位置にわずかなずれを生み、精密な合成や合成後の再エンコードで目立つことがあります。

変換(YUV → RGB)の考え方と代表的な式

YUVからRGBへの変換式は色空間(BT.601/BT.709)とレンジ(限定/フル)によって係数が変わります。放送用(リミテッドレンジ)のBT.601に基づく代表的な式(8ビット、Y'は16-235、C = 128基準)は次のようになります。

  • R = 1.164 × (Y - 16) + 1.596 × (V - 128)
  • G = 1.164 × (Y - 16) - 0.392 × (U - 128) - 0.813 × (V - 128)
  • B = 1.164 × (Y - 16) + 2.017 × (U - 128)

フルレンジ(0-255)の場合はスケーリング係数が異なり、単純化すると 1.0 × (Y - 0) で始める等の違いがあります。実際のソフトウェアでは色域やガンマ補正、クリッピング(0-255への丸め)を適切に行う必要があります。I420データそのものは係数を持たないため、適切な色変換パラメータの指定が重要です。

利用分野・エコシステムとの関係

I420はシンプルでメモリの並びが直感的なため、多くのライブラリやハードウェアで利用・サポートされています。主な利用例を挙げます。

  • ビデオコーデック(H.264/HEVC等):内部ピクセル表現やデコード出力で使用されることが多い。
  • ストリーミング・リアルタイム通信(WebRTCなど):効率的にCPU/GPUで扱えるフォーマットとして用いられる場合がある。
  • 画像処理ライブラリ(libyuv, FFmpeg, OpenCVなど):変換・スケーリング・回転をサポート。
  • モバイルプラットフォーム(AndroidのYUV_420_888等):カメラサブシステムからの生データ取得やエンコーダ入出力に関連。

実装上の注意点・よくあるトラブル

I420を扱う際に見られる主な注意点とトラブル例は以下の通りです。

  • U/Vの入れ替えミス(I420 と YV12 の取り違え)で色が赤と青で反転する。
  • 行ストライド(linesize)を無視して連続メモリとして扱うと表示が乱れる。特にライブラリがピッチを付ける場合は各行ごとにコピーが必要。
  • 幅・高さが奇数のときのチャネルサイズ計算ミスでバッファオーバー/アクセス違反になる。ceil(W/2)×ceil(H/2) を使うか、実装仕様に合わせる。
  • 色空間情報を無視すると色がくすむ・派手に見えるなどの違いが出る。BT.601/709/2020やリミテッド/フルを正しく扱う。
  • ハードウェアアクセラレーションが NV12 等を優先するケースが多いため、I420 ↔ NV12 の変換コストがパフォーマンスのボトルネックになることがある。
  • 回転やリサイズ時のクロマ補間(ニアレスト、バイリニア、ランチョスなど)によって結果が大きく変わる。特に低ビットレートや強い圧縮でクロマが粗いと顕著。

具体例:バッファサイズの計算例

例1:幅が偶数・高さが偶数(例 640×480)

  • Y: 640×480 = 307200
  • U: 320×240 = 76800
  • V: 320×240 = 76800
  • 合計 = 307200 + 76800 + 76800 = 460800 = 1.5 × 640 × 480

例2:幅・高さが奇数(例 5×3)

  • Y: 5×3 = 15
  • U: ceil(5/2)=3, ceil(3/2)=2 → 3×2 = 6
  • V: 6
  • 合計 = 15 + 6 + 6 = 27 バイト

まとめ

I420はシンプルかつ広く普及したYUV 4:2:0平面フォーマットであり、Y, U, Vの平面順序(Y→U→V)とサブサンプリング(水平・垂直ともに2分の1)が重要な特徴です。色空間情報やストライド、U/Vの順序、クロマサンプリング位置などのメタ情報はフォーマット本体には含まれないため、映像処理時にはそれらを明確に管理する必要があります。実装上はバッファサイズ、行ストライド、奇数寸法、U/Vの取り扱いに注意すれば、I420は非常に扱いやすいフォーマットです。

参考文献