From a3e032d000a87210776b7cf274515f120c515579 Mon Sep 17 00:00:00 2001 From: "Adriano (daitarn)" Date: Sun, 25 Oct 2026 18:07:52 +0100 Subject: [PATCH] Disegno Tecnico: BMP convertiti in PNG nel browser, errore upload nel riquadro. Refs #107 Co-Authored-By: Claude Sonnet 5.5 --- .../flask_app/static/js/image_to_png.js | 38 +++++++++++++++++++ .../templates/maker/recipe_editor.html | 8 ++++ .../templates/maker/task_editor.html | 18 +++++++++ .../flask_app/tests/js/test_image_to_png.js | 32 ++++++++++++++++ .../flask_app/tests/test_image_to_png_js.py | 31 +++++++++++++++ .../translations/en/LC_MESSAGES/messages.po | 4 ++ .../translations/it/LC_MESSAGES/messages.po | 4 ++ 7 files changed, 135 insertions(+) create mode 100644 src/frontend/flask_app/static/js/image_to_png.js create mode 100644 src/frontend/flask_app/tests/js/test_image_to_png.js create mode 100644 src/frontend/flask_app/tests/test_image_to_png_js.py diff --git a/src/frontend/flask_app/static/js/image_to_png.js b/src/frontend/flask_app/static/js/image_to_png.js new file mode 100644 index 0000000..b86c576 --- /dev/null +++ b/src/frontend/flask_app/static/js/image_to_png.js @@ -0,0 +1,38 @@ +/** + * image_to_png.js - #107: converte nel browser le immagini che il backend non ammette (es. BMP) in PNG. + * + * Cosa fa: tmfNeedsPng(type) dice se il MIME e' un'immagine fuori da PNG/JPEG/GIF/WebP; + * tmfImageToPng(file) la ridisegna su canvas e ritorna un File PNG (null se illeggibile, es. TIFF). + * Come si usa: await tmfImageToPng(file) prima del ritaglio e del caricamento. + * Dipende da: createImageBitmap e canvas del browser (non servono nei test: il caso "nessuna conversione" e' puro). + */ +// #107: tipi che il backend ammette gia': non vanno convertiti +const TMF_PNG_PASSTHROUGH = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/webp']; + +// #107: true per un'immagine (image/*) non ammessa dal backend, es. image/bmp +function tmfNeedsPng(type) { + return typeof type === 'string' && type.indexOf('image/') === 0 && TMF_PNG_PASSTHROUGH.indexOf(type) === -1; +} + +// #107: converte in PNG con canvas; ritorna il file invariato se non serve, null se il browser non sa decodificarlo +async function tmfImageToPng(file) { + if (!file || !tmfNeedsPng(file.type)) return file; + try { + const bitmap = await createImageBitmap(file); + const canvas = document.createElement('canvas'); + canvas.width = bitmap.width; + canvas.height = bitmap.height; + canvas.getContext('2d').drawImage(bitmap, 0, 0); + if (bitmap.close) bitmap.close(); + const blob = await new Promise(function (resolve) { canvas.toBlob(resolve, 'image/png'); }); + if (!blob) return null; + const base = (file.name || 'immagine').replace(/\.[^.]+$/, ''); + return new File([blob], base + '.png', { type: 'image/png' }); + } catch (err) { + // #107: formato non decodificabile dal browser (es. TIFF) + return null; + } +} + +// #107: export per il test node (nel browser module non esiste) +if (typeof module !== 'undefined') module.exports = { tmfNeedsPng, tmfImageToPng }; diff --git a/src/frontend/flask_app/templates/maker/recipe_editor.html b/src/frontend/flask_app/templates/maker/recipe_editor.html index 2d97091..5ea9128 100644 --- a/src/frontend/flask_app/templates/maker/recipe_editor.html +++ b/src/frontend/flask_app/templates/maker/recipe_editor.html @@ -504,6 +504,7 @@ {% block extra_js %} +{# #107 #} +{# #107 #}