dynamsoft-capture-vision-react-native 3.4.1300 → 3.4.3010

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/LICENSE +4 -4
  2. package/README.md +62 -62
  3. package/android/README.md +14 -14
  4. package/android/build.gradle +167 -163
  5. package/android/gradle.properties +20 -20
  6. package/android/settings.gradle +5 -5
  7. package/android/src/main/AndroidManifest.xml +6 -6
  8. package/android/src/main/AndroidManifest_noPackage.xml +5 -5
  9. package/android/src/main/cpp/CMakeLists.txt +21 -21
  10. package/android/src/main/cpp/ImgHO.cpp +94 -94
  11. package/android/src/main/cpp/ImgHO.h +34 -34
  12. package/android/src/main/cpp/JsiCore.cpp +296 -296
  13. package/android/src/main/cpp/JsiCore.h +51 -51
  14. package/android/src/main/cpp/JsiCvr.cpp +332 -332
  15. package/android/src/main/cpp/JsiCvr.h +54 -54
  16. package/android/src/main/cpp/JsiDbr.cpp +283 -283
  17. package/android/src/main/cpp/JsiDbr.h +26 -26
  18. package/android/src/main/cpp/JsiDce.cpp +59 -59
  19. package/android/src/main/cpp/JsiDce.h +17 -17
  20. package/android/src/main/cpp/JsiDcp.cpp +51 -51
  21. package/android/src/main/cpp/JsiDcp.h +31 -31
  22. package/android/src/main/cpp/JsiDdn.cpp +50 -50
  23. package/android/src/main/cpp/JsiDdn.h +28 -28
  24. package/android/src/main/cpp/JsiDlr.cpp +60 -60
  25. package/android/src/main/cpp/JsiDlr.h +26 -26
  26. package/android/src/main/cpp/JsiUtility.cpp +604 -604
  27. package/android/src/main/cpp/JsiUtility.h +26 -26
  28. package/android/src/main/cpp/RawBuffer.cpp +23 -23
  29. package/android/src/main/cpp/RawBuffer.h +24 -24
  30. package/android/src/main/cpp/android_log.h +14 -14
  31. package/android/src/main/dysJniLibsFor86/debug/arm64-v8a/librn_dys.so +0 -0
  32. package/android/src/main/dysJniLibsFor86/debug/armeabi-v7a/librn_dys.so +0 -0
  33. package/android/src/main/dysJniLibsFor86/debug/x86/librn_dys.so +0 -0
  34. package/android/src/main/dysJniLibsFor86/debug/x86_64/librn_dys.so +0 -0
  35. package/android/src/main/dysJniLibsFor86/release/arm64-v8a/librn_dys.so +0 -0
  36. package/android/src/main/dysJniLibsFor86/release/armeabi-v7a/librn_dys.so +0 -0
  37. package/android/src/main/dysJniLibsFor86/release/x86/librn_dys.so +0 -0
  38. package/android/src/main/dysJniLibsFor86/release/x86_64/librn_dys.so +0 -0
  39. package/android/src/main/java/com/dynamsoft/reactnativelib/CVRModule.kt +137 -137
  40. package/android/src/main/java/com/dynamsoft/reactnativelib/CameraViewManager.kt +62 -62
  41. package/android/src/main/java/com/dynamsoft/reactnativelib/DCEModule.kt +125 -125
  42. package/android/src/main/java/com/dynamsoft/reactnativelib/DynamsoftBaseModule.kt +8 -8
  43. package/android/src/main/java/com/dynamsoft/reactnativelib/ISAModule.kt +73 -73
  44. package/android/src/main/java/com/dynamsoft/reactnativelib/ImageEditorViewManager.kt +14 -14
  45. package/android/src/main/java/com/dynamsoft/reactnativelib/ImageEditorViewModule.kt +35 -35
  46. package/android/src/main/java/com/dynamsoft/reactnativelib/ImageManagerModule.kt +15 -15
  47. package/android/src/main/java/com/dynamsoft/reactnativelib/LicenseModule.kt +29 -29
  48. package/android/src/main/java/com/dynamsoft/reactnativelib/MultiCrossFilterModule.kt +83 -83
  49. package/android/src/main/java/com/dynamsoft/reactnativelib/ReactNativeDcvPackage.kt +32 -32
  50. package/android/src/main/java/com/dynamsoft/reactnativelib/VersionsModule.kt +41 -41
  51. package/android/src/main/java/com/dynamsoft/reactnativelib/basicutils/Basic.kt +44 -44
  52. package/android/src/main/java/com/dynamsoft/reactnativelib/basicutils/ForCore.kt +50 -50
  53. package/android/src/main/java/com/dynamsoft/reactnativelib/basicutils/ForCvr.kt +129 -129
  54. package/android/src/main/java/com/dynamsoft/reactnativelib/basicutils/ForDBR.kt +157 -157
  55. package/android/src/main/java/com/dynamsoft/reactnativelib/basicutils/ForDCE.kt +110 -110
  56. package/android/src/main/java/com/dynamsoft/reactnativelib/basicutils/ForDCP.kt +49 -49
  57. package/android/src/main/java/com/dynamsoft/reactnativelib/basicutils/ForDDN.kt +85 -85
  58. package/android/src/main/java/com/dynamsoft/reactnativelib/basicutils/ForDLR.kt +72 -72
  59. package/android/src/main/java/com/dynamsoft/reactnativelib/basicutils/ImageUtil.kt +58 -58
  60. package/android/src/main/java/com/dynamsoft/reactnativelib/core/ImageSourceAdapterModuleImpl.kt +120 -120
  61. package/android/src/main/java/com/dynamsoft/reactnativelib/cvr/CaptureVisionRouterModuleImpl.kt +306 -306
  62. package/android/src/main/java/com/dynamsoft/reactnativelib/dce/CameraEnhancerModuleImpl.kt +247 -247
  63. package/android/src/main/java/com/dynamsoft/reactnativelib/dce/CameraLifeCycleOwner.java +14 -14
  64. package/android/src/main/java/com/dynamsoft/reactnativelib/dce/CameraViewManagerImpl.kt +77 -77
  65. package/android/src/main/java/com/dynamsoft/reactnativelib/dce/ImageEditorViewManagerImpl.kt +15 -15
  66. package/android/src/main/java/com/dynamsoft/reactnativelib/dce/ImageEditorViewModuleImpl.kt +110 -110
  67. package/android/src/main/java/com/dynamsoft/reactnativelib/dce/RNCameraView.kt +20 -20
  68. package/android/src/main/java/com/dynamsoft/reactnativelib/dce/RNImageEditorView.kt +19 -19
  69. package/android/src/main/java/com/dynamsoft/reactnativelib/license/LicenseModuleImpl.kt +39 -39
  70. package/android/src/main/java/com/dynamsoft/reactnativelib/utility/ImageManagerModuleImpl.kt +120 -120
  71. package/android/src/main/java/com/dynamsoft/reactnativelib/utility/MultiCrossFilterModuleImpl.kt +111 -111
  72. package/app.plugin.js +21 -21
  73. package/dynamsoft-capture-vision-react-native.podspec +24 -24
  74. package/ios/CPP/DSImageData+HostObject.h +18 -18
  75. package/ios/CPP/DSImageData+HostObject.mm +38 -38
  76. package/ios/CPP/ImageDataHostObject.cpp +87 -87
  77. package/ios/CPP/ImageDataHostObject.hpp +35 -35
  78. package/ios/CPP/MutableRawBuffer.cpp +23 -23
  79. package/ios/CPP/MutableRawBuffer.hpp +23 -23
  80. package/ios/CPP/RNDynamsoft+JSI.h +22 -22
  81. package/ios/CPP/RNDynamsoft+JSI.mm +303 -303
  82. package/ios/CPP/RNDynamsoft+Json.h +93 -93
  83. package/ios/CPP/RNDynamsoft+Json.m +733 -733
  84. package/ios/CPP/YeetJSIUtils.h +56 -56
  85. package/ios/CPP/YeetJSIUtils.mm +208 -208
  86. package/ios/RNDynamsoftCameraView.h +31 -31
  87. package/ios/RNDynamsoftCameraView.m +108 -108
  88. package/ios/RNDynamsoftCameraViewManager.h +14 -14
  89. package/ios/RNDynamsoftCameraViewManager.m +195 -195
  90. package/ios/RNDynamsoftCaptureVisionRouter.h +18 -18
  91. package/ios/RNDynamsoftCaptureVisionRouter.mm +532 -532
  92. package/ios/RNDynamsoftImageEditorView.h +17 -17
  93. package/ios/RNDynamsoftImageEditorView.m +25 -25
  94. package/ios/RNDynamsoftImageEditorViewManager.h +14 -14
  95. package/ios/RNDynamsoftImageEditorViewManager.mm +183 -183
  96. package/ios/RNDynamsoftImageManager.h +14 -14
  97. package/ios/RNDynamsoftImageManager.mm +369 -369
  98. package/ios/RNDynamsoftImageSourceAdapter.h +19 -19
  99. package/ios/RNDynamsoftImageSourceAdapter.mm +255 -255
  100. package/ios/RNDynamsoftLicense.h +14 -14
  101. package/ios/RNDynamsoftLicense.m +62 -62
  102. package/ios/RNDynamsoftMultiCrossFilter.h +14 -14
  103. package/ios/RNDynamsoftMultiCrossFilter.m +145 -145
  104. package/ios/RNDynamsoftVersions.h +13 -13
  105. package/ios/RNDynamsoftVersions.m +27 -27
  106. package/package.json +48 -48
  107. package/src/NativeDynamsoftVersionsModule.tsx +20 -20
  108. package/src/VersionsModule.tsx +7 -7
  109. package/src/core/CapturedResultBase.tsx +18 -18
  110. package/src/core/CapturedResultItem.tsx +23 -23
  111. package/src/core/CoreModule.tsx +9 -9
  112. package/src/core/DSRect.tsx +29 -29
  113. package/src/core/EnumCaptureResultItemType.tsx +52 -52
  114. package/src/core/EnumColourChannelUsageType.tsx +26 -26
  115. package/src/core/EnumCrossVerificationStatus.tsx +46 -46
  116. package/src/core/EnumGrayscaleEnhancementMode.tsx +46 -46
  117. package/src/core/EnumGrayscaleTransformationMode.tsx +35 -35
  118. package/src/core/EnumImageFileFormat.tsx +6 -6
  119. package/src/core/EnumPixelFormat.tsx +53 -53
  120. package/src/core/ImageData.tsx +87 -87
  121. package/src/core/ImageSourceAdapter.tsx +160 -160
  122. package/src/core/NativeDynamsoftImageSourceAdapterModule.tsx +29 -29
  123. package/src/core/Point.tsx +13 -13
  124. package/src/core/Quadrilateral.tsx +12 -12
  125. package/src/core/index.tsx +18 -18
  126. package/src/cvr/CaptureVisionRouter.tsx +683 -683
  127. package/src/cvr/CaptureVisionRouterModule.tsx +9 -9
  128. package/src/cvr/CapturedResult.tsx +123 -123
  129. package/src/cvr/CapturedResultFilter.tsx +13 -13
  130. package/src/cvr/CapturedResultReceiver.tsx +71 -71
  131. package/src/cvr/EnumPresetTemplate.tsx +81 -81
  132. package/src/cvr/NativeDynamsoftCaptureVisionRouterModule.tsx +25 -25
  133. package/src/cvr/SimplifiedCaptureVisionSettings.tsx +61 -61
  134. package/src/cvr/index.tsx +11 -11
  135. package/src/dbr/BarcodeDetails.tsx +51 -51
  136. package/src/dbr/BarcodeReaderModule.tsx +9 -9
  137. package/src/dbr/BarcodeResultItem.tsx +65 -65
  138. package/src/dbr/DecodedBarcodesResult.tsx +14 -14
  139. package/src/dbr/ECISegment.tsx +23 -23
  140. package/src/dbr/EnumBarcodeFormat.tsx +112 -112
  141. package/src/dbr/EnumDeblurMode.tsx +29 -29
  142. package/src/dbr/EnumLocalizationMode.tsx +27 -27
  143. package/src/dbr/EnumQRCodeErrorCorrectionLevel.tsx +6 -6
  144. package/src/dbr/SimplifiedBarcodeReaderSettings.tsx +80 -80
  145. package/src/dbr/index.tsx +9 -9
  146. package/src/dce/CameraEnhancer.tsx +254 -254
  147. package/src/dce/CameraEnhancerModule.tsx +9 -9
  148. package/src/dce/CameraView.tsx +100 -100
  149. package/src/dce/DynamsoftCameraViewNativeComponent.ts +96 -96
  150. package/src/dce/DynamsoftImageEditorViewNativeComponent.ts +9 -9
  151. package/src/dce/EnumCameraPosition.tsx +25 -25
  152. package/src/dce/EnumDrawingLayerId.tsx +17 -17
  153. package/src/dce/EnumEnhancedFeatures.tsx +24 -24
  154. package/src/dce/EnumFocusMode.tsx +6 -6
  155. package/src/dce/EnumResolution.tsx +8 -8
  156. package/src/dce/EnumTorchState.tsx +10 -10
  157. package/src/dce/FeedBack.tsx +28 -28
  158. package/src/dce/ImageEditorView.tsx +131 -131
  159. package/src/dce/NativeDynamsoftCameraViewModule.tsx +47 -47
  160. package/src/dce/NativeDynamsoftImageEditorViewModule.ts +9 -9
  161. package/src/dce/index.tsx +13 -13
  162. package/src/dcp/CodeParserDedicatorModule.tsx +9 -9
  163. package/src/dcp/CodeParserModule.tsx +9 -9
  164. package/src/dcp/EnumMappingStatus.tsx +14 -14
  165. package/src/dcp/EnumValidationStatus.tsx +14 -14
  166. package/src/dcp/ParsedResult.tsx +14 -14
  167. package/src/dcp/ParsedResultItem.tsx +50 -50
  168. package/src/dcp/index.tsx +8 -8
  169. package/src/ddn/DeskewedImageResultItem.tsx +40 -40
  170. package/src/ddn/DetectedQuadResultItem.tsx +31 -31
  171. package/src/ddn/DocumentNormalizerModule.tsx +9 -9
  172. package/src/ddn/EnhancedImageResultItem.tsx +20 -20
  173. package/src/ddn/EnumImageColourMode.tsx +14 -14
  174. package/src/ddn/ProcessedDocumentResult.tsx +27 -27
  175. package/src/ddn/SimplifiedDocumentNormalizerSettings.tsx +65 -65
  176. package/src/ddn/index.tsx +11 -11
  177. package/src/dip/ImageProcessingModule.tsx +9 -9
  178. package/src/dip/index.tsx +1 -1
  179. package/src/dlr/CharacterResult.tsx +28 -28
  180. package/src/dlr/LabelRecognizerModule.tsx +9 -9
  181. package/src/dlr/RecognizedTextLinesResult.tsx +19 -19
  182. package/src/dlr/SimplifiedLabelRecognizerSettings.tsx +33 -33
  183. package/src/dlr/TextLineResultItem.tsx +41 -41
  184. package/src/dlr/index.tsx +8 -8
  185. package/src/index.tsx +13 -13
  186. package/src/license/LicenseManager.tsx +49 -49
  187. package/src/license/LicenseModule.tsx +9 -9
  188. package/src/license/NativeDynamsoftLicenseModule.tsx +7 -7
  189. package/src/license/index.tsx +7 -7
  190. package/src/utility/CrossVerificationCriteria.tsx +11 -11
  191. package/src/utility/EnumFilterType.tsx +5 -5
  192. package/src/utility/ImageManager.tsx +348 -348
  193. package/src/utility/MultiFrameResultCrossFilter.tsx +183 -183
  194. package/src/utility/NativeDynamsoftImageManagerModule.tsx +7 -7
  195. package/src/utility/NativeDynamsoftMultiCrossFilterModule.tsx +18 -18
  196. package/src/utility/UtilityModule.tsx +9 -9
  197. package/src/utility/index.tsx +4 -4
  198. package/android/.gitignore +0 -4
@@ -1,369 +1,369 @@
1
- /*
2
- * Copyright © Dynamsoft Corporation. All rights reserved.
3
- */
4
-
5
- #import "RNDynamsoftImageManager.h"
6
- #import <DynamsoftCaptureVisionBundle/DynamsoftCaptureVisionBundle.h>
7
- #import <React/RCTBridge+Private.h>
8
- #import <React/RCTUtils.h>
9
- #import <jsi/jsi.h>
10
- #import <sys/utsname.h>
11
- #import "YeetJSIUtils.h"
12
- #import "DSImageData+HostObject.h"
13
- #import "RNDynamsoft+Json.h"
14
- #import "RNDynamsoft+JSI.h"
15
-
16
- using namespace facebook::jsi;
17
- using namespace facebook;
18
- using namespace std;
19
-
20
- @interface RNDynamsoftImageManager ()
21
-
22
- @property (nonatomic, strong) DSImageIO *manager;
23
- @property (nonatomic, strong) DSImageDrawer *drawer;
24
- @property (nonatomic, strong) DSImageProcessor *processor;
25
-
26
- @end
27
-
28
- @implementation RNDynamsoftImageManager
29
-
30
- - (instancetype)init
31
- {
32
- self = [super init];
33
- if (self) {
34
- _manager = [[DSImageIO alloc] init];
35
- _drawer = [[DSImageDrawer alloc] init];
36
- _processor = [[DSImageProcessor alloc] init];
37
- }
38
- return self;
39
- }
40
-
41
- RCT_EXPORT_MODULE(DynamsoftImageManagerModule)
42
-
43
- #pragma mark - Global JSI
44
- // --- RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install) ---
45
- RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install)
46
- {
47
- RCTBridge *bridge = self.bridge;
48
-
49
- if ([bridge respondsToSelector:NSSelectorFromString(@"parentBridge")]) {
50
- bridge = [bridge valueForKey:@"parentBridge"];
51
- }
52
-
53
- RCTCxxBridge *cxxBridge = (RCTCxxBridge *)bridge;
54
- if (cxxBridge == nil || cxxBridge.runtime == nil) {
55
- return @false;
56
- }
57
-
58
- auto jsiRuntime = (jsi::Runtime*) cxxBridge.runtime;
59
- if (jsiRuntime == nil) {
60
- return @false;
61
- }
62
-
63
- install(*(facebook::jsi::Runtime *)cxxBridge.runtime, self);
64
- return @true;
65
- }
66
-
67
- // --- Helper Functions and Lambdas ---
68
- static void installHostFunction(
69
- jsi::Runtime &jsiRuntime,
70
- const char* name,
71
- unsigned int argCount,
72
- HostFunctionType hostFunction) {
73
-
74
- auto func = Function::createFromHostFunction(
75
- jsiRuntime,
76
- PropNameID::forAscii(jsiRuntime, name),
77
- argCount,
78
- std::move(hostFunction)
79
- );
80
- jsiRuntime.global().setProperty(jsiRuntime, name, std::move(func));
81
- }
82
-
83
- // --- JSI Installation Logic ---
84
- static void install(jsi::Runtime &jsiRuntime, RNDynamsoftImageManager *rnManager) {
85
- using namespace jsi;
86
-
87
- // 1. Helper Lambda: Extract ImageDataHostObject from JSI Value
88
- auto getHostImageData = [&](Runtime &runtime, const Value &value) -> std::optional<ImageDataHostObject> {
89
- // Optimization: isObject() check does not require runtime
90
- if (!value.isObject()) return std::nullopt;
91
- auto obj = value.getObject(runtime);
92
- // isHostObject<> requires runtime
93
- if (!obj.isHostObject<ImageDataHostObject>(runtime)) return std::nullopt;
94
- return ImageDataHostObject::getHOFromObject(runtime, obj);
95
- };
96
-
97
- // 2. Helper Lambda: Create JSI Host Object from DSImageData and return
98
- auto createJsiHostObject = [&](Runtime &runtime, DSImageData *imageData) -> Value {
99
- if (!imageData) return Value::null();
100
- auto host = [imageData hostObject];
101
- return Object::createFromHostObject(runtime, std::make_shared<ImageDataHostObject>(host));
102
- };
103
-
104
- // imageIO_readFromFile(path)
105
- installHostFunction(jsiRuntime, "imageIO_readFromFile", 1,
106
- [rnManager, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
107
- // Check count and type (isString() does not need runtime)
108
- if (count < 1 || !args[0].isString()) return Value::null();
109
-
110
- NSString *path = convertJSIStringToNSString(runtime, args[0].getString(runtime));
111
- NSError *error = nil;
112
- DSImageData *imageData = [rnManager.manager readFromFile:path error:&error];
113
-
114
- return createJsiHostObject(runtime, imageData);
115
- }
116
- );
117
-
118
- // imageIO_saveToFile(imageData, path, overwrite)
119
- installHostFunction(jsiRuntime, "imageIO_saveToFile", 3,
120
- [rnManager, getHostImageData](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
121
- // Check count, data object (isObject() does not need runtime) and path (isString() does not need runtime)
122
- if (count < 3 || !args[1].isString() || !args[2].isBool()) return Value(false);
123
-
124
- auto hostOpt = getHostImageData(runtime, args[0]);
125
- if (!hostOpt) return Value(false);
126
-
127
- DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
128
- NSString *path = convertJSIStringToNSString(runtime, args[1].getString(runtime));
129
- bool overwrite = args[2].getBool();
130
-
131
- NSError *error = nil;
132
- BOOL success = [rnManager.manager saveToFile:data path:path overWrite:overwrite error:&error];
133
- return Value(success && !error);
134
- }
135
- );
136
-
137
- // imageIO_readFromMemory(arrayBuffer)
138
- installHostFunction(jsiRuntime, "imageIO_readFromMemory", 1,
139
- [rnManager, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
140
- // Check count and type (isObject() does not need runtime)
141
- if (count < 1 || !args[0].isObject()) return Value::null();
142
-
143
- jsi::Object jsObj = args[0].getObject(runtime);
144
- // isArrayBuffer() requires runtime
145
- if (!jsObj.isArrayBuffer(runtime)) return Value::null();
146
-
147
- jsi::ArrayBuffer buffer = jsObj.getArrayBuffer(runtime);
148
- NSData *data = convertArrayBufferToNSData(runtime, buffer);
149
- if (!data || data.length == 0) return Value::null();
150
-
151
- NSError *error = nil;
152
- DSImageData *imageData = [rnManager.manager readFromMemory:data error:&error];
153
-
154
- return createJsiHostObject(runtime, imageData);
155
- }
156
- );
157
-
158
- // imageIO_saveToMemory(imageData, format)
159
- installHostFunction(jsiRuntime, "imageIO_saveToMemory", 2,
160
- [rnManager, getHostImageData](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
161
- // Check count and format type (isNumber() does not need runtime)
162
- if (count < 2 || !args[1].isNumber()) return Value::null();
163
-
164
- auto hostOpt = getHostImageData(runtime, args[0]);
165
- if (!hostOpt) return Value::null();
166
-
167
- DSImageData *imageData = [DSImageData imageDataFromHostObject:*hostOpt];
168
- NSInteger format = args[1].asNumber(); // Enum is passed as number
169
- NSError *error = nil;
170
-
171
- NSData *data = [rnManager.manager saveToMemory:imageData imageFormat:(DSImageFileFormat)format error:&error];
172
- if (!data || error) return Value::null();
173
-
174
- // Note: converNSDataToArrayBuffer is assumed to be defined elsewhere and is correct
175
- return Value(converNSDataToArrayBuffer(runtime, data));
176
- }
177
- );
178
-
179
- // Helper lambda for simple image processing functions (2 arguments: data, value)
180
- auto processImageTwoArg =
181
- [rnManager, getHostImageData, createJsiHostObject](
182
- Runtime &runtime,
183
- const Value *args,
184
- size_t count,
185
- std::function<DSImageData*(DSImageData*, NSInteger)> processorBlock
186
- ) -> Value {
187
- if (count < 2 || !args[1].isNumber()) return Value::null();
188
- auto hostOpt = getHostImageData(runtime, args[0]);
189
- if (!hostOpt) return Value::null();
190
-
191
- NSInteger arg2 = args[1].asNumber();
192
- DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
193
- DSImageData *outData = processorBlock(data, arg2);
194
-
195
- return createJsiHostObject(runtime, outData);
196
- };
197
-
198
- // imageProcessor_adjustBrightness(imageData, brightness)
199
- installHostFunction(jsiRuntime, "imageProcessor_adjustBrightness", 2,
200
- [rnManager, processImageTwoArg](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
201
- return processImageTwoArg(runtime, args, count,
202
- [rnManager](DSImageData* data, NSInteger brightness) {
203
- return [rnManager.processor adjust:data brightness:brightness];
204
- }
205
- );
206
- }
207
- );
208
-
209
- // imageProcessor_adjustContrast(imageData, contrast)
210
- installHostFunction(jsiRuntime, "imageProcessor_adjustContrast", 2,
211
- [rnManager, processImageTwoArg](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
212
- return processImageTwoArg(runtime, args, count,
213
- [rnManager](DSImageData* data, NSInteger contrast) {
214
- return [rnManager.processor adjust:data contrast:contrast];
215
- }
216
- );
217
- }
218
- );
219
-
220
- // imageProcessor_filterImage(imageData, filterType)
221
- installHostFunction(jsiRuntime, "imageProcessor_filterImage", 2,
222
- [rnManager, processImageTwoArg](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
223
- return processImageTwoArg(runtime, args, count,
224
- [rnManager](DSImageData* data, NSInteger filterType) {
225
- return [rnManager.processor filterImage:data filterType:(DSFilterType)filterType];
226
- }
227
- );
228
- }
229
- );
230
-
231
- // imageProcessor_cropImage(imageData, rect)
232
- installHostFunction(jsiRuntime, "imageProcessor_cropImage", 2,
233
- [rnManager, getHostImageData, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
234
- // Check count and rect object (isObject() does not need runtime)
235
- if (count < 2 || !args[1].isObject()) return Value::null();
236
- auto hostOpt = getHostImageData(runtime, args[0]);
237
- if (!hostOpt) return Value::null();
238
-
239
- DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
240
- DSRect *rect = convertJSIValueToDSRect(runtime, args[1].getObject(runtime));
241
-
242
- NSError *error = nil;
243
- DSImageData *outData = [rnManager.processor cropImage:data rect:rect error:&error];
244
-
245
- return createJsiHostObject(runtime, outData);
246
- }
247
- );
248
-
249
- // imageProcessor_cropAndDeskewImage(data, quad, dstWidth, dstHeight, padding)
250
- installHostFunction(jsiRuntime, "imageProcessor_cropAndDeskewImage", 5,
251
- [rnManager, getHostImageData, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
252
- // Check count, quad object, and number types (isObject()/isNumber() do not need runtime)
253
- if (count < 5 || !args[1].isObject() || !args[2].isNumber() || !args[3].isNumber() || !args[4].isNumber()) return Value::null();
254
- auto hostOpt = getHostImageData(runtime, args[0]);
255
- if (!hostOpt) return Value::null();
256
-
257
- DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
258
- DSQuadrilateral *quad = convertJSIValueToDSQuadrilateral(runtime, args[1].getObject(runtime));
259
- NSInteger dstWidth = args[2].asNumber();
260
- NSInteger dstHeight = args[3].asNumber();
261
- NSInteger padding = args[4].asNumber();
262
-
263
- NSError *error = nil;
264
- DSImageData *outData = [rnManager.processor cropAndDeskewImage:data quad:quad dstWidth:dstWidth dstHeight:dstHeight padding:padding error:&error];
265
-
266
- return createJsiHostObject(runtime, outData);
267
- }
268
- );
269
-
270
- // imageProcessor_convertToGray(imageData, r, g, b)
271
- installHostFunction(jsiRuntime, "imageProcessor_convertToGray", 4,
272
- [rnManager, getHostImageData, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
273
- // Check count and float types
274
- if (count < 4 || !args[1].isNumber() || !args[2].isNumber() || !args[3].isNumber()) return Value::null();
275
- auto hostOpt = getHostImageData(runtime, args[0]);
276
- if (!hostOpt) return Value::null();
277
-
278
- CGFloat r = args[1].asNumber();
279
- CGFloat g = args[2].asNumber();
280
- CGFloat b = args[3].asNumber();
281
-
282
- DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
283
- DSImageData *outData = [rnManager.processor convertToGray:data r:r g:g b:b];
284
-
285
- return createJsiHostObject(runtime, outData);
286
- }
287
- );
288
-
289
- // imageProcessor_convertToBinaryGlobal(imageData, threshold, invert)
290
- installHostFunction(jsiRuntime, "imageProcessor_convertToBinaryGlobal", 3,
291
- [rnManager, getHostImageData, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
292
- // Check count, number, and bool types
293
- if (count < 3 || !args[1].isNumber() || !args[2].isBool()) return Value::null();
294
- auto hostOpt = getHostImageData(runtime, args[0]);
295
- if (!hostOpt) return Value::null();
296
-
297
- NSInteger threshold = args[1].asNumber();
298
- BOOL invert = args[2].getBool();
299
-
300
- DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
301
- DSImageData *outData = [rnManager.processor convertToBinaryGlobal:data threshold:threshold invert:invert];
302
-
303
- return createJsiHostObject(runtime, outData);
304
- }
305
- );
306
-
307
- // imageProcessor_convertToBinaryLocal(imageData, blockSize, compensation, invert)
308
- installHostFunction(jsiRuntime, "imageProcessor_convertToBinaryLocal", 4,
309
- [rnManager, getHostImageData, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
310
- // Check count, number, number, and bool types
311
- if (count < 4 || !args[1].isNumber() || !args[2].isNumber() || !args[3].isBool()) return Value::null();
312
- auto hostOpt = getHostImageData(runtime, args[0]);
313
- if (!hostOpt) return Value::null();
314
-
315
- NSInteger blockSize = args[1].asNumber();
316
- NSInteger compensation = args[2].asNumber();
317
- BOOL invert = args[3].getBool();
318
-
319
- DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
320
- DSImageData *outData = [rnManager.processor convertToBinaryLocal:data blockSize:blockSize compensation:compensation invert:invert];
321
-
322
- return createJsiHostObject(runtime, outData);
323
- }
324
- );
325
-
326
- // imageDrawer_drawOnImage(data, quads, hexColor, thickness)
327
- installHostFunction(jsiRuntime, "imageDrawer_drawOnImage", 4,
328
- [rnManager, getHostImageData, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
329
- // Check count, quads array object, color number, and thickness number
330
- if (count < 4 || !args[1].isObject() || !args[2].isNumber() || !args[3].isNumber()) return Value::null();
331
- auto hostOpt = getHostImageData(runtime, args[0]);
332
- if (!hostOpt) return Value::null();
333
-
334
- DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
335
-
336
- // Validate and extract array
337
- Object jsArrayObj = args[1].getObject(runtime);
338
- if (!jsArrayObj.isArray(runtime)) return Value::null();
339
- Array jsArray = jsArrayObj.getArray(runtime);
340
- size_t size = jsArray.size(runtime);
341
-
342
- NSMutableArray<DSQuadrilateral *> *quads = [NSMutableArray arrayWithCapacity:size];
343
- for (size_t i = 0; i < size; i++) {
344
- auto val = jsArray.getValueAtIndex(runtime, i);
345
- // Check if element is an object before conversion
346
- if (val.isObject()) {
347
- DSQuadrilateral *quad = convertJSIValueToDSQuadrilateral(runtime, val.getObject(runtime));
348
- [quads addObject:quad];
349
- }
350
- }
351
-
352
- // Extract colour and thickness
353
- NSInteger hex = args[2].asNumber();
354
- int thickness = args[3].asNumber();
355
-
356
- // Original logic for color conversion is correct
357
- UIColor *color = [UIColor colorWithRed:((hex >> 16) & 0xFF) / 255.0
358
- green:((hex >> 8) & 0xFF) / 255.0
359
- blue:(hex & 0xFF) / 255.0
360
- alpha:((hex >> 24) & 0xFF) / 255.0];
361
-
362
- DSImageData *outData = [rnManager.drawer drawOnImage:data quads:[quads copy] colour:color thickness:thickness];
363
-
364
- return createJsiHostObject(runtime, outData);
365
- }
366
- );
367
- }
368
-
369
- @end
1
+ /*
2
+ * Copyright © Dynamsoft Corporation. All rights reserved.
3
+ */
4
+
5
+ #import "RNDynamsoftImageManager.h"
6
+ #import <DynamsoftCaptureVisionBundle/DynamsoftCaptureVisionBundle.h>
7
+ #import <React/RCTBridge+Private.h>
8
+ #import <React/RCTUtils.h>
9
+ #import <jsi/jsi.h>
10
+ #import <sys/utsname.h>
11
+ #import "YeetJSIUtils.h"
12
+ #import "DSImageData+HostObject.h"
13
+ #import "RNDynamsoft+Json.h"
14
+ #import "RNDynamsoft+JSI.h"
15
+
16
+ using namespace facebook::jsi;
17
+ using namespace facebook;
18
+ using namespace std;
19
+
20
+ @interface RNDynamsoftImageManager ()
21
+
22
+ @property (nonatomic, strong) DSImageIO *manager;
23
+ @property (nonatomic, strong) DSImageDrawer *drawer;
24
+ @property (nonatomic, strong) DSImageProcessor *processor;
25
+
26
+ @end
27
+
28
+ @implementation RNDynamsoftImageManager
29
+
30
+ - (instancetype)init
31
+ {
32
+ self = [super init];
33
+ if (self) {
34
+ _manager = [[DSImageIO alloc] init];
35
+ _drawer = [[DSImageDrawer alloc] init];
36
+ _processor = [[DSImageProcessor alloc] init];
37
+ }
38
+ return self;
39
+ }
40
+
41
+ RCT_EXPORT_MODULE(DynamsoftImageManagerModule)
42
+
43
+ #pragma mark - Global JSI
44
+ // --- RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install) ---
45
+ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install)
46
+ {
47
+ RCTBridge *bridge = self.bridge;
48
+
49
+ if ([bridge respondsToSelector:NSSelectorFromString(@"parentBridge")]) {
50
+ bridge = [bridge valueForKey:@"parentBridge"];
51
+ }
52
+
53
+ RCTCxxBridge *cxxBridge = (RCTCxxBridge *)bridge;
54
+ if (cxxBridge == nil || cxxBridge.runtime == nil) {
55
+ return @false;
56
+ }
57
+
58
+ auto jsiRuntime = (jsi::Runtime*) cxxBridge.runtime;
59
+ if (jsiRuntime == nil) {
60
+ return @false;
61
+ }
62
+
63
+ install(*(facebook::jsi::Runtime *)cxxBridge.runtime, self);
64
+ return @true;
65
+ }
66
+
67
+ // --- Helper Functions and Lambdas ---
68
+ static void installHostFunction(
69
+ jsi::Runtime &jsiRuntime,
70
+ const char* name,
71
+ unsigned int argCount,
72
+ HostFunctionType hostFunction) {
73
+
74
+ auto func = Function::createFromHostFunction(
75
+ jsiRuntime,
76
+ PropNameID::forAscii(jsiRuntime, name),
77
+ argCount,
78
+ std::move(hostFunction)
79
+ );
80
+ jsiRuntime.global().setProperty(jsiRuntime, name, std::move(func));
81
+ }
82
+
83
+ // --- JSI Installation Logic ---
84
+ static void install(jsi::Runtime &jsiRuntime, RNDynamsoftImageManager *rnManager) {
85
+ using namespace jsi;
86
+
87
+ // 1. Helper Lambda: Extract ImageDataHostObject from JSI Value
88
+ auto getHostImageData = [&](Runtime &runtime, const Value &value) -> std::optional<ImageDataHostObject> {
89
+ // Optimization: isObject() check does not require runtime
90
+ if (!value.isObject()) return std::nullopt;
91
+ auto obj = value.getObject(runtime);
92
+ // isHostObject<> requires runtime
93
+ if (!obj.isHostObject<ImageDataHostObject>(runtime)) return std::nullopt;
94
+ return ImageDataHostObject::getHOFromObject(runtime, obj);
95
+ };
96
+
97
+ // 2. Helper Lambda: Create JSI Host Object from DSImageData and return
98
+ auto createJsiHostObject = [&](Runtime &runtime, DSImageData *imageData) -> Value {
99
+ if (!imageData) return Value::null();
100
+ auto host = [imageData hostObject];
101
+ return Object::createFromHostObject(runtime, std::make_shared<ImageDataHostObject>(host));
102
+ };
103
+
104
+ // imageIO_readFromFile(path)
105
+ installHostFunction(jsiRuntime, "imageIO_readFromFile", 1,
106
+ [rnManager, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
107
+ // Check count and type (isString() does not need runtime)
108
+ if (count < 1 || !args[0].isString()) return Value::null();
109
+
110
+ NSString *path = convertJSIStringToNSString(runtime, args[0].getString(runtime));
111
+ NSError *error = nil;
112
+ DSImageData *imageData = [rnManager.manager readFromFile:path error:&error];
113
+
114
+ return createJsiHostObject(runtime, imageData);
115
+ }
116
+ );
117
+
118
+ // imageIO_saveToFile(imageData, path, overwrite)
119
+ installHostFunction(jsiRuntime, "imageIO_saveToFile", 3,
120
+ [rnManager, getHostImageData](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
121
+ // Check count, data object (isObject() does not need runtime) and path (isString() does not need runtime)
122
+ if (count < 3 || !args[1].isString() || !args[2].isBool()) return Value(false);
123
+
124
+ auto hostOpt = getHostImageData(runtime, args[0]);
125
+ if (!hostOpt) return Value(false);
126
+
127
+ DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
128
+ NSString *path = convertJSIStringToNSString(runtime, args[1].getString(runtime));
129
+ bool overwrite = args[2].getBool();
130
+
131
+ NSError *error = nil;
132
+ BOOL success = [rnManager.manager saveToFile:data path:path overWrite:overwrite error:&error];
133
+ return Value(success && !error);
134
+ }
135
+ );
136
+
137
+ // imageIO_readFromMemory(arrayBuffer)
138
+ installHostFunction(jsiRuntime, "imageIO_readFromMemory", 1,
139
+ [rnManager, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
140
+ // Check count and type (isObject() does not need runtime)
141
+ if (count < 1 || !args[0].isObject()) return Value::null();
142
+
143
+ jsi::Object jsObj = args[0].getObject(runtime);
144
+ // isArrayBuffer() requires runtime
145
+ if (!jsObj.isArrayBuffer(runtime)) return Value::null();
146
+
147
+ jsi::ArrayBuffer buffer = jsObj.getArrayBuffer(runtime);
148
+ NSData *data = convertArrayBufferToNSData(runtime, buffer);
149
+ if (!data || data.length == 0) return Value::null();
150
+
151
+ NSError *error = nil;
152
+ DSImageData *imageData = [rnManager.manager readFromMemory:data error:&error];
153
+
154
+ return createJsiHostObject(runtime, imageData);
155
+ }
156
+ );
157
+
158
+ // imageIO_saveToMemory(imageData, format)
159
+ installHostFunction(jsiRuntime, "imageIO_saveToMemory", 2,
160
+ [rnManager, getHostImageData](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
161
+ // Check count and format type (isNumber() does not need runtime)
162
+ if (count < 2 || !args[1].isNumber()) return Value::null();
163
+
164
+ auto hostOpt = getHostImageData(runtime, args[0]);
165
+ if (!hostOpt) return Value::null();
166
+
167
+ DSImageData *imageData = [DSImageData imageDataFromHostObject:*hostOpt];
168
+ NSInteger format = args[1].asNumber(); // Enum is passed as number
169
+ NSError *error = nil;
170
+
171
+ NSData *data = [rnManager.manager saveToMemory:imageData imageFormat:(DSImageFileFormat)format error:&error];
172
+ if (!data || error) return Value::null();
173
+
174
+ // Note: converNSDataToArrayBuffer is assumed to be defined elsewhere and is correct
175
+ return Value(converNSDataToArrayBuffer(runtime, data));
176
+ }
177
+ );
178
+
179
+ // Helper lambda for simple image processing functions (2 arguments: data, value)
180
+ auto processImageTwoArg =
181
+ [rnManager, getHostImageData, createJsiHostObject](
182
+ Runtime &runtime,
183
+ const Value *args,
184
+ size_t count,
185
+ std::function<DSImageData*(DSImageData*, NSInteger)> processorBlock
186
+ ) -> Value {
187
+ if (count < 2 || !args[1].isNumber()) return Value::null();
188
+ auto hostOpt = getHostImageData(runtime, args[0]);
189
+ if (!hostOpt) return Value::null();
190
+
191
+ NSInteger arg2 = args[1].asNumber();
192
+ DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
193
+ DSImageData *outData = processorBlock(data, arg2);
194
+
195
+ return createJsiHostObject(runtime, outData);
196
+ };
197
+
198
+ // imageProcessor_adjustBrightness(imageData, brightness)
199
+ installHostFunction(jsiRuntime, "imageProcessor_adjustBrightness", 2,
200
+ [rnManager, processImageTwoArg](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
201
+ return processImageTwoArg(runtime, args, count,
202
+ [rnManager](DSImageData* data, NSInteger brightness) {
203
+ return [rnManager.processor adjust:data brightness:brightness];
204
+ }
205
+ );
206
+ }
207
+ );
208
+
209
+ // imageProcessor_adjustContrast(imageData, contrast)
210
+ installHostFunction(jsiRuntime, "imageProcessor_adjustContrast", 2,
211
+ [rnManager, processImageTwoArg](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
212
+ return processImageTwoArg(runtime, args, count,
213
+ [rnManager](DSImageData* data, NSInteger contrast) {
214
+ return [rnManager.processor adjust:data contrast:contrast];
215
+ }
216
+ );
217
+ }
218
+ );
219
+
220
+ // imageProcessor_filterImage(imageData, filterType)
221
+ installHostFunction(jsiRuntime, "imageProcessor_filterImage", 2,
222
+ [rnManager, processImageTwoArg](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
223
+ return processImageTwoArg(runtime, args, count,
224
+ [rnManager](DSImageData* data, NSInteger filterType) {
225
+ return [rnManager.processor filterImage:data filterType:(DSFilterType)filterType];
226
+ }
227
+ );
228
+ }
229
+ );
230
+
231
+ // imageProcessor_cropImage(imageData, rect)
232
+ installHostFunction(jsiRuntime, "imageProcessor_cropImage", 2,
233
+ [rnManager, getHostImageData, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
234
+ // Check count and rect object (isObject() does not need runtime)
235
+ if (count < 2 || !args[1].isObject()) return Value::null();
236
+ auto hostOpt = getHostImageData(runtime, args[0]);
237
+ if (!hostOpt) return Value::null();
238
+
239
+ DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
240
+ DSRect *rect = convertJSIValueToDSRect(runtime, args[1].getObject(runtime));
241
+
242
+ NSError *error = nil;
243
+ DSImageData *outData = [rnManager.processor cropImage:data rect:rect error:&error];
244
+
245
+ return createJsiHostObject(runtime, outData);
246
+ }
247
+ );
248
+
249
+ // imageProcessor_cropAndDeskewImage(data, quad, dstWidth, dstHeight, padding)
250
+ installHostFunction(jsiRuntime, "imageProcessor_cropAndDeskewImage", 5,
251
+ [rnManager, getHostImageData, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
252
+ // Check count, quad object, and number types (isObject()/isNumber() do not need runtime)
253
+ if (count < 5 || !args[1].isObject() || !args[2].isNumber() || !args[3].isNumber() || !args[4].isNumber()) return Value::null();
254
+ auto hostOpt = getHostImageData(runtime, args[0]);
255
+ if (!hostOpt) return Value::null();
256
+
257
+ DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
258
+ DSQuadrilateral *quad = convertJSIValueToDSQuadrilateral(runtime, args[1].getObject(runtime));
259
+ NSInteger dstWidth = args[2].asNumber();
260
+ NSInteger dstHeight = args[3].asNumber();
261
+ NSInteger padding = args[4].asNumber();
262
+
263
+ NSError *error = nil;
264
+ DSImageData *outData = [rnManager.processor cropAndDeskewImage:data quad:quad dstWidth:dstWidth dstHeight:dstHeight padding:padding error:&error];
265
+
266
+ return createJsiHostObject(runtime, outData);
267
+ }
268
+ );
269
+
270
+ // imageProcessor_convertToGray(imageData, r, g, b)
271
+ installHostFunction(jsiRuntime, "imageProcessor_convertToGray", 4,
272
+ [rnManager, getHostImageData, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
273
+ // Check count and float types
274
+ if (count < 4 || !args[1].isNumber() || !args[2].isNumber() || !args[3].isNumber()) return Value::null();
275
+ auto hostOpt = getHostImageData(runtime, args[0]);
276
+ if (!hostOpt) return Value::null();
277
+
278
+ CGFloat r = args[1].asNumber();
279
+ CGFloat g = args[2].asNumber();
280
+ CGFloat b = args[3].asNumber();
281
+
282
+ DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
283
+ DSImageData *outData = [rnManager.processor convertToGray:data r:r g:g b:b];
284
+
285
+ return createJsiHostObject(runtime, outData);
286
+ }
287
+ );
288
+
289
+ // imageProcessor_convertToBinaryGlobal(imageData, threshold, invert)
290
+ installHostFunction(jsiRuntime, "imageProcessor_convertToBinaryGlobal", 3,
291
+ [rnManager, getHostImageData, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
292
+ // Check count, number, and bool types
293
+ if (count < 3 || !args[1].isNumber() || !args[2].isBool()) return Value::null();
294
+ auto hostOpt = getHostImageData(runtime, args[0]);
295
+ if (!hostOpt) return Value::null();
296
+
297
+ NSInteger threshold = args[1].asNumber();
298
+ BOOL invert = args[2].getBool();
299
+
300
+ DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
301
+ DSImageData *outData = [rnManager.processor convertToBinaryGlobal:data threshold:threshold invert:invert];
302
+
303
+ return createJsiHostObject(runtime, outData);
304
+ }
305
+ );
306
+
307
+ // imageProcessor_convertToBinaryLocal(imageData, blockSize, compensation, invert)
308
+ installHostFunction(jsiRuntime, "imageProcessor_convertToBinaryLocal", 4,
309
+ [rnManager, getHostImageData, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
310
+ // Check count, number, number, and bool types
311
+ if (count < 4 || !args[1].isNumber() || !args[2].isNumber() || !args[3].isBool()) return Value::null();
312
+ auto hostOpt = getHostImageData(runtime, args[0]);
313
+ if (!hostOpt) return Value::null();
314
+
315
+ NSInteger blockSize = args[1].asNumber();
316
+ NSInteger compensation = args[2].asNumber();
317
+ BOOL invert = args[3].getBool();
318
+
319
+ DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
320
+ DSImageData *outData = [rnManager.processor convertToBinaryLocal:data blockSize:blockSize compensation:compensation invert:invert];
321
+
322
+ return createJsiHostObject(runtime, outData);
323
+ }
324
+ );
325
+
326
+ // imageDrawer_drawOnImage(data, quads, hexColor, thickness)
327
+ installHostFunction(jsiRuntime, "imageDrawer_drawOnImage", 4,
328
+ [rnManager, getHostImageData, createJsiHostObject](Runtime &runtime, const Value &, const Value *args, size_t count) -> Value {
329
+ // Check count, quads array object, color number, and thickness number
330
+ if (count < 4 || !args[1].isObject() || !args[2].isNumber() || !args[3].isNumber()) return Value::null();
331
+ auto hostOpt = getHostImageData(runtime, args[0]);
332
+ if (!hostOpt) return Value::null();
333
+
334
+ DSImageData *data = [DSImageData imageDataFromHostObject:*hostOpt];
335
+
336
+ // Validate and extract array
337
+ Object jsArrayObj = args[1].getObject(runtime);
338
+ if (!jsArrayObj.isArray(runtime)) return Value::null();
339
+ Array jsArray = jsArrayObj.getArray(runtime);
340
+ size_t size = jsArray.size(runtime);
341
+
342
+ NSMutableArray<DSQuadrilateral *> *quads = [NSMutableArray arrayWithCapacity:size];
343
+ for (size_t i = 0; i < size; i++) {
344
+ auto val = jsArray.getValueAtIndex(runtime, i);
345
+ // Check if element is an object before conversion
346
+ if (val.isObject()) {
347
+ DSQuadrilateral *quad = convertJSIValueToDSQuadrilateral(runtime, val.getObject(runtime));
348
+ [quads addObject:quad];
349
+ }
350
+ }
351
+
352
+ // Extract colour and thickness
353
+ NSInteger hex = args[2].asNumber();
354
+ int thickness = args[3].asNumber();
355
+
356
+ // Original logic for color conversion is correct
357
+ UIColor *color = [UIColor colorWithRed:((hex >> 16) & 0xFF) / 255.0
358
+ green:((hex >> 8) & 0xFF) / 255.0
359
+ blue:(hex & 0xFF) / 255.0
360
+ alpha:((hex >> 24) & 0xFF) / 255.0];
361
+
362
+ DSImageData *outData = [rnManager.drawer drawOnImage:data quads:[quads copy] colour:color thickness:thickness];
363
+
364
+ return createJsiHostObject(runtime, outData);
365
+ }
366
+ );
367
+ }
368
+
369
+ @end