Inpainting

인페인팅

Painting a mask over part of an image so only that region is regenerated while everything outside it stays untouched.

Also known as: Masked editingGenerative fill
···
html
<div class="wrap">
  <canvas id="cv"></canvas>
  <div class="panel">마스크 안쪽만 다시 생성</div>
</div>
css
.wrap{position:relative;width:100%;height:100%}
#cv{position:absolute;inset:0;width:100%;height:100%}
.panel{position:absolute;top:10px;left:10px;z-index:2;padding:6px 10px;border-radius:10px;
  background:rgba(13,13,18,0.55);backdrop-filter:blur(6px);border:1px solid rgba(255,255,255,0.15);
  font-size:11px;font-weight:700;color:#f1f0ec}
js
const cv = document.getElementById('cv'), ctx = cv.getContext('2d');
function fit() { const dpr = Math.min(devicePixelRatio || 1, 2); cv.width = innerWidth * dpr; cv.height = innerHeight * dpr; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); }
addEventListener('resize', fit); fit();

function mulberry32(a) { return function () { a |= 0; a = a + 0x6D2B79F5 | 0; let t = Math.imul(a ^ a >>> 15, 1 | a); t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t; return ((t ^ t >>> 14) >>> 0) / 4294967296; }; }

function paintBase(w, h) {
  const r = mulberry32(5);
  const g = ctx.createLinearGradient(0, 0, 0, h);
  g.addColorStop(0, 'hsl(200 50% 62%)'); g.addColorStop(1, 'hsl(210 40% 32%)');
  ctx.fillStyle = g; ctx.fillRect(0, 0, w, h);
  ctx.beginPath(); ctx.arc(w * 0.18, h * 0.2, Math.min(w, h) * 0.08, 0, Math.PI * 2); ctx.fillStyle = 'hsl(48 85% 78%)'; ctx.fill();
  for (let l = 0; l < 2; l++) {
    ctx.beginPath(); ctx.moveTo(0, h);
    for (let i = 0; i <= 6; i++) { const x = w * i / 6; const y = h * (0.55 + l * 0.16) - r() * h * 0.1; ctx.lineTo(x, y); }
    ctx.lineTo(w, h); ctx.closePath();
    ctx.fillStyle = 'hsl(150 30% ' + (22 + l * 12) + '%)'; ctx.fill();
  }
}
function paintFill(mx, my, mw, mh, seed) {
  const r = mulberry32(seed);
  ctx.fillStyle = 'hsl(' + Math.floor(r() * 360) + ' 55% 45%)'; ctx.fillRect(mx, my, mw, mh);
  for (let i = 0; i < 6; i++) {
    ctx.beginPath(); ctx.arc(mx + r() * mw, my + r() * mh, Math.min(mw, mh) * (0.1 + r() * 0.15), 0, Math.PI * 2);
    ctx.fillStyle = 'hsl(' + Math.floor(r() * 360) + ' 70% 60%)'; ctx.fill();
  }
}
function render(seed) {
  const w = innerWidth, h = innerHeight;
  ctx.clearRect(0, 0, w, h);
  paintBase(w, h);
  const mx = w * 0.32, my = h * 0.32, mw = w * 0.38, mh = h * 0.4;
  ctx.save(); ctx.beginPath(); ctx.rect(mx, my, mw, mh); ctx.clip();
  paintFill(mx, my, mw, mh, seed);
  ctx.restore();
  ctx.setLineDash([6, 4]); ctx.strokeStyle = 'rgba(255,255,255,0.85)'; ctx.lineWidth = 2;
  ctx.strokeRect(mx, my, mw, mh); ctx.setLineDash([]);
}
const variants = [11, 22, 33];
let vi = 0;
function loop() { render(variants[vi]); vi = (vi + 1) % variants.length; setTimeout(loop, 1500); }
loop();

The user paints a mask (a binary in/out region) over what should change, and at every step of generation the pixels outside the mask are forced back to the original image's values (lightly renoised to match that step). So only the inside of the mask actually evolves.

The prompt describes what should appear inside the mask, not the whole picture. Common uses are removing or replacing an object, re-rendering just a flawed patch of a result, or swapping a small region for different content.

A hard mask edge tends to show a visible seam where color and texture do not quite match. Most tools feather the mask boundary softly so the transition reads naturally instead.

The demo below clips the canvas to a mask region and redraws only what is inside it with a different pattern each cycle, leaving everything outside completely untouched — a simulation, not real mask-guided generation.

When to use

Use it when only a specific part needs fixing or replacing, not the whole image. Write the prompt around what belongs inside the mask.