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:
parent
3e8b18b127
commit
dd83e6f36e
2 changed files with 43 additions and 11 deletions
30
app/app.py
30
app/app.py
|
|
@ -686,9 +686,11 @@ def check_resize():
|
||||||
try:
|
try:
|
||||||
sizes = [int(s) for s in raw_sizes if int(s) in RESIZE_SIZES]
|
sizes = [int(s) for s in raw_sizes if int(s) in RESIZE_SIZES]
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
return jsonify({"conflicts": []})
|
sizes = []
|
||||||
|
|
||||||
formats = [f for f in raw_formats if f in RESIZE_FORMATS]
|
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)
|
stem = re.sub(r"_\d+x\d+$", "", target.stem)
|
||||||
parent = target.parent
|
parent = target.parent
|
||||||
|
|
||||||
|
|
@ -701,6 +703,19 @@ def check_resize():
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
pass
|
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 = []
|
conflicts = []
|
||||||
for fmt in formats:
|
for fmt in formats:
|
||||||
for w, h in all_dims:
|
for w, h in all_dims:
|
||||||
|
|
@ -764,8 +779,14 @@ def resize_image():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
all_dims = square_dims + custom_dims
|
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")
|
conflict = request.form.get("conflict", "skip")
|
||||||
if conflict not in ("backup", "overwrite", "rename", "skip"):
|
if conflict not in ("backup", "overwrite", "rename", "skip"):
|
||||||
|
|
@ -842,6 +863,9 @@ def resize_image():
|
||||||
|
|
||||||
else:
|
else:
|
||||||
img = Image.open(target)
|
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)
|
img = img.resize((w, h), Image.LANCZOS)
|
||||||
if fmt == "png":
|
if fmt == "png":
|
||||||
if img.mode not in ("RGBA", "RGB", "L"):
|
if img.mode not in ("RGBA", "RGB", "L"):
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="resize-actions">
|
<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>
|
<span class="resize-hint">Les fichiers sont créés dans le même dossier</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -261,19 +261,27 @@
|
||||||
return `${w}x${h}`;
|
return `${w}x${h}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function canSubmit() {
|
function countCopies() {
|
||||||
const hasSizes = Array.from(szCbs).some(c => c.checked) || getCustomDim() !== null;
|
const nSizes = Array.from(szCbs).filter(c => c.checked).length
|
||||||
const hasFmts = Array.from(fmtCbs).some(c => c.checked);
|
+ (getCustomDim() ? 1 : 0)
|
||||||
return hasSizes && hasFmts;
|
|| 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() {
|
function updateBtn() {
|
||||||
btn.disabled = !canSubmit();
|
btn.textContent = btnLabel();
|
||||||
conflictPanel.style.display = 'none';
|
conflictPanel.style.display = 'none';
|
||||||
resizeResolved = false;
|
resizeResolved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[...szCbs, ...fmtCbs].forEach(c => c.addEventListener('change', updateBtn));
|
[...szCbs, ...fmtCbs].forEach(c => c.addEventListener('change', updateBtn));
|
||||||
|
updateBtn();
|
||||||
|
|
||||||
function appendDims(fd) {
|
function appendDims(fd) {
|
||||||
szCbs.forEach(c => { if (c.checked) fd.append('sizes', c.value); });
|
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.innerHTML = '<p class="resize-err-title">Erreur réseau.</p>';
|
||||||
}
|
}
|
||||||
result.style.display = 'block';
|
result.style.display = 'block';
|
||||||
btn.textContent = 'Générer les copies';
|
btn.textContent = btnLabel();
|
||||||
btn.disabled = !canSubmit();
|
btn.disabled = false;
|
||||||
resizeResolved = false;
|
resizeResolved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue