mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-08-02 01:08:05 +00:00
fix(web): size the live preview from the PNG's real dimensions, not config
The initial SSE render sized the preview image (and both overlay canvases) from the server-reported config dimensions (cols x chain_length, rows x parallel), while the scale slider's re-render path sized from img.naturalWidth/naturalHeight. Whenever the snapshot PNG's actual size disagrees with the config (stale config, display service not restarted after a hardware change), the initial render stretched the image at a fractional ratio - blurry despite image-rendering: pixelated - and touching the scale slider "fixed" it. Reported live on the devpi test rig. Both paths now size from the loaded image's natural dimensions inside img.onload (which also removes a transient wrong-size flash between src assignment and load). The meta label now reports the true snapshot size. The preview card also gets overflow-x-auto so on narrow screens a wide preview scrolls at its exact pixel-perfect size instead of being squeezed into the viewport (fractional downscaling of pixel art also reads as blur). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KEZK1P1Q1fu5pcuVrkrCFZ
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
84c41dfbf0
commit
b6a8a88665
@@ -1870,29 +1870,35 @@
|
|||||||
// Current scale from slider
|
// Current scale from slider
|
||||||
const scale = parseInt(document.getElementById('scaleRange')?.value || '8');
|
const scale = parseInt(document.getElementById('scaleRange')?.value || '8');
|
||||||
|
|
||||||
// Update image and meta label
|
// Update image and meta label. Size everything from the PNG's
|
||||||
|
// OWN dimensions (naturalWidth/Height) once it has loaded —
|
||||||
|
// not from the server-reported config dimensions. If the
|
||||||
|
// config disagrees with what the display service actually
|
||||||
|
// renders (stale config, service not yet restarted), sizing
|
||||||
|
// from config stretches the image at a fractional ratio and
|
||||||
|
// the preview looks blurry until the scale slider forces a
|
||||||
|
// re-render. The slider path always used natural dimensions;
|
||||||
|
// now both paths do.
|
||||||
img.style.imageRendering = 'pixelated';
|
img.style.imageRendering = 'pixelated';
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
|
const nw = img.naturalWidth || data.width || 128;
|
||||||
|
const nh = img.naturalHeight || data.height || 64;
|
||||||
|
const width = nw * scale;
|
||||||
|
const height = nh * scale;
|
||||||
|
img.style.width = width + 'px';
|
||||||
|
img.style.height = height + 'px';
|
||||||
|
ledCanvas.width = width;
|
||||||
|
ledCanvas.height = height;
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
const meta = document.getElementById('previewMeta');
|
||||||
|
if (meta) {
|
||||||
|
meta.textContent = `${nw} x ${nh} @ ${scale}x`;
|
||||||
|
}
|
||||||
|
drawGrid(canvas, nw, nh, scale);
|
||||||
renderLedDots();
|
renderLedDots();
|
||||||
};
|
};
|
||||||
img.src = `data:image/png;base64,${data.image}`;
|
img.src = `data:image/png;base64,${data.image}`;
|
||||||
|
|
||||||
const meta = document.getElementById('previewMeta');
|
|
||||||
if (meta) {
|
|
||||||
meta.textContent = `${data.width || 128} x ${data.height || 64} @ ${scale}x`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size the canvases to match
|
|
||||||
const width = (data.width || 128) * scale;
|
|
||||||
const height = (data.height || 64) * scale;
|
|
||||||
img.style.width = width + 'px';
|
|
||||||
img.style.height = height + 'px';
|
|
||||||
ledCanvas.width = width;
|
|
||||||
ledCanvas.height = height;
|
|
||||||
canvas.width = width;
|
|
||||||
canvas.height = height;
|
|
||||||
drawGrid(canvas, data.width || 128, data.height || 64, scale);
|
|
||||||
renderLedDots();
|
|
||||||
} else {
|
} else {
|
||||||
stage.style.display = 'none';
|
stage.style.display = 'none';
|
||||||
placeholder.style.display = 'block';
|
placeholder.style.display = 'block';
|
||||||
|
|||||||
@@ -321,7 +321,10 @@
|
|||||||
<h3 class="text-md font-medium text-gray-900 mb-4">
|
<h3 class="text-md font-medium text-gray-900 mb-4">
|
||||||
<i class="fas fa-desktop"></i> Live Display Preview
|
<i class="fas fa-desktop"></i> Live Display Preview
|
||||||
</h3>
|
</h3>
|
||||||
<div class="bg-gray-900 rounded-lg p-6 border border-gray-700" style="position: relative;">
|
<!-- overflow-x-auto: on narrow screens a wide preview scrolls at its
|
||||||
|
true pixel-perfect size instead of being squeezed (fractional
|
||||||
|
downscaling of pixel art reads as blur) -->
|
||||||
|
<div class="bg-gray-900 rounded-lg p-6 border border-gray-700 overflow-x-auto" style="position: relative;">
|
||||||
<div id="previewStage" class="preview-stage" style="display:none; position:relative; display:inline-block;">
|
<div id="previewStage" class="preview-stage" style="display:none; position:relative; display:inline-block;">
|
||||||
<div id="previewMeta" style="position:absolute; top:-28px; left:0; color:#ddd; font-size:12px; opacity:0.85;"></div>
|
<div id="previewMeta" style="position:absolute; top:-28px; left:0; color:#ddd; font-size:12px; opacity:0.85;"></div>
|
||||||
<img id="displayImage" style="image-rendering: pixelated; display: block;" alt="LED Matrix Display">
|
<img id="displayImage" style="image-rendering: pixelated; display: block;" alt="LED Matrix Display">
|
||||||
|
|||||||
Reference in New Issue
Block a user