1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <ani.h>
17 #include <array>
18 #include <iostream>
19 #include "image_source_ani.h"
20 #include "pixel_map_ani.h"
21 #include "image_ani_utils.h"
22 #include "log_tags.h"
23 #include "media_errors.h"
24 #include "image_log.h"
25 #include "string_ex.h"
26
27 #undef LOG_DOMAIN
28 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
29
30 #undef LOG_TAG
31 #define LOG_TAG "ImageSourceAni"
32
33 namespace OHOS {
34 namespace Media {
35 using namespace std;
36
37 static const string FILE_URL_PREFIX = "file://";
38
ANIUtils_ANIStringToStdString2(ani_env * env,ani_string ani_str)39 std::string ANIUtils_ANIStringToStdString2(ani_env *env, ani_string ani_str)
40 {
41 ani_size strSize;
42 env->String_GetUTF8Size(ani_str, &strSize);
43
44 std::vector<char> buffer(strSize + 1); // +1 for null terminator
45 char* utfBuffer = buffer.data();
46
47 ani_size bytes_written = 0;
48 if (ANI_OK != env->String_GetUTF8(ani_str, utfBuffer, strSize + 1, &bytes_written)) {
49 IMAGE_LOGE("ANIUtils_ANIStringToStdString fail");
50 return "";
51 }
52
53 utfBuffer[bytes_written] = '\0';
54 std::string content = std::string(utfBuffer);
55 return content;
56 }
57
FileUrlToRawPath(const string & path)58 static string FileUrlToRawPath(const string &path)
59 {
60 if (path.size() > FILE_URL_PREFIX.size() &&
61 (path.compare(0, FILE_URL_PREFIX.size(), FILE_URL_PREFIX) == 0)) {
62 return path.substr(FILE_URL_PREFIX.size());
63 }
64 return path;
65 }
66
CreateImageSourceAni(ani_env * env,ani_object obj)67 ani_object ImageSourceAni::CreateImageSourceAni([[maybe_unused]] ani_env* env, ani_object obj)
68 {
69 std::unique_ptr<ImageSourceAni> pImageSourceAni = std::make_unique<ImageSourceAni>();
70 ani_class stringClass;
71 env->FindClass("Lstd/core/String;", &stringClass);
72 ani_boolean isString;
73 env->Object_InstanceOf(obj, stringClass, &isString);
74 if (isString) {
75 string fileUrl = ANIUtils_ANIStringToStdString2(env, static_cast<ani_string>(obj));
76 IMAGE_LOGI("Image source URI: %{public}s", fileUrl.c_str());
77 pImageSourceAni->filePath_ = FileUrlToRawPath(fileUrl);
78 SourceOptions opts;
79 uint32_t errorCode;
80 pImageSourceAni->nativeImageSource_ =
81 ImageSource::CreateImageSource(pImageSourceAni->filePath_, opts, errorCode);
82 if (pImageSourceAni->nativeImageSource_ == nullptr) {
83 IMAGE_LOGE("CreateImageSource failed'");
84 }
85 }
86
87 ani_class arrayBufferClass;
88 env->FindClass("Lescompat/ArrayBuffer;", &arrayBufferClass);
89 ani_boolean isArrayBuffer;
90 env->Object_InstanceOf(obj, arrayBufferClass, &isArrayBuffer);
91 if (isArrayBuffer) {
92 ani_int length;
93 env->Object_CallMethodByName_Int(obj, "getByteLength", nullptr, &length);
94 IMAGE_LOGI("Object is ArraryBuffer Length: %{public}d", length);
95 }
96
97 ani_class intClass;
98 env->FindClass("Lstd/core/Int;", &intClass);
99 ani_boolean isInt;
100 env->Object_InstanceOf(obj, intClass, &isInt);
101 if (isInt) {
102 ani_int fd;
103 env->Object_CallMethodByName_Int(obj, "unboxed", ":I", &fd);
104 IMAGE_LOGI("Image source fd: %{public}d", fd);
105 SourceOptions opts;
106 uint32_t errorCode;
107 pImageSourceAni->nativeImageSource_ = ImageSource::CreateImageSource(fd, opts, errorCode);
108 }
109
110 if (pImageSourceAni->nativeImageSource_ == nullptr) {
111 IMAGE_LOGE("CreateImageSource failed'");
112 }
113
114 return ImageAniUtils::CreateAniImageSource(env, pImageSourceAni);
115 }
116
GetImageInfo(ani_env * env,ani_object obj,ani_int indexObj)117 static ani_object GetImageInfo([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj, ani_int indexObj)
118 {
119 ani_status ret;
120 IMAGE_LOGE("[GetImageInfo] Object_GetField_Long in");
121 ani_long nativeObj {};
122 if ((ret = env->Object_GetFieldByName_Long(obj, "nativeObj", &nativeObj)) != ANI_OK) {
123 IMAGE_LOGE("[GetImageInfo] Object_GetField_Long fetch field");
124 return nullptr;
125 }
126 IMAGE_LOGE("[GetImageInfo] Object_GetField_Long sucess ");
127 ImageSourceAni* imageSourceAni = reinterpret_cast<ImageSourceAni*>(nativeObj);
128 int index = reinterpret_cast<int>(indexObj);
129 IMAGE_LOGE("[GetImageInfo] index: %{public}d", index);
130 ImageInfo imgInfo;
131 if (imageSourceAni != nullptr) {
132 IMAGE_LOGI("[GetImageInfo] get imageSourceAni success ");
133 } else {
134 IMAGE_LOGE("[GetImageInfo] imageSourceAni is nullptr ");
135 return nullptr;
136 }
137 return ImageAniUtils::CreateImageInfoValueFromNative(env, imgInfo, nullptr);
138 }
139
parseEnumFromStruct(ani_env * env,ani_object & param,string propertyGet,string enumType)140 static ani_int parseEnumFromStruct(ani_env* env, ani_object ¶m, string propertyGet, string enumType)
141 {
142 ani_status ret;
143 ani_ref enumRef;
144 if (ANI_OK != (ret = env->Object_CallMethodByName_Ref(param, propertyGet.c_str(), enumType.c_str(), &enumRef))) {
145 IMAGE_LOGE("Object_CallMethodByName_Int enumRef Failed: %{public}d", ret);
146 return 0;
147 }
148 ani_boolean undefined;
149 env->Reference_IsUndefined(enumRef, &undefined);
150 if (undefined) {
151 IMAGE_LOGI("Enum %{public}s is undefined", propertyGet.c_str());
152 return 0;
153 }
154
155 ani_int enumIndex;
156 if (ANI_OK != env->EnumItem_GetValue_Int(static_cast<ani_enum_item>(enumRef), &enumIndex)) {
157 IMAGE_LOGE("EnumItem_GetValue_Int enumIndex Failed: %{public}d", ret);
158 return 0;
159 }
160 return enumIndex;
161 }
162
ParseRegion(ani_env * env,ani_object region,Rect & rect)163 static bool ParseRegion([[maybe_unused]] ani_env* env, ani_object region, Rect& rect)
164 {
165 ani_boolean undefined;
166 env->Reference_IsUndefined(region, &undefined);
167 if (undefined) {
168 IMAGE_LOGE("ParseRegion argument undefined");
169 return false;
170 }
171
172 ani_ref size;
173 if (ANI_OK != env->Object_CallMethodByName_Ref(region, "<get>size", ":L@ohos/multimedia/image/image/Size;",
174 &size)) {
175 IMAGE_LOGE("Object_GetFieldByName_Ref Failed");
176 return false;
177 }
178 if (ANI_OK != env->Object_CallMethodByName_Int(reinterpret_cast<ani_object>(size), "<get>width", ":I",
179 &rect.width)) {
180 IMAGE_LOGE("Object_CallMethodByName_Int width Failed");
181 return false;
182 }
183 if (ANI_OK != env->Object_CallMethodByName_Int(reinterpret_cast<ani_object>(size), "<get>height", ":I",
184 &rect.height)) {
185 IMAGE_LOGE("Object_CallMethodByName_Int height Failed");
186 return false;
187 }
188
189 if (ANI_OK != env->Object_CallMethodByName_Int(region, "<get>x", ":I", &rect.left)) {
190 IMAGE_LOGE("Object_CallMethodByName_Int x Failed");
191 return false;
192 }
193 if (ANI_OK != env->Object_CallMethodByName_Int(region, "<get>y", ":I", &rect.top)) {
194 IMAGE_LOGE("Object_CallMethodByName_Int y Failed");
195 return false;
196 }
197
198 return true;
199 }
200
ParseDecodingOptions2(ani_env * env,ani_object & param,DecodeOptions & opts)201 static bool ParseDecodingOptions2([[maybe_unused]] ani_env* env, ani_object ¶m, DecodeOptions &opts)
202 {
203 ani_status ret;
204 ani_ref size;
205 if (ANI_OK != env->Object_CallMethodByName_Ref(param, "<get>desiredSize",
206 ":L@ohos/multimedia/image/image/Size;", &size)) {
207 IMAGE_LOGE("Object_CallMethodByName_Ref size Faild");
208 }
209 if (ANI_OK != env->Object_CallMethodByName_Int(reinterpret_cast<ani_object>(size), "<get>width", ":I",
210 &opts.desiredSize.width)) {
211 IMAGE_LOGE("Object_CallMethodByName_Int width Faild");
212 }
213 if ((ret = env->Object_CallMethodByName_Int(reinterpret_cast<ani_object>(size), "<get>height", ":I",
214 &opts.desiredSize.height)) != ANI_OK) {
215 IMAGE_LOGE("Object_CallMethodByName_Int height Faild :%{public}d", ret);
216 }
217
218 ani_ref regionRef;
219 if (ANI_OK != env->Object_CallMethodByName_Ref(param, "<get>desiredRegion",
220 ":L@ohos/multimedia/image/image/Region;", ®ionRef)) {
221 IMAGE_LOGE("Object_CallMethodByName_Ref desiredRegion Faild");
222 }
223 if (!ParseRegion(env, static_cast<ani_object>(regionRef), opts.desiredRegion)) {
224 IMAGE_LOGE("Parse desiredRegion Faild");
225 }
226 opts.desiredPixelFormat = PixelFormat(parseEnumFromStruct(env, param, "<get>desiredPixelFormat",
227 ":L@ohos/multimedia/image/image/PixelMapFormat;"));
228 ani_ref fitDensityRef;
229 if (ANI_OK != (ret = env->Object_CallMethodByName_Ref(param,
230 "<get>fitDensity", ":Lstd/core/Int;", &fitDensityRef))) {
231 IMAGE_LOGE("Object_CallMethodByName_Ref Faild fitDensityRef:%{public}d", ret);
232 }
233 ani_int fitDensity;
234 if ((ret = env->Object_CallMethodByName_Int(reinterpret_cast<ani_object>(fitDensityRef),
235 "unboxed", ":I", &fitDensity)) != ANI_OK) {
236 IMAGE_LOGE("Object_CallMethodByName_Int Faild fitDensity:%{public}d", ret);
237 }
238 return true;
239 }
240
ParseDecodingOptions(ani_env * env,ani_object para,DecodeOptions & opts)241 static bool ParseDecodingOptions([[maybe_unused]] ani_env* env, ani_object para, DecodeOptions &opts)
242 {
243 ani_boolean isUndefined;
244 ani_status ret;
245 ani_ref indexRef;
246 if (ANI_OK != (ret = env->Object_CallMethodByName_Ref(para, "<get>index", ":Lstd/core/Int;", &indexRef))) {
247 IMAGE_LOGE("Object_CallMethodByName_Ref Faild indexRef:%{public}d", ret);
248 }
249 env->Reference_IsUndefined(indexRef, &isUndefined);
250 if (!isUndefined) {
251 ani_int index;
252 if (env->Object_CallMethodByName_Int(reinterpret_cast<ani_object>(indexRef),
253 "unboxed", ":I", &index) != ANI_OK) {
254 IMAGE_LOGE("Object_CallMethodByName_Int Faild");
255 }
256 }
257
258 ani_ref sampleRef;
259 if (ANI_OK != (ret = env->Object_CallMethodByName_Ref(para, "<get>sampleSize", ":Lstd/core/Int;", &sampleRef))) {
260 IMAGE_LOGE("Object_CallMethodByName_Ref Faild sampleRef:%{public}d", ret);
261 }
262 ani_int sample;
263 if ((ret = env->Object_CallMethodByName_Int(reinterpret_cast<ani_object>(sampleRef),
264 "unboxed", ":I", &sample)) != ANI_OK) {
265 IMAGE_LOGE("Object_CallMethodByName_Int Faild sample:%{public}d", ret);
266 }
267
268 ani_ref rotateRef;
269 if (ANI_OK != (ret = env->Object_CallMethodByName_Ref(para, "<get>rotate", ":Lstd/core/Int;", &rotateRef))) {
270 IMAGE_LOGE("Object_CallMethodByName_Ref Faild rotateRef:%{public}d", ret);
271 }
272 ani_int rotate;
273 if ((ret = env->Object_CallMethodByName_Int(reinterpret_cast<ani_object>(rotateRef),
274 "unboxed", ":I", &rotate)) != ANI_OK) {
275 IMAGE_LOGE("Object_CallMethodByName_Int Faild rotate:%{public}d", ret);
276 }
277
278 ani_ref editableRef;
279 if (ANI_OK != (ret = env->Object_CallMethodByName_Ref(para, "<get>editable", ":Lstd/core/Boolean;",
280 &editableRef))) {
281 IMAGE_LOGE("Object_CallMethodByName_Ref Faild editableRef:%{public}d", ret);
282 }
283 ani_boolean editable;
284 if ((ret = env->Object_CallMethodByName_Boolean(reinterpret_cast<ani_object>(editableRef),
285 "unboxed", ":Z", &editable)) != ANI_OK) {
286 IMAGE_LOGE("Object_CallMethodByName_Int Faild editable:%{public}d", ret);
287 }
288 opts.editable = static_cast<bool>(editable);
289
290 if (!ParseDecodingOptions2(env, para, opts)) {
291 return false;
292 }
293
294 return true;
295 }
296
CreatePixelMap(ani_env * env,ani_object obj,ani_object para)297 static ani_object CreatePixelMap([[maybe_unused]] ani_env* env,
298 [[maybe_unused]] ani_object obj, [[maybe_unused]]ani_object para)
299 {
300 ani_status ret;
301 ani_long nativeObj {};
302 if ((ret = env->Object_GetFieldByName_Long(obj, "nativeObj", &nativeObj)) != ANI_OK) {
303 IMAGE_LOGE("[CreatePixelMap] Object_GetField_Long fetch field ");
304 return nullptr;
305 }
306 ImageSourceAni* imageSourceAni = reinterpret_cast<ImageSourceAni*>(nativeObj);
307 ImageInfo imgInfo;
308 imgInfo.encodedFormat = "abcdefg";
309 if (imageSourceAni != nullptr) {
310 } else {
311 IMAGE_LOGE("[CreatePixelMap] imageSourceAni is nullptr");
312 }
313
314 DecodeOptions opts;
315 ParseDecodingOptions(env, para, opts);
316
317 return PixelMapAni::CreatePixelMap(env, std::make_shared<PixelMap>());
318 }
319
ModifyImageProperty(ani_env * env,ani_object obj,ani_long longObj,ani_object key,ani_object value)320 static void ModifyImageProperty([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj,
321 ani_long longObj, ani_object key, ani_object value)
322 {
323 IMAGE_LOGE("ModifyImageProperty in ");
324 ani_status ret;
325 ani_long nativeObj {};
326 if ((ret = env->Object_GetFieldByName_Long(obj, "nativeObj", &nativeObj)) != ANI_OK) {
327 IMAGE_LOGE("[ModifyImageProperty] Object_GetField_Long fetch field ");
328 return;
329 }
330 ImageSourceAni* imageSourceAni = reinterpret_cast<ImageSourceAni*>(nativeObj);
331 if (imageSourceAni == nullptr) {
332 IMAGE_LOGE("[ModifyImageProperty] get imageSourceAni failed");
333 }
334 IMAGE_LOGE("[ModifyImageProperty] get imageSourceAni success");
335
336 ani_class stringClass;
337 env->FindClass("Lstd/core/String;", &stringClass);
338 ani_boolean isString;
339 env->Object_InstanceOf(key, stringClass, &isString);
340 std::string keyS = "";
341 if (isString) {
342 keyS = ANIUtils_ANIStringToStdString2(env, static_cast<ani_string>(key));
343 }
344 std::string valueS = ANIUtils_ANIStringToStdString2(env, static_cast<ani_string>(value));
345 IMAGE_LOGI("ModifyImageProperty get key:%{public}s value:%{public}s", keyS.c_str(), valueS.c_str());
346 }
347
348
349 template <typename F>
forEachMapEntry(ani_env * env,ani_object map_object,F && callback)350 static bool forEachMapEntry(ani_env *env, ani_object map_object, F &&callback)
351 {
352 ani_ref keys;
353 if (ANI_OK != env->Object_CallMethodByName_Ref(map_object, "keys", ":Lescompat/IterableIterator;", &keys)) {
354 IMAGE_LOGE("Failed to get keys iterator");
355 return false;
356 }
357
358 bool success = true;
359 while (success) {
360 ani_ref next;
361 ani_boolean done;
362
363 if (ANI_OK != env->Object_CallMethodByName_Ref(static_cast<ani_object>(keys), "next", nullptr, &next)) {
364 IMAGE_LOGE("Failed to get next key");
365 success = false;
366 break;
367 }
368
369 if (ANI_OK != env->Object_GetFieldByName_Boolean(static_cast<ani_object>(next), "done", &done)) {
370 IMAGE_LOGE("Failed to check iterator done");
371 success = false;
372 break;
373 }
374 if (done) {
375 IMAGE_LOGE("[forEachMapEntry] done break");
376 break;
377 }
378
379 ani_ref key_value;
380 if (ANI_OK != env->Object_GetFieldByName_Ref(static_cast<ani_object>(next), "value", &key_value)) {
381 IMAGE_LOGE("Failed to get key value");
382 success = false;
383 break;
384 }
385
386 ani_ref value_obj;
387 if (ANI_OK != env->Object_CallMethodByName_Ref(map_object, "$_get", nullptr, &value_obj, key_value)) {
388 IMAGE_LOGE("Failed to get value for key");
389 success = false;
390 break;
391 }
392
393 callback(key_value, value_obj);
394 }
395 return success;
396 }
397
398
399 class ANIIntanceHelper {
400 public:
401 ANIIntanceHelper() = default;
ANIIntanceHelper(ani_env * aniEnv)402 explicit ANIIntanceHelper(ani_env *aniEnv) { env = aniEnv; };
Init()403 bool Init()
404 {
405 if (ANI_OK != env->FindClass("Lstd/core/String;", &stringType)) {
406 IMAGE_LOGE("FindClass std/core/String failed");
407 return false;
408 }
409 if (ANI_OK != env->FindClass("Lescompat/Record;", &recordType)) {
410 IMAGE_LOGE("FindClass Lescompat/Record; failed");
411 return false;
412 }
413 if (ANI_OK != env->FindClass("Lstd/core/Numeric;", &numberType)) {
414 IMAGE_LOGE("Lstd/core/Numeric; failed");
415 return false;
416 }
417 inited = true;
418 return true;
419 }
isString(ani_object obj)420 bool isString(ani_object obj)
421 {
422 if (!inited) {
423 return false;
424 }
425 ani_boolean is_string;
426 if (ANI_OK != env->Object_InstanceOf(static_cast<ani_object>(obj),
427 static_cast<ani_type>(stringType), &is_string)) {
428 IMAGE_LOGE("Call Object_InstanceOf failed");
429 return false;
430 }
431 return (bool)is_string;
432 }
isRecord(ani_object obj)433 bool isRecord(ani_object obj)
434 {
435 if (!inited) {
436 return false;
437 }
438 ani_boolean is_record;
439 if (ANI_OK != env->Object_InstanceOf(static_cast<ani_object>(obj),
440 static_cast<ani_type>(recordType), &is_record)) {
441 IMAGE_LOGE("Call Object_InstanceOf failed");
442 return false;
443 }
444 return (bool)is_record;
445 }
isNumber(ani_object obj)446 bool isNumber(ani_object obj)
447 {
448 if (!inited) {
449 return false;
450 }
451 ani_boolean is_number;
452 if (ANI_OK != env->Object_InstanceOf(static_cast<ani_object>(obj),
453 static_cast<ani_type>(numberType), &is_number)) {
454 IMAGE_LOGE("Call Object_InstanceOf Fail");
455 return false;
456 }
457 return (bool)is_number;
458 }
isArray(ani_object obj)459 bool isArray(ani_object obj)
460 {
461 if (!inited) {
462 return false;
463 }
464 ani_size arrayLength;
465 if (ANI_OK !=
466 env->Array_GetLength(static_cast<ani_array>(obj), &arrayLength)) {
467 return false;
468 }
469 return true;
470 }
471 private:
472 ani_class stringType = nullptr;
473 ani_class recordType = nullptr;
474 ani_class numberType = nullptr;
475 ani_env *env;
476 bool inited = false;
477 };
478
ProcMapEntry(ani_env * env,ani_ref key,ani_ref value,ImageSourceAni * imageSourceAni,ANIIntanceHelper & ih)479 bool ProcMapEntry(ani_env* env, ani_ref key, ani_ref value, ImageSourceAni* imageSourceAni, ANIIntanceHelper &ih)
480 {
481 auto imageSource = imageSourceAni->nativeImageSource_;
482 if (imageSource == nullptr) {
483 IMAGE_LOGE("[ProcMapEntry] imageSource nullptr");
484 return false;
485 }
486 if (!ih.isString(static_cast<ani_object>(key))) {
487 IMAGE_LOGE("[ProcMapEntry] key is not string");
488 return false;
489 }
490 auto keyStr = ANIUtils_ANIStringToStdString2(env, static_cast<ani_string>(key));
491 auto valueStr = ANIUtils_ANIStringToStdString2(env, static_cast<ani_string>(value));
492 IMAGE_LOGI("[ProcMapEntry] ProcMapEntry key:%{public}s value:%{public}s", keyStr.c_str(), valueStr.c_str());
493
494 if (!IsSameTextStr(imageSourceAni->filePath_, "")) {
495 imageSource->ModifyImageProperty(0, keyStr, valueStr, imageSourceAni->filePath_);
496 } else if (imageSourceAni->fileDescriptor_ != -1) {
497 imageSource->ModifyImageProperty(0, keyStr, valueStr, imageSourceAni->fileDescriptor_);
498 } else {
499 IMAGE_LOGE("There is no image source!");
500 return false;
501 }
502 return true;
503 }
504
ModifyImageProperties(ani_env * env,ani_object obj,ani_object recordsObj)505 static void ModifyImageProperties([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj, ani_object recordsObj)
506 {
507 ImageSourceAni* imageSourceAni = ImageAniUtils::GetImageSourceAniFromEnv(env, obj);
508 if (imageSourceAni == nullptr) {
509 IMAGE_LOGE("[GetImageSourceFromEnv] imageSource nullptr");
510 return;
511 }
512
513 ANIIntanceHelper ih(env);
514 if (!ih.Init()) {
515 IMAGE_LOGE("[ModifyImageProperties] ih init fail");
516 return;
517 }
518
519 forEachMapEntry(env, recordsObj,
520 [env, &imageSourceAni, &ih](ani_ref key, ani_ref value) -> bool {
521 return ProcMapEntry(env, key, value, imageSourceAni, ih);
522 });
523 }
524
ParseArrayString(ani_env * env,ani_object arrayObj,std::vector<std::string> & strings)525 bool ParseArrayString([[maybe_unused]] ani_env* env, ani_object arrayObj, std::vector<std::string> &strings)
526 {
527 ani_double length;
528 if (ANI_OK != env->Object_GetPropertyByName_Double(arrayObj, "length", &length)) {
529 IMAGE_LOGE("Object_GetPropecortyByName_Double length Failed");
530 return false;
531 }
532 for (int i = 0; i < int(length); i++) {
533 ani_ref stringEntryRef;
534 if (ANI_OK != env->Object_CallMethodByName_Ref(arrayObj, "$_get",
535 "I:Lstd/core/Object;", &stringEntryRef, (ani_int)i)) {
536 IMAGE_LOGE("Object_GetPropertyByName_Double length Failed");
537 return false;
538 }
539 strings.emplace_back(ANIUtils_ANIStringToStdString2(env, static_cast<ani_string>(stringEntryRef)));
540 }
541 return true;
542 }
543
GetImageProperties(ani_env * env,ani_object obj,ani_object arrayObj)544 static ani_object GetImageProperties([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj,
545 ani_object arrayObj)
546 {
547 auto imageSource = ImageAniUtils::GetImageSourceFromEnv(env, obj);
548 if (imageSource == nullptr) {
549 IMAGE_LOGE("[GetImageProperties] imageSource nullptr");
550 return nullptr;
551 }
552
553 vector<string> keyStrArray;
554 ParseArrayString(env, arrayObj, keyStrArray);
555
556 vector<pair<string, string>> kVStrArray;
557 uint32_t errCode = SUCCESS;
558 for (auto keyStrIt = keyStrArray.begin(); keyStrIt != keyStrArray.end(); ++keyStrIt) {
559 string valueStr = "";
560 errCode = imageSource->GetImagePropertyString(0, *keyStrIt, valueStr);
561 if (errCode == SUCCESS) {
562 kVStrArray.emplace_back(make_pair(*keyStrIt, valueStr));
563 } else {
564 kVStrArray.emplace_back(make_pair(*keyStrIt, ""));
565 IMAGE_LOGE("errCode: %{public}u , exif key: %{public}s", errCode, keyStrIt->c_str());
566 }
567 }
568
569 ani_object argumentObj = {};
570 ani_method recordSetMethod = ImageAniUtils::GetRecordSetMethod(env, argumentObj);
571 if (recordSetMethod == nullptr) {
572 IMAGE_LOGE("[GetImageProperties] recordSetMethod nullptr");
573 }
574
575 ani_status status;
576 for (auto iter = kVStrArray.begin(); iter != kVStrArray.end(); ++iter) {
577 string key = iter->first;
578 string value = iter->second;
579 ani_string ani_key;
580 ani_string ani_value;
581 status = env->String_NewUTF8(key.c_str(), key.length(), &ani_key);
582 if (status != ANI_OK) {
583 IMAGE_LOGE("String_NewUTF8 key failed status :%{public}u", status);
584 return nullptr;
585 }
586 status = env->String_NewUTF8(value.c_str(), value.length(), &ani_value);
587 if (status != ANI_OK) {
588 IMAGE_LOGE("String_NewUTF8 value failed status : %{public}u", status);
589 return nullptr;
590 }
591 status = env->Object_CallMethod_Void(argumentObj, recordSetMethod, ani_key, ani_value);
592 if (status != ANI_OK) {
593 IMAGE_LOGE("Object_CallMethod_Void value failed status : %{public}u", status);
594 return nullptr;
595 }
596 }
597 return argumentObj;
598 }
599
Release(ani_env * env,ani_object obj)600 static void Release([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj)
601 {
602 ani_status ret;
603 ani_long nativeObj {};
604 if ((ret = env->Object_GetFieldByName_Long(obj, "nativeObj", &nativeObj)) != ANI_OK) {
605 IMAGE_LOGE("[Release] Object_GetField_Long fetch field ret:%{public}d", ret);
606 return;
607 }
608 ImageSourceAni* imageSourceAni = reinterpret_cast<ImageSourceAni*>(nativeObj);
609 imageSourceAni->nativeImageSource_ = nullptr;
610 }
611
Init(ani_env * env)612 ani_status ImageSourceAni::Init(ani_env* env)
613 {
614 static const char *className = "L@ohos/multimedia/image/image/ImageSourceInner;";
615 ani_class cls;
616 if (ANI_OK != env->FindClass(className, &cls)) {
617 IMAGE_LOGE("Not found ");
618 return ANI_ERROR;
619 }
620 std::array methods = {
621 ani_native_function {"nativeGetImageInfo", "I:L@ohos/multimedia/image/image/ImageInfo;",
622 reinterpret_cast<void*>(OHOS::Media::GetImageInfo)},
623 ani_native_function {"nativeCreatePixelMap",
624 "L@ohos/multimedia/image/image/DecodingOptions;:L@ohos/multimedia/image/image/PixelMap;",
625 reinterpret_cast<void*>(OHOS::Media::CreatePixelMap)},
626 ani_native_function {"modifyImageProperty", "JLstd/core/String;Lstd/core/String;:V",
627 reinterpret_cast<void*>(OHOS::Media::ModifyImageProperty)},
628 ani_native_function {"nativeModifyImageProperties", "Lescompat/Record;:V",
629 reinterpret_cast<void*>(OHOS::Media::ModifyImageProperties)},
630 ani_native_function {"nativeGetImageProperties", "Lescompat/Array;:Lescompat/Record;",
631 reinterpret_cast<void*>(OHOS::Media::GetImageProperties)},
632 ani_native_function {"release", ":V", reinterpret_cast<void *>(OHOS::Media::Release)},
633 };
634 ani_status ret = env->Class_BindNativeMethods(cls, methods.data(), methods.size());
635 if (ANI_OK != ret) {
636 IMAGE_LOGE("[ImageSourceAni] Cannot bind native methods ret: %{public}d", ret);
637 return ANI_ERROR;
638 };
639 return ANI_OK;
640 }
641 } // Media
642 } // OHOS
643