Multi-pose : même photo dupliquée + crop to fill
- La photo en cours est dupliquée dans toutes les zones du template - Crop to fill : l'image remplit chaque zone au maximum (pas de bords) - Fonctionne avec l'image éditée (filtres, etc.) pas juste l'originale Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -313,79 +313,73 @@ class EditorScreen(QWidget):
|
|||||||
if not zones:
|
if not zones:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Utilise la photo en cours (ou l'image éditée du canvas)
|
||||||
|
source_pixmap = None
|
||||||
|
if self.pixmap_item:
|
||||||
|
source_pixmap = self.pixmap_item.pixmap()
|
||||||
|
elif self.current_image_path:
|
||||||
|
source_pixmap = QPixmap(self.current_image_path)
|
||||||
|
|
||||||
|
if not source_pixmap or source_pixmap.isNull():
|
||||||
|
return
|
||||||
|
|
||||||
self.multipose_zones = zones
|
self.multipose_zones = zones
|
||||||
self.multipose_images = {}
|
self.multipose_source = source_pixmap
|
||||||
|
|
||||||
# Demander les photos pour chaque zone
|
# Taille canvas = format d'impression (ex: 1800x1200 pour 15x10)
|
||||||
sr = self.scene.sceneRect()
|
canvas_w = 1800
|
||||||
canvas_w, canvas_h = int(sr.width()) or 1800, int(sr.height()) or 1200
|
canvas_h = 1200
|
||||||
|
|
||||||
|
self._render_multipose(source_pixmap, zones, canvas_w, canvas_h)
|
||||||
|
|
||||||
|
def _crop_to_fill(self, pixmap, target_w, target_h):
|
||||||
|
"""Crop centré pour remplir exactement target_w x target_h."""
|
||||||
|
src_w = pixmap.width()
|
||||||
|
src_h = pixmap.height()
|
||||||
|
src_ratio = src_w / src_h
|
||||||
|
target_ratio = target_w / target_h
|
||||||
|
|
||||||
|
if src_ratio > target_ratio:
|
||||||
|
# Image trop large → crop horizontal
|
||||||
|
new_w = int(src_h * target_ratio)
|
||||||
|
x_offset = (src_w - new_w) // 2
|
||||||
|
cropped = pixmap.copy(x_offset, 0, new_w, src_h)
|
||||||
|
else:
|
||||||
|
# Image trop haute → crop vertical
|
||||||
|
new_h = int(src_w / target_ratio)
|
||||||
|
y_offset = (src_h - new_h) // 2
|
||||||
|
cropped = pixmap.copy(0, y_offset, src_w, new_h)
|
||||||
|
|
||||||
|
return cropped.scaled(target_w, target_h,
|
||||||
|
Qt.AspectRatioMode.IgnoreAspectRatio,
|
||||||
|
Qt.TransformationMode.SmoothTransformation)
|
||||||
|
|
||||||
|
def _render_multipose(self, source_pixmap, zones, canvas_w, canvas_h):
|
||||||
|
"""Dessine le multi-pose : même image dupliquée, crop to fill."""
|
||||||
self.scene.clear()
|
self.scene.clear()
|
||||||
self.pixmap_item = None
|
self.pixmap_item = None
|
||||||
|
|
||||||
# Canvas blanc
|
|
||||||
white = QImage(canvas_w, canvas_h, QImage.Format.Format_ARGB32)
|
|
||||||
white.fill(QColor(255, 255, 255))
|
|
||||||
bg = self.scene.addPixmap(QPixmap.fromImage(white))
|
|
||||||
self.scene.setSceneRect(QRectF(0, 0, canvas_w, canvas_h))
|
|
||||||
|
|
||||||
# Dessiner les zones avec numéros
|
|
||||||
for i, (zx, zy, zw, zh) in enumerate(zones):
|
|
||||||
rx = int(zx * canvas_w)
|
|
||||||
ry = int(zy * canvas_h)
|
|
||||||
rw = int(zw * canvas_w)
|
|
||||||
rh = int(zh * canvas_h)
|
|
||||||
|
|
||||||
# Bordure de zone
|
|
||||||
from PyQt6.QtWidgets import QGraphicsRectItem
|
|
||||||
from PyQt6.QtGui import QPen, QBrush
|
|
||||||
rect = self.scene.addRect(rx + 2, ry + 2, rw - 4, rh - 4,
|
|
||||||
QPen(QColor(100, 100, 100), 2),
|
|
||||||
QBrush(QColor(240, 240, 240)))
|
|
||||||
|
|
||||||
# Numéro
|
|
||||||
text = self.scene.addText(str(i + 1), QFont("", 40))
|
|
||||||
text.setDefaultTextColor(QColor(150, 150, 150))
|
|
||||||
text.setPos(rx + rw / 2 - 20, ry + rh / 2 - 30)
|
|
||||||
|
|
||||||
self.view.fitInView(self.scene.sceneRect(), Qt.AspectRatioMode.KeepAspectRatio)
|
|
||||||
|
|
||||||
# Charger les photos depuis la galerie d'import
|
|
||||||
import_photos = self.main_window.import_screen.photos
|
|
||||||
if import_photos:
|
|
||||||
self._fill_multipose_from_list(import_photos, zones, canvas_w, canvas_h)
|
|
||||||
|
|
||||||
def _fill_multipose_from_list(self, photos, zones, canvas_w, canvas_h):
|
|
||||||
"""Remplit les zones multi-pose avec les premières photos disponibles."""
|
|
||||||
self.scene.clear()
|
|
||||||
|
|
||||||
# Canvas blanc
|
# Canvas blanc
|
||||||
white = QImage(canvas_w, canvas_h, QImage.Format.Format_ARGB32)
|
white = QImage(canvas_w, canvas_h, QImage.Format.Format_ARGB32)
|
||||||
white.fill(QColor(255, 255, 255))
|
white.fill(QColor(255, 255, 255))
|
||||||
self.pixmap_item = self.scene.addPixmap(QPixmap.fromImage(white))
|
self.pixmap_item = self.scene.addPixmap(QPixmap.fromImage(white))
|
||||||
self.scene.setSceneRect(QRectF(0, 0, canvas_w, canvas_h))
|
self.scene.setSceneRect(QRectF(0, 0, canvas_w, canvas_h))
|
||||||
|
|
||||||
gap = 4 # espace entre les photos
|
gap = 6 # espace entre les zones
|
||||||
|
|
||||||
for i, (zx, zy, zw, zh) in enumerate(zones):
|
for i, (zx, zy, zw, zh) in enumerate(zones):
|
||||||
if i >= len(photos):
|
|
||||||
break
|
|
||||||
rx = int(zx * canvas_w) + gap
|
rx = int(zx * canvas_w) + gap
|
||||||
ry = int(zy * canvas_h) + gap
|
ry = int(zy * canvas_h) + gap
|
||||||
rw = int(zw * canvas_w) - gap * 2
|
rw = int(zw * canvas_w) - gap * 2
|
||||||
rh = int(zh * canvas_h) - gap * 2
|
rh = int(zh * canvas_h) - gap * 2
|
||||||
|
|
||||||
pixmap = QPixmap(photos[i])
|
if rw <= 0 or rh <= 0:
|
||||||
if pixmap.isNull():
|
|
||||||
continue
|
continue
|
||||||
scaled = pixmap.scaled(rw, rh,
|
|
||||||
Qt.AspectRatioMode.KeepAspectRatio,
|
# Crop to fill : l'image remplit toute la zone
|
||||||
Qt.TransformationMode.SmoothTransformation)
|
filled = self._crop_to_fill(source_pixmap, rw, rh)
|
||||||
item = self.scene.addPixmap(scaled)
|
item = self.scene.addPixmap(filled)
|
||||||
# Centrer dans la zone
|
item.setPos(rx, ry)
|
||||||
offset_x = rx + (rw - scaled.width()) / 2
|
|
||||||
offset_y = ry + (rh - scaled.height()) / 2
|
|
||||||
item.setPos(offset_x, offset_y)
|
|
||||||
|
|
||||||
self.view.fitInView(self.scene.sceneRect(), Qt.AspectRatioMode.KeepAspectRatio)
|
self.view.fitInView(self.scene.sceneRect(), Qt.AspectRatioMode.KeepAspectRatio)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user