Skip to content

Instantly share code, notes, and snippets.

@Fordi
Last active December 8, 2018 07:24
Show Gist options
  • Save Fordi/bb7e55ef97a07b57dc9b5df11cdfd396 to your computer and use it in GitHub Desktop.
Save Fordi/bb7e55ef97a07b57dc9b5df11cdfd396 to your computer and use it in GitHub Desktop.
Convert a picture to dice
<html>
<head>
<title>Picture-to-Dice</title>
<script>
const loadImg = (file) => {
const reader = new FileReader();
const src = new Image();
const count = parseInt(document.getElementById('count').value) || 64000;
const canvas = document.createElement('canvas');
const preview = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const ptx = preview.getContext('2d');
let aspect, width, height;
const faces = [
[0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 1, 0, 1, 0, 0],
[1, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 1, 0, 1, 1, 0, 1]
];
const drawDie = (x, y, n) => {
// Draw the box
ptx.fillStyle = 'transparent';
ptx.strokeStyle = '#888888';
ptx.beginPath();
ptx.moveTo(x * 9 + 2, y * 9);
ptx.lineTo(x * 9 + 6, y * 9);
ptx.arcTo(x * 9 + 8, y * 9, x * 9 + 8, y * 9 + 2, 2);
ptx.lineTo(x * 9 + 8, y * 9 + 6);
ptx.arcTo(x * 9 + 8, y * 9 + 8, x * 9 + 6, y * 9 + 8, 2);
ptx.lineTo(x * 9 + 2, y * 9 + 8);
ptx.arcTo(x * 9, y * 9 + 8, x * 9, y * 9 + 6, 2);
ptx.lineTo(x * 9, y * 9 + 2);
ptx.arcTo(x * 9, y * 9, x * 9 + 2, y * 9, 2);
ptx.stroke();
ptx.closePath();
ptx.fillStyle = '#000000';
ptx.strokeStyle = 'transparent';
const face = faces[n];
for (let iy = 0; iy < 3; iy++) {
for (let ix = 0; ix < 3; ix++) {
if (face[iy * 3 + ix]) {
ptx.beginPath();
ptx.ellipse(
x * 9 + 2 + ix * 2,
y * 9 + 2 + iy * 2,
0.5,
0.5,
0,
0,
2 * Math.PI
);
ptx.fill();
ptx.closePath();
}
}
}
};
reader.onload = (e) => {
src.onload = () => {
let aspect = src.width / src.height;
if (aspect === 1) {
width = height = Math.floor(Math.sqrt(count));
} else if (aspect > 1) {
height = Math.ceil(Math.sqrt(count / aspect));
width = Math.floor(count / height);
} else {
width = Math.ceil(Math.sqrt(count * aspect));
height = Math.floor(count / height);
}
canvas.width = width;
canvas.height = height;
preview.width = width * 9;
preview.height = height * 9;
ptx.fillStyle = '#FFFFFF';
ptx.fillRect(0, 0, width*9, height*9);
ctx.drawImage(src, 0, 0, src.width, src.height, 0, 0, width, height);
const data = ctx.getImageData(0, 0, width, height);
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const p = (y * width + x) * 4;
const r = data.data[p] / 255;
const g = data.data[p + 1] / 255;
const b = data.data[p + 2] / 255;
let lum = 1 - (r + g + b) / 3;
let die = Math.floor((lum * 5.999));
drawDie(x, y, die);
}
}
document.body.appendChild(preview);
}
src.setAttribute('src', e.target.result);
};
reader.readAsDataURL(file);
};
</script>
</head>
<body>
<dl>
<dt><label for="count">Dice count</label></dt>
<dd><input id="count" type="number" placeholder="64000" /></dd>
</dl>
<dl>
<dt><label for="image">Image</label></dt>
<dd>
<input id="image" type="file" onchange="loadImg(this.files[0])" accept="image/gif, image/jpeg, image/png" />
<img id="preview" />
</dd>
</dl>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment