無料画像編集ソフト開発記 第5回:GitHub公開の露光量計算とAIによる修正
露光量は、これまでの参照・実装作業で整えた共通調整構造へ新しい計算をつないだ機能だ。今回はPhotoshotのGitHubコードから色変換、EV計算、バージョン分岐を読む。特定の外部露光量実装を取り込んだと確認できる記録はない。
出典照合 · 2026年10月16日改訂
記事を読む ↓

再利用した共通コードの位置を見る
前の回ではKonvaとglfx.jsの実装を参照した。露光量で確認できる再利用箇所はPhotoshotのcompileAdjustmentで、下の条件にbrightness、levels、curvesと並んでexposureが入っている。
別の編集機を作るのではなく、既存のレイヤー、LUT、マスク処理へ計算を追加した。AIと書いた新しいコードを、それまでの構造へ接続した形だ。
if (['brightness', 'levels', 'curves', 'exposure', 'invert', 'posterize'].includes(t)) {const tables = ['r', 'g', 'b'].map((channel) =>
Float64Array.from({ length: 256 }, (_, i) => {
let x = i / 255;旧経路はsRGB変換を使った
露光量は保存された表示用チャンネル値へEVを足すだけではない。旧経路ではlinearでsRGBを線形化し、srgbで表示用の値へ戻していた。
下は標準的な色変換式をTypeScriptで表したPhotoshotのコードだ。特定のGitHubからこの二行を複製した記録は確認できない。AIとコードを書くことと、数学の原理を発明することは区別したい。
const linear = (s: number) => (s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4);
const srgb = (s: number) => (s <= 0.0031308 ? 12.92 * s : 1.055 * s ** (1 / 2.4) - 0.055);露光量・オフセット・ガンマを修正
中心となるのは2 ** v.ev。+1 EVなら線形側の値を2倍、−1なら半分にし、オフセットとガンマを処理する。ただし変換空間と計算順序で結果は変わる。
比較後のrevision 2は2.2乗の経路を使い、旧調整はlinear/srgb経路を維持する。下の分岐は新旧の計算を同じ関数に残している実際のコードだ。
if (t === 'exposure')
x =
a.revision === 2
? clamp(x ** 2.2 * 2 ** v.ev + v.offset) ** (1 / (2.2 * v.gamma))
: srgb(clamp(linear(x) * 2 ** v.ev + v.offset) ** (1 / v.gamma));新計算で以前の作品を変えない
式の変更より難しいのは保存済みデータの意味を守ることだった。旧調整を開いただけで新計算が適用されると、利用者が何も変えなくても色が変わってしまう。
revision分岐はそのための互換性ルールで、カーブと同じ方針を引き継いでいる。新関数だけでなく、既存データがどの経路を選ぶかまで修正した。
露光量テストと写真結果
写真例はEV +0.35、オフセット−0.004、ガンマ1.05。元の人物画像はAI生成素材で、画面と結果はPhotoshotによるものだ。
過去のPhotoshop比較チャートでは+1 / 0 / 1の平均差が約0.015、最大2。−0.7 / 0.015 / 1.2は約0.015、最大1だった。記録された二条件の結果であり、あらゆるHDR・色管理環境を対象とする数値ではない。
第1〜5回はコードを探し、つなぎ、直す記録
最初の五回を通じた方法は共通している。Reactや初期PixiJSを実際に利用し、Konvaやglfx.jsの実装を読み、文書・レイヤー・計算・UIをAIと書いたコードでつなぎ、比較結果から修正する。
露光量は、その組み合わせが次の機能の基盤になる例だ。抜粋は公開v0.16.0を基準とし、何を利用して何を実装したかをたどれるよう、出典と検証範囲を残した。
