AI生成の動作例用写真 / 編集前
DEVELOPMENT JOURNAL / 09
Photoshot
GITHUB × AI
無料Photoshop代替の開発記

白黒をつくる六つの色

白黒のために色処理エンジンを作り直す必要はありませんでした。PhotoshotのHSL変換と合成を再利用し、AIと色別のグレー計算やスライダーを接続しました。再利用できる部品が増えるほど、次の編集機能に必要な作業範囲は小さくなります。

PHOTOSHOT DEVELOPMENT JOURNAL / 09

AI生成の動作例用写真。編集画面と出力画像は実際のPhotoshotで作成しました。

Photoshot無料Photoshop代替の開発記 / 09FOUNDATION

ソースから始める。

既存の色処理部品から別の道具へ

新機能ごとに外部リポジトリが一つ対応するわけではありません。内部につないである変換・保存・合成のコードも重要な再利用資産です。白黒ツールはその上に、AIと計算と操作を追加した例です。

この機能について、特定のGitHub白黒フィルターを取り込んだ記録は確認できませんでした。既存のHSL変換と共通合成処理を再利用し、色系統ごとの設定と灰色計算をAIと書きました。GitHubはその実装を確認できる公開先です。

赤・黄・緑・シアン・青・マゼンタをcolor0〜color5に保存します。初期値も一律ではありません。元の色がどの程度の灰色になるかを編集可能にするのが、この機能の中心です。

色相環の隣の2つの設定を混ぜる

元のRGBから色相hを求め、6倍して色区間を特定します。整数部分iで区間を、小数部分fで隣の設定を混ぜる割合を決めます。赤と黄の間なら両スライダーが効き、最後のマゼンタから赤への区間も剰余演算でつながります。

ここで求めるweightは肌を認識する値ではありません。元の色に基づく混合係数なので、赤みのある肌と赤い服が似た方向に変わることがあります。

六つの色の間の補間は、元の色とスライダー設定をつなぐコードです。AIと書いた部分は既存のHSL変換を使い、グレーの結果を共通の合成経路に渡します。この境界に、全体を作り直さなくてよい理由が表れています。

src/adjustments.ts · v0.16.0
L149–160
Photoshotの実装コード ↗
blackwhite: {
  name: '흑백',
  description: '원본의 색상별 밝기를 조절하며 흑백으로 변환합니다.',
  controls: colorNames
    .slice(0, 6)
    .map((n, i) => control('color' + i, n, -100, 300, [40, 60, 40, 60, 20, 80][i]))
    .concat(
      control('tint', '색조 입히기', 0, 1),
      control('tintHue', '색조', 0, 360, 40),
      control('tintSaturation', '색조 채도', 0, 100, 25),
    ),
},
src/adjustments.ts · v0.16.0
L692–699
Photoshotの実装コード ↗
if (t === 'blackwhite') {
  const [h] = hsl(r, g, b, scratch),
    pos = h * 6,
    i = Math.floor(pos) % 6,
    f = pos - Math.floor(pos),
    weight = (v['color' + i] * (1 - f) + v['color' + ((i + 1) % 6)] * f) / 100;
  const gray = clamp(Math.min(r, g, b) + (Math.max(r, g, b) - Math.min(r, g, b)) * weight);
  out.fill(gray);
Photoshot無料Photoshop代替の開発記 / 09IMPLEMENTATION

計算の
内側へ。

無彩色を保ち、有彩色の明るさを変える

灰色値はRGBの最小値に「最大値−最小値」とweightの積を加えて求めます。もともと灰色なら最大値と最小値の差は0です。色調付けをオフにした状態では、色別スライダーを動かしても元の無彩色を保ちます。

純赤はcolor0を直接使うので55なら灰色は0.55、8ビット出力では約140です。純黄60は153、純青5は約13。これは式の説明用の単色例であり、写真全体の平均輝度やPhotoshopとの誤差ではありません。

色調付けとマスクは別の段階

out.fill(gray)は3チャンネルに同じ値を入れます。tintが有効なら、その後に指定した色相と彩度で色調を付けます。白黒の混合値を変える作業と、セピアなどの色を加える作業を分けています。

マスクと不透明度は共通の合成段階で処理します。顔だけの明るさを変える場合は、式に顔認識を期待するのではなく、調整レイヤーのマスクで範囲を指定します。

PHOTOSHOT / SOURCE NOTES09

コードを読む。

src/adjustments.ts · v0.16.0
L699–700
Photoshotの実装コード ↗
out.fill(gray);
if (v.tint) fromHsl(v.tintHue / 360, v.tintSaturation / 100, gray, out);
Photoshot無料Photoshop代替の開発記 / 09IN PRACTICE

エディターで見る。

実際のPhotoshot作業画面。設定と写真を一緒に確認できます。
実際のPhotoshot作業画面。設定と写真を一緒に確認できます。

写真例の6つの値を残す

保存済みの写真例は赤55、黄60、緑40、シアン60、青5、マゼンタ80で、色調付けはオフです。原画像はAI生成で、編集画面と出力は実際のポトショットの結果です。

AIの価値はグレースケール変換の概念を初めてつくることではありません。既存コードの役割を維持し、新しい混合計算と操作を接続することでした。共通の土台があるほど、代替エディターの拡張を具体的で小さな作業に分けられます。

省略した設定を推測せずに済むよう、6つの値をすべて記録しました。本稿は色に基づく白黒調整の実装記録です。次回はフィルター色と濃度から色変換を組み立てます。

Photoshot無料Photoshop代替の開発記 / 09BEFORE / AFTER

写真で見る結果。

AI生成の動作例用写真 / 編集前
01 / AI生成の動作例用写真 / 編集前
Photoshotの出力 / 編集結果
02 / Photoshotの出力 / 編集結果

AI生成の動作例用写真。編集画面と出力画像は実際のPhotoshotで作成しました。

参考資料とコード

Photoshot / adjustments.ts ↗