Skip to content

Commit 03ee7e6

Browse files
committed
add cvRunAsync, cvtColorAsync, gaussianBlurAsync
1 parent 85a2290 commit 03ee7e6

22 files changed

+1153
-870
lines changed

example/lib/main.dart

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,18 @@ class _MyAppState extends State<MyApp> {
4040
gray = cv.cvtColor(im, cv.COLOR_BGR2GRAY);
4141
blur = cv.gaussianBlur(im, (7, 7), 2, sigmaY: 2);
4242
}
43-
return (
44-
cv.imencode(cv.ImageFormat.png.ext, gray),
45-
cv.imencode(cv.ImageFormat.png.ext, blur)
46-
);
43+
return (cv.imencode(".png", gray), cv.imencode(".png", blur));
4744
});
4845

46+
Future<(cv.Mat, cv.Mat)> heavyTaskAsync(cv.Mat im) async {
47+
late cv.Mat gray, blur;
48+
for (var i = 0; i < 1000; i++) {
49+
gray = await cv.cvtColorAsync(im, cv.COLOR_BGR2GRAY);
50+
blur = await cv.gaussianBlurAsync(im, (7, 7), 2, sigmaY: 2);
51+
}
52+
return (gray, blur);
53+
}
54+
4955
@override
5056
Widget build(BuildContext context) {
5157
return MaterialApp(
@@ -80,9 +86,13 @@ class _MyAppState extends State<MyApp> {
8086
final data = await DefaultAssetBundle.of(context).load("images/lenna.png");
8187
final bytes = data.buffer.asUint8List();
8288
// heavy computation
83-
final (gray, blur) = await heavyTask(bytes);
89+
// final (gray, blur) = await heavyTask(bytes);
90+
// setState(() {
91+
// images = [bytes, gray, blur];
92+
// });
93+
final (gray, blur) = await heavyTaskAsync(cv.imdecode(bytes, cv.IMREAD_COLOR));
8494
setState(() {
85-
images = [bytes, gray, blur];
95+
images = [bytes, cv.imencode(".png", gray), cv.imencode(".png", blur)];
8696
});
8797
},
8898
child: const Text("Process"),

ffigen.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ headers:
1818
- src/core/core.h
1919
- src/core/exception.h
2020
- src/core/svd.h
21+
- src/core/types.h
2122
- src/core/vec.h
2223
- src/core/version.h
2324
- src/dnn/asyncarray.h
@@ -30,6 +31,7 @@ headers:
3031
- src/highgui/highgui.h
3132
- src/imgcodecs/imgcodecs.h
3233
- src/imgproc/imgproc.h
34+
- src/imgproc/imgproc_async.h
3335
- src/objdetect/objdetect.h
3436
- src/photo/photo.h
3537
- src/stitching/stitching.h
@@ -52,6 +54,7 @@ headers:
5254
- src/highgui/highgui.h
5355
- src/imgcodecs/imgcodecs.h
5456
- src/imgproc/imgproc.h
57+
- src/imgproc/imgproc_async.h
5558
- src/objdetect/objdetect.h
5659
- src/photo/photo.h
5760
- src/stitching/stitching.h

lib/src/core/base.dart

Lines changed: 37 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33

44
library cv;
55

6+
import 'dart:async';
67
import 'dart:ffi' as ffi;
78
import 'dart:ffi';
89
import 'dart:io';
910

1011
import 'package:equatable/equatable.dart';
1112
import 'package:ffi/ffi.dart';
1213

13-
import "../opencv.g.dart" show CvStatus, CvNative;
14+
import "../opencv.g.dart" as cvg;
1415
import "exception.dart" show CvException;
1516

1617
const _libraryName = "opencv_dart";
@@ -35,6 +36,7 @@ const int CV_I32_MIN = -2147483648;
3536
const double CV_F32_MAX = 3.4028234663852886e+38;
3637
const double CV_F64_MAX = 1.7976931348623157e+308;
3738

39+
// load native library
3840
ffi.DynamicLibrary loadNativeLibrary() {
3941
if (Platform.isIOS) return ffi.DynamicLibrary.process();
4042
final defaultLibPath = switch (Platform.operatingSystem) {
@@ -47,8 +49,9 @@ ffi.DynamicLibrary loadNativeLibrary() {
4749
return ffi.DynamicLibrary.open(libPath);
4850
}
4951

50-
final CFFI = CvNative(loadNativeLibrary());
52+
final CFFI = cvg.CvNative(loadNativeLibrary());
5153

54+
// base structures
5255
abstract class CvObject<T extends ffi.NativeType> implements ffi.Finalizable {}
5356

5457
abstract class ICvStruct<T extends ffi.Struct> extends CvObject<T> {
@@ -62,8 +65,8 @@ abstract class CvStruct<T extends ffi.Struct> extends ICvStruct<T> with Equatabl
6265
CvStruct.fromPointer(super.ptr) : super.fromPointer();
6366
}
6467

65-
void cvRun(ffi.Pointer<CvStatus> Function() func) {
66-
final s = func();
68+
// error handler
69+
void throwIfFailed(ffi.Pointer<cvg.CvStatus> s) {
6770
final code = s.ref.code;
6871
// String err = s.ref.err.cast<Utf8>().toDartString();
6972
final msg = s.ref.msg.cast<Utf8>().toDartString();
@@ -76,8 +79,33 @@ void cvRun(ffi.Pointer<CvStatus> Function() func) {
7679
}
7780
}
7881

79-
R cvRunArena<R>(R Function(Arena arena) computation,
80-
[Allocator wrappedAllocator = calloc, bool keep = false]) {
82+
// sync runner
83+
void cvRun(ffi.Pointer<cvg.CvStatus> Function() func) => throwIfFailed(func());
84+
85+
// async runner
86+
typedef VoidPtr = ffi.Pointer<ffi.Void>;
87+
Future<T> cvRunAsync<T>(
88+
ffi.Pointer<cvg.CvStatus> Function(cvg.CvCallback_1 callback) func,
89+
void Function(Completer<T> completer, VoidPtr p) onComplete,
90+
) {
91+
final completer = Completer<T>();
92+
late final NativeCallable<cvg.CvCallback_1Function> ccallback;
93+
void onResponse(VoidPtr p) {
94+
onComplete(completer, p);
95+
ccallback.close();
96+
}
97+
98+
ccallback = ffi.NativeCallable.listener(onResponse);
99+
throwIfFailed(func(ccallback.nativeFunction));
100+
return completer.future;
101+
}
102+
103+
// Arena wrapper
104+
R cvRunArena<R>(
105+
R Function(Arena arena) computation, [
106+
Allocator wrappedAllocator = calloc,
107+
bool keep = false,
108+
]) {
81109
final arena = Arena(wrappedAllocator);
82110
bool isAsync = false;
83111
try {
@@ -94,12 +122,14 @@ R cvRunArena<R>(R Function(Arena arena) computation,
94122
}
95123
}
96124

125+
// finalizers
97126
typedef NativeFinalizerFunctionT<T extends ffi.NativeType>
98127
= ffi.Pointer<ffi.NativeFunction<ffi.Void Function(T token)>>;
99128

100129
ffi.NativeFinalizer OcvFinalizer<T extends ffi.NativeType>(NativeFinalizerFunctionT<T> func) =>
101130
ffi.NativeFinalizer(func.cast<ffi.NativeFinalizerFunction>());
102131

132+
// native types
103133
typedef U8 = ffi.UnsignedChar;
104134
typedef I8 = ffi.Char;
105135
typedef U16 = ffi.UnsignedShort;
@@ -109,43 +139,7 @@ typedef I32 = ffi.Int;
109139
typedef F32 = ffi.Float;
110140
typedef F64 = ffi.Double;
111141

142+
// others
112143
extension PointerCharExtension on ffi.Pointer<ffi.Char> {
113144
String toDartString() => cast<Utf8>().toDartString();
114145
}
115-
116-
enum ImageFormat {
117-
// Windows bitmaps - *.bmp, *.dib (always supported)
118-
bmp(ext: ".bmp"),
119-
dib(ext: ".dib"),
120-
// JPEG files - *.jpeg, *.jpg, *.jpe (see the Note section)
121-
jpg(ext: ".jpg"),
122-
jpeg(ext: ".jpeg"),
123-
jpe(ext: ".jpe"),
124-
// JPEG 2000 files - *.jp2 (see the Note section)
125-
jp2(ext: ".jp2"),
126-
// Portable Network Graphics - *.png (see the Note section)
127-
png(ext: ".png"),
128-
// WebP - *.webp (see the Note section)
129-
webp(ext: ".webp"),
130-
// Portable image format - *.pbm, *.pgm, *.ppm *.pxm, *.pnm (always supported)
131-
pbm(ext: ".pbm"),
132-
pgm(ext: ".pgm"),
133-
ppm(ext: ".ppm"),
134-
pxm(ext: ".pxm"),
135-
pnm(ext: ".pnm"),
136-
// Sun rasters - *.sr, *.ras (always supported)
137-
sr(ext: ".sr"),
138-
ras(ext: ".ras"),
139-
// TIFF files - *.tiff, *.tif (see the Note section)
140-
tiff(ext: ".tiff"),
141-
tif(ext: ".tif"),
142-
// OpenEXR Image files - *.exr (see the Note section)
143-
exr(ext: ".exr"),
144-
// Radiance HDR - *.hdr, *.pic (always supported)
145-
hdr(ext: ".hdr"),
146-
pic(ext: ".pic");
147-
// Raster and Vector geospatial data supported by GDAL (see the Note section)
148-
149-
const ImageFormat({required this.ext});
150-
final String ext;
151-
}

lib/src/core/mat.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class Mat extends CvStruct<cvg.Mat> {
6565

6666
factory Mat.empty() {
6767
final p = calloc<cvg.Mat>();
68-
cvRun(() => CFFI.Mat_New(p, ffi.nullptr));
68+
cvRun(() => CFFI.Mat_New(p));
6969
final mat = Mat._(p);
7070
return mat;
7171
}

lib/src/gapi/gcomputation.dart

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,18 @@ class GComputation extends CvStruct<cvg.GComputation> {
4444
return GComputation.fromPointer(p);
4545
}
4646

47-
Future<Mat> apply(Mat inMat) async {
48-
final completer = Completer<Mat>();
49-
late final NativeCallable<cvg.MatCallbackFunction> callback;
50-
void onResponse(cvg.MatPtr p) {
51-
completer.complete(Mat.fromPointer(p));
52-
callback.close();
53-
}
54-
55-
callback = ffi.NativeCallable.listener(onResponse);
56-
cvRun(() => CFFI.gapi_GComputation_apply(ref, inMat.ref, callback.nativeFunction));
57-
return completer.future;
58-
}
47+
// Future<Mat> apply(Mat inMat) async {
48+
// final completer = Completer<Mat>();
49+
// late final NativeCallable<cvg.MatCallbackFunction> callback;
50+
// void onResponse(cvg.MatPtr p) {
51+
// completer.complete(Mat.fromPointer(p));
52+
// callback.close();
53+
// }
54+
55+
// callback = ffi.NativeCallable.listener(onResponse);
56+
// cvRun(() => CFFI.gapi_GComputation_apply(ref, inMat.ref, callback.nativeFunction));
57+
// return completer.future;
58+
// }
5959

6060
// Mat applyMIMO(Mat inMat) => apply(inMat);
6161

lib/src/imgproc/imgproc.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
library cv;
44

5+
import 'dart:async';
56
import 'dart:ffi' as ffi;
7+
import 'dart:ffi';
68

79
import 'package:ffi/ffi.dart';
810

@@ -75,6 +77,11 @@ Mat cvtColor(Mat src, int code, {Mat? dst}) {
7577
return dst;
7678
}
7779

80+
Future<Mat> cvtColorAsync(Mat src, int code, {Mat? dst}) async => cvRunAsync<Mat>(
81+
(callback) => CFFI.CvtColor_Async(src.ref, code, callback),
82+
(completer, p) => completer.complete(Mat.fromPointer(p.cast())),
83+
);
84+
7885
/// EqualizeHist Equalizes the histogram of a grayscale image.
7986
///
8087
/// For further details, please see:
@@ -571,6 +578,22 @@ Mat gaussianBlur(
571578
return dst;
572579
}
573580

581+
Future<Mat> gaussianBlurAsync(
582+
Mat src,
583+
Size ksize,
584+
double sigmaX, {
585+
Mat? dst,
586+
double sigmaY = 0,
587+
int borderType = BORDER_DEFAULT,
588+
}) async =>
589+
using<Future<Mat>>(
590+
(arena) => cvRunAsync(
591+
(callback) =>
592+
CFFI.GaussianBlur_Async(src.ref, ksize.toSize(arena).ref, sigmaX, sigmaY, borderType, callback),
593+
(completer, p) => completer.complete(Mat.fromPointer(p.cast())),
594+
),
595+
);
596+
574597
/// GetGaussianKernel returns Gaussian filter coefficients.
575598
///
576599
/// For further details, please see:

0 commit comments

Comments
 (0)