fix: retour arriere leger zoom du au 85% crop

This commit is contained in:
qguillaume
2026-06-05 23:55:43 +02:00
parent f0b15941cf
commit 13cf5b70e0
2 changed files with 66 additions and 39 deletions

View File

@@ -9,17 +9,28 @@ import '../analysis/analysis_screen.dart';
import 'widgets/crop_overlay.dart';
class CropScreen extends StatefulWidget {
/// Image affichée/recadrée dans cet écran. Au tout premier passage, c'est
/// aussi l'image originale. Lors des allers-retours, on recharge toujours
/// l'ORIGINAL ici (jamais une image déjà recadrée) pour éviter le zoom
/// cumulatif.
final String imagePath;
/// Chemin de l'image ORIGINALE (jamais recadrée). Si null, [imagePath] est
/// considéré comme l'original (premier passage depuis la caméra/galerie).
final String? originalImagePath;
final TargetType targetType;
final double? initialScale;
final Offset? initialOffset;
/// Rotation à restaurer au retour (en degrés). Le zoom n'est volontairement
/// PAS restauré : on repart toujours de l'image entière.
final double? initialRotation;
const CropScreen({
super.key,
required this.imagePath,
this.originalImagePath,
required this.targetType,
this.initialScale,
this.initialOffset,
this.initialRotation,
});
@override
@@ -45,14 +56,20 @@ class _CropScreenState extends State<CropScreen> {
late Size _viewportSize;
late double _cropSize;
/// L'image effectivement travaillée par cet écran : toujours l'originale.
String get _workingImagePath =>
widget.originalImagePath ?? widget.imagePath;
@override
void initState() {
super.initState();
// On restaure uniquement la rotation (pas le zoom).
_rotation = widget.initialRotation ?? 0.0;
_loadImageInfo();
}
Future<void> _loadImageInfo() async {
final file = File(widget.imagePath);
final file = File(_workingImagePath);
final decodedImage = await decodeImageFromList(await file.readAsBytes());
if (mounted) {
setState(() {
@@ -254,7 +271,7 @@ class _CropScreenState extends State<CropScreen> {
// On passe de 0.95 à 0.85 pour matcher parfaitement avec l'appareil photo !
_cropSize = math.min(displayWidth, displayHeight)* 0.85;
if (_scale == 1.0 && _offset == Offset.zero && _rotation == 0.0) {
if (_scale == 1.0 && _offset == Offset.zero) {
_initializeImagePosition();
}
@@ -273,7 +290,7 @@ class _CropScreenState extends State<CropScreen> {
..rotateZ(_rotation * (math.pi / 180)),
alignment: Alignment.center,
child: Image.file(
File(widget.imagePath),
File(_workingImagePath),
fit: BoxFit.contain,
width: _viewportSize.width,
height: _viewportSize.height,
@@ -358,18 +375,10 @@ class _CropScreenState extends State<CropScreen> {
displayWidth = _viewportSize.height * imageAspect;
}
final minDisplayDim = math.min(displayWidth, displayHeight);
// 2. Calcul du scale initial basé sur la dimension de l'image (et non du viewport)
_scale = widget.initialScale ?? 1.0;
if (_scale < 1.0 && widget.initialScale == null) _scale = 1.0;
// 3. Réinitialisation propre de l'offset au centre de la zone d'affichage
if (widget.initialOffset != null) {
_offset = widget.initialOffset!;
} else {
_offset = Offset.zero; // Force l'image à se centrer parfaitement sur la croix verte
}
// On repart TOUJOURS de l'image entière, centrée, sans zoom :
// c'est ce qui empêche tout cumul de recadrage entre les allers-retours.
_scale = 1.0;
_offset = Offset.zero;
}
void _onScaleStart(ScaleStartDetails details) {
@@ -402,9 +411,10 @@ class _CropScreenState extends State<CropScreen> {
_scale = savedScale;
_offset = savedOffset;
// AJOUT DE LA DECOUPE ET DU REDRESSEMENT GÉOMÉTRIQUE PHYSIQUE
// Le crop est TOUJOURS calculé sur l'image originale, jamais sur un
// résultat déjà recadré.
final croppedImagePath = await _cropService.cropToSquare(
widget.imagePath,
_workingImagePath,
cropRect,
rotationDegrees: _rotation,
);
@@ -419,12 +429,13 @@ class _CropScreenState extends State<CropScreen> {
MaterialPageRoute(
builder: (_) => AnalysisScreen(
imagePath: croppedImagePath,
// On fait suivre l'ORIGINAL et la rotation choisie, pour pouvoir
// revenir au centrage sans jamais re-recadrer le résultat.
originalImagePath: _workingImagePath,
cropRotation: _rotation,
targetType: widget.targetType,
initialCenterX: targetCenterX,
initialCenterY: targetCenterY,
cropScale: 1.0,
cropOffset: Offset.zero,
cropRotation: 0.0,
),
),
);