I play a lot of Minecraft, and every time I wanted to build pixel art from an image I hit the same wall: manually matching each pixel to the closest block color, then counting how many of each block I'd need. For a 64×64 build that's 4,000+ blocks to plan by hand. So I built a tool to do it in a second — BlockMosaic.
It converts any image into Minecraft blocks right in the browser. No upload, no signup. Here's what went into it and a few things I learned.
Everything runs client-side
The whole pipeline is in-browser — your image never touches a server. That's a privacy win and it means zero server cost, but it also forced some interesting constraints.
The image→blocks conversion runs in a Web Worker so the UI stays responsive, and the heavy code is lazy-loaded with a dynamic import so it never bloats the first paint. The page content itself is server-rendered (static export) for SEO, while the interactive tool hydrates separately.
Matching colors to blocks
The core is simple: downsample the image to a grid, then match each cell to the nearest block by squared RGB distance. The fun part was the palette.
I needed accurate average colors for ~160 blocks. Instead of eyeballing them, I extracted the official block textures from the Minecraft client jar and computed the average color of each texture programmatically (averaging only non-transparent pixels, and the first frame of animated textures). Biome-tinted textures like grass are grayscale in the file, so those got a manual override.
I also added dithering (Floyd–Steinberg and ordered) — when you reduce to a limited block palette, error diffusion makes gradients read way smoother than nearest-match alone.
Exporting builds
Previewing is nice, but the real value is not placing 4,000 blocks by hand. So the tool exports:
-
.litematicfor the Litematica mod -
.schemfor WorldEdit -
.mcfunctionassetblockcommands
Both schematic formats are NBT under the hood. There's no NBT library small enough that I wanted to ship, so I wrote a tiny big-endian NBT writer and used the browser's built-in CompressionStream for gzip. The trickiest bit was Litematica's bit-packed block-state array (palette indices packed across 64-bit longs) — BigInt made that bearable.
As a bonus I added a Litematica → Schematic file converter (reads a .litematic, re-emits a .schem), which meant writing the NBT reader too.
Things I'd tell my past self
- Web Workers + dynamic import are the cheap way to keep a heavy client tool from wrecking your load time.
-
CompressionStream/DecompressionStreamare in every modern browser now — you rarely need a gzip dependency anymore. - Computing palette colors from real assets beats hand-tuning every time, and it's a 50-line script.
Try it
If you build in Minecraft (or just want to pixelate an image), give it a go:
- Minecraft pixel art generator — image → blocks, with a block shopping list
- Image to pixel art — generic pixelation, not just Minecraft
- Image to schematic — export a buildable blueprint
It's free and runs entirely in your browser. I'd love feedback — especially on color accuracy and which export formats you'd want next. What would you build first?
Top comments (0)