- Intégration selphy_print (backend CUPS dyesub Mitsubishi CP-K60DW-S) - Formats impression : 15x20, 10x15, 10x15 2-strips avec cadre et orientation portrait/paysage - Cadres d'impression par format (strip/10x15/15x20) : upload, sélection, aperçu live - Cadres démo générés : pellicule noir/vintage/couleurs + bordures classique/doré/rose gold - Écran de choix de cadre avant capture (clic direct, aperçu grand format) - Filtres réduits à 3 (Couleur, N&B, Sépia) et appliqués sur tous les strips - Port 80 via authbind, route /admin avec redirection auto depuis poste distant - Autologin LightDM corrigé (pam-autologin-service) - Bouton évacuer bourrage papier dans admin - Fix : _gp_lock manquant dans Camera.__init__ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
215 lines
6.9 KiB
JavaScript
215 lines
6.9 KiB
JavaScript
/* Module effets - Filtres, overlays et fond vert */
|
|
|
|
let filtreActuel = 'original';
|
|
let overlayActuel = null;
|
|
let fondActuel = null;
|
|
|
|
async function chargerFiltres() {
|
|
const filtres = await apiGet('/api/filtres');
|
|
const barre = document.getElementById('barre-filtres');
|
|
barre.innerHTML = '';
|
|
|
|
for (const [id, nom] of Object.entries(filtres)) {
|
|
const btn = document.createElement('button');
|
|
btn.className = 'btn-filtre' + (id === 'original' ? ' actif' : '');
|
|
btn.textContent = nom;
|
|
btn.addEventListener('click', () => appliquerFiltreUI(id, btn));
|
|
barre.appendChild(btn);
|
|
}
|
|
}
|
|
|
|
async function appliquerFiltreUI(filtre, btn) {
|
|
document.querySelectorAll('.btn-filtre').forEach(b => b.classList.remove('actif'));
|
|
btn.classList.add('actif');
|
|
filtreActuel = filtre;
|
|
|
|
if (modeActuel === 'multi') {
|
|
// En mode multi : ré-assembler le strip avec le filtre appliqué sur chaque photo
|
|
await appliquerFiltreStrip(filtre);
|
|
return;
|
|
}
|
|
|
|
if (filtre === 'original') {
|
|
const chemin = '/data/photos/' + photosSession[0];
|
|
document.getElementById('photo-resultat').src = chemin;
|
|
document.getElementById('photo-partage').src = chemin;
|
|
photoFinale = photosSession[0];
|
|
afficherCadreOverlay(cadreChoisi);
|
|
return;
|
|
}
|
|
|
|
const resultat = await apiPost('/api/filtre', {
|
|
photo: photosSession[0],
|
|
filtre: filtre,
|
|
});
|
|
|
|
if (resultat.nom) {
|
|
photoFinale = resultat.nom;
|
|
document.getElementById('photo-resultat').src = '/data/exports/' + resultat.nom;
|
|
document.getElementById('photo-partage').src = '/data/exports/' + resultat.nom;
|
|
afficherCadreOverlay(cadreChoisi);
|
|
}
|
|
}
|
|
|
|
async function appliquerFiltreStrip(filtre) {
|
|
let photosAAssembler = photosSession;
|
|
let source = 'photos'; // les originaux sont dans data/photos/
|
|
|
|
if (filtre !== 'original') {
|
|
const promises = photosSession.map(p => apiPost('/api/filtre', { photo: p, filtre }));
|
|
const resultats = await Promise.all(promises);
|
|
photosAAssembler = resultats.filter(r => r.nom).map(r => r.nom);
|
|
source = 'exports'; // les filtrés sont dans data/exports/
|
|
if (photosAAssembler.length === 0) return;
|
|
}
|
|
|
|
const mode = config.multi_shot?.mode || 'strip';
|
|
const endpoint = mode === 'strip' ? '/api/strip' : '/api/collage';
|
|
const resultat = await apiPost(endpoint, { photos: photosAAssembler, source });
|
|
|
|
if (resultat.nom) {
|
|
photoFinale = resultat.nom;
|
|
if (resultat.impression) photoImpression = resultat.impression;
|
|
const src = '/data/exports/' + resultat.nom;
|
|
document.getElementById('photo-resultat').src = src;
|
|
document.getElementById('photo-partage').src = src;
|
|
afficherCadreOverlay(cadreChoisi);
|
|
}
|
|
}
|
|
|
|
function afficherCadreOverlay(nom) {
|
|
const el = document.getElementById('cadre-overlay-preview');
|
|
if (!el) return;
|
|
if (!nom) {
|
|
el.classList.add('cache');
|
|
el.src = '';
|
|
return;
|
|
}
|
|
const config_imp = config.impression || {};
|
|
const fmt = (config_imp.format || '15x20').replace('-2up', '');
|
|
el.src = `/assets/cadres/${fmt}/${nom}`;
|
|
el.classList.remove('cache');
|
|
}
|
|
|
|
async function chargerOverlays() {
|
|
const overlays = await apiGet('/api/overlays');
|
|
const barre = document.getElementById('barre-overlays');
|
|
|
|
if (overlays.length === 0) {
|
|
barre.classList.add('cache');
|
|
return;
|
|
}
|
|
|
|
barre.classList.remove('cache');
|
|
barre.innerHTML = '';
|
|
|
|
const btnAucun = document.createElement('button');
|
|
btnAucun.className = 'btn-overlay actif';
|
|
btnAucun.textContent = 'Sans cadre';
|
|
btnAucun.addEventListener('click', () => retirerOverlay(btnAucun));
|
|
barre.appendChild(btnAucun);
|
|
|
|
for (const nom of overlays) {
|
|
const btn = document.createElement('button');
|
|
btn.className = 'btn-overlay';
|
|
btn.textContent = nom.replace('.png', '');
|
|
btn.addEventListener('click', () => appliquerOverlayUI(nom, btn));
|
|
barre.appendChild(btn);
|
|
}
|
|
}
|
|
|
|
async function appliquerOverlayUI(nom, btn) {
|
|
document.querySelectorAll('.btn-overlay').forEach(b => b.classList.remove('actif'));
|
|
btn.classList.add('actif');
|
|
overlayActuel = nom;
|
|
|
|
const photo = photosSession[0];
|
|
const resultat = await apiPost('/api/overlay', { photo, overlay: nom });
|
|
|
|
if (resultat.nom) {
|
|
photoFinale = resultat.nom;
|
|
document.getElementById('photo-resultat').src = '/data/exports/' + resultat.nom;
|
|
document.getElementById('photo-partage').src = '/data/exports/' + resultat.nom;
|
|
}
|
|
}
|
|
|
|
function retirerOverlay(btn) {
|
|
document.querySelectorAll('.btn-overlay').forEach(b => b.classList.remove('actif'));
|
|
btn.classList.add('actif');
|
|
overlayActuel = null;
|
|
|
|
if (filtreActuel !== 'original') {
|
|
appliquerFiltreUI(filtreActuel, document.querySelector('.btn-filtre.actif'));
|
|
} else {
|
|
const chemin = '/data/photos/' + photosSession[0];
|
|
document.getElementById('photo-resultat').src = chemin;
|
|
document.getElementById('photo-partage').src = chemin;
|
|
photoFinale = photosSession[0];
|
|
}
|
|
}
|
|
|
|
// === Fond vert (chroma key) ===
|
|
|
|
async function chargerFonds() {
|
|
const fonds = await apiGet('/api/fonds');
|
|
const barre = document.getElementById('barre-fonds');
|
|
|
|
if (!config.fonctionnalites?.chroma_key || fonds.length === 0) {
|
|
barre.classList.add('cache');
|
|
return;
|
|
}
|
|
|
|
barre.classList.remove('cache');
|
|
barre.innerHTML = '';
|
|
fondActuel = null;
|
|
|
|
// Bouton "original" (pas de chroma key)
|
|
const btnOriginal = document.createElement('button');
|
|
btnOriginal.className = 'btn-fond actif';
|
|
btnOriginal.innerHTML = '<span style="font-size:0.7rem;color:var(--texte-secondaire)">Original</span>';
|
|
btnOriginal.addEventListener('click', () => retirerFond(btnOriginal));
|
|
barre.appendChild(btnOriginal);
|
|
|
|
for (const nom of fonds) {
|
|
const btn = document.createElement('button');
|
|
btn.className = 'btn-fond';
|
|
const img = document.createElement('img');
|
|
img.src = `/assets/backgrounds/${nom}`;
|
|
img.alt = nom;
|
|
btn.appendChild(img);
|
|
btn.addEventListener('click', () => appliquerFondUI(nom, btn));
|
|
barre.appendChild(btn);
|
|
}
|
|
}
|
|
|
|
async function appliquerFondUI(nom, btn) {
|
|
document.querySelectorAll('.btn-fond').forEach(b => b.classList.remove('actif'));
|
|
btn.classList.add('actif');
|
|
fondActuel = nom;
|
|
|
|
const photo = photosSession[0];
|
|
const resultat = await apiPost('/api/chroma', { photo, fond: nom });
|
|
|
|
if (resultat.nom) {
|
|
photoFinale = resultat.nom;
|
|
document.getElementById('photo-resultat').src = '/data/exports/' + resultat.nom;
|
|
document.getElementById('photo-partage').src = '/data/exports/' + resultat.nom;
|
|
}
|
|
}
|
|
|
|
function retirerFond(btn) {
|
|
document.querySelectorAll('.btn-fond').forEach(b => b.classList.remove('actif'));
|
|
btn.classList.add('actif');
|
|
fondActuel = null;
|
|
|
|
// Revenir a la photo originale ou avec filtre
|
|
if (filtreActuel !== 'original') {
|
|
appliquerFiltreUI(filtreActuel, document.querySelector('.btn-filtre.actif'));
|
|
} else {
|
|
const chemin = '/data/photos/' + photosSession[0];
|
|
document.getElementById('photo-resultat').src = chemin;
|
|
document.getElementById('photo-partage').src = chemin;
|
|
photoFinale = photosSession[0];
|
|
}
|
|
}
|