Skip to content

Instantly share code, notes, and snippets.

@AdoHaha
Created January 12, 2026 18:11
Show Gist options
  • Select an option

  • Save AdoHaha/16ea674d9a836e04d5088bb802d7bfdb to your computer and use it in GitHub Desktop.

Select an option

Save AdoHaha/16ea674d9a836e04d5088bb802d7bfdb to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JSON Bounding Box Drawer</title>
<style>
body {
font-family: sans-serif;
margin: 20px;
background: #f0f0f0;
}
.controls {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
margin-bottom: 20px;
display: flex;
gap: 20px;
flex-wrap: wrap;
}
.input-group {
flex: 1;
min-width: 300px;
display: flex;
flex-direction: column;
gap: 10px;
}
textarea {
width: 100%;
height: 150px;
font-family: monospace;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
.canvas-container {
position: relative;
display: inline-block;
background: white;
border: 1px solid #ccc;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
overflow: auto;
max-width: 100%;
}
canvas {
display: block;
}
button {
padding: 10px 20px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background: #0056b3;
}
.error {
color: red;
margin-top: 5px;
display: none;
}
</style>
</head>
<body>
<div class="controls">
<div class="input-group">
<label for="imageInput"><strong>1. Select Image:</strong></label>
<input type="file" id="imageInput" accept="image/*">
<p style="font-size: 0.9em; color: #666;">Select 'aniaprawa_pos_z.png' or similar.</p>
</div>
<div class="input-group">
<label for="jsonInput"><strong>2. Paste JSON:</strong></label>
<textarea id="jsonInput" placeholder='[{"box_2d": [535, 638, 561, 663], "label": "pinky finger fingertip"}]'></textarea>
<button onclick="draw()">Render Boxes</button>
<div id="errorMsg" class="error"></div>
</div>
</div>
<div class="canvas-container">
<canvas id="outputCanvas"></canvas>
</div>
<script>
const imageInput = document.getElementById('imageInput');
const jsonInput = document.getElementById('jsonInput');
const canvas = document.getElementById('outputCanvas');
const ctx = canvas.getContext('2d');
const errorMsg = document.getElementById('errorMsg');
let currentImage = null;
// Default JSON example
jsonInput.value = JSON.stringify([
{"box_2d": [535, 638, 561, 663], "label": "pinky finger fingertip"}
], null, 2);
imageInput.addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(event) {
const img = new Image();
img.onload = function() {
currentImage = img;
draw();
}
img.src = event.target.result;
}
reader.readAsDataURL(file);
});
function draw() {
errorMsg.style.display = 'none';
errorMsg.textContent = '';
if (!currentImage) {
// Try to clear if no image, or just wait
canvas.width = 800;
canvas.height = 600;
ctx.fillStyle = '#eee';
ctx.fillRect(0,0, 800, 600);
ctx.fillStyle = '#666';
ctx.font = '20px sans-serif';
ctx.fillText('Please select an image first', 280, 300);
return;
}
// Resize canvas to match image
canvas.width = currentImage.width;
canvas.height = currentImage.height;
// Draw Image
ctx.drawImage(currentImage, 0, 0);
// Parse JSON
let data = [];
try {
data = JSON.parse(jsonInput.value);
} catch (e) {
errorMsg.textContent = 'Invalid JSON: ' + e.message;
errorMsg.style.display = 'block';
return;
}
if (!Array.isArray(data)) {
errorMsg.textContent = 'JSON must be an array.';
errorMsg.style.display = 'block';
return;
}
// Draw Boxes
// Coordinate system is 0-1000
const scaleX = currentImage.width / 1000;
const scaleY = currentImage.height / 1000;
ctx.lineWidth = 2;
ctx.font = '14px sans-serif';
data.forEach((item, index) => {
if (!item.box_2d || item.box_2d.length !== 4) return;
const [x1_raw, y1_raw, x2_raw, y2_raw] = item.box_2d;
const x1 = x1_raw * scaleX;
const y1 = y1_raw * scaleY;
const x2 = x2_raw * scaleX;
const y2 = y2_raw * scaleY;
const w = x2 - x1;
const h = y2 - y1;
// Pick a color (hashed from label or index)
const hue = (index * 137.5) % 360;
const color = `hsla(${hue}, 70%, 50%, 1)`;
const bgColor = `hsla(${hue}, 70%, 50%, 0.2)`;
// Draw Box
ctx.strokeStyle = color;
ctx.fillStyle = bgColor;
ctx.strokeRect(x1, y1, w, h);
ctx.fillRect(x1, y1, w, h);
// Draw Label
if (item.label) {
const text = item.label;
const textWidth = ctx.measureText(text).width;
const textHeight = 16;
ctx.fillStyle = color;
ctx.fillRect(x1, y1 - textHeight - 4, textWidth + 8, textHeight + 4);
ctx.fillStyle = 'white';
ctx.textBaseline = 'top';
ctx.fillText(text, x1 + 4, y1 - textHeight - 2);
}
});
}
// Initial Draw call to show placeholder
draw();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment