記事一覧へ

なぜ普通の反転アプリだと顔が青くなる?C-41ネガの「オレンジ色かぶり除去」の仕組み

顔が青くなる反転ツールは、どれも同じ誤りを犯しています。濃度空間の問題を線形の問題として扱っているのです。式の導出とシェーダーを示します。

公開 2026年8月26日更新 2026年9月2日約3分で読めます·Yichen Lab

翻拍したネガを一般的な画像編集アプリで「色を反転」すると、顔がシアンに転びます。よくある診断である「ホワイトバランスがずれている」は誤りで、だから色温度スライダーをいくら動かしても最後まで合いません。この色かぶりはフィルムに意図的に焼き込まれており、除去に必要なのは減算ではなく除算です。

1. そもそもなぜフィルムベースはオレンジ色なのか

カラーネガのシアン・マゼンタ色素は分光的に純粋ではなく、本来吸収すべきでない波長まで吸収します(不要吸収)。放置すればネガから再現される全ての色が濁ります。C-41 全般で採用されている対策がカラードカプラーで、未反応のカプラーが黄橙色のまま残り、補正すべき不要吸収とちょうど同じ形のポジマスクを形成します。あのオレンジは欠陥ではなく、内蔵された補正フィルターです。

そこから導かれる帰結

現像済みC-41ネガは意図的に中性ではありません。ベースが中性だと仮定する反転処理は、開始時点で別の方程式を解いています。

2. 線形反転(1 − RGB)という罠

フィルムの応答は指数的です。光学濃度は D = log₁₀(1 / T)(T は透過率)で定義され、露光に対して線形なのは透過率ではなく濃度のほうです。8bit sRGB 値を 255 - x で反転すると透過率を反転することになり、オレンジ成分はシアンに反転して残り、透過率スケールの圧縮された側にある暗部は紺色のベタに潰れます。

3. 濃度空間でのマスク減算

濃度空間ではベース除去は単純な減算です:D_image = D_pixel − D_base。両辺を指数に戻すと減算は除算になり、T_image = T_pixel / T_base となります。シェーダーがサンプリングしたマスク色で「割る」のはこのためです。その後の1つのべき関数が、乳剤の非線形応答を復元します。

src/lib/film-inverter/shaders.ts — 核心部分
vec3 inverted = pow(max(vec3(0.0), 1.0 - (pixel / mask)), vec3(u_filmCurve));
inverted = clamp((inverted - u_black) / (u_white - u_black), 0.0, 1.0);
inverted = pow(inverted, vec3(1.0 / u_gamma));
  • pixel / mask — 濃度空間におけるオレンジベースの減算。
  • u_filmCurve(約1.45〜1.60)— 平坦なランプではなくS字の乳剤特性を復元。
  • u_black / u_white — レベル伸張。白飛び黒潰れなくヒストグラムを使い切る。
  • u_gamma(1.8)— 表示系の伝達関数を補償。これがないと中間調が暗く濁ります。

4. `mask` を正しく取る:40×40+外れ値除去

補正全体がチャンネルごとの1つの数値に依存するため、ホコリ1ピクセルで1コマ全体が破綻します。NegaScan は未露光ベース(歯孔の隙間やコマ間)の 40×40 領域を平均し、平均前に標準偏差1.5倍を超えるサンプルを棄却します。手作業のマスク切りなしに、粒状ノイズ・ホコリ・キズを除外できます。

5. 実際に動かしてみる

ライブ反転 — ドラッグして比較FUJIFILM SUPERIA 200 // 35MM
ネガポジ
フル機能のワークベンチを開く

ワークベンチと同じシェーダーが、あなたのGPU上で動作します。仕切りをドラッグし、手元のネガ画像をドロップして挙動を確認してください。

どのピクセルをフィルムベースとして使ったか答えられない反転ツールは、推測しています。その推測の後始末を、あなたが毎コマ引き受けることになります。

あわせて読みたい