An image pixelator in two drawImage calls
I saw @rauchg share a little
"Pixelate Me" app (built in v0, designed by Taras Donchenko) and wanted to
rebuild the core. It's a satisfying one, because the effect that looks like it
needs a shader is really just two drawImage calls. Drop something in:
The whole trick
To pixelate, shrink then grow. Draw the image into a tiny canvas (say a sixteenth of the size) with smoothing on, so each block averages to one color. Then draw that tiny canvas back to full size with smoothing off, so every sample becomes a hard square instead of a blurry gradient:
const sw = Math.round(w / block); // 1/16th the width
const sh = Math.round(h / block);
const tmp = document.createElement("canvas");
tmp.width = sw; tmp.height = sh;
tmp.getContext("2d").drawImage(img, 0, 0, sw, sh); // shrink (smooth)
ctx.imageSmoothingEnabled = false; // the whole trick
ctx.drawImage(tmp, 0, 0, sw, sh, 0, 0, w, h); // blow it back upThat one flag, imageSmoothingEnabled = false, is the difference between a
blurry upscale and crisp pixel art. The block size is just the divisor: bigger
divisor, chunkier pixels.
Keep it full resolution
It's tempting to do all this at display size, but then your export is basically a screenshot. Run it at the image's native dimensions instead and the PNG you download is sharp at full size. Transparency rides along for free, so a cut-out subject stays cut out against whatever you drop it onto.
Recreated from Pixelate Me by @rauchg, designed by Taras Donchenko. Grab the component on the Image Pixelator page.
Ask your agent to implement this
Read the full writeup at https://seangeng.com/writing/an-image-pixelator.md and implement it in my project.
It covers: An image pixelator in two drawImage calls — Drop a picture, pick a block size, export a pixel-art PNG. The whole effect is drawing the image tiny, then scaling it back up with image smoothing turned off.
Requirements:
- Follow the technique/approach exactly as described in the writeup.
- Adapt names, colors, and styling to my project's existing conventions.
- If it's a component, make it reusable with sensible props and TypeScript types.
- Keep it accessible: semantic HTML, keyboard support, and respect prefers-reduced-motion.
- When done, tell me which files you created or changed and how to use it.Paste into Claude Code, Codex, Cursor, or any agent. view raw .md download source .zip