Autocalibration de la cible sur le centre de la cible ok + petite correction de la distortion mais pas tres fonctionnel
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
library;
|
library;
|
||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:cunning_document_scanner/cunning_document_scanner.dart';
|
import 'package:google_mlkit_document_scanner/google_mlkit_document_scanner.dart';
|
||||||
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 '../../core/constants/app_constants.dart';
|
import '../../core/constants/app_constants.dart';
|
||||||
@@ -84,8 +84,8 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
floatingActionButton: _selectedImagePath != null
|
floatingActionButton: _selectedImagePath != null
|
||||||
? FloatingActionButton.extended(
|
? FloatingActionButton.extended(
|
||||||
onPressed: _analyzeImage,
|
onPressed: _analyzeImage,
|
||||||
icon: const Icon(Icons.analytics),
|
icon: const Icon(Icons.arrow_forward),
|
||||||
label: const Text('Analyser'),
|
label: const Text('Suivant'),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
);
|
);
|
||||||
@@ -205,10 +205,18 @@ class _CaptureScreenState extends State<CaptureScreen> {
|
|||||||
setState(() => _isLoading = true);
|
setState(() => _isLoading = true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final List<String>? pictures = await CunningDocumentScanner.getPictures();
|
final options = DocumentScannerOptions(
|
||||||
|
documentFormat: DocumentFormat.jpeg,
|
||||||
|
mode: ScannerMode.base,
|
||||||
|
pageLimit: 1,
|
||||||
|
isGalleryImport: false,
|
||||||
|
);
|
||||||
|
|
||||||
if (pictures != null && pictures.isNotEmpty) {
|
final scanner = DocumentScanner(options: options);
|
||||||
setState(() => _selectedImagePath = pictures.first);
|
final documents = await scanner.scanDocument();
|
||||||
|
|
||||||
|
if (documents.images.isNotEmpty) {
|
||||||
|
setState(() => _selectedImagePath = documents.images.first);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
|||||||
@@ -13,20 +13,13 @@ class CropOverlay extends StatelessWidget {
|
|||||||
/// Afficher la grille des tiers
|
/// Afficher la grille des tiers
|
||||||
final bool showGrid;
|
final bool showGrid;
|
||||||
|
|
||||||
const CropOverlay({
|
const CropOverlay({super.key, required this.cropSize, this.showGrid = true});
|
||||||
super.key,
|
|
||||||
required this.cropSize,
|
|
||||||
this.showGrid = true,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return CustomPaint(
|
return CustomPaint(
|
||||||
size: Size.infinite,
|
size: Size.infinite,
|
||||||
painter: _CropOverlayPainter(
|
painter: _CropOverlayPainter(cropSize: cropSize, showGrid: showGrid),
|
||||||
cropSize: cropSize,
|
|
||||||
showGrid: showGrid,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,10 +28,7 @@ class _CropOverlayPainter extends CustomPainter {
|
|||||||
final double cropSize;
|
final double cropSize;
|
||||||
final bool showGrid;
|
final bool showGrid;
|
||||||
|
|
||||||
_CropOverlayPainter({
|
_CropOverlayPainter({required this.cropSize, required this.showGrid});
|
||||||
required this.cropSize,
|
|
||||||
required this.showGrid,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void paint(Canvas canvas, Size size) {
|
void paint(Canvas canvas, Size size) {
|
||||||
@@ -77,6 +67,9 @@ class _CropOverlayPainter extends CustomPainter {
|
|||||||
if (showGrid) {
|
if (showGrid) {
|
||||||
_drawGrid(canvas, cropRect);
|
_drawGrid(canvas, cropRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dessiner le point central (croix)
|
||||||
|
_drawCenterPoint(canvas, cropRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _drawCorners(Canvas canvas, Rect rect) {
|
void _drawCorners(Canvas canvas, Rect rect) {
|
||||||
@@ -171,6 +164,38 @@ class _CropOverlayPainter extends CustomPainter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _drawCenterPoint(Canvas canvas, Rect rect) {
|
||||||
|
final centerPaint = Paint()
|
||||||
|
..color = Colors.white.withValues(alpha: 0.8)
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 2;
|
||||||
|
|
||||||
|
const size = 10.0;
|
||||||
|
final centerX = rect.center.dx;
|
||||||
|
final centerY = rect.center.dy;
|
||||||
|
|
||||||
|
// Ligne horizontale
|
||||||
|
canvas.drawLine(
|
||||||
|
Offset(centerX - size, centerY),
|
||||||
|
Offset(centerX + size, centerY),
|
||||||
|
centerPaint,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Ligne verticale
|
||||||
|
canvas.drawLine(
|
||||||
|
Offset(centerX, centerY - size),
|
||||||
|
Offset(centerX, centerY + size),
|
||||||
|
centerPaint,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Petit cercle central pour précision (optionnel, mais aide à viser)
|
||||||
|
canvas.drawCircle(
|
||||||
|
rect.center,
|
||||||
|
2,
|
||||||
|
Paint()..color = Colors.red.withValues(alpha: 0.6),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool shouldRepaint(covariant _CropOverlayPainter oldDelegate) {
|
bool shouldRepaint(covariant _CropOverlayPainter oldDelegate) {
|
||||||
return cropSize != oldDelegate.cropSize || showGrid != oldDelegate.showGrid;
|
return cropSize != oldDelegate.cropSize || showGrid != oldDelegate.showGrid;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ library;
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
import 'package:image/image.dart' as img;
|
import 'package:image/image.dart' as img;
|
||||||
|
import 'package:opencv_dart/opencv_dart.dart' as cv;
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
/// Paramètres de distorsion calculés à partir de la calibration
|
/// Paramètres de distorsion calculés à partir de la calibration
|
||||||
@@ -281,16 +282,56 @@ class DistortionCorrectionService {
|
|||||||
final p11 = image.getPixel(x1, y1);
|
final p11 = image.getPixel(x1, y1);
|
||||||
|
|
||||||
// Interpoler chaque canal
|
// Interpoler chaque canal
|
||||||
final r = _lerp2D(p00.r.toDouble(), p10.r.toDouble(), p01.r.toDouble(), p11.r.toDouble(), wx, wy);
|
final r = _lerp2D(
|
||||||
final g = _lerp2D(p00.g.toDouble(), p10.g.toDouble(), p01.g.toDouble(), p11.g.toDouble(), wx, wy);
|
p00.r.toDouble(),
|
||||||
final b = _lerp2D(p00.b.toDouble(), p10.b.toDouble(), p01.b.toDouble(), p11.b.toDouble(), wx, wy);
|
p10.r.toDouble(),
|
||||||
final a = _lerp2D(p00.a.toDouble(), p10.a.toDouble(), p01.a.toDouble(), p11.a.toDouble(), wx, wy);
|
p01.r.toDouble(),
|
||||||
|
p11.r.toDouble(),
|
||||||
|
wx,
|
||||||
|
wy,
|
||||||
|
);
|
||||||
|
final g = _lerp2D(
|
||||||
|
p00.g.toDouble(),
|
||||||
|
p10.g.toDouble(),
|
||||||
|
p01.g.toDouble(),
|
||||||
|
p11.g.toDouble(),
|
||||||
|
wx,
|
||||||
|
wy,
|
||||||
|
);
|
||||||
|
final b = _lerp2D(
|
||||||
|
p00.b.toDouble(),
|
||||||
|
p10.b.toDouble(),
|
||||||
|
p01.b.toDouble(),
|
||||||
|
p11.b.toDouble(),
|
||||||
|
wx,
|
||||||
|
wy,
|
||||||
|
);
|
||||||
|
final a = _lerp2D(
|
||||||
|
p00.a.toDouble(),
|
||||||
|
p10.a.toDouble(),
|
||||||
|
p01.a.toDouble(),
|
||||||
|
p11.a.toDouble(),
|
||||||
|
wx,
|
||||||
|
wy,
|
||||||
|
);
|
||||||
|
|
||||||
return img.ColorRgba8(r.round().clamp(0, 255), g.round().clamp(0, 255), b.round().clamp(0, 255), a.round().clamp(0, 255));
|
return img.ColorRgba8(
|
||||||
|
r.round().clamp(0, 255),
|
||||||
|
g.round().clamp(0, 255),
|
||||||
|
b.round().clamp(0, 255),
|
||||||
|
a.round().clamp(0, 255),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interpolation linéaire 2D
|
/// Interpolation linéaire 2D
|
||||||
double _lerp2D(double v00, double v10, double v01, double v11, double wx, double wy) {
|
double _lerp2D(
|
||||||
|
double v00,
|
||||||
|
double v10,
|
||||||
|
double v01,
|
||||||
|
double v11,
|
||||||
|
double wx,
|
||||||
|
double wy,
|
||||||
|
) {
|
||||||
final top = v00 * (1 - wx) + v10 * wx;
|
final top = v00 * (1 - wx) + v10 * wx;
|
||||||
final bottom = v01 * (1 - wx) + v11 * wx;
|
final bottom = v01 * (1 - wx) + v11 * wx;
|
||||||
return top * (1 - wy) + bottom * wy;
|
return top * (1 - wy) + bottom * wy;
|
||||||
@@ -320,7 +361,9 @@ class DistortionCorrectionService {
|
|||||||
final height = image.height;
|
final height = image.height;
|
||||||
|
|
||||||
// Convertir les coordonnées normalisées en pixels
|
// Convertir les coordonnées normalisées en pixels
|
||||||
final srcCorners = corners.map((c) => (x: c.x * width, y: c.y * height)).toList();
|
final srcCorners = corners
|
||||||
|
.map((c) => (x: c.x * width, y: c.y * height))
|
||||||
|
.toList();
|
||||||
|
|
||||||
// Calculer la taille du rectangle destination
|
// Calculer la taille du rectangle destination
|
||||||
// On prend la moyenne des largeurs et hauteurs
|
// On prend la moyenne des largeurs et hauteurs
|
||||||
@@ -336,20 +379,21 @@ class DistortionCorrectionService {
|
|||||||
final result = img.Image(width: dstWidth, height: dstHeight);
|
final result = img.Image(width: dstWidth, height: dstHeight);
|
||||||
|
|
||||||
// Calculer la matrice de transformation perspective
|
// Calculer la matrice de transformation perspective
|
||||||
final matrix = _computePerspectiveMatrix(
|
final matrix = _computePerspectiveMatrix(srcCorners, [
|
||||||
srcCorners,
|
(x: 0.0, y: 0.0),
|
||||||
[
|
(x: dstWidth.toDouble(), y: 0.0),
|
||||||
(x: 0.0, y: 0.0),
|
(x: dstWidth.toDouble(), y: dstHeight.toDouble()),
|
||||||
(x: dstWidth.toDouble(), y: 0.0),
|
(x: 0.0, y: dstHeight.toDouble()),
|
||||||
(x: dstWidth.toDouble(), y: dstHeight.toDouble()),
|
]);
|
||||||
(x: 0.0, y: dstHeight.toDouble()),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
// Appliquer la transformation
|
// Appliquer la transformation
|
||||||
for (int y = 0; y < dstHeight; y++) {
|
for (int y = 0; y < dstHeight; y++) {
|
||||||
for (int x = 0; x < dstWidth; x++) {
|
for (int x = 0; x < dstWidth; x++) {
|
||||||
final src = _applyPerspectiveTransform(matrix, x.toDouble(), y.toDouble());
|
final src = _applyPerspectiveTransform(
|
||||||
|
matrix,
|
||||||
|
x.toDouble(),
|
||||||
|
y.toDouble(),
|
||||||
|
);
|
||||||
|
|
||||||
if (src.x >= 0 && src.x < width && src.y >= 0 && src.y < height) {
|
if (src.x >= 0 && src.x < width && src.y >= 0 && src.y < height) {
|
||||||
final pixel = _bilinearInterpolate(image, src.x, src.y);
|
final pixel = _bilinearInterpolate(image, src.x, src.y);
|
||||||
@@ -408,7 +452,10 @@ class DistortionCorrectionService {
|
|||||||
// Le système 'a' est de taille 8x9 (8 équations, 9 inconnues).
|
// Le système 'a' est de taille 8x9 (8 équations, 9 inconnues).
|
||||||
// On fixe h8 = 1.0 pour résoudre le système, ce qui nous donne un système 8x8.
|
// On fixe h8 = 1.0 pour résoudre le système, ce qui nous donne un système 8x8.
|
||||||
final int n = 8;
|
final int n = 8;
|
||||||
final List<List<double>> matrix = List.generate(n, (i) => List<double>.from(a[i]));
|
final List<List<double>> matrix = List.generate(
|
||||||
|
n,
|
||||||
|
(i) => List<double>.from(a[i]),
|
||||||
|
);
|
||||||
|
|
||||||
// Vecteur B (les constantes de l'autre côté de l'égalité)
|
// Vecteur B (les constantes de l'autre côté de l'égalité)
|
||||||
// Dans DLT, -h8 * dx (ou dy) devient le terme constant.
|
// Dans DLT, -h8 * dx (ou dy) devient le terme constant.
|
||||||
@@ -462,7 +509,11 @@ class DistortionCorrectionService {
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
({double x, double y}) _applyPerspectiveTransform(List<double> h, double x, double y) {
|
({double x, double y}) _applyPerspectiveTransform(
|
||||||
|
List<double> h,
|
||||||
|
double x,
|
||||||
|
double y,
|
||||||
|
) {
|
||||||
final w = h[6] * x + h[7] * y + h[8];
|
final w = h[6] * x + h[7] * y + h[8];
|
||||||
if (w.abs() < 1e-10) {
|
if (w.abs() < 1e-10) {
|
||||||
return (x: x, y: y);
|
return (x: x, y: y);
|
||||||
@@ -471,4 +522,158 @@ class DistortionCorrectionService {
|
|||||||
final ny = (h[3] * x + h[4] * y + h[5]) / w;
|
final ny = (h[3] * x + h[4] * y + h[5]) / w;
|
||||||
return (x: nx, y: ny);
|
return (x: nx, y: ny);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Corrige la perspective en se basant sur la détection de cercles (ellipses)
|
||||||
|
/// dans l'image.
|
||||||
|
///
|
||||||
|
/// Cette méthode tente de détecter l'ellipse la plus proéminente (la cible)
|
||||||
|
/// et calcule une transformation pour la rendre parfaitement circulaire.
|
||||||
|
Future<String> correctPerspectiveUsingCircles(String imagePath) async {
|
||||||
|
try {
|
||||||
|
// 1. Charger l'image avec OpenCV
|
||||||
|
final src = cv.imread(imagePath, flags: cv.IMREAD_COLOR);
|
||||||
|
if (src.isEmpty) throw Exception("Impossible de charger l'image");
|
||||||
|
|
||||||
|
// 2. Prétraitement
|
||||||
|
final gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY);
|
||||||
|
final blurred = cv.gaussianBlur(gray, (5, 5), 0);
|
||||||
|
|
||||||
|
// Canny edge detector avec seuil adaptatif (Otsu)
|
||||||
|
final thresh = cv.threshold(
|
||||||
|
blurred,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
cv.THRESH_BINARY | cv.THRESH_OTSU,
|
||||||
|
);
|
||||||
|
final edges = cv.canny(blurred, thresh.$1 * 0.5, thresh.$1);
|
||||||
|
|
||||||
|
// 3. Trouver les contours
|
||||||
|
final contoursResult = cv.findContours(
|
||||||
|
edges,
|
||||||
|
cv.RETR_EXTERNAL,
|
||||||
|
cv.CHAIN_APPROX_SIMPLE,
|
||||||
|
);
|
||||||
|
final contours = contoursResult.$1;
|
||||||
|
|
||||||
|
if (contours.isEmpty) return imagePath; // Pas de contours trouvés
|
||||||
|
|
||||||
|
// 4. Trouver le meilleur candidat ellipse
|
||||||
|
cv.RotatedRect? bestEllipse;
|
||||||
|
double maxArea = 0;
|
||||||
|
|
||||||
|
for (final contour in contours) {
|
||||||
|
if (contour.length < 5)
|
||||||
|
continue; // fitEllipse nécessite au moins 5 points
|
||||||
|
|
||||||
|
final area = cv.contourArea(contour);
|
||||||
|
if (area < 1000) continue; // Ignorer les trop petits bruits
|
||||||
|
|
||||||
|
final ellipse = cv.fitEllipse(contour);
|
||||||
|
|
||||||
|
// Critère de sélection: on cherche la plus grande ellipse qui est proche d'un cercle
|
||||||
|
// Mais comme on veut corriger la distorsion, elle PEUT être aplatie.
|
||||||
|
// Donc on prend juste la plus grande ellipse raisonnablement centrée.
|
||||||
|
if (area > maxArea) {
|
||||||
|
maxArea = area;
|
||||||
|
bestEllipse = ellipse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestEllipse == null) return imagePath;
|
||||||
|
|
||||||
|
// 5. Calculer la transformation perspective
|
||||||
|
// L'idée est de mapper les 4 sommets de l'ellipse détectée vers un cercle parfait.
|
||||||
|
// Ou plus simplement, mapper le rectangle englobant de l'ellipse vers un carré.
|
||||||
|
|
||||||
|
// Points source: les 4 coins du rotated rect de l'ellipse
|
||||||
|
// Note: opencv_dart RotatedRect points() non dispo directement?
|
||||||
|
// On peut utiliser boxPoints(ellipse)
|
||||||
|
final boxPoints = cv.boxPoints(bestEllipse);
|
||||||
|
// boxPoints returns Mat (4x2 float32)
|
||||||
|
|
||||||
|
// Extraire les 4 points
|
||||||
|
final List<cv.Point> srcPoints = [];
|
||||||
|
|
||||||
|
for (int i = 0; i < boxPoints.length; i++) {
|
||||||
|
// On accède directement au point à l'index i
|
||||||
|
final point2f = boxPoints[i];
|
||||||
|
|
||||||
|
// On convertit les coordonnées float en int pour cv.Point
|
||||||
|
srcPoints.add(cv.Point(point2f.x.toInt(), point2f.y.toInt()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trier les points pour avoir: TL, TR, BR, BL
|
||||||
|
_sortPoints(srcPoints);
|
||||||
|
|
||||||
|
// Dimensions cibles
|
||||||
|
final side = math
|
||||||
|
.max(bestEllipse.size.width, bestEllipse.size.height)
|
||||||
|
.toInt();
|
||||||
|
|
||||||
|
final List<cv.Point> dstPoints = [
|
||||||
|
cv.Point(0, 0),
|
||||||
|
cv.Point(side, 0),
|
||||||
|
cv.Point(side, side),
|
||||||
|
cv.Point(0, side),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Matrice de perspective
|
||||||
|
final M = cv.getPerspectiveTransform(
|
||||||
|
cv.VecPoint.fromList(srcPoints),
|
||||||
|
cv.VecPoint.fromList(dstPoints),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 6. Warper l'image
|
||||||
|
final corrected = cv.warpPerspective(src, M, (side, side));
|
||||||
|
|
||||||
|
// 7. Sauvegarder
|
||||||
|
final tempDir = await getTemporaryDirectory();
|
||||||
|
final timestamp = DateTime.now().millisecondsSinceEpoch;
|
||||||
|
final outputPath = '${tempDir.path}/corrected_circle_$timestamp.jpg';
|
||||||
|
|
||||||
|
cv.imwrite(outputPath, corrected);
|
||||||
|
|
||||||
|
return outputPath;
|
||||||
|
} catch (e) {
|
||||||
|
// En cas d'erreur, retourner l'image originale
|
||||||
|
print('Erreur correction perspective cercles: $e');
|
||||||
|
return imagePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trie les points dans l'ordre: Top-Left, Top-Right, Bottom-Right, Bottom-Left
|
||||||
|
void _sortPoints(List<cv.Point> points) {
|
||||||
|
// Calculer le centre de gravité
|
||||||
|
double cx = 0;
|
||||||
|
double cy = 0;
|
||||||
|
for (final p in points) {
|
||||||
|
cx += p.x;
|
||||||
|
cy += p.y;
|
||||||
|
}
|
||||||
|
cx /= points.length;
|
||||||
|
cy /= points.length;
|
||||||
|
|
||||||
|
points.sort((a, b) {
|
||||||
|
// Trier par angle autour du centre
|
||||||
|
final angleA = math.atan2(a.y - cy, a.x - cx);
|
||||||
|
final angleB = math.atan2(b.y - cy, b.x - cx);
|
||||||
|
return angleA.compareTo(angleB);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Re-trier pour être sûr:
|
||||||
|
points.sort((a, b) => (a.y + a.x).compareTo(b.y + b.x));
|
||||||
|
final tl = points[0];
|
||||||
|
final br = points[3];
|
||||||
|
|
||||||
|
// Reste tr et bl
|
||||||
|
final remaining = [points[1], points[2]];
|
||||||
|
remaining.sort((a, b) => a.x.compareTo(b.x));
|
||||||
|
final bl = remaining[0];
|
||||||
|
final tr = remaining[1];
|
||||||
|
|
||||||
|
points[0] = tl;
|
||||||
|
points[1] = tr;
|
||||||
|
points[2] = br;
|
||||||
|
points[3] = bl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
64
pubspec.lock
64
pubspec.lock
@@ -81,14 +81,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.7"
|
version: "3.0.7"
|
||||||
cunning_document_scanner:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: cunning_document_scanner
|
|
||||||
sha256: de0c0705799f7d5cc9b82b67bfb8b3e965a1fbff4afbd70ea10cd1dad4f3a98c
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.4.0"
|
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -224,6 +216,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.3"
|
version: "2.1.3"
|
||||||
|
google_mlkit_document_scanner:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: google_mlkit_document_scanner
|
||||||
|
sha256: "67428ddb853880c8185049a5834cd328e6420921a74786f6aadee0b76f8536bd"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.1"
|
||||||
hooks:
|
hooks:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -488,54 +488,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "2.3.0"
|
||||||
permission_handler:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: permission_handler
|
|
||||||
sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "12.0.1"
|
|
||||||
permission_handler_android:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: permission_handler_android
|
|
||||||
sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "13.0.1"
|
|
||||||
permission_handler_apple:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: permission_handler_apple
|
|
||||||
sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "9.4.7"
|
|
||||||
permission_handler_html:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: permission_handler_html
|
|
||||||
sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.1.3+5"
|
|
||||||
permission_handler_platform_interface:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: permission_handler_platform_interface
|
|
||||||
sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "4.3.0"
|
|
||||||
permission_handler_windows:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: permission_handler_windows
|
|
||||||
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.2.1"
|
|
||||||
petitparser:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ dependencies:
|
|||||||
opencv_dart: ^2.1.0
|
opencv_dart: ^2.1.0
|
||||||
|
|
||||||
# Image capture from camera/gallery
|
# Image capture from camera/gallery
|
||||||
image_picker: ^1.0.7
|
image_picker: ^1.2.1
|
||||||
cunning_document_scanner: ^1.4.0
|
google_mlkit_document_scanner: ^0.2.0
|
||||||
|
|
||||||
# Local database for history
|
# Local database for history
|
||||||
sqflite: ^2.3.2
|
sqflite: ^2.3.2
|
||||||
|
|||||||
@@ -7,11 +7,8 @@
|
|||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <file_selector_windows/file_selector_windows.h>
|
#include <file_selector_windows/file_selector_windows.h>
|
||||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
FileSelectorWindowsRegisterWithRegistrar(
|
FileSelectorWindowsRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
||||||
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
|
||||||
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
file_selector_windows
|
file_selector_windows
|
||||||
permission_handler_windows
|
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|||||||
Reference in New Issue
Block a user