Fix issue with size of first image getting applied to all images. Fixes issue #61

This commit is contained in:
javl
2026-08-15 11:16:24 +02:00
parent 8453661825
commit a30874d8f1
2 changed files with 58 additions and 22 deletions
+26 -20
View File
@@ -171,7 +171,11 @@ const CONVERSION_BYTES_PER_VALUE = new Map([
// An images collection with helper methods
function Images() {
const collection = [];
this.push = (img, canvas, glyph) => { collection.push({ img, canvas, glyph }); };
this.push = (img, canvas, glyph, width, height) => {
collection.push({
img, canvas, glyph, width, height,
});
};
this.remove = (image) => {
const i = collection.indexOf(image);
if (i !== -1) collection.splice(i, 1);
@@ -217,9 +221,11 @@ function placeImage(_image) {
const { canvas } = _image;
const ctx = canvas.getContext('2d');
// reset canvas size
canvas.width = Number.isFinite(settings.screenWidth) && settings.screenWidth > 0 ? settings.screenWidth : 1;
canvas.height = Number.isFinite(settings.screenHeight) && settings.screenHeight > 0 ? settings.screenHeight : 1;
// reset canvas size (falls back to the canvas' current size for images,
// like a re-imported byte array, that aren't tracked in the image list
// with their own width/height)
canvas.width = Number.isFinite(_image.width) && _image.width > 0 ? _image.width : canvas.width;
canvas.height = Number.isFinite(_image.height) && _image.height > 0 ? _image.height : canvas.height;
// eslint-disable-next-line no-param-reassign
_image.ctx = ctx;
ctx.save();
@@ -358,8 +364,8 @@ function placeImage(_image) {
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (settings.rotation === 90) {
canvas.width = settings.screenHeight;
canvas.height = settings.screenWidth;
canvas.width = clone.height;
canvas.height = clone.width;
ctx.setTransform(1, 0, 0, 1, canvas.width, 0);
ctx.rotate(Math.PI / 2);
ctx.drawImage(clone, 0, 0);
@@ -368,8 +374,8 @@ function placeImage(_image) {
ctx.rotate(Math.PI);
ctx.drawImage(clone, 0, 0);
} else if (settings.rotation === 270) {
canvas.width = settings.screenHeight;
canvas.height = settings.screenWidth;
canvas.width = clone.height;
canvas.height = clone.width;
ctx.setTransform(1, 0, 0, 1, 0, canvas.height);
ctx.rotate(Math.PI * 1.5);
ctx.drawImage(clone, 0, 0);
@@ -399,6 +405,7 @@ function updateAllImages() {
}
// Easy way to update settings controlled by a textfield
// eslint-disable-next-line no-unused-vars
function updateInteger(fieldName) {
settings[fieldName] = parseInt(document.getElementById(fieldName).value);
updateAllImages();
@@ -730,11 +737,10 @@ function handleImageSelection(evt) {
w.min = 1;
w.className = 'size-input';
w.value = img.width;
settings.screenWidth = img.width;
w.oninput = () => {
canvas.width = w.value;
updateAllImages();
updateInteger('screenWidth');
const image = images.get(img);
image.width = parseInt(w.value, 10);
placeImage(image);
};
const h = document.createElement('input');
@@ -744,11 +750,10 @@ function handleImageSelection(evt) {
h.min = 1;
h.className = 'size-input';
h.value = img.height;
settings.screenHeight = img.height;
h.oninput = () => {
canvas.height = h.value;
updateAllImages();
updateInteger('screenHeight');
const image = images.get(img);
image.height = parseInt(h.value, 10);
placeImage(image);
};
const gil = document.createElement('span');
@@ -759,7 +764,8 @@ function handleImageSelection(evt) {
gi.type = 'text';
gi.name = 'glyph';
gi.className = 'glyph-input';
gi.value = file.name.split('.')[0];
const [fileName] = file.name.split('.');
gi.value = fileName;
gi.onchange = () => {
const image = images.get(img);
image.glyph = gi.value;
@@ -820,7 +826,7 @@ function handleImageSelection(evt) {
canvas.height = img.height;
canvasContainer.appendChild(canvas);
images.push(img, canvas, file.name.split('.')[0]);
images.push(img, canvas, file.name.split('.')[0], img.width, img.height);
if (images.length() > 1) {
document.getElementById('all-same-size').style.display = 'block';
}
@@ -895,8 +901,8 @@ function generateOutputString() {
const storageNote = settings.esp32Format ? '' : ' in PROGMEM';
outputString += `// Array of all bitmaps for convenience. (Total bytes used to store images${storageNote} = ${bytesUsed})\n`;
}
outputString += `const int ${getIdentifier()}_allArray_LEN = ${varQuickArray.length};\n`;
outputString += `const ${getImageType()}* ${getIdentifier()}_allArray[${varQuickArray.length}] = {\n\t${varQuickArray.join(',\n\t')}\n};\n`;
outputString += `const int ${getIdentifier()}allArray_LEN = ${varQuickArray.length};\n`;
outputString += `const ${getImageType()}* ${getIdentifier()}allArray[${varQuickArray.length}] = {\n\t${varQuickArray.join(',\n\t')}\n};\n`;
break;
}
+32 -2
View File
@@ -272,6 +272,32 @@ def run_roundtrip(page, output, draw_mode, width, height):
return page.input_value("#code-output")
def run_multi_image_independent_sizes(page):
"""Each image in a multi-image upload keeps its own canvas size; setting
one image's width/height must not resize any other image's canvas.
Regression test for a bug where every canvas was forced to the size of
the first uploaded image."""
page.goto(INDEX_HTML.as_uri())
page.set_input_files("#file-input", [str(TEST_IMAGE), str(TEST_IMAGE)])
page.wait_for_function("document.querySelectorAll('#image-size-settings li').length === 2")
page.fill("#image-size-settings li:nth-child(1) input[name='width']", "50")
page.fill("#image-size-settings li:nth-child(1) input[name='height']", "60")
page.fill("#image-size-settings li:nth-child(2) input[name='width']", "20")
page.fill("#image-size-settings li:nth-child(2) input[name='height']", "10")
sizes = page.evaluate(
"[images.getByIndex(0).canvas.width, images.getByIndex(0).canvas.height,"
" images.getByIndex(1).canvas.width, images.getByIndex(1).canvas.height]"
)
expected = [50, 60, 20, 10]
if sizes != expected:
print("FAIL multi_image_independent_sizes")
return [f"multi_image_independent_sizes: expected canvas sizes {expected}, got {sizes}"]
print("ok multi_image_independent_sizes")
return []
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
@@ -364,19 +390,23 @@ def main():
page.set_input_files("#file-input", str(TEST_IMAGE))
page.wait_for_selector("#image-size-settings li")
if not args.update:
failures.extend(run_multi_image_independent_sizes(page))
browser.close()
if args.update:
print(f"\nWrote {len(SCENARIOS)} golden files to {GOLDEN_DIR}")
return
total = len(SCENARIOS) + 1
if failures:
print(f"\n{len(failures)} of {len(SCENARIOS)} scenarios failed:")
print(f"\n{len(failures)} of {total} scenarios failed:")
for f in failures:
print(f" - {f}")
sys.exit(1)
print(f"\nAll {len(SCENARIOS)} scenarios match golden output.")
print(f"\nAll {total} scenarios match golden output.")
if __name__ == "__main__":