Pellicule : marge de coupe plus large + warmup LiveView apres capture

La coupe physique du K60 n'est jamais parfaitement centree, donc une marge
noire trop fine fait perdre la pellicule d'un cote du strip dedouble. Marge
de coupe (perforations) elargie de 34 a 55px (~4.6mm) de chaque cote.

Ajoute aussi un warmup LiveView (_chauffer_liveview) juste apres la remontee
du miroir post-capture : consomme les ~1-2s de stabilisation pendant le
spinner de traitement plutot que de laisser le preview du countdown suivant
figé sur l'ancienne photo.
This commit is contained in:
2026-06-21 23:47:06 +02:00
parent 640715282c
commit f49d5511ef
4 changed files with 29 additions and 7 deletions

View File

@@ -172,6 +172,7 @@ class Camera:
tmp_path = str(chemin_dest) + ".tmp"
fichier_camera.save(tmp_path)
self.activer_viewfinder() # Miroir relevé immédiatement après la prise
self._chauffer_liveview() # Absorbe la stabilisation LiveView ici (spinner visible), pas sur le countdown suivant
from PIL import ImageOps as PILImageOps
img = PILImageOps.exif_transpose(PILImage.open(tmp_path))
if img.width > 4000:
@@ -189,6 +190,19 @@ class Camera:
log.error(f"Erreur capture DSLR : {e}")
return None
def _chauffer_liveview(self, tentatives: int = 8, pause: float = 0.15):
"""Consomme les premieres frames LiveView juste apres la remontee du miroir
(souvent en erreur ~1-2s le temps que l'AF/capteur se stabilise), pendant
que le spinner de traitement est affiche — pour que le preview du prochain
countdown soit deja a jour au lieu de rester figé sur l'ancienne photo."""
for _ in range(tentatives):
try:
with self._gp_lock:
self.camera.capture_preview()
return
except Exception:
time.sleep(pause)
def _capture_webcam(self, chemin_dest: Path) -> Path | None:
if not self.webcam or not self.webcam.isOpened():
return None

View File

@@ -47,8 +47,13 @@ def creer_strip(photos: list[Path], marge: int = 10, couleur_fond: str = "#00000
bande_largeur = 600
bande_hauteur = 1800
# Zone perforations pellicule (gauche et droite)
perf_largeur = 34
# Zone perforations pellicule (gauche et droite). Cette zone noire est aussi
# la marge de securite pour la coupe physique du K60 : la feuille pleine
# (2 bandes cote a cote) est coupee au centre apres impression, et la coupe
# n'est jamais parfaitement precise. Une marge trop fine fait que la coupe
# tombe dans la photo d'un cote (pellicule absente d'un cote, visible de
# l'autre). Elargie a 55px (~4.6mm) pour absorber le jeu mecanique du cutter.
perf_largeur = 55
zone_photos_largeur = bande_largeur - perf_largeur * 2
# Taille de chaque photo dans la bande (separees par bandes noires)
@@ -70,16 +75,19 @@ def creer_strip(photos: list[Path], marge: int = 10, couleur_fond: str = "#00000
draw = ImageDraw.Draw(strip)
# Bords pellicule noirs (deja le fond)
# Perforations pellicule (gauche) - trous blancs dans le bord noir
# Perforations pellicule (gauche) - trous gris dans le bord noir, centrees
# dans la marge (laisse du noir plein des 2 cotes pour la marge de coupe)
trou_largeur = 26
trou_x = (perf_largeur - trou_largeur) // 2
for py in range(marge + 10, bande_hauteur - marge, 44):
draw.rounded_rectangle(
[8, py, perf_largeur - 8, py + 22],
[trou_x, py, trou_x + trou_largeur, py + 22],
radius=5, fill=(60, 60, 60)
)
# Perforations pellicule (droite)
for py in range(marge + 10, bande_hauteur - marge, 44):
draw.rounded_rectangle(
[bande_largeur - perf_largeur + 8, py, bande_largeur - 8, py + 22],
[bande_largeur - perf_largeur + trou_x, py, bande_largeur - perf_largeur + trou_x + trou_largeur, py + 22],
radius=5, fill=(60, 60, 60)
)