Skip to content

Commit 95547f4

Browse files
authored
Merge pull request #46 from rainyl/mat-ptr
New API: Mat::ptr -> Mat.ptrAt
2 parents eeb9686 + 2ce4a25 commit 95547f4

File tree

7 files changed

+872
-5
lines changed

7 files changed

+872
-5
lines changed

lib/src/core/base.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ typedef NativeFinalizerFunctionT<T extends ffi.NativeType>
100100
ffi.NativeFinalizer OcvFinalizer<T extends ffi.NativeType>(NativeFinalizerFunctionT<T> func) =>
101101
ffi.NativeFinalizer(func.cast<ffi.NativeFinalizerFunction>());
102102

103+
typedef U8 = ffi.UnsignedChar;
104+
typedef I8 = ffi.Char;
105+
typedef U16 = ffi.UnsignedShort;
106+
typedef I16 = ffi.Short;
107+
// typedef U32 = ffi.UnsignedInt;
108+
typedef I32 = ffi.Int;
109+
typedef F32 = ffi.Float;
110+
typedef F64 = ffi.Double;
111+
103112
enum ImageFormat {
104113
// Windows bitmaps - *.bmp, *.dib (always supported)
105114
bmp(ext: ".bmp"),

lib/src/core/mat.dart

Lines changed: 149 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ class Mat extends CvStruct<cvg.Mat> {
545545
}
546546

547547
/// equivalent to Mat::at\<T\>(i0, i1, i2) = val;
548-
/// where T might be basic value types like uchar, char, int.
548+
/// where T might be int, double.
549549
/// or cv::Vec<> like cv::Vec3b
550550
///
551551
/// example
@@ -568,6 +568,154 @@ class Mat extends CvStruct<cvg.Mat> {
568568
// https://github.com/dart-lang/sdk/issues/43390#issuecomment-690993957
569569
bool isSubtype<S, T>() => <S>[] is List<T>;
570570

571+
/// equivalent to Mat::ptr\<T\>(i0, i1, i2)
572+
///
573+
/// **DANGEROUS**
574+
///
575+
/// returns a pointer to operate Mat directly and effectively, use with caution!
576+
///
577+
/// Example:
578+
/// ```dart
579+
/// final mat = cv.Mat.ones(3, 3, cv.MatType.CV_8UC1);
580+
/// mat.set<int>(0, 0, 99);
581+
///
582+
/// final ptr = mat.ptrAt<cv.U8>(0, 0);
583+
/// print(ptr[0]); // 99
584+
///
585+
/// ptr[0] = 21;
586+
/// // Mat::ptr(i, j)
587+
/// print(mat.at<int>(0, 0)); // 21
588+
/// print(ptr[0]); // 21
589+
///
590+
/// final ptr1 = mat.ptrAt<cv.U8>(0);
591+
/// print(ptr1[0]); // 21
592+
/// print(List.generate(mat.cols, (i)=>ptr1[i]); // [21, 1, 1]
593+
/// ```
594+
///
595+
/// https://docs.opencv.org/4.x/d3/d63/classcv_1_1Mat.html#a8b2912f6a6f5d55a3c9a7aae9134d862
596+
ffi.Pointer<T> ptrAt<T extends ffi.NativeType>(int i0, [int? i1, int? i2]) {
597+
if (T == ffi.UnsignedChar) return ptrU8(i0, i1, i2) as ffi.Pointer<T>;
598+
if (T == ffi.Char) return ptrI8(i0, i1, i2) as ffi.Pointer<T>;
599+
if (T == ffi.UnsignedShort) return ptrU16(i0, i1, i2) as ffi.Pointer<T>;
600+
if (T == ffi.Short) return ptrI16(i0, i1, i2) as ffi.Pointer<T>;
601+
if (T == ffi.Int) return ptrI32(i0, i1, i2) as ffi.Pointer<T>;
602+
if (T == ffi.Float) return ptrF32(i0, i1, i2) as ffi.Pointer<T>;
603+
if (T == ffi.Double) return ptrF64(i0, i1, i2) as ffi.Pointer<T>;
604+
throw UnsupportedError("ptr<$T>() is not supported!");
605+
}
606+
607+
ffi.Pointer<ffi.UnsignedChar> ptrU8(int i0, [int? i1, int? i2]) {
608+
final p = calloc<ffi.Pointer<ffi.UnsignedChar>>();
609+
if (i1 == null && i2 == null) {
610+
cvRun(() => CFFI.Mat_Ptr_u8_1(ref, i0, p));
611+
} else if (i1 != null && i2 == null) {
612+
cvRun(() => CFFI.Mat_Ptr_u8_2(ref, i0, i1, p));
613+
} else if (i1 != null && i2 != null) {
614+
cvRun(() => CFFI.Mat_Ptr_u8_3(ref, i0, i1, i2, p));
615+
} else {
616+
throw UnsupportedError("ptrU8($i0, $i1, $i2) is not supported!");
617+
}
618+
final ret = p.value.cast<ffi.UnsignedChar>();
619+
calloc.free(p);
620+
return ret;
621+
}
622+
623+
ffi.Pointer<ffi.Char> ptrI8(int i0, [int? i1, int? i2]) {
624+
final p = calloc<ffi.Pointer<ffi.Char>>();
625+
if (i1 == null && i2 == null) {
626+
cvRun(() => CFFI.Mat_Ptr_i8_1(ref, i0, p));
627+
} else if (i1 != null && i2 == null) {
628+
cvRun(() => CFFI.Mat_Ptr_i8_2(ref, i0, i1, p));
629+
} else if (i1 != null && i2 != null) {
630+
cvRun(() => CFFI.Mat_Ptr_i8_3(ref, i0, i1, i2, p));
631+
} else {
632+
throw UnsupportedError("ptrI8($i0, $i1, $i2) is not supported!");
633+
}
634+
final ret = p.value.cast<ffi.Char>();
635+
calloc.free(p);
636+
return ret;
637+
}
638+
639+
ffi.Pointer<ffi.UnsignedShort> ptrU16(int i0, [int? i1, int? i2]) {
640+
final p = calloc<ffi.Pointer<ffi.UnsignedShort>>();
641+
if (i1 == null && i2 == null) {
642+
cvRun(() => CFFI.Mat_Ptr_u16_1(ref, i0, p));
643+
} else if (i1 != null && i2 == null) {
644+
cvRun(() => CFFI.Mat_Ptr_u16_2(ref, i0, i1, p));
645+
} else if (i1 != null && i2 != null) {
646+
cvRun(() => CFFI.Mat_Ptr_u16_3(ref, i0, i1, i2, p));
647+
} else {
648+
throw UnsupportedError("ptrU16($i0, $i1, $i2) is not supported!");
649+
}
650+
final ret = p.value.cast<ffi.UnsignedShort>();
651+
calloc.free(p);
652+
return ret;
653+
}
654+
655+
ffi.Pointer<ffi.Short> ptrI16(int i0, [int? i1, int? i2]) {
656+
final p = calloc<ffi.Pointer<ffi.Short>>();
657+
if (i1 == null && i2 == null) {
658+
cvRun(() => CFFI.Mat_Ptr_i16_1(ref, i0, p));
659+
} else if (i1 != null && i2 == null) {
660+
cvRun(() => CFFI.Mat_Ptr_i16_2(ref, i0, i1, p));
661+
} else if (i1 != null && i2 != null) {
662+
cvRun(() => CFFI.Mat_Ptr_i16_3(ref, i0, i1, i2, p));
663+
} else {
664+
throw UnsupportedError("ptrI16($i0, $i1, $i2) is not supported!");
665+
}
666+
final ret = p.value.cast<ffi.Short>();
667+
calloc.free(p);
668+
return ret;
669+
}
670+
671+
ffi.Pointer<ffi.Int> ptrI32(int i0, [int? i1, int? i2]) {
672+
final p = calloc<ffi.Pointer<ffi.Int>>();
673+
if (i1 == null && i2 == null) {
674+
cvRun(() => CFFI.Mat_Ptr_i32_1(ref, i0, p));
675+
} else if (i1 != null && i2 == null) {
676+
cvRun(() => CFFI.Mat_Ptr_i32_2(ref, i0, i1, p));
677+
} else if (i1 != null && i2 != null) {
678+
cvRun(() => CFFI.Mat_Ptr_i32_3(ref, i0, i1, i2, p));
679+
} else {
680+
throw UnsupportedError("ptrI32($i0, $i1, $i2) is not supported!");
681+
}
682+
final ret = p.value.cast<ffi.Int>();
683+
calloc.free(p);
684+
return ret;
685+
}
686+
687+
ffi.Pointer<ffi.Float> ptrF32(int i0, [int? i1, int? i2]) {
688+
final p = calloc<ffi.Pointer<ffi.Float>>();
689+
if (i1 == null && i2 == null) {
690+
cvRun(() => CFFI.Mat_Ptr_f32_1(ref, i0, p));
691+
} else if (i1 != null && i2 == null) {
692+
cvRun(() => CFFI.Mat_Ptr_f32_2(ref, i0, i1, p));
693+
} else if (i1 != null && i2 != null) {
694+
cvRun(() => CFFI.Mat_Ptr_f32_3(ref, i0, i1, i2, p));
695+
} else {
696+
throw UnsupportedError("ptrF32($i0, $i1, $i2) is not supported!");
697+
}
698+
final ret = p.value.cast<ffi.Float>();
699+
calloc.free(p);
700+
return ret;
701+
}
702+
703+
ffi.Pointer<ffi.Double> ptrF64(int i0, [int? i1, int? i2]) {
704+
final p = calloc<ffi.Pointer<ffi.Double>>();
705+
if (i1 == null && i2 == null) {
706+
cvRun(() => CFFI.Mat_Ptr_f64_1(ref, i0, p));
707+
} else if (i1 != null && i2 == null) {
708+
cvRun(() => CFFI.Mat_Ptr_f64_2(ref, i0, i1, p));
709+
} else if (i1 != null && i2 != null) {
710+
cvRun(() => CFFI.Mat_Ptr_f64_3(ref, i0, i1, i2, p));
711+
} else {
712+
throw UnsupportedError("ptrF64($i0, $i1, $i2) is not supported!");
713+
}
714+
final ret = p.value.cast<ffi.Double>();
715+
calloc.free(p);
716+
return ret;
717+
}
718+
571719
// TODO: for now, dart do not support operator overloading
572720
// https://github.com/dart-lang/language/issues/2456
573721
// waiting for it's implementation and add more methods

0 commit comments

Comments
 (0)