processing_camera_image_i.dart
5.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import 'dart:ffi';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'package:ffi/ffi.dart' as ffi;
import 'package:image/image.dart' as imglib;
import 'const.dart';
import 'processing_camera_image.dart';
class IProcessingCameraImage implements ProcessingCameraImage {
static IProcessingCameraImage? _instance;
late final ConvertImageRGBFlutter _convertImageRGB;
late final ConvertImageGrayFlutter _convertImageGrayFlutter;
late final ConvertImageGray8BitFlutter _convertImageGray8BitFlutter;
factory IProcessingCameraImage() {
_instance ??= IProcessingCameraImage._();
return _instance!;
}
IProcessingCameraImage._() {
final DynamicLibrary convertImageLib = Platform.isAndroid
? DynamicLibrary.open("libconvertImage.so")
: DynamicLibrary.process();
_convertImageRGB = convertImageLib
.lookup<NativeFunction<ConvertImageRGBC>>('convert_image_rgb')
.asFunction<ConvertImageRGBFlutter>();
_convertImageGrayFlutter = convertImageLib
.lookup<NativeFunction<ConvertImageGrayC>>('convert_image_gray_scale')
.asFunction<ConvertImageGrayFlutter>();
_convertImageGray8BitFlutter = convertImageLib
.lookup<NativeFunction<ConvertImageGray8BitC>>(
'convert_image_gray_scale_8bit')
.asFunction<ConvertImageGray8BitFlutter>();
}
/// [ProcessCameraImageToRGB].
@override
imglib.Image? processCameraImageToRGB({
int? width,
int? height,
Uint8List? plane0,
Uint8List? plane1,
Uint8List? plane2,
double? rotationAngle,
int? bytesPerRowPlane0,
int? bytesPerRowPlane1,
int? bytesPerPixelPlan1,
}) {
if (width == null ||
height == null ||
plane0?.isEmpty == null ||
plane1?.isEmpty == null ||
plane2?.isEmpty == null ||
bytesPerRowPlane0 == null ||
bytesPerRowPlane1 == null ||
bytesPerPixelPlan1 == null) {
return null;
}
rotationAngle ??= 0;
double rad =
(rotationAngle * 3.14159265358979323846264338327950288 / 180.0);
double sinVal = sin(rad).abs();
double cosVal = cos(rad).abs();
int newImgWidth = (sinVal * height + cosVal * bytesPerRowPlane0).toInt();
int newImgHeight = (sinVal * bytesPerRowPlane0 + cosVal * height).toInt();
// Allocate memory for the 3 planes of the image
Pointer<Uint8> p = ffi.malloc.allocate(plane0?.length ?? 0);
Pointer<Uint8> p1 = ffi.malloc.allocate(plane1?.length ?? 0);
Pointer<Uint8> p2 = ffi.malloc.allocate(plane2?.length ?? 0);
// Assign the planes data to the pointers of the image
Uint8List pointerList = p.asTypedList(plane0?.length ?? 0);
Uint8List pointerList1 = p1.asTypedList(plane1?.length ?? 0);
Uint8List pointerList2 = p2.asTypedList(plane2?.length ?? 0);
pointerList.setRange(0, plane0?.length ?? 0, plane0 ?? Uint8List(0));
pointerList1.setRange(0, plane1?.length ?? 0, plane1 ?? Uint8List(0));
pointerList2.setRange(0, plane2?.length ?? 0, plane2 ?? Uint8List(0));
// Call the convertImage function and convert the YUV to RGB
Pointer<Uint32> imgP = _convertImageRGB(p, p1, p2, bytesPerRowPlane1,
bytesPerPixelPlan1, bytesPerRowPlane0, height, rotationAngle);
// Get the pointer of the data returned from the function to a List
List<int> imgData = imgP.asTypedList(((newImgWidth) * (newImgHeight)));
// Generate image from the converted data
imglib.Image img =
imglib.Image.fromBytes(newImgWidth, newImgHeight, imgData);
// Free the memory space allocated
// from the planes and the converted data
ffi.malloc.free(p);
ffi.malloc.free(p1);
ffi.malloc.free(p2);
ffi.malloc.free(imgP);
return img;
}
/// [processCameraImageToGray].
@override
imglib.Image? processCameraImageToGray({
int? width,
int? height,
Uint8List? plane0,
double? rotationAngle,
}) {
if (width == null || height == null || plane0?.isEmpty == null) {
return null;
}
rotationAngle ??= 0;
double rad =
(rotationAngle * 3.14159265358979323846264338327950288 / 180.0);
double sinVal = sin(rad).abs();
double cosVal = cos(rad).abs();
int newImgWidth = (sinVal * height + cosVal * width).toInt();
int newImgHeight = (sinVal * width + cosVal * height).toInt();
Pointer<Uint8> p = ffi.malloc.allocate(plane0?.length ?? 0);
Uint8List pointerList = p.asTypedList(plane0?.length ?? 0);
pointerList.setRange(0, plane0?.length ?? 0, plane0 ?? Uint8List(0));
Pointer<Uint32> imgP =
_convertImageGrayFlutter(p, width, height, rotationAngle);
List<int> imgData = imgP.asTypedList(newImgWidth * newImgHeight);
imglib.Image img =
imglib.Image.fromBytes(newImgWidth, newImgHeight, imgData);
ffi.malloc.free(p);
ffi.malloc.free(imgP);
return img;
}
/// [processCameraImageToGray8Bit].
@override
Uint8List? processCameraImageToGray8Bit({
int? width,
int? height,
Uint8List? plane0,
double? rotationAngle,
}) {
if (width == null || height == null || plane0?.isEmpty == null) {
return null;
}
rotationAngle ??= 0;
double rad =
(rotationAngle * 3.14159265358979323846264338327950288 / 180.0);
double sinVal = sin(rad).abs();
double cosVal = cos(rad).abs();
int newImgWidth = (sinVal * height + cosVal * width).toInt();
int newImgHeight = (sinVal * width + cosVal * height).toInt();
Pointer<Uint8> p = ffi.malloc.allocate(plane0?.length ?? 0);
Uint8List pointerList = p.asTypedList(plane0?.length ?? 0);
pointerList.setRange(0, plane0?.length ?? 0, plane0 ?? Uint8List(0));
Pointer<Uint8> imgP =
_convertImageGray8BitFlutter(p, width, height, rotationAngle);
Uint8List imgData = imgP.asTypedList(newImgHeight * newImgWidth);
ffi.malloc.free(p);
ffi.malloc.free(imgP);
return imgData;
}
}