fix(crop): synchroniser les calculs avec le mode BoxFit.cover et activer la découpe physique
This commit is contained in:
@@ -156,7 +156,7 @@ class _CropScreenState extends State<CropScreen> {
|
||||
style: TextStyle(color: Colors.white70, fontSize: 13, fontWeight: FontWeight.w600),
|
||||
),
|
||||
Text(
|
||||
'${_rotation.toStringAsFixed(1)}°', // Affiche désormais le dixième de degré pour la précision
|
||||
'${_rotation.toStringAsFixed(1)}°',
|
||||
style: const TextStyle(color: Color(0xFF00FF00), fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
@@ -167,9 +167,9 @@ class _CropScreenState extends State<CropScreen> {
|
||||
Expanded(
|
||||
child: Slider(
|
||||
value: _rotation,
|
||||
min: -15.0, // Pivot maximum à gauche bridé à 15°
|
||||
max: 15.0, // Pivot maximum à droite bridé à 15°
|
||||
divisions: 300, // 300 divisions pour obtenir un cran ultra-précis tous les 0,1°
|
||||
min: -15.0,
|
||||
max: 15.0,
|
||||
divisions: 300,
|
||||
label: '${_rotation.toStringAsFixed(1)}°',
|
||||
activeColor: const Color(0xFF1A73E8),
|
||||
inactiveColor: Colors.white12,
|
||||
@@ -182,7 +182,6 @@ class _CropScreenState extends State<CropScreen> {
|
||||
),
|
||||
const Icon(Icons.rotate_right, color: Colors.white38, size: 20),
|
||||
const SizedBox(width: 4),
|
||||
// Petit bouton Reset rapide pour cette jauge
|
||||
IconButton(
|
||||
icon: const Icon(Icons.restart_alt, color: Colors.white54, size: 20),
|
||||
onPressed: () {
|
||||
@@ -260,7 +259,7 @@ class _CropScreenState extends State<CropScreen> {
|
||||
alignment: Alignment.center,
|
||||
child: Image.file(
|
||||
File(widget.imagePath),
|
||||
fit: BoxFit.contain,
|
||||
fit: BoxFit.cover,
|
||||
width: _viewportSize.width,
|
||||
height: _viewportSize.height,
|
||||
),
|
||||
@@ -302,7 +301,6 @@ class _CropScreenState extends State<CropScreen> {
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
// Zone visible : Rectangle parfait sans aucun BorderRadius
|
||||
Center(
|
||||
child: Container(
|
||||
width: _cropSize,
|
||||
@@ -335,13 +333,14 @@ class _CropScreenState extends State<CropScreen> {
|
||||
final imageAspect = _imageSize!.width / _imageSize!.height;
|
||||
final viewportAspect = _viewportSize.width / _viewportSize.height;
|
||||
|
||||
// Initialisation calée sur la logique BoxFit.cover
|
||||
double displayWidth, displayHeight;
|
||||
if (imageAspect > viewportAspect) {
|
||||
displayWidth = _viewportSize.width;
|
||||
displayHeight = _viewportSize.width / imageAspect;
|
||||
} else {
|
||||
displayHeight = _viewportSize.height;
|
||||
displayWidth = _viewportSize.height * imageAspect;
|
||||
} else {
|
||||
displayWidth = _viewportSize.width;
|
||||
displayHeight = _viewportSize.width / imageAspect;
|
||||
}
|
||||
|
||||
final minDisplayDim = math.min(displayWidth, displayHeight);
|
||||
@@ -372,8 +371,17 @@ class _CropScreenState extends State<CropScreen> {
|
||||
setState(() => _isLoading = true);
|
||||
try {
|
||||
final cropRect = _calculateCropRect();
|
||||
final targetCenterX = cropRect.x + cropRect.width / 2;
|
||||
final targetCenterY = cropRect.y + cropRect.height / 2;
|
||||
|
||||
// DECOUPE ET REDRESSEMENT PHYSIQUE DE L'IMAGE
|
||||
final croppedImagePath = await _cropService.cropToSquare(
|
||||
widget.imagePath,
|
||||
cropRect,
|
||||
rotationDegrees: _rotation,
|
||||
);
|
||||
|
||||
// On recalcule le centre relatif de la cible pour l'image carrée finale (qui vaut 0.5, 0.5 par défaut)
|
||||
const targetCenterX = 0.5;
|
||||
const targetCenterY = 0.5;
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
@@ -381,13 +389,13 @@ class _CropScreenState extends State<CropScreen> {
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => AnalysisScreen(
|
||||
imagePath: widget.imagePath,
|
||||
imagePath: croppedImagePath, // On passe le fichier carré proprement détouré !
|
||||
targetType: widget.targetType,
|
||||
initialCenterX: targetCenterX,
|
||||
initialCenterY: targetCenterY,
|
||||
cropScale: _scale,
|
||||
cropOffset: _offset,
|
||||
cropRotation: _rotation,
|
||||
cropScale: 1.0, // Réinitialisé car l'image physique est déjà à la bonne échelle
|
||||
cropOffset: Offset.zero, // Réinitialisé car l'image physique est déjà centrée
|
||||
cropRotation: 0.0, // Réinitialisé car l'image physique est déjà redressée
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -395,25 +403,27 @@ class _CropScreenState extends State<CropScreen> {
|
||||
if (mounted) {
|
||||
setState(() => _isLoading = false);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Erreur: $e'), backgroundColor: AppTheme.errorColor),
|
||||
SnackBar(content: Text('Erreur de découpe: $e'), backgroundColor: AppTheme.errorColor),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calcule précisément le CropRect basé sur la géométrie BoxFit.cover
|
||||
CropRect _calculateCropRect() {
|
||||
if (_imageSize == null) return const CropRect(x: 0, y: 0, width: 1, height: 1);
|
||||
|
||||
final imageAspect = _imageSize!.width / _imageSize!.height;
|
||||
final viewportAspect = _viewportSize.width / _viewportSize.height;
|
||||
|
||||
// Dimensions réelles de rendu en mode BoxFit.cover
|
||||
double displayWidth, displayHeight;
|
||||
if (imageAspect > viewportAspect) {
|
||||
displayWidth = _viewportSize.width;
|
||||
displayHeight = _viewportSize.width / imageAspect;
|
||||
} else {
|
||||
displayHeight = _viewportSize.height;
|
||||
displayWidth = _viewportSize.height * imageAspect;
|
||||
} else {
|
||||
displayWidth = _viewportSize.width;
|
||||
displayHeight = _viewportSize.width / imageAspect;
|
||||
}
|
||||
|
||||
final scaledWidth = displayWidth * _scale;
|
||||
@@ -434,10 +444,10 @@ class _CropScreenState extends State<CropScreen> {
|
||||
final relCropHeight = _cropSize / scaledHeight;
|
||||
|
||||
return CropRect(
|
||||
x: relCropLeft,
|
||||
y: relCropTop,
|
||||
width: relCropWidth,
|
||||
height: relCropHeight,
|
||||
x: relCropLeft.clamp(0.0, 1.0),
|
||||
y: relCropTop.clamp(0.0, 1.0),
|
||||
width: relCropWidth.clamp(0.0, 1.0),
|
||||
height: relCropHeight.clamp(0.0, 1.0),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user