Fix impression pellicule : strip genere en paysage au lieu du portrait attendu
creer_strip() produisait une bande paysage (1800x595) alors que printer.py
('10x15-2up' -> PageSize ...-div2) et tous les cadres existants (assets/cadres/strip/*.png)
attendent une bande portrait fixe 600x1800 (5x15cm), dupliquee et coupee
automatiquement par l'imprimante. Le mismatch faisait pivoter/etirer
l'image a l'impression (StpiShrinkOutput=Crop sur un ratio incompatible),
d'ou le rendu deforme coupe en 2 mauvais morceaux au lieu de 2 pellicules
identiques.
- creer_strip() : bande 600x1800 portrait, photos empilees verticalement,
perforations sur les cotes (au lieu de haut/bas)
- Cadre de visee live (camera.js) : formule de ratio mise a jour en
consequence pour rester fidele au resultat final
This commit is contained in:
@@ -31,27 +31,31 @@ def _crop_center(img: Image.Image, ratio_cible: float) -> Image.Image:
|
|||||||
|
|
||||||
def creer_strip(photos: list[Path], marge: int = 10, couleur_fond: str = "#000000",
|
def creer_strip(photos: list[Path], marge: int = 10, couleur_fond: str = "#000000",
|
||||||
cadre: str | None = None) -> Path:
|
cadre: str | None = None) -> Path:
|
||||||
"""Cree une bande portrait style pellicule (4 photos de gauche a droite).
|
"""Cree une bande portrait style pellicule (photos empilees de haut en bas).
|
||||||
|
|
||||||
Pellicule noire avec perforations, photos separees par des bandes noires.
|
Pellicule noire avec perforations sur les cotes, photos separees par des
|
||||||
Plus large : utilise toute la hauteur d'un 10x15 paysage divise en 2.
|
bandes noires. Taille fixe 600x1800px (5x15cm a 300dpi) : c'est le format
|
||||||
|
attendu par l'imprimante en mode "10x15-2up" (PageSize ...-div2), qui
|
||||||
|
duplique et decoupe automatiquement la bande en 2 exemplaires sur une
|
||||||
|
feuille 10x15. Doit rester strictement portrait (largeur < hauteur) et a
|
||||||
|
cette taille exacte pour eviter toute rotation/etirement a l'impression.
|
||||||
"""
|
"""
|
||||||
nb = len(photos)
|
nb = len(photos)
|
||||||
images = [Image.open(p) for p in photos]
|
images = [Image.open(p) for p in photos]
|
||||||
|
|
||||||
# Dimensions de la bande : largeur d'un 10x15 paysage, hauteur = moitie
|
# Dimensions de la bande : format fixe attendu par printer.py (FORMATS["10x15-2up"])
|
||||||
bande_largeur = LARGEUR_10x15_L
|
bande_largeur = 600
|
||||||
bande_hauteur = (HAUTEUR_10x15_L - marge) // 2
|
bande_hauteur = 1800
|
||||||
|
|
||||||
# Zone perforations pellicule (haut et bas)
|
# Zone perforations pellicule (gauche et droite)
|
||||||
perf_hauteur = 34
|
perf_largeur = 34
|
||||||
zone_photos_hauteur = bande_hauteur - perf_hauteur * 2
|
zone_photos_largeur = bande_largeur - perf_largeur * 2
|
||||||
|
|
||||||
# Taille de chaque photo dans la bande (separees par bandes noires)
|
# Taille de chaque photo dans la bande (separees par bandes noires)
|
||||||
sep = 12 # separateur noir entre photos
|
sep = 12 # separateur noir entre photos
|
||||||
espace_photos = bande_largeur - marge * 2 - sep * (nb - 1)
|
espace_photos = bande_hauteur - marge * 2 - sep * (nb - 1)
|
||||||
largeur_cellule = espace_photos // nb
|
hauteur_cellule = espace_photos // nb
|
||||||
hauteur_cellule = zone_photos_hauteur
|
largeur_cellule = zone_photos_largeur
|
||||||
ratio_cellule = largeur_cellule / hauteur_cellule
|
ratio_cellule = largeur_cellule / hauteur_cellule
|
||||||
|
|
||||||
# Recadrer et redimensionner
|
# Recadrer et redimensionner
|
||||||
@@ -66,24 +70,24 @@ def creer_strip(photos: list[Path], marge: int = 10, couleur_fond: str = "#00000
|
|||||||
draw = ImageDraw.Draw(strip)
|
draw = ImageDraw.Draw(strip)
|
||||||
|
|
||||||
# Bords pellicule noirs (deja le fond)
|
# Bords pellicule noirs (deja le fond)
|
||||||
# Perforations pellicule (haut) - trous blancs dans le bord noir
|
# Perforations pellicule (gauche) - trous blancs dans le bord noir
|
||||||
for px in range(marge + 10, bande_largeur - marge, 44):
|
for py in range(marge + 10, bande_hauteur - marge, 44):
|
||||||
draw.rounded_rectangle(
|
draw.rounded_rectangle(
|
||||||
[px, 8, px + 22, perf_hauteur - 8],
|
[8, py, perf_largeur - 8, py + 22],
|
||||||
radius=5, fill=(60, 60, 60)
|
radius=5, fill=(60, 60, 60)
|
||||||
)
|
)
|
||||||
# Perforations pellicule (bas)
|
# Perforations pellicule (droite)
|
||||||
for px in range(marge + 10, bande_largeur - marge, 44):
|
for py in range(marge + 10, bande_hauteur - marge, 44):
|
||||||
draw.rounded_rectangle(
|
draw.rounded_rectangle(
|
||||||
[px, bande_hauteur - perf_hauteur + 8, px + 22, bande_hauteur - 8],
|
[bande_largeur - perf_largeur + 8, py, bande_largeur - 8, py + 22],
|
||||||
radius=5, fill=(60, 60, 60)
|
radius=5, fill=(60, 60, 60)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Coller les photos (separees par des bandes noires verticales)
|
# Coller les photos (separees par des bandes noires horizontales)
|
||||||
x = marge
|
y = marge
|
||||||
for img in images_redim:
|
for img in images_redim:
|
||||||
strip.paste(img, (x, perf_hauteur))
|
strip.paste(img, (perf_largeur, y))
|
||||||
x += largeur_cellule + sep
|
y += hauteur_cellule + sep
|
||||||
|
|
||||||
if cadre:
|
if cadre:
|
||||||
strip = appliquer_cadre_impression(strip, "strip", cadre)
|
strip = appliquer_cadre_impression(strip, "strip", cadre)
|
||||||
|
|||||||
@@ -739,7 +739,7 @@
|
|||||||
|
|
||||||
<script src="/js/websocket.js?v=3"></script>
|
<script src="/js/websocket.js?v=3"></script>
|
||||||
<script src="/js/app.js?v=4"></script>
|
<script src="/js/app.js?v=4"></script>
|
||||||
<script src="/js/camera.js?v=7"></script>
|
<script src="/js/camera.js?v=8"></script>
|
||||||
<script src="/js/effects.js?v=3"></script>
|
<script src="/js/effects.js?v=3"></script>
|
||||||
<script src="/js/gallery.js?v=3"></script>
|
<script src="/js/gallery.js?v=3"></script>
|
||||||
<script src="/js/share.js?v=5"></script>
|
<script src="/js/share.js?v=5"></script>
|
||||||
|
|||||||
@@ -87,13 +87,12 @@ function getRatioCelluleAttendu() {
|
|||||||
const nb = getNombrePhotos();
|
const nb = getNombrePhotos();
|
||||||
const mode = config.multi_shot?.mode || 'strip';
|
const mode = config.multi_shot?.mode || 'strip';
|
||||||
if (mode === 'strip') {
|
if (mode === 'strip') {
|
||||||
// Reproduit creer_strip() dans backend/collage.py
|
// Reproduit creer_strip() dans backend/collage.py (bande portrait 600x1800, photos empilees)
|
||||||
const bandeLargeur = 1800, bandeHauteurTotale = 1200, marge = 10, sep = 12, perfHauteur = 34;
|
const bandeLargeur = 600, bandeHauteur = 1800, marge = 10, sep = 12, perfLargeur = 34;
|
||||||
const bandeHauteur = Math.floor((bandeHauteurTotale - marge) / 2);
|
const zonePhotosLargeur = bandeLargeur - perfLargeur * 2;
|
||||||
const zonePhotosHauteur = bandeHauteur - perfHauteur * 2;
|
const espacePhotos = bandeHauteur - marge * 2 - sep * (nb - 1);
|
||||||
const espacePhotos = bandeLargeur - marge * 2 - sep * (nb - 1);
|
const hauteurCellule = Math.floor(espacePhotos / nb);
|
||||||
const largeurCellule = Math.floor(espacePhotos / nb);
|
return zonePhotosLargeur / hauteurCellule;
|
||||||
return largeurCellule / zonePhotosHauteur;
|
|
||||||
} else {
|
} else {
|
||||||
// Reproduit creer_collage() dans backend/collage.py
|
// Reproduit creer_collage() dans backend/collage.py
|
||||||
const colonnes = 2;
|
const colonnes = 2;
|
||||||
|
|||||||
Reference in New Issue
Block a user