AI 생성 시연 사진 / 편집 전
DEVELOPMENT JOURNAL / 06
Photoshot
GITHUB × AI
무료 포토샵 개발기

활기와 채도의 차이

색마다 채도를 다르게 바꾸는 활기 구현은 이미 GitHub에 있었습니다. 무료 포토샵에 필요한 것은 그 아이디어를 이해하고 기존 조정 엔진에서 사용할 수 있게 만드는 일이었습니다. glfx.js를 읽은 뒤 AI와 별도 HSL 계산을 작성하고 측정 응답까지 연결한 과정에서 그 역할을 살펴봅니다.

PHOTOSHOT DEVELOPMENT JOURNAL / 06

AI 생성 시연용 사진. 편집 화면과 출력 이미지는 실제 포토샷에서 만들었습니다.

Photoshot무료 포토샵 개발기 / 06FOUNDATION

출처에서 시작하다.

색을 다루는 코드도 이미 공개돼 있었다

공개 구현은 출발점을 앞당겨 주었습니다. 어떤 입력으로 색의 반응을 나눌 수 있는지 코드로 확인할 수 있었기 때문입니다. AI와 한 작업은 그 코드를 그대로 실행하는 데 그치지 않고, 포토샷의 색 변환과 조정 레이어에 맞는 구현을 연결하는 것이었습니다.

2026년 9월 18일 개발 세션에는 glfx.js의 vibrance.js 원문을 열어 읽은 기록이 남아 있습니다. RGB의 최댓값과 평균을 이용해 색마다 반응을 달리하는 짧은 셰이더였습니다. 한 슬라이더가 모든 색에 같은 변화량을 줄 필요는 없다는 점을 확인할 수 있었습니다.

포토샷에는 이 셰이더를 그대로 넣지 않았습니다. 당시 개발 노트도 HSL 채도에 (1−S) 가중치를 주는 별도 계산이라고 적고 있습니다. 참고한 외부 구현과 AI가 포토샷용으로 작성한 계산을 구분해서 보는 것이 이번 편의 출발점입니다.

덜 선명한 색에 더 큰 가중치를 주기

아래는 GitHub에 공개한 포토샷 코드입니다. s는 0~1 범위의 채도입니다. 활기 값에 (1−s)를 곱하므로 같은 양의 활기를 주어도 채도가 높은 색은 추가 증가율이 작아집니다. 채도 슬라이더는 그 뒤에 별도의 배율로 곱해집니다.

이것은 HSL 경로의 설명입니다. 현재 공개본의 모든 활기 처리가 이 두 줄을 거치는 것은 아닙니다. 보호 옵션을 켠 revision 2 조정은 다음 절의 측정 응답 경로를 사용합니다.

여기서 재사용한 것은 한 외부 필터 전체가 아니라, 이미 구현된 색 처리 아이디어와 내부의 조정 기반입니다. AI와 작성한 계산이 같은 엔진에 들어가면서 다른 조정과 마찬가지로 값을 저장하고 마스크를 적용할 수 있게 됐습니다.

src/adjustments.ts · v0.16.0
L646–647
포토샷 구현 코드 ↗
const gain = (v.vibrance / 100) * (1 - s) * (1 - 0.75 * skin);
fromHsl(h, clamp(s * (1 + gain) * (1 + v.saturation / 100)), l, out);
Photoshot무료 포토샵 개발기 / 06IMPLEMENTATION

계산의
안쪽으로.

AI와 측정 응답을 기존 엔진에 연결했다

후속 구현은 합성 RGB 색상표를 Photoshop에 입력해 얻은 반응을 데이터로 사용합니다. 소스 주석에는 Photoshop 27.3.1에서 측정한 17×17×17 RGB 격자라고 명시돼 있습니다. 이 데이터는 Adobe의 프리셋 파일이나 glfx.js에서 가져온 표가 아닙니다.

AI와 작성한 연결 코드는 먼저 활기 응답을 적용하고, 그 결과에 채도 응답을 적용합니다. 샘플에 없는 색과 슬라이더 값은 보간합니다. 측정값을 보관하는 파일과 이를 호출하는 조정 엔진을 나누어 기존 레이어 구조에 연결했습니다.

‘피부색 보호’가 얼굴을 찾는 것은 아니다

설정 이름만 보면 얼굴을 찾아 피부에만 별도 처리를 할 것 같습니다. 하지만 이 경로가 받는 것은 RGB와 슬라이더 값입니다. 사람의 얼굴인지, 비슷한 색의 벽이나 옷인지는 알지 못합니다. 같은 RGB라면 같은 계산을 받습니다.

따라서 이 옵션은 색 반응 방식을 선택하는 기능으로 설명하는 것이 정확합니다. 특정 인물만 조정하려면 별도의 레이어 마스크가 필요합니다. 측정 격자 사이를 보간하는 구현이므로 Photoshop과 모든 사진에서 똑같다는 주장도 할 수 없습니다.

PHOTOSHOT / SOURCE NOTES06

코드를 읽다.

src/adjustments.ts · v0.16.0
L634–642
포토샷 구현 코드 ↗
} else if (a.revision === 2 && v.skin) {
  scratch[0] = r;
  scratch[1] = g;
  scratch[2] = b;
  applyVibranceResponse(scratch, v.vibrance, 0, out);
  scratch[0] = out[0];
  scratch[1] = out[1];
  scratch[2] = out[2];
  applyVibranceResponse(scratch, v.saturation, 1, out);
src/vibrance-response.ts · v0.16.0
L60–67
포토샷 구현 코드 ↗
const p = Math.max(0, Math.min(20, (value + 100) / 10)),
  lo = Math.floor(p),
  hi = Math.min(20, lo + 1),
  f = p - lo,
  a = data[mode * 21 + lo],
  b = data[mode * 21 + hi];
table = new Float32Array(a.length);
for (let i = 0; i < a.length; i++) table[i] = a[i] + (b[i] - a[i]) * f;
Photoshot무료 포토샵 개발기 / 06IN PRACTICE

편집 화면에서.

실제 포토샷 작업 화면. 설정과 사진을 함께 확인할 수 있습니다.
실제 포토샷 작업 화면. 설정과 사진을 함께 확인할 수 있습니다.

사진 예시와 확인 범위

사진 예시에는 활기 +30, 채도 −5, 피부색 보호 켜짐을 적용했습니다. AI로 생성한 인물 사진을 실제 포토샷에서 편집한 화면과 결과입니다. 꽃과 옷처럼 색이 서로 다른 부분을 함께 놓고 변화를 비교할 수 있습니다.

공개 저장소의 tests/vibrance.mjs에는 기본값에서의 색 유지, 알파 보존, 극단값과 잘못된 입력을 검사하는 코드가 들어 있습니다. 사진으로 결과를 살펴보고, 코드로 계산의 기본 동작을 확인하는 두 가지 과정이 필요합니다.

활기 기능 역시 AI가 새로운 색 이론을 발명해 가능해진 사례는 아닙니다. 공개 구현을 읽을 수 있는 기반 위에서 자체 계산과 측정 데이터를 연결하는 작업을 AI와 수행한 사례입니다. 기존 기술을 조합하되 필요한 부분을 고칠 수 있어야 실제 편집 기능이 됩니다.

이번 기능은 GitHub에서 읽은 아이디어, AI와 작성한 계산, 측정 데이터를 연결한 결과입니다. 다음 편에서는 파랑처럼 특정 색 범위만 골라 조정하는 코드를 살펴보겠습니다.

Photoshot무료 포토샵 개발기 / 06BEFORE / AFTER

사진으로 보는 결과.

AI 생성 시연 사진 / 편집 전
01 / AI 생성 시연 사진 / 편집 전
포토샷 출력 / 편집 결과
02 / 포토샷 출력 / 편집 결과

AI 생성 시연용 사진. 편집 화면과 출력 이미지는 실제 포토샷에서 만들었습니다.