Last active
December 8, 2018 07:24
-
-
Save Fordi/bb7e55ef97a07b57dc9b5df11cdfd396 to your computer and use it in GitHub Desktop.
Convert a picture to dice
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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