크롭 앤 스트레이튼

Crop and straighten

기울어진 수평선을 회전으로 바로잡고 불필요한 가장자리를 잘라내 구도를 다시 짜는, 가장 기본적인 편집 단계.

다른 이름: Crop & straighten수평 맞추기
···
html
<div class="wrap">
  <div class="stage"><canvas id="c" width="300" height="180"></canvas></div>
  <div class="hud"><span>회전 후 빈 모서리를 크롭으로 제거</span><b id="ang">0.0°</b></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:space-between;gap:8px;font:700 clamp(9px,2.2vmin,11px)/1 ui-monospace,monospace;color:var(--muted)}
.hud b{color:var(--fg)}
js
var W = 300, H = 180;
var pc = document.createElement('canvas'); pc.width = W; pc.height = H;
var pctx = pc.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(pctx, W, H);
var c = document.getElementById('c'), ctx = c.getContext('2d');
var t = 0;
function frame() {
  t += 0.012;
  var angleDeg = Math.sin(t) * 6;
  var angle = angleDeg * Math.PI / 180;
  ctx.fillStyle = '#0a0a0a'; ctx.fillRect(0, 0, W, H);
  ctx.save();
  ctx.translate(W / 2, H / 2);
  ctx.rotate(angle);
  ctx.drawImage(pc, -W / 2, -H / 2);
  ctx.restore();
  var marginX = W * Math.abs(Math.sin(angle)) * 0.55;
  var marginY = H * Math.abs(Math.sin(angle)) * 0.55;
  var cx0 = marginX, cy0 = marginY, cw = W - marginX * 2, ch = H - marginY * 2;
  ctx.fillStyle = 'rgba(0,0,0,0.6)';
  ctx.fillRect(0, 0, W, cy0);
  ctx.fillRect(0, cy0 + ch, W, H - (cy0 + ch));
  ctx.fillRect(0, cy0, cx0, ch);
  ctx.fillRect(cx0 + cw, cy0, W - (cx0 + cw), ch);
  ctx.strokeStyle = '#fff'; ctx.lineWidth = 1.5; ctx.strokeRect(cx0, cy0, cw, ch);
  ctx.strokeStyle = 'rgba(255,255,255,0.35)'; ctx.lineWidth = 1;
  for (var k = 1; k < 3; k++) {
    var gx = cx0 + cw * k / 3;
    ctx.beginPath(); ctx.moveTo(gx, cy0); ctx.lineTo(gx, cy0 + ch); ctx.stroke();
    var gy = cy0 + ch * k / 3;
    ctx.beginPath(); ctx.moveTo(cx0, gy); ctx.lineTo(cx0 + cw, gy); ctx.stroke();
  }
  document.getElementById('ang').textContent = angleDeg.toFixed(1) + '°';
  requestAnimationFrame(frame);
}
frame();

스트레이튼은 사진 전체를 캔버스 중심을 기준으로 몇 도 회전시키는 것뿐입니다 — 수평선이나 건물의 수직선을 기준 삼아 그 각도만큼 반대로 돌립니다. 회전을 걸면 네 모서리가 캔버스 밖으로 빠져나오므로, 크롭으로 그 빈 삼각형이 안 보이게 잘라내는 과정이 항상 따라붙습니다. 이 데모는 회전 각도를 애니메이션으로 흔들며, 기울기가 바뀔 때마다 크롭 사각형이 자동으로 안쪽으로 줄어들어 빈 모서리가 절대 보이지 않도록 하는 모습을 보여줍니다.

촬영 당시 수평이 살짝 안 맞았을 때(바다·지평선이 기운 사진), 또는 의도적으로 구도를 다시 짜서 불필요한 배경을 덜어내고 피사체를 삼분할선에 맞추고 싶을 때 가장 먼저 하는 손질입니다. 대부분의 다른 보정(톤·색)보다 먼저 하는 것이 좋습니다 — 나중에 하면 크롭된 만큼 이미 건 보정도 함께 잘려나가기 때문입니다.

회전 각도를 과하게 주면 원본에서 살릴 수 있는 화각이 급격히 줄어들어(모서리를 크게 잘라내야 하므로) 크롭 후 남는 화면이 좁아집니다. 수평선이 여러 개(바다 수평선 + 건물 창틀처럼 서로 다른 각도)인 사진에서는 하나를 기준으로 맞추면 다른 하나가 여전히 기울어 보인다는 점도 흔히 간과됩니다.

언제 쓰나

수평·수직이 살짝 틀어졌거나 구도를 다시 짜고 싶을 때 가장 먼저 합니다. 각도를 과하게 주면 크롭 후 남는 화각이 급격히 좁아집니다.