fix(crop): stabiliser le rectangle géométrique de découpe et l'enchaînement des zooms
This commit is contained in:
@@ -42,28 +42,40 @@ class ImageCropService {
|
||||
/// Taille de sortie maximale pour les images recadrées
|
||||
static const int maxOutputSize = 1024;
|
||||
|
||||
/// Recadre une image en format carré
|
||||
/// Recadre une image en format carré en prenant en compte l'angle de rotation.
|
||||
///
|
||||
/// [sourcePath] - Chemin vers l'image source
|
||||
/// [cropRect] - Zone de recadrage normalisée (0.0 à 1.0)
|
||||
/// [rotationDegrees] - L'angle appliqué à la jauge haute précision du CropScreen
|
||||
/// [outputSize] - Taille de sortie en pixels (carré)
|
||||
///
|
||||
/// Retourne le chemin vers l'image recadrée dans le dossier temporaire
|
||||
Future<String> cropToSquare(
|
||||
String sourcePath,
|
||||
CropRect cropRect, {
|
||||
int outputSize = maxOutputSize,
|
||||
}) async {
|
||||
String sourcePath,
|
||||
CropRect cropRect, {
|
||||
double rotationDegrees = 0.0, // FIX : On intercepte la rotation ici !
|
||||
int outputSize = maxOutputSize,
|
||||
}) async {
|
||||
// Charger l'image source
|
||||
final file = File(sourcePath);
|
||||
final bytes = await file.readAsBytes();
|
||||
final originalImage = img.decodeImage(bytes);
|
||||
img.Image? originalImage = img.decodeImage(bytes);
|
||||
|
||||
if (originalImage == null) {
|
||||
throw Exception('Impossible de décoder l\'image: $sourcePath');
|
||||
}
|
||||
|
||||
// Calculer les coordonnées en pixels
|
||||
// FIX CRITIQUE : Si l'utilisateur a pivoté l'image, on applique d'abord la rotation
|
||||
// aux pixels bruts pour que le découpage rectiligne qui suit tape au bon endroit.
|
||||
if (rotationDegrees != 0.0) {
|
||||
originalImage = img.copyRotate(
|
||||
originalImage,
|
||||
angle: rotationDegrees,
|
||||
interpolation: img.Interpolation.cubic,
|
||||
);
|
||||
}
|
||||
|
||||
// Calculer les coordonnées en pixels sur la géométrie de l'image redressée
|
||||
final srcX = (cropRect.x * originalImage.width).round();
|
||||
final srcY = (cropRect.y * originalImage.height).round();
|
||||
final srcWidth = (cropRect.width * originalImage.width).round();
|
||||
@@ -75,7 +87,7 @@ class ImageCropService {
|
||||
final clampedWidth = math.min(srcWidth, originalImage.width - clampedX);
|
||||
final clampedHeight = math.min(srcHeight, originalImage.height - clampedY);
|
||||
|
||||
// Recadrer l'image
|
||||
// Recadrer l'image redressée
|
||||
img.Image cropped = img.copyCrop(
|
||||
originalImage,
|
||||
x: clampedX,
|
||||
@@ -87,10 +99,10 @@ class ImageCropService {
|
||||
// Redimensionner à la taille de sortie si nécessaire
|
||||
if (cropped.width != outputSize || cropped.height != outputSize) {
|
||||
cropped = img.copyResize(
|
||||
cropped,
|
||||
width: outputSize,
|
||||
height: outputSize,
|
||||
interpolation: img.Interpolation.cubic,
|
||||
cropped,
|
||||
width: outputSize,
|
||||
height: outputSize,
|
||||
interpolation: img.Interpolation.cubic,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -106,26 +118,18 @@ class ImageCropService {
|
||||
}
|
||||
|
||||
/// Calcule la zone de recadrage carrée maximale centrée sur l'image
|
||||
///
|
||||
/// [imageWidth] - Largeur de l'image en pixels
|
||||
/// [imageHeight] - Hauteur de l'image en pixels
|
||||
///
|
||||
/// Retourne un CropRect normalisé pour un carré centré
|
||||
CropRect getDefaultSquareCrop(int imageWidth, int imageHeight) {
|
||||
final aspectRatio = imageWidth / imageHeight;
|
||||
|
||||
if (aspectRatio > 1) {
|
||||
// Image plus large que haute - centrer horizontalement
|
||||
final squareWidth = imageHeight / imageWidth;
|
||||
final x = (1 - squareWidth) / 2;
|
||||
return CropRect(x: x, y: 0, width: squareWidth, height: 1);
|
||||
} else if (aspectRatio < 1) {
|
||||
// Image plus haute que large - centrer verticalement
|
||||
final squareHeight = imageWidth / imageHeight;
|
||||
final y = (1 - squareHeight) / 2;
|
||||
return CropRect(x: 0, y: y, width: 1, height: squareHeight);
|
||||
} else {
|
||||
// Déjà carré
|
||||
return const CropRect(x: 0, y: 0, width: 1, height: 1);
|
||||
}
|
||||
}
|
||||
@@ -147,7 +151,7 @@ class ImageCropService {
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignorer les erreurs de nettoyage
|
||||
// Ignorer les erreurs
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user