fix: freeze et deformation lors de la prise de la photo (rotation)
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:isolate';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
@@ -17,7 +18,6 @@ import 'widgets/image_source_button.dart';
|
|||||||
import '../../services/image_crop_service.dart';
|
import '../../services/image_crop_service.dart';
|
||||||
import '../../services/opencv_target_service.dart';
|
import '../../services/opencv_target_service.dart';
|
||||||
import '../../services/parallelism_service.dart'; // NOUVEAU
|
import '../../services/parallelism_service.dart'; // NOUVEAU
|
||||||
import '../../services/target_rectify_service.dart'; // NOUVEAU : redressement
|
|
||||||
import 'package:image/image.dart' as img;
|
import 'package:image/image.dart' as img;
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
@@ -64,9 +64,6 @@ class _CaptureScreenState extends State<CaptureScreen>
|
|||||||
ParallelismData? _parallelismData;
|
ParallelismData? _parallelismData;
|
||||||
StreamSubscription<ParallelismData>? _parallelismSubscription;
|
StreamSubscription<ParallelismData>? _parallelismSubscription;
|
||||||
|
|
||||||
// Service de redressement de cible (warp perspective)
|
|
||||||
final TargetRectifyService _rectifyService = TargetRectifyService();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -735,36 +732,11 @@ class _CaptureScreenState extends State<CaptureScreen>
|
|||||||
|
|
||||||
final XFile photo = await _cameraController!.takePicture();
|
final XFile photo = await _cameraController!.takePicture();
|
||||||
|
|
||||||
// NOUVEAU : redressement automatique de la cible (warp perspective).
|
// Pas de redressement perspective automatique ici : il déformait l'image
|
||||||
// On écrit le résultat dans un fichier dédié, à côté de l'original.
|
// (écrasement en carré + rotation de l'axe de l'ellipse) et gelait le
|
||||||
|
// thread UI. Le recentrage ET la rotation se font manuellement à l'écran
|
||||||
|
// de centrage suivant, qui est précis et non destructeur.
|
||||||
String finalPath = photo.path;
|
String finalPath = photo.path;
|
||||||
try {
|
|
||||||
final tempDir = await getTemporaryDirectory();
|
|
||||||
final rectifiedPath =
|
|
||||||
'${tempDir.path}/rectified_${DateTime.now().millisecondsSinceEpoch}.jpg';
|
|
||||||
|
|
||||||
final result = await _rectifyService.rectify(
|
|
||||||
inputPath: photo.path,
|
|
||||||
outputPath: rectifiedPath,
|
|
||||||
);
|
|
||||||
|
|
||||||
finalPath = result.outputPath;
|
|
||||||
|
|
||||||
if (mounted && result.rectified) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
duration: const Duration(seconds: 2),
|
|
||||||
content: Text(
|
|
||||||
'Cible redressée automatiquement '
|
|
||||||
'(inclinaison ${result.estimatedTiltDegrees.toStringAsFixed(1)}° corrigée)',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
debugPrint('Redressement ignoré: $e');
|
|
||||||
finalPath = photo.path; // on garde la photo originale en secours
|
|
||||||
}
|
|
||||||
|
|
||||||
// PERF : on dégrade fortement la photo juste après la capture.
|
// PERF : on dégrade fortement la photo juste après la capture.
|
||||||
// Une résolution réduite suffit pour la calibration et le plotting,
|
// Une résolution réduite suffit pour la calibration et le plotting,
|
||||||
@@ -795,7 +767,15 @@ class _CaptureScreenState extends State<CaptureScreen>
|
|||||||
/// Baisser `maxSide` (ex. 900) ou `quality` (ex. 60) rend le chargement
|
/// Baisser `maxSide` (ex. 900) ou `quality` (ex. 60) rend le chargement
|
||||||
/// encore plus rapide au prix d'un peu de finesse à l'écran.
|
/// encore plus rapide au prix d'un peu de finesse à l'écran.
|
||||||
Future<String> _downscaleForPipeline(String sourcePath) async {
|
Future<String> _downscaleForPipeline(String sourcePath) async {
|
||||||
final bytes = await File(sourcePath).readAsBytes();
|
// On résout le chemin de sortie sur le thread UI (path_provider a besoin
|
||||||
|
// du canal de plateforme), puis tout le travail lourd (décodage, resize,
|
||||||
|
// réencodage JPEG) part dans un Isolate → aucun gel du thread UI.
|
||||||
|
final tempDir = await getTemporaryDirectory();
|
||||||
|
final outPath =
|
||||||
|
'${tempDir.path}/downscaled_${DateTime.now().millisecondsSinceEpoch}.jpg';
|
||||||
|
|
||||||
|
return Isolate.run(() {
|
||||||
|
final bytes = File(sourcePath).readAsBytesSync();
|
||||||
final decoded = img.decodeImage(bytes);
|
final decoded = img.decodeImage(bytes);
|
||||||
if (decoded == null) return sourcePath;
|
if (decoded == null) return sourcePath;
|
||||||
|
|
||||||
@@ -813,11 +793,9 @@ class _CaptureScreenState extends State<CaptureScreen>
|
|||||||
interpolation: img.Interpolation.linear, // rapide
|
interpolation: img.Interpolation.linear, // rapide
|
||||||
);
|
);
|
||||||
|
|
||||||
final tempDir = await getTemporaryDirectory();
|
File(outPath).writeAsBytesSync(img.encodeJpg(resized, quality: 70));
|
||||||
final outPath =
|
|
||||||
'${tempDir.path}/downscaled_${DateTime.now().millisecondsSinceEpoch}.jpg';
|
|
||||||
await File(outPath).writeAsBytes(img.encodeJpg(resized, quality: 70));
|
|
||||||
return outPath;
|
return outPath;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user