fix: resize ICO et comportement sans sélection

- Convertit le mode palette (ICO, GIF) en RGBA avant LANCZOS pour
  éviter l'erreur de resampling sur les sources ICO
- Sans dimension sélectionnée : conserve les dimensions d'origine
- Sans format sélectionné : conserve le format d'origine
- Bouton toujours actif, texte dynamique "Générer la copie / N copies"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Alpinux 2026-05-06 10:11:17 +02:00
parent 3e8b18b127
commit dd83e6f36e
2 changed files with 43 additions and 11 deletions

View file

@ -686,9 +686,11 @@ def check_resize():
try:
sizes = [int(s) for s in raw_sizes if int(s) in RESIZE_SIZES]
except (ValueError, TypeError):
return jsonify({"conflicts": []})
sizes = []
formats = [f for f in raw_formats if f in RESIZE_FORMATS]
src_ext = target.suffix.lstrip(".")
stem = re.sub(r"_\d+x\d+$", "", target.stem)
parent = target.parent
@ -701,6 +703,19 @@ def check_resize():
except (ValueError, TypeError):
pass
# Pas de dimensions sélectionnées → conserver celles d'origine
if not all_dims:
try:
src = Image.open(target)
all_dims = [(src.width, src.height)]
src.close()
except Exception:
return jsonify({"conflicts": []})
# Pas de format sélectionné → conserver le format d'origine
if not formats:
formats = [src_ext]
conflicts = []
for fmt in formats:
for w, h in all_dims:
@ -764,8 +779,14 @@ def resize_image():
pass
all_dims = square_dims + custom_dims
if not all_dims or not formats:
return jsonify({"error": "Aucune dimension ou format valide"}), 400
# Pas de dimensions sélectionnées → conserver celles d'origine
if not all_dims:
all_dims = [(max_w, max_h)]
# Pas de format sélectionné → conserver le format d'origine
if not formats:
formats = [ext.lstrip(".")]
conflict = request.form.get("conflict", "skip")
if conflict not in ("backup", "overwrite", "rename", "skip"):
@ -842,6 +863,9 @@ def resize_image():
else:
img = Image.open(target)
# LANCZOS ne supporte pas le mode palette (ICO, GIF…)
if img.mode not in ("RGB", "RGBA", "L", "LA", "I", "F"):
img = img.convert("RGBA")
img = img.resize((w, h), Image.LANCZOS)
if fmt == "png":
if img.mode not in ("RGBA", "RGB", "L"):

View file

@ -143,7 +143,7 @@
{% endif %}
<div class="resize-actions">
<button id="resize-btn" class="btn btn-primary" disabled>Générer les copies</button>
<button id="resize-btn" class="btn btn-primary">Générer la copie</button>
<span class="resize-hint">Les fichiers sont créés dans le même dossier</span>
</div>
@ -261,19 +261,27 @@
return `${w}x${h}`;
}
function canSubmit() {
const hasSizes = Array.from(szCbs).some(c => c.checked) || getCustomDim() !== null;
const hasFmts = Array.from(fmtCbs).some(c => c.checked);
return hasSizes && hasFmts;
function countCopies() {
const nSizes = Array.from(szCbs).filter(c => c.checked).length
+ (getCustomDim() ? 1 : 0)
|| 1; // 0 sélectionné → dimensions d'origine conservées
const nFmts = Array.from(fmtCbs).filter(c => c.checked).length || 1;
return nSizes * nFmts;
}
function btnLabel() {
const n = countCopies();
return n === 1 ? 'Générer la copie' : `Générer les ${n} copies`;
}
function updateBtn() {
btn.disabled = !canSubmit();
btn.textContent = btnLabel();
conflictPanel.style.display = 'none';
resizeResolved = false;
}
[...szCbs, ...fmtCbs].forEach(c => c.addEventListener('change', updateBtn));
updateBtn();
function appendDims(fd) {
szCbs.forEach(c => { if (c.checked) fd.append('sizes', c.value); });
@ -318,8 +326,8 @@
result.innerHTML = '<p class="resize-err-title">Erreur réseau.</p>';
}
result.style.display = 'block';
btn.textContent = 'Générer les copies';
btn.disabled = !canSubmit();
btn.textContent = btnLabel();
btn.disabled = false;
resizeResolved = false;
}