@@ -23,6 +23,41 @@ class AndroidPlatformContext : public PlatformContext {
2323private:
2424 jobject _blobModule;
2525
26+ std::vector<uint8_t > resolveBlob (JNIEnv *env, const std::string &blobId,
27+ double offset, double size) {
28+ if (!_blobModule) {
29+ throw std::runtime_error (" BlobModule instance is null" );
30+ }
31+
32+ jclass blobModuleClass = env->GetObjectClass (_blobModule);
33+ if (!blobModuleClass) {
34+ throw std::runtime_error (" Couldn't find BlobModule class" );
35+ }
36+
37+ jmethodID resolveMethod = env->GetMethodID (blobModuleClass, " resolve" ,
38+ " (Ljava/lang/String;II)[B" );
39+ if (!resolveMethod) {
40+ throw std::runtime_error (" Couldn't find resolve method in BlobModule" );
41+ }
42+
43+ jstring jBlobId = env->NewStringUTF (blobId.c_str ());
44+ jbyteArray blobData = (jbyteArray)env->CallObjectMethod (
45+ _blobModule, resolveMethod, jBlobId, static_cast <jint>(offset),
46+ static_cast <jint>(size));
47+ env->DeleteLocalRef (jBlobId);
48+
49+ if (!blobData) {
50+ throw std::runtime_error (" Couldn't retrieve blob data" );
51+ }
52+
53+ jsize len = env->GetArrayLength (blobData);
54+ std::vector<uint8_t > data (len);
55+ env->GetByteArrayRegion (blobData, 0 , len,
56+ reinterpret_cast <jbyte *>(data.data ()));
57+ env->DeleteLocalRef (blobData);
58+ return data;
59+ }
60+
2661public:
2762 explicit AndroidPlatformContext (jobject blobModule)
2863 : _blobModule(blobModule) {}
@@ -52,188 +87,106 @@ class AndroidPlatformContext : public PlatformContext {
5287 throw std::runtime_error (" Couldn't get JNI environment" );
5388 }
5489
55- // Use the BlobModule instance from _blobModule
56- if (!_blobModule) {
57- throw std::runtime_error (" BlobModule instance is null" );
58- }
90+ auto data = resolveBlob (env, blobId, offset, size);
91+ return createImageBitmapFromData (data);
92+ }
5993
60- // Get the resolve method ID
61- jclass blobModuleClass = env->GetObjectClass (_blobModule);
62- if (!blobModuleClass) {
63- throw std::runtime_error (" Couldn't find BlobModule class" );
64- }
94+ void createImageBitmapAsync (
95+ std::string blobId, double offset, double size,
96+ std::function<void (ImageData)> onSuccess,
97+ std::function<void(std::string)> onError) override {
98+ std::thread ([this , blobId = std::move (blobId), offset, size,
99+ onSuccess = std::move (onSuccess),
100+ onError = std::move (onError)]() {
101+ jni::Environment::ensureCurrentThreadIsAttached ();
102+ try {
103+ JNIEnv *env = facebook::jni::Environment::current ();
104+ if (!env) {
105+ throw std::runtime_error (" Couldn't get JNI environment" );
106+ }
107+ auto data = resolveBlob (env, blobId, offset, size);
108+ auto result = createImageBitmapFromData (data);
109+ onSuccess (std::move (result));
110+ } catch (const std::exception &e) {
111+ onError (e.what ());
112+ }
113+ }).detach ();
114+ }
65115
66- jmethodID resolveMethod = env->GetMethodID (blobModuleClass, " resolve" ,
67- " (Ljava/lang/String;II)[B" );
68- if (!resolveMethod) {
69- throw std::runtime_error (" Couldn't find resolve method in BlobModule" );
70- }
116+ ImageData createImageBitmapFromData (std::span<uint8_t > data) override {
117+ jni::Environment::ensureCurrentThreadIsAttached ();
71118
72- // Resolve the blob data
73- jstring jBlobId = env->NewStringUTF (blobId.c_str ());
74- jbyteArray blobData = (jbyteArray)env->CallObjectMethod (
75- _blobModule, resolveMethod, jBlobId, static_cast <jint>(offset),
76- static_cast <jint>(size));
77- env->DeleteLocalRef (jBlobId);
119+ JNIEnv *env = facebook::jni::Environment::current ();
120+ if (!env) {
121+ throw std::runtime_error (" Couldn't get JNI environment" );
122+ }
78123
79- if (!blobData) {
80- throw std::runtime_error (" Couldn't retrieve blob data" );
124+ // Create jbyteArray from the raw bytes
125+ jbyteArray byteArray = env->NewByteArray (static_cast <jsize>(data.size ()));
126+ if (!byteArray) {
127+ throw std::runtime_error (" Couldn't allocate byte array" );
81128 }
129+ env->SetByteArrayRegion (byteArray, 0 , static_cast <jsize>(data.size ()),
130+ reinterpret_cast <const jbyte *>(data.data ()));
82131
83- // Create a Bitmap from the blob data
132+ // Decode via BitmapFactory
84133 jclass bitmapFactoryClass =
85134 env->FindClass (" android/graphics/BitmapFactory" );
86135 jmethodID decodeByteArrayMethod =
87136 env->GetStaticMethodID (bitmapFactoryClass, " decodeByteArray" ,
88137 " ([BII)Landroid/graphics/Bitmap;" );
89- jint blobLength = env-> GetArrayLength (blobData );
138+ jint length = static_cast <jint>(data. size () );
90139 jobject bitmap = env->CallStaticObjectMethod (
91- bitmapFactoryClass, decodeByteArrayMethod, blobData , 0 , blobLength );
140+ bitmapFactoryClass, decodeByteArrayMethod, byteArray , 0 , length );
92141
93142 if (!bitmap) {
94- env->DeleteLocalRef (blobData );
143+ env->DeleteLocalRef (byteArray );
95144 throw std::runtime_error (" Couldn't decode image" );
96145 }
97146
98- // Get bitmap info
99147 AndroidBitmapInfo bitmapInfo;
100148 if (AndroidBitmap_getInfo (env, bitmap, &bitmapInfo) !=
101149 ANDROID_BITMAP_RESULT_SUCCESS) {
102- env->DeleteLocalRef (blobData );
150+ env->DeleteLocalRef (byteArray );
103151 env->DeleteLocalRef (bitmap);
104152 throw std::runtime_error (" Couldn't get bitmap info" );
105153 }
106154
107- // Lock the bitmap pixels
108155 void *bitmapPixels;
109156 if (AndroidBitmap_lockPixels (env, bitmap, &bitmapPixels) !=
110157 ANDROID_BITMAP_RESULT_SUCCESS) {
111- env->DeleteLocalRef (blobData );
158+ env->DeleteLocalRef (byteArray );
112159 env->DeleteLocalRef (bitmap);
113160 throw std::runtime_error (" Couldn't lock bitmap pixels" );
114161 }
115162
116- // Copy the bitmap data
117- std::vector<uint8_t > imageData (bitmapInfo.height * bitmapInfo.stride );
118- memcpy (imageData.data (), bitmapPixels, imageData.size ());
163+ ImageData result;
164+ result.width = static_cast <int >(bitmapInfo.width );
165+ result.height = static_cast <int >(bitmapInfo.height );
166+ result.data .resize (bitmapInfo.height * bitmapInfo.stride );
167+ memcpy (result.data .data (), bitmapPixels, result.data .size ());
119168
120- // Unlock the bitmap pixels
121169 AndroidBitmap_unlockPixels (env, bitmap);
122170
123- // Clean up JNI references
124- env->DeleteLocalRef (blobData);
171+ env->DeleteLocalRef (byteArray);
125172 env->DeleteLocalRef (bitmap);
126173
127- ImageData result;
128- result.width = static_cast <int >(bitmapInfo.width );
129- result.height = static_cast <int >(bitmapInfo.height );
130- result.data = imageData;
131174 return result;
132175 }
133176
134- void createImageBitmapAsync (
135- std::string blobId, double offset, double size,
136- std::function<void (ImageData)> onSuccess,
177+ void createImageBitmapFromDataAsync (
178+ std::span<uint8_t > data, std::function<void (ImageData)> onSuccess,
137179 std::function<void(std::string)> onError) override {
138- // Capture blobModule for the background thread
139- jobject blobModule = _blobModule;
140-
141- // Dispatch to a background thread
142- std::thread ([blobModule, blobId = std::move (blobId), offset, size,
180+ std::thread ([this , ownedData = std::vector<uint8_t >(data.begin (), data.end ()),
143181 onSuccess = std::move (onSuccess),
144- onError = std::move (onError)]() {
182+ onError = std::move (onError)]() mutable {
145183 jni::Environment::ensureCurrentThreadIsAttached ();
146-
147- JNIEnv *env = facebook::jni::Environment::current ();
148- if (!env) {
149- onError (" Couldn't get JNI environment" );
150- return ;
151- }
152-
153- if (!blobModule) {
154- onError (" BlobModule instance is null" );
155- return ;
156- }
157-
158- // Get the resolve method ID
159- jclass blobModuleClass = env->GetObjectClass (blobModule);
160- if (!blobModuleClass) {
161- onError (" Couldn't find BlobModule class" );
162- return ;
163- }
164-
165- jmethodID resolveMethod = env->GetMethodID (blobModuleClass, " resolve" ,
166- " (Ljava/lang/String;II)[B" );
167- if (!resolveMethod) {
168- onError (" Couldn't find resolve method in BlobModule" );
169- return ;
170- }
171-
172- // Resolve the blob data
173- jstring jBlobId = env->NewStringUTF (blobId.c_str ());
174- jbyteArray blobData = (jbyteArray)env->CallObjectMethod (
175- blobModule, resolveMethod, jBlobId, static_cast <jint>(offset),
176- static_cast <jint>(size));
177- env->DeleteLocalRef (jBlobId);
178-
179- if (!blobData) {
180- onError (" Couldn't retrieve blob data" );
181- return ;
184+ try {
185+ auto result = createImageBitmapFromData (ownedData);
186+ onSuccess (std::move (result));
187+ } catch (const std::exception &e) {
188+ onError (e.what ());
182189 }
183-
184- // Create a Bitmap from the blob data
185- jclass bitmapFactoryClass =
186- env->FindClass (" android/graphics/BitmapFactory" );
187- jmethodID decodeByteArrayMethod =
188- env->GetStaticMethodID (bitmapFactoryClass, " decodeByteArray" ,
189- " ([BII)Landroid/graphics/Bitmap;" );
190- jint blobLength = env->GetArrayLength (blobData);
191- jobject bitmap = env->CallStaticObjectMethod (
192- bitmapFactoryClass, decodeByteArrayMethod, blobData, 0 , blobLength);
193-
194- if (!bitmap) {
195- env->DeleteLocalRef (blobData);
196- onError (" Couldn't decode image" );
197- return ;
198- }
199-
200- // Get bitmap info
201- AndroidBitmapInfo bitmapInfo;
202- if (AndroidBitmap_getInfo (env, bitmap, &bitmapInfo) !=
203- ANDROID_BITMAP_RESULT_SUCCESS) {
204- env->DeleteLocalRef (blobData);
205- env->DeleteLocalRef (bitmap);
206- onError (" Couldn't get bitmap info" );
207- return ;
208- }
209-
210- // Lock the bitmap pixels
211- void *bitmapPixels;
212- if (AndroidBitmap_lockPixels (env, bitmap, &bitmapPixels) !=
213- ANDROID_BITMAP_RESULT_SUCCESS) {
214- env->DeleteLocalRef (blobData);
215- env->DeleteLocalRef (bitmap);
216- onError (" Couldn't lock bitmap pixels" );
217- return ;
218- }
219-
220- // Copy the bitmap data
221- std::vector<uint8_t > imageData (bitmapInfo.height * bitmapInfo.stride );
222- memcpy (imageData.data (), bitmapPixels, imageData.size ());
223-
224- // Unlock the bitmap pixels
225- AndroidBitmap_unlockPixels (env, bitmap);
226-
227- // Clean up JNI references
228- env->DeleteLocalRef (blobData);
229- env->DeleteLocalRef (bitmap);
230-
231- ImageData result;
232- result.width = static_cast <int >(bitmapInfo.width );
233- result.height = static_cast <int >(bitmapInfo.height );
234- result.data = std::move (imageData);
235-
236- onSuccess (std::move (result));
237190 }).detach ();
238191 }
239192};
0 commit comments