86d9b351b1
- Import ZIP produits (HEIC/JPG/PNG, structure dossiers conservée) - Rotation des images ±90° avec aperçu CSS et export canvas - Slider récupération des bords (feather 0–5 px) - Lightbox plein écran (clic miniature, Échap, fond noir) - Fix timeout HEIC 30s → 120s - Fix MIME type blobs JSZip pour heic2any - Dockerfile nginx:alpine + docker-compose.yml pour déploiement Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
47 lines
1.4 KiB
JavaScript
47 lines
1.4 KiB
JavaScript
/**
|
|
* Rotation d'un Blob image via Canvas.
|
|
* @param {Blob} blob — image source (JPEG)
|
|
* @param {number} degrees — angle de rotation en degrés (0, 90, 180, 270)
|
|
* @returns {Promise<Blob>} Blob JPEG pivoté, ou le blob original si degrees === 0
|
|
*/
|
|
export async function rotateBlob(blob, degrees) {
|
|
const norm = ((degrees % 360) + 360) % 360;
|
|
if (norm === 0) return blob;
|
|
|
|
const url = URL.createObjectURL(blob);
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const img = new Image();
|
|
|
|
img.onload = () => {
|
|
// Pour 90° ou 270°, largeur et hauteur sont inversées
|
|
const swap = norm === 90 || norm === 270;
|
|
const w = swap ? img.naturalHeight : img.naturalWidth;
|
|
const h = swap ? img.naturalWidth : img.naturalHeight;
|
|
|
|
const canvas = document.createElement('canvas');
|
|
canvas.width = w;
|
|
canvas.height = h;
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
ctx.translate(w / 2, h / 2);
|
|
ctx.rotate((norm * Math.PI) / 180);
|
|
ctx.drawImage(img, -img.naturalWidth / 2, -img.naturalHeight / 2);
|
|
|
|
URL.revokeObjectURL(url);
|
|
canvas.toBlob(
|
|
b => b ? resolve(b) : reject(new Error('rotateBlob : toBlob a retourné null')),
|
|
'image/jpeg',
|
|
0.92
|
|
);
|
|
};
|
|
|
|
img.onerror = () => {
|
|
URL.revokeObjectURL(url);
|
|
reject(new Error('rotateBlob : impossible de charger le blob'));
|
|
};
|
|
|
|
img.src = url;
|
|
});
|
|
}
|