Dodge and burn

닷지 앤 번

Paint brightness or darkness onto specific parts of a photo — like a brush — to sculpt depth and guide the eye.

Also known as: 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();

The name comes from the darkroom — blocking the enlarger's light by hand (dodging, less exposure, brighter) or giving one spot extra light (burning, more exposure, darker) to change brightness on part of the print. Digitally the idea is identical: add or subtract brightness only where a brush passes over. This demo sweeps a soft circular mask back and forth across the photo, lightening where it lands on one side and darkening on the other.

Photographers use it on portraits to lift cheekbones and the tip of the nose toward the light while deepening the jawline and neck shadow, sculpting the face's sense of depth — or on landscapes to brighten the subject that should draw the eye while pressing the edges of the frame darker, like a soft vignette.

A hard-edged pass looks like a smudge. Real dodge-and-burn work is many low-opacity passes layered on top of each other so the edge disappears. Because it only touches local areas, not the whole tone range, an overall exposure problem should be fixed with exposure or levels first.

When to use

Use it to sculpt a portrait's depth or guide the eye in a landscape. Layer many low-opacity passes so no brush edge shows.