닷지 앤 번

Dodge and burn

붓으로 칠하듯 사진의 특정 부분만 밝게(닷지) 또는 어둡게(번) 만들어 입체감과 시선을 조각하는 기법.

다른 이름: Dodge & burn부분 밝기 보정
···
html
<div class="wrap">
  <div class="stage"><canvas id="c" width="300" height="180"></canvas></div>
  <div class="hud"><span>원형 마스크로 닷지·번을 자동 시연</span></div>
</div>
css
.wrap{position:absolute;inset:0;padding:clamp(8px,3vmin,20px);display:flex;flex-direction:column;gap:6px}
.stage{position:relative;flex:1;min-height:0}
canvas{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;border-radius:10px;border:1px solid var(--line);background:#0a0a0a}
.hud{display:flex;justify-content:center;font:700 clamp(9px,2.2vmin,11px)/1 ui-monospace,monospace;color:var(--muted)}
js
var W = 300, H = 180;
var c = document.getElementById('c'), ctx = c.getContext('2d');

function paintPhoto(cx, w, h) {
  var g = cx.createLinearGradient(0, 0, 0, h * 0.62);
  g.addColorStop(0, '#5b86c9'); g.addColorStop(0.55, '#bcd6ea'); g.addColorStop(1, '#f5e0ad');
  cx.fillStyle = g; cx.fillRect(0, 0, w, h);
  var sx = w * 0.74, sy = h * 0.22, sr = h * 0.11;
  var sg = cx.createRadialGradient(sx, sy, 0, sx, sy, sr * 3.2);
  sg.addColorStop(0, 'rgba(255,247,214,0.9)'); sg.addColorStop(1, 'rgba(255,247,214,0)');
  cx.fillStyle = sg; cx.fillRect(0, 0, w, h * 0.62);
  cx.fillStyle = '#fff8df'; cx.beginPath(); cx.arc(sx, sy, sr, 0, 7); cx.fill();
  cx.fillStyle = '#6f9152';
  cx.beginPath(); cx.moveTo(0, h * 0.64);
  for (var x = 0; x <= w; x += 14) cx.lineTo(x, h * 0.64 - Math.sin(x * 0.014) * h * 0.05 - Math.sin(x * 0.032 + 1.2) * h * 0.02);
  cx.lineTo(w, h); cx.lineTo(0, h); cx.closePath(); cx.fill();
  cx.fillStyle = '#405f38';
  cx.beginPath(); cx.moveTo(0, h * 0.79);
  for (var x2 = 0; x2 <= w; x2 += 14) cx.lineTo(x2, h * 0.79 - Math.sin(x2 * 0.022 + 0.6) * h * 0.035);
  cx.lineTo(w, h); cx.lineTo(0, h); cx.closePath(); cx.fill();
  var tx = w * 0.2, ty = h * 0.8;
  cx.strokeStyle = '#3a2a1c'; cx.lineWidth = Math.max(1.5, w * 0.008);
  cx.beginPath(); cx.moveTo(tx, ty); cx.lineTo(tx - w * 0.01, ty - h * 0.13); cx.stroke();
  cx.fillStyle = '#2e4a28';
  for (var i = 0; i < 5; i++) { cx.beginPath(); cx.arc(tx + (i - 2) * w * 0.013, ty - h * 0.15 - (i % 2) * h * 0.018, w * 0.028, 0, 7); cx.fill(); }
  cx.fillStyle = '#1e1e1c';
  cx.beginPath(); cx.arc(w * 0.56, h * 0.745, h * 0.018, 0, 7); cx.fill();
  cx.fillRect(w * 0.555, h * 0.76, w * 0.01, h * 0.06);
  var img = cx.getImageData(0, 0, w, h), d = img.data;
  for (var p = 0; p < d.length; p += 4) { var n = (Math.random() - 0.5) * 10; d[p] += n; d[p + 1] += n; d[p + 2] += n; }
  cx.putImageData(img, 0, 0);
}
paintPhoto(ctx, W, H);
var orig = ctx.getImageData(0, 0, W, H);
var t = 0;
function frame() {
  t += 0.02;
  var dodgeX = W * (0.28 + Math.sin(t) * 0.14), dodgeY = H * (0.42 + Math.cos(t * 1.3) * 0.14);
  var burnX = W * (0.72 - Math.sin(t) * 0.14), burnY = H * (0.62 - Math.cos(t * 1.3) * 0.14);
  var radius = H * 0.34;
  var out = ctx.createImageData(W, H);
  var id = orig.data, od = out.data;
  for (var y = 0; y < H; y++) {
    for (var x = 0; x < W; x++) {
      var idx = (y * W + x) * 4;
      var dD = Math.hypot(x - dodgeX, y - dodgeY) / radius;
      var dB = Math.hypot(x - burnX, y - burnY) / radius;
      var dodgeAmt = Math.max(0, 1 - dD) * 70;
      var burnAmt = Math.max(0, 1 - dB) * 70;
      var delta = dodgeAmt - burnAmt;
      od[idx] = Math.min(255, Math.max(0, id[idx] + delta));
      od[idx + 1] = Math.min(255, Math.max(0, id[idx + 1] + delta));
      od[idx + 2] = Math.min(255, Math.max(0, id[idx + 2] + delta));
      od[idx + 3] = 255;
    }
  }
  ctx.putImageData(out, 0, 0);
  requestAnimationFrame(frame);
}
frame();

이름은 암실 인화 시절 확대기 빛을 손으로 가리거나(닷지, 덜 노광 → 밝게) 더 쬐어(번, 더 노광 → 어둡게) 인화지 일부의 밝기를 바꾸던 데서 왔습니다. 디지털에서는 원리가 같습니다 — 붓이 지나간 자리의 픽셀에만 곱셈 또는 덧셈으로 밝기를 더하거나 뺍니다. 이 데모는 원형 마스크(가우시안 감쇠)가 사진 위를 오가며 지나간 자리는 밝히고(닷지) 반대편은 어둡게(번) 만듭니다.

인물 사진에서 광대·코끝처럼 빛을 받는 부위는 살짝 밝히고 턱선·목 그림자 쪽은 살짝 어둡게 해서 얼굴의 입체감을 강조할 때, 또는 풍경에서 시선을 끌고 싶은 피사체만 밝히고 주변부를 어둡게 눌러(비네팅처럼) 시선을 유도할 때 씁니다.

경계가 티 나게 뚜렷하면 붓이 지나간 자국이 얼룩처럼 보입니다. 그래서 실제 작업은 불투명도를 낮춘 붓으로 아주 여러 번 겹쳐 칠해 경계를 부드럽게 만듭니다. 톤 전체가 아니라 국소적으로만 건드리는 도구이기 때문에, 화면 전체 밝기가 아쉬우면 노출이나 레벨을 먼저 쓰는 게 맞습니다.

언제 쓰나

인물의 입체감을 살리거나 풍경에서 시선을 유도하고 싶을 때 씁니다. 붓 자국이 보이지 않도록 낮은 불투명도로 여러 번 겹쳐 칠하세요.