feat: Add document scanner package

This commit is contained in:
Anton Stubenbord
2023-02-22 18:17:50 +01:00
parent a8a41b38a8
commit 9c5a45f329
105 changed files with 3998 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
import 'dart:ffi';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui';
import 'package:ffi/ffi.dart';
import 'package:paperless_document_scanner/types/edge_detection_result.dart';
final DynamicLibrary _nativeInteropLib = Platform.isAndroid
? DynamicLibrary.open("libnative_edge_detection.so")
: DynamicLibrary.process();
class EdgeDetection {
static Future<EdgeDetectionResult> detectEdgesFromFile(String path) async {
final detectEdges = _nativeInteropLib
.lookup<NativeFunction<_c_detect_edges_from_file>>(
"detect_edges_from_file")
.asFunction<_dart_detect_edges_from_file>();
NativeEdgeDetectionResult detectionResult =
detectEdges(path.toNativeUtf8()).ref;
return EdgeDetectionResult(
topLeft: Offset(
detectionResult.topLeft.ref.x, detectionResult.topLeft.ref.y),
topRight: Offset(
detectionResult.topRight.ref.x, detectionResult.topRight.ref.y),
bottomLeft: Offset(
detectionResult.bottomLeft.ref.x, detectionResult.bottomLeft.ref.y),
bottomRight: Offset(detectionResult.bottomRight.ref.x,
detectionResult.bottomRight.ref.y));
}
static Future<EdgeDetectionResult> detectEdges(Uint8List bytes) async {
final detectEdges = _nativeInteropLib
.lookup<NativeFunction<_c_detect_edges>>("detect_edges")
.asFunction<_dart_detect_edges>();
Pointer<Uint8> imgBuffer = malloc.allocate<Uint8>(bytes.lengthInBytes);
Uint8List buffer = imgBuffer.asTypedList(bytes.lengthInBytes);
buffer.setAll(0, bytes);
NativeEdgeDetectionResult detectionResult = detectEdges(
imgBuffer,
buffer.lengthInBytes,
).ref;
final result = EdgeDetectionResult(
topLeft: Offset(
detectionResult.topLeft.ref.x,
detectionResult.topLeft.ref.y,
),
topRight: Offset(
detectionResult.topRight.ref.x,
detectionResult.topRight.ref.y,
),
bottomLeft: Offset(
detectionResult.bottomLeft.ref.x,
detectionResult.bottomLeft.ref.y,
),
bottomRight: Offset(
detectionResult.bottomRight.ref.x,
detectionResult.bottomRight.ref.y,
),
);
return result;
}
}
typedef _c_detect_edges_from_file = Pointer<NativeEdgeDetectionResult> Function(
Pointer<Utf8> imagePath,
);
typedef _c_detect_edges = Pointer<NativeEdgeDetectionResult> Function(
Pointer<Uint8> bytes,
Int32 byteSize,
);
typedef _dart_detect_edges_from_file = Pointer<NativeEdgeDetectionResult>
Function(
Pointer<Utf8> imagePath,
);
typedef _dart_detect_edges = Pointer<NativeEdgeDetectionResult> Function(
Pointer<Uint8> bytes,
int byteSize,
);

View File

@@ -0,0 +1,112 @@
import 'dart:ffi';
import 'dart:io';
import 'dart:typed_data';
import 'package:ffi/ffi.dart';
import 'package:paperless_document_scanner/types/edge_detection_result.dart';
final DynamicLibrary _nativeInteropLib = Platform.isAndroid
? DynamicLibrary.open("libnative_edge_detection.so")
: DynamicLibrary.process();
class ImageProcessing {
static Future<bool> processImageFromFile(
String path,
EdgeDetectionResult result,
) async {
final processImage = _nativeInteropLib
.lookup<NativeFunction<_c_process_image_from_file>>(
"process_image_from_file")
.asFunction<_dart_process_image_from_file>();
return processImage(
path.toNativeUtf8(),
result.topLeft.dx,
result.topLeft.dy,
result.topRight.dx,
result.topRight.dy,
result.bottomLeft.dx,
result.bottomLeft.dy,
result.bottomRight.dx,
result.bottomRight.dy,
) ==
1;
}
static Future<bool> processImage(
Uint8List bytes,
EdgeDetectionResult result,
) async {
final processImage = _nativeInteropLib
.lookup<NativeFunction<_c_process_image>>("process_image")
.asFunction<_dart_process_image>();
final imgBuffer = malloc.allocate<Uint8>(bytes.lengthInBytes);
Uint8List buffer = imgBuffer.asTypedList(bytes.lengthInBytes);
buffer.setAll(0, bytes);
return processImage(
imgBuffer,
bytes.lengthInBytes,
result.topLeft.dx,
result.topLeft.dy,
result.topRight.dx,
result.topRight.dy,
result.bottomLeft.dx,
result.bottomLeft.dy,
result.bottomRight.dx,
result.bottomRight.dy,
) ==
1;
}
}
typedef _c_process_image_from_file = Int8 Function(
Pointer<Utf8> imagePath,
Double topLeftX,
Double topLeftY,
Double topRightX,
Double topRightY,
Double bottomLeftX,
Double bottomLeftY,
Double bottomRightX,
Double bottomRightY,
);
typedef _c_process_image = Int8 Function(
Pointer<Uint8> imagePath,
Int32 byteSize,
Double topLeftX,
Double topLeftY,
Double topRightX,
Double topRightY,
Double bottomLeftX,
Double bottomLeftY,
Double bottomRightX,
Double bottomRightY,
);
typedef _dart_process_image_from_file = int Function(
Pointer<Utf8> imagePath,
double topLeftX,
double topLeftY,
double topRightX,
double topRightY,
double bottomLeftX,
double bottomLeftY,
double bottomRightX,
double bottomRightY,
);
typedef _dart_process_image = int Function(
Pointer<Uint8> imagePath,
int byteSize,
double topLeftX,
double topLeftY,
double topRightX,
double topRightY,
double bottomLeftX,
double bottomLeftY,
double bottomRightX,
double bottomRightY,
);

View File

@@ -0,0 +1,2 @@
export 'modules/edge_detection.dart';
export 'modules/image_processing.dart';

View File

@@ -0,0 +1,49 @@
import 'dart:ui';
import 'package:ffi/ffi.dart';
import 'dart:ffi';
class Coordinate extends Struct {
@Double()
external double x;
@Double()
external double y;
factory Coordinate.allocate(double x, double y) => malloc<Coordinate>().ref
..x = x
..y = y;
}
class NativeEdgeDetectionResult extends Struct {
external Pointer<Coordinate> topLeft;
external Pointer<Coordinate> topRight;
external Pointer<Coordinate> bottomLeft;
external Pointer<Coordinate> bottomRight;
factory NativeEdgeDetectionResult.allocate(
Pointer<Coordinate> topLeft,
Pointer<Coordinate> topRight,
Pointer<Coordinate> bottomLeft,
Pointer<Coordinate> bottomRight,
) =>
malloc<NativeEdgeDetectionResult>().ref
..topLeft = topLeft
..topRight = topRight
..bottomLeft = bottomLeft
..bottomRight = bottomRight;
}
class EdgeDetectionResult {
final Offset topLeft;
final Offset topRight;
final Offset bottomLeft;
final Offset bottomRight;
EdgeDetectionResult({
required this.topLeft,
required this.topRight,
required this.bottomLeft,
required this.bottomRight,
});
}