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

短い式にも接続が要る

反転は1−xで表せます。既知の式から編集機能にするには、原画像の保持、マスク、不透明度、合成、設定保存の接続が必要でした。

PHOTOSHOT DEVELOPMENT JOURNAL / 13

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

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

ソースから始める。

短い式の先にある開発

0〜1の成分xを1−xに置き換えます。この数学をAIが発明したのではなく、既存の変換表と文書構造に接続しました。

明るさ、レベル、カーブで使う256入力の変換表経路を再利用します。保存と合成を他の調整と同じ規則に保てます。

RGBとアルファを分ける

8ビットRGBなら0は255、255は0、64は191になります。各色成分に同じ式を適用します。色の反転はマスク反転やアルファを1−アルファにする処理とは別です。

共通処理は完全に透明な画素を飛ばし、元のアルファを保持します。透明背景が色の反転によって不透明になることを避けます。

src/adjustments.ts · v0.16.0
L550–554
Photoshotの実装コード ↗
    return (r, g, b, out) => {
      out[0] = tables[0][r];
      out[1] = tables[1][g];
      out[2] = tables[2][b];
    };
Photoshot無料Photoshop代替の開発記 / 13IMPLEMENTATION

計算の
内側へ。

同じ反転を二度適用する

理想の式を二度適用すれば1−(1−x)=xです。ただし実際の文書では、不透明度、マスク、途中の処理も条件に含まれます。

明るさを変えてから反転する結果と、反転してから明るさを変える結果は必ずしも同じではありません。短い数式だけではレイヤー順序の影響を説明できません。

マスクと合成は共通の経路

計算した色を不透明度、マスク、描画モードとともに共通合成器へ渡します。原画像を残し、設定を保存して再編集できます。

本日16種の既存検査で恒等条件、アルファ、プロジェクト保存往復、合成経路の一致を確認しました。これは保管済み写真の作例とは別であり、新たなマスク写真を撮影したという主張ではありません。

PHOTOSHOT / SOURCE NOTES13

コードを読む。

src/adjustments.ts · v0.16.0
L539–547
Photoshotの実装コード ↗
              ? 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));
        if (t === 'invert') x = 1 - x;
        if (t === 'posterize')
          x =
            a.revision === 2
              ? Math.min(v.steps - 1, Math.floor((i * v.steps) / 256)) / (v.steps - 1)
              : Math.round(x * (v.steps - 1)) / (v.steps - 1);
        return clamp(x);
src/adjustments.ts · v0.16.0
L836–853
Photoshotの実装コード ↗
    beforeRGB: RGB = [0, 0, 0],
    mixed: RGB = [0, 0, 0];
  for (let i = start; i < end; i += 4) {
    if (!data[i + 3]) continue;
    let amount = opacity * (mask ? mask[i + 3] / 255 : 1);
    if (blend === 'dissolve') amount = pixelNoise(i / 4) < amount ? 1 : 0;
    if (!amount) continue;
    compiled(data[i], data[i + 1], data[i + 2], out);
    for (let c = 0; c < 3; c++) beforeRGB[c] = data[i + c] / 255;
    if (a.values.dither && (a.type === 'lookup' || a.type === 'gradient'))
      for (let c = 0; c < 3; c++) out[c] = clamp(out[c] + (pixelNoise(i / 4) - 0.5) / 255);
    blendRGB(beforeRGB, out, blend, mixed);
    for (let c = 0; c < 3; c++)
      data[i + c] = Math.round(clamp(beforeRGB[c] + (mixed[c] - beforeRGB[c]) * amount) * 255);
  }
}
src/adjustments.ts · v0.16.0
L253–265
Photoshotの実装コード ↗
export function isIdentityAdjustment(a: Adjustment): boolean {
  if (a.type === 'lookup') return !a.cube;
  if (a.type === 'curves') return channels.every((c) => a.curves![c].every((p) => p.x === p.y));
  if (a.type === 'photo') return a.values.density === 0;
  if (['blackwhite', 'gradient', 'invert', 'posterize', 'threshold'].includes(a.type)) return false;
  if (a.bands?.some((b) => b.hue || b.saturation || b.lightness)) return false;
  return definitions[a.type].controls.every(
    (c) =>
      ['preserve', 'relative', 'skin', 'legacy', 'colorizeHue', 'colorizeSaturation'].includes(
        c.key,
      ) || (a.values[c.key] ?? c.initial) === c.initial,
  );
}
Photoshot無料Photoshop代替の開発記 / 13IN PRACTICE

エディターで見る。

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

実際の出力と次の機能

保存作例は数値調節のない反転調整、不透明度100%です。原画像はAI生成人物写真で、操作画面と出力は実際のPhotoshotの資料です。

この回の中心は新しい色の公式より、同じ編集モデルに組み込む接続です。次回は連続値を限られた階調にまとめるポスタリゼーションを扱います。

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

写真で見る結果。

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

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