thuanpm

fix function for IOS

@@ -5,25 +5,55 @@ uint32_t *convertImage(uint8_t *plane0, uint8_t *plane1, uint8_t *plane2, int by @@ -5,25 +5,55 @@ uint32_t *convertImage(uint8_t *plane0, uint8_t *plane1, uint8_t *plane2, int by
5 import 'dart:ffi'; 5 import 'dart:ffi';
6 6
7 /* 7 /*
8 - native convert camera image to rgb 8 + native convert camera image YUV420p to rgb
9 */ 9 */
10 -typedef ConvertImageRGBC = Pointer<Uint32> Function(Pointer<Uint8>,  
11 - Pointer<Uint8>, Pointer<Uint8>, Int32, Int32, Int32, Int32, Double);  
12 -typedef ConvertImageRGBFlutter = Pointer<Uint32> Function(  
13 - Pointer<Uint8>, Pointer<Uint8>, Pointer<Uint8>, int, int, int, int, double); 10 +typedef ConvertImageYuv420pToRGBC = Pointer<Uint32> Function(
  11 + Pointer<Uint8>,
  12 + Pointer<Uint8>,
  13 + Pointer<Uint8>,
  14 + Int32,
  15 + Int32,
  16 + Int32,
  17 + Int32,
  18 + Double,
  19 + Uint32,
  20 + Bool,
  21 + Bool,
  22 +);
  23 +typedef ConvertImageYuv420pToRGBFlutter = Pointer<Uint32> Function(
  24 + Pointer<Uint8>,
  25 + Pointer<Uint8>,
  26 + Pointer<Uint8>,
  27 + int,
  28 + int,
  29 + int,
  30 + int,
  31 + double,
  32 + int,
  33 + bool,
  34 + bool,
  35 +);
14 36
15 /* 37 /*
16 - native convert camera image to grayscale 32 bit 38 + native convert camera image YUV420p to grayscale 32 bit
17 */ 39 */
18 -typedef ConvertImageGrayC = Pointer<Uint32> Function(  
19 - Pointer<Uint8>, Int32, Int32, Double);  
20 -typedef ConvertImageGrayFlutter = Pointer<Uint32> Function(  
21 - Pointer<Uint8>, int, int, double); 40 +typedef ConvertImageYuv420pToGrayC = Pointer<Uint32> Function(
  41 + Pointer<Uint8>, Int32, Int32, Double, Uint32, Bool, Bool);
  42 +typedef ConvertImageYuv420pToGrayFlutter = Pointer<Uint32> Function(
  43 + Pointer<Uint8>, int, int, double, int, bool, bool);
22 44
23 /* 45 /*
24 - native convert camera image to grayscale 8 bit 46 + native convert camera image YUV420p to grayscale 8 bit
25 */ 47 */
26 -typedef ConvertImageGray8BitC = Pointer<Uint8> Function(  
27 - Pointer<Uint8>, Int32, Int32, Double);  
28 -typedef ConvertImageGray8BitFlutter = Pointer<Uint8> Function(  
29 - Pointer<Uint8>, int, int, double); 48 +typedef ConvertImageYuv420pToGray8BitC = Pointer<Uint8> Function(
  49 + Pointer<Uint8>, Int32, Int32, Double, Uint8, Bool, Bool);
  50 +typedef ConvertImageYuv420pToGray8BitFlutter = Pointer<Uint8> Function(
  51 + Pointer<Uint8>, int, int, double, int, bool, bool);
  52 +
  53 +/*
  54 + native convert camera image YUV420sp( or NV12) to rgb
  55 +*/
  56 +typedef ConvertImageNV12ToRGBC = Pointer<Uint32> Function(Pointer<Uint8>,
  57 + Pointer<Uint8>, Int32, Int32, Int32, Int32, Double, Uint32, Bool, Bool);
  58 +typedef ConvertImageNV12ToRGBFlutter = Pointer<Uint32> Function(Pointer<Uint8>,
  59 + Pointer<Uint8>, int, int, int, int, double, int, bool, bool);
@@ -17,6 +17,9 @@ abstract class ProcessingCameraImage { @@ -17,6 +17,9 @@ abstract class ProcessingCameraImage {
17 int? bytesPerRowPlane0, 17 int? bytesPerRowPlane0,
18 int? bytesPerRowPlane1, 18 int? bytesPerRowPlane1,
19 int? bytesPerPixelPlan1, 19 int? bytesPerPixelPlan1,
  20 + int backGroundColor = 0xFFFFFFFF,
  21 + bool isFlipHoriozntal = false,
  22 + bool isFlipVectical = false,
20 }); 23 });
21 24
22 /// [processCameraImageToGray]. for Android with YUV420. 25 /// [processCameraImageToGray]. for Android with YUV420.
@@ -25,22 +28,35 @@ abstract class ProcessingCameraImage { @@ -25,22 +28,35 @@ abstract class ProcessingCameraImage {
25 int? height, 28 int? height,
26 Uint8List? plane0, 29 Uint8List? plane0,
27 double? rotationAngle, 30 double? rotationAngle,
  31 + int backGroundColor = 0xFFFFFFFF,
  32 + bool isFlipHoriozntal = false,
  33 + bool isFlipVectical = false,
28 }); 34 });
29 35
30 - /// [processCameraImageToRGBIOS]. for IOS with YUV420. 36 + /// [processCameraImageToRGBIOS]. for IOS with NV12.
31 imglib.Image? processCameraImageToRGBIOS({ 37 imglib.Image? processCameraImageToRGBIOS({
32 int? width, 38 int? width,
33 int? height, 39 int? height,
34 Uint8List? plane0, 40 Uint8List? plane0,
  41 + Uint8List? plane1,
35 double? rotationAngle, 42 double? rotationAngle,
  43 + int? bytesPerRowPlane0,
  44 + int? bytesPerRowPlane1,
  45 + int? bytesPerPixelPlan1,
  46 + int backGroundColor = 0xFFFFFFFF,
  47 + bool isFlipHoriozntal = false,
  48 + bool isFlipVectical = false,
36 }); 49 });
37 50
38 - /// [processCameraImageToGrayIOS]. for IOS with YUV420. 51 + /// [processCameraImageToGrayIOS]. for IOS with NV12.
39 imglib.Image? processCameraImageToGrayIOS({ 52 imglib.Image? processCameraImageToGrayIOS({
40 int? width, 53 int? width,
41 int? height, 54 int? height,
42 Uint8List? plane0, 55 Uint8List? plane0,
43 double? rotationAngle, 56 double? rotationAngle,
  57 + int backGroundColor = 0xFFFFFFFF,
  58 + bool isFlipHoriozntal = false,
  59 + bool isFlipVectical = false,
44 }); 60 });
45 61
46 /// [processCameraImageToGray8Bit]. for Android with YUV420. 62 /// [processCameraImageToGray8Bit]. for Android with YUV420.
@@ -49,5 +65,8 @@ abstract class ProcessingCameraImage { @@ -49,5 +65,8 @@ abstract class ProcessingCameraImage {
49 int? height, 65 int? height,
50 Uint8List? plane0, 66 Uint8List? plane0,
51 double? rotationAngle, 67 double? rotationAngle,
  68 + int backGroundColor = 0xFF,
  69 + bool isFlipHoriozntal = false,
  70 + bool isFlipVectical = false,
52 }); 71 });
53 } 72 }
@@ -11,9 +11,11 @@ import 'processing_camera_image.dart'; @@ -11,9 +11,11 @@ import 'processing_camera_image.dart';
11 11
12 class IProcessingCameraImage implements ProcessingCameraImage { 12 class IProcessingCameraImage implements ProcessingCameraImage {
13 static IProcessingCameraImage? _instance; 13 static IProcessingCameraImage? _instance;
14 - late final ConvertImageRGBFlutter _convertImageRGB;  
15 - late final ConvertImageGrayFlutter _convertImageGrayFlutter;  
16 - late final ConvertImageGray8BitFlutter _convertImageGray8BitFlutter; 14 + late final ConvertImageYuv420pToRGBFlutter _convertImageYuv420pToRGB;
  15 + late final ConvertImageYuv420pToGrayFlutter _convertImageYuv420pToGray;
  16 + late final ConvertImageYuv420pToGray8BitFlutter
  17 + _convertImageYuv420pToGray8Bit;
  18 + late final ConvertImageNV12ToRGBFlutter _convertImageNV12ToRGB;
17 19
18 factory IProcessingCameraImage() { 20 factory IProcessingCameraImage() {
19 _instance ??= IProcessingCameraImage._(); 21 _instance ??= IProcessingCameraImage._();
@@ -24,18 +26,24 @@ class IProcessingCameraImage implements ProcessingCameraImage { @@ -24,18 +26,24 @@ class IProcessingCameraImage implements ProcessingCameraImage {
24 final DynamicLibrary convertImageLib = Platform.isAndroid 26 final DynamicLibrary convertImageLib = Platform.isAndroid
25 ? DynamicLibrary.open("libconvertImage.so") 27 ? DynamicLibrary.open("libconvertImage.so")
26 : DynamicLibrary.process(); 28 : DynamicLibrary.process();
27 - _convertImageRGB = convertImageLib  
28 - .lookup<NativeFunction<ConvertImageRGBC>>('convert_image_rgb')  
29 - .asFunction<ConvertImageRGBFlutter>();  
30 -  
31 - _convertImageGrayFlutter = convertImageLib  
32 - .lookup<NativeFunction<ConvertImageGrayC>>('convert_image_gray_scale')  
33 - .asFunction<ConvertImageGrayFlutter>();  
34 -  
35 - _convertImageGray8BitFlutter = convertImageLib  
36 - .lookup<NativeFunction<ConvertImageGray8BitC>>(  
37 - 'convert_image_gray_scale_8bit')  
38 - .asFunction<ConvertImageGray8BitFlutter>(); 29 + _convertImageYuv420pToRGB = convertImageLib
  30 + .lookup<NativeFunction<ConvertImageYuv420pToRGBC>>(
  31 + 'convert_image_yuv420p_to_rgb')
  32 + .asFunction<ConvertImageYuv420pToRGBFlutter>();
  33 +
  34 + _convertImageYuv420pToGray = convertImageLib
  35 + .lookup<NativeFunction<ConvertImageYuv420pToGrayC>>(
  36 + 'convert_image_yuv420p_to_gray')
  37 + .asFunction<ConvertImageYuv420pToGrayFlutter>();
  38 +
  39 + _convertImageYuv420pToGray8Bit = convertImageLib
  40 + .lookup<NativeFunction<ConvertImageYuv420pToGray8BitC>>(
  41 + 'convert_image_yuv420p_to_gray_8bit')
  42 + .asFunction<ConvertImageYuv420pToGray8BitFlutter>();
  43 + _convertImageNV12ToRGB = convertImageLib
  44 + .lookup<NativeFunction<ConvertImageNV12ToRGBC>>(
  45 + 'convert_image_nv12_to_rgb')
  46 + .asFunction<ConvertImageNV12ToRGBFlutter>();
39 } 47 }
40 48
41 /// [ProcessCameraImageToRGB]. 49 /// [ProcessCameraImageToRGB].
@@ -50,12 +58,18 @@ class IProcessingCameraImage implements ProcessingCameraImage { @@ -50,12 +58,18 @@ class IProcessingCameraImage implements ProcessingCameraImage {
50 int? bytesPerRowPlane0, 58 int? bytesPerRowPlane0,
51 int? bytesPerRowPlane1, 59 int? bytesPerRowPlane1,
52 int? bytesPerPixelPlan1, 60 int? bytesPerPixelPlan1,
  61 + int backGroundColor = 0xFFFFFFFF,
  62 + bool isFlipHoriozntal = false,
  63 + bool isFlipVectical = false,
53 }) { 64 }) {
54 if (width == null || 65 if (width == null ||
55 height == null || 66 height == null ||
56 - plane0?.isEmpty == null ||  
57 - plane1?.isEmpty == null ||  
58 - plane2?.isEmpty == null || 67 + plane0 == null ||
  68 + plane1 == null ||
  69 + plane2 == null ||
  70 + plane0.isEmpty ||
  71 + plane1.isEmpty ||
  72 + plane2.isEmpty ||
59 bytesPerRowPlane0 == null || 73 bytesPerRowPlane0 == null ||
60 bytesPerRowPlane1 == null || 74 bytesPerRowPlane1 == null ||
61 bytesPerPixelPlan1 == null) { 75 bytesPerPixelPlan1 == null) {
@@ -70,21 +84,32 @@ class IProcessingCameraImage implements ProcessingCameraImage { @@ -70,21 +84,32 @@ class IProcessingCameraImage implements ProcessingCameraImage {
70 int newImgHeight = (sinVal * bytesPerRowPlane0 + cosVal * height).toInt(); 84 int newImgHeight = (sinVal * bytesPerRowPlane0 + cosVal * height).toInt();
71 85
72 // Allocate memory for the 3 planes of the image 86 // Allocate memory for the 3 planes of the image
73 - Pointer<Uint8> p = ffi.malloc.allocate(plane0?.length ?? 0);  
74 - Pointer<Uint8> p1 = ffi.malloc.allocate(plane1?.length ?? 0);  
75 - Pointer<Uint8> p2 = ffi.malloc.allocate(plane2?.length ?? 0); 87 + Pointer<Uint8> p = ffi.malloc.allocate(plane0.length);
  88 + Pointer<Uint8> p1 = ffi.malloc.allocate(plane1.length);
  89 + Pointer<Uint8> p2 = ffi.malloc.allocate(plane2.length);
76 90
77 // Assign the planes data to the pointers of the image 91 // Assign the planes data to the pointers of the image
78 - Uint8List pointerList = p.asTypedList(plane0?.length ?? 0);  
79 - Uint8List pointerList1 = p1.asTypedList(plane1?.length ?? 0);  
80 - Uint8List pointerList2 = p2.asTypedList(plane2?.length ?? 0);  
81 - pointerList.setRange(0, plane0?.length ?? 0, plane0 ?? Uint8List(0));  
82 - pointerList1.setRange(0, plane1?.length ?? 0, plane1 ?? Uint8List(0));  
83 - pointerList2.setRange(0, plane2?.length ?? 0, plane2 ?? Uint8List(0)); 92 + Uint8List pointerList = p.asTypedList(plane0.length);
  93 + Uint8List pointerList1 = p1.asTypedList(plane1.length);
  94 + Uint8List pointerList2 = p2.asTypedList(plane2.length);
  95 + pointerList.setRange(0, plane0.length, plane0);
  96 + pointerList1.setRange(0, plane1.length, plane1);
  97 + pointerList2.setRange(0, plane2.length, plane2);
84 98
85 // Call the convertImage function and convert the YUV to RGB 99 // Call the convertImage function and convert the YUV to RGB
86 - Pointer<Uint32> imgP = _convertImageRGB(p, p1, p2, bytesPerRowPlane1,  
87 - bytesPerPixelPlan1, bytesPerRowPlane0, height, rotationAngle); 100 + Pointer<Uint32> imgP = _convertImageYuv420pToRGB(
  101 + p,
  102 + p1,
  103 + p2,
  104 + bytesPerRowPlane1,
  105 + bytesPerPixelPlan1,
  106 + bytesPerRowPlane0,
  107 + height,
  108 + rotationAngle,
  109 + backGroundColor,
  110 + isFlipVectical,
  111 + isFlipHoriozntal,
  112 + );
88 113
89 // Get the pointer of the data returned from the function to a List 114 // Get the pointer of the data returned from the function to a List
90 List<int> imgData = imgP.asTypedList(((newImgWidth) * (newImgHeight))); 115 List<int> imgData = imgP.asTypedList(((newImgWidth) * (newImgHeight)));
@@ -109,6 +134,9 @@ class IProcessingCameraImage implements ProcessingCameraImage { @@ -109,6 +134,9 @@ class IProcessingCameraImage implements ProcessingCameraImage {
109 int? height, 134 int? height,
110 Uint8List? plane0, 135 Uint8List? plane0,
111 double? rotationAngle, 136 double? rotationAngle,
  137 + int backGroundColor = 0xFFFFFFFF,
  138 + bool isFlipHoriozntal = false,
  139 + bool isFlipVectical = false,
112 }) { 140 }) {
113 if (width == null || height == null || plane0?.isEmpty == null) { 141 if (width == null || height == null || plane0?.isEmpty == null) {
114 return null; 142 return null;
@@ -126,8 +154,15 @@ class IProcessingCameraImage implements ProcessingCameraImage { @@ -126,8 +154,15 @@ class IProcessingCameraImage implements ProcessingCameraImage {
126 Uint8List pointerList = p.asTypedList(plane0?.length ?? 0); 154 Uint8List pointerList = p.asTypedList(plane0?.length ?? 0);
127 pointerList.setRange(0, plane0?.length ?? 0, plane0 ?? Uint8List(0)); 155 pointerList.setRange(0, plane0?.length ?? 0, plane0 ?? Uint8List(0));
128 156
129 - Pointer<Uint32> imgP =  
130 - _convertImageGrayFlutter(p, width, height, rotationAngle); 157 + Pointer<Uint32> imgP = _convertImageYuv420pToGray(
  158 + p,
  159 + width,
  160 + height,
  161 + rotationAngle,
  162 + backGroundColor,
  163 + isFlipVectical,
  164 + isFlipHoriozntal,
  165 + );
131 166
132 List<int> imgData = imgP.asTypedList(newImgWidth * newImgHeight); 167 List<int> imgData = imgP.asTypedList(newImgWidth * newImgHeight);
133 imglib.Image img = 168 imglib.Image img =
@@ -146,6 +181,9 @@ class IProcessingCameraImage implements ProcessingCameraImage { @@ -146,6 +181,9 @@ class IProcessingCameraImage implements ProcessingCameraImage {
146 int? height, 181 int? height,
147 Uint8List? plane0, 182 Uint8List? plane0,
148 double? rotationAngle, 183 double? rotationAngle,
  184 + int backGroundColor = 0xFF,
  185 + bool isFlipHoriozntal = false,
  186 + bool isFlipVectical = false,
149 }) { 187 }) {
150 if (width == null || height == null || plane0?.isEmpty == null) { 188 if (width == null || height == null || plane0?.isEmpty == null) {
151 return null; 189 return null;
@@ -164,8 +202,15 @@ class IProcessingCameraImage implements ProcessingCameraImage { @@ -164,8 +202,15 @@ class IProcessingCameraImage implements ProcessingCameraImage {
164 Uint8List pointerList = p.asTypedList(plane0?.length ?? 0); 202 Uint8List pointerList = p.asTypedList(plane0?.length ?? 0);
165 pointerList.setRange(0, plane0?.length ?? 0, plane0 ?? Uint8List(0)); 203 pointerList.setRange(0, plane0?.length ?? 0, plane0 ?? Uint8List(0));
166 204
167 - Pointer<Uint8> imgP =  
168 - _convertImageGray8BitFlutter(p, width, height, rotationAngle); 205 + Pointer<Uint8> imgP = _convertImageYuv420pToGray8Bit(
  206 + p,
  207 + width,
  208 + height,
  209 + rotationAngle,
  210 + backGroundColor,
  211 + isFlipVectical,
  212 + isFlipHoriozntal,
  213 + );
169 214
170 Uint8List imgData = imgP.asTypedList(newImgHeight * newImgWidth); 215 Uint8List imgData = imgP.asTypedList(newImgHeight * newImgWidth);
171 216
@@ -181,17 +226,72 @@ class IProcessingCameraImage implements ProcessingCameraImage { @@ -181,17 +226,72 @@ class IProcessingCameraImage implements ProcessingCameraImage {
181 int? width, 226 int? width,
182 int? height, 227 int? height,
183 Uint8List? plane0, 228 Uint8List? plane0,
  229 + Uint8List? plane1,
184 double? rotationAngle, 230 double? rotationAngle,
  231 + int? bytesPerRowPlane0,
  232 + int? bytesPerRowPlane1,
  233 + int? bytesPerPixelPlan1,
  234 + int backGroundColor = 0xFFFFFFFF,
  235 + bool isFlipHoriozntal = false,
  236 + bool isFlipVectical = false,
185 }) { 237 }) {
186 - if (width == null || height == null || plane0 == null || plane0.isEmpty) { 238 + if (width == null ||
  239 + height == null ||
  240 + plane0 == null ||
  241 + plane1 == null ||
  242 + plane0.isEmpty ||
  243 + plane1.isEmpty ||
  244 + bytesPerRowPlane0 == null ||
  245 + bytesPerRowPlane1 == null ||
  246 + bytesPerPixelPlan1 == null) {
187 return null; 247 return null;
188 } 248 }
189 - if (rotationAngle != null) {  
190 - imglib.copyRotate(  
191 - imglib.Image.fromBytes(width, height, List<int>.from(plane0)),  
192 - rotationAngle);  
193 - }  
194 - return imglib.Image.fromBytes(width, height, List<int>.from(plane0)); 249 + rotationAngle ??= 0;
  250 + double rad =
  251 + (rotationAngle * 3.14159265358979323846264338327950288 / 180.0);
  252 + double sinVal = sin(rad).abs();
  253 + double cosVal = cos(rad).abs();
  254 + int newImgWidth = (sinVal * height + cosVal * bytesPerRowPlane0).toInt();
  255 + int newImgHeight = (sinVal * bytesPerRowPlane0 + cosVal * height).toInt();
  256 +
  257 + // Allocate memory for the 3 planes of the image
  258 + Pointer<Uint8> p = ffi.malloc.allocate(plane0.length);
  259 + Pointer<Uint8> p1 = ffi.malloc.allocate(plane1.length);
  260 +
  261 + // Assign the planes data to the pointers of the image
  262 + Uint8List pointerList = p.asTypedList(plane0.length);
  263 + Uint8List pointerList1 = p1.asTypedList(plane1.length);
  264 + pointerList.setRange(0, plane0.length, plane0);
  265 + pointerList1.setRange(0, plane1.length, plane1);
  266 +
  267 + // Call the convertImage function and convert the YUV to RGB
  268 + Pointer<Uint32> imgP = _convertImageNV12ToRGB(
  269 + p,
  270 + p1,
  271 + bytesPerRowPlane1,
  272 + bytesPerPixelPlan1,
  273 + bytesPerRowPlane0,
  274 + height,
  275 + rotationAngle,
  276 + backGroundColor,
  277 + isFlipVectical,
  278 + isFlipHoriozntal,
  279 + );
  280 +
  281 + // Get the pointer of the data returned from the function to a List
  282 + final imgData = imgP.asTypedList(((newImgWidth) * (newImgHeight)));
  283 +
  284 + // // Generate image from the converted data
  285 + imglib.Image img =
  286 + imglib.Image.fromBytes(newImgWidth, newImgHeight, imgData);
  287 +
  288 + // Free the memory space allocated
  289 + // from the planes and the converted data
  290 + ffi.malloc.free(p);
  291 + ffi.malloc.free(p1);
  292 + ffi.malloc.free(imgP);
  293 +
  294 + return img;
195 } 295 }
196 296
197 /// [processCameraImageToGrayIOS]. for IOS with YUV420. 297 /// [processCameraImageToGrayIOS]. for IOS with YUV420.
@@ -201,12 +301,18 @@ class IProcessingCameraImage implements ProcessingCameraImage { @@ -201,12 +301,18 @@ class IProcessingCameraImage implements ProcessingCameraImage {
201 int? height, 301 int? height,
202 Uint8List? plane0, 302 Uint8List? plane0,
203 double? rotationAngle, 303 double? rotationAngle,
  304 + int backGroundColor = 0xFFFFFFFF,
  305 + bool isFlipHoriozntal = false,
  306 + bool isFlipVectical = false,
204 }) { 307 }) {
205 return processCameraImageToGray( 308 return processCameraImageToGray(
206 height: height, 309 height: height,
207 width: width, 310 width: width,
208 plane0: plane0, 311 plane0: plane0,
209 rotationAngle: rotationAngle, 312 rotationAngle: rotationAngle,
  313 + backGroundColor: backGroundColor,
  314 + isFlipHoriozntal: isFlipHoriozntal,
  315 + isFlipVectical: isFlipVectical,
210 ); 316 );
211 } 317 }
212 } 318 }