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 "image_ani_utils.h"
17 #include <array>
18 #include <iostream>
19 #include "pixel_map_ani.h"
20 #include "log_tags.h"
21 #include "media_errors.h"
22 #include "image_log.h"
23
24 #undef LOG_DOMAIN
25 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
26
27 #undef LOG_TAG
28 #define LOG_TAG "AniUtilsAni"
29
30 namespace OHOS {
31 namespace Media {
32 using namespace std;
33
GetPixelMapFromEnv(ani_env * env,ani_object obj)34 PixelMap* ImageAniUtils::GetPixelMapFromEnv([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj)
35 {
36 return ImageAniUtils::GetPixelMapFromEnvSp(env, obj).get();
37 }
38
GetPixelMapFromEnvSp(ani_env * env,ani_object obj)39 shared_ptr<PixelMap> ImageAniUtils::GetPixelMapFromEnvSp([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj)
40 {
41 ani_status ret;
42 ani_long nativeObj {};
43 if ((ret = env->Object_GetFieldByName_Long(obj, "nativeObj", &nativeObj)) != ANI_OK) {
44 IMAGE_LOGE("[GetPixelMapFromEnv] Object_GetField_Long fetch failed");
45 return nullptr;
46 }
47 PixelMapAni* pixelmapAni = reinterpret_cast<PixelMapAni*>(nativeObj);
48 if (!pixelmapAni) {
49 IMAGE_LOGE("[GetPixelMapFromEnv] pixelmapAni nullptr");
50 return nullptr;
51 }
52 return pixelmapAni->nativePixelMap_;
53 }
54
GetImageSourceAniFromEnv(ani_env * env,ani_object obj)55 ImageSourceAni* ImageAniUtils::GetImageSourceAniFromEnv([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj)
56 {
57 ani_status ret;
58 ani_long nativeObj {};
59 if ((ret = env->Object_GetFieldByName_Long(obj, "nativeObj", &nativeObj)) != ANI_OK) {
60 IMAGE_LOGE("[GetImageSourceFromEnv] Object_GetField_Long fetch failed");
61 return nullptr;
62 }
63 return reinterpret_cast<ImageSourceAni*>(nativeObj);
64 }
65
GetImageSourceFromEnv(ani_env * env,ani_object obj)66 shared_ptr<ImageSource> ImageAniUtils::GetImageSourceFromEnv([[maybe_unused]] ani_env* env,
67 [[maybe_unused]] ani_object obj)
68 {
69 ImageSourceAni* imageSourceAni = ImageAniUtils::GetImageSourceAniFromEnv(env, obj);
70 if (!imageSourceAni) {
71 IMAGE_LOGE("[GetPictureFromEnv] imageSourceAni nullptr");
72 return nullptr;
73 }
74 return imageSourceAni->nativeImageSource_;
75 }
76
GetPictureFromEnv(ani_env * env,ani_object obj)77 shared_ptr<Picture> ImageAniUtils::GetPictureFromEnv([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj)
78 {
79 ani_status ret;
80 ani_long nativeObj {};
81 if ((ret = env->Object_GetFieldByName_Long(obj, "nativeObj", &nativeObj)) != ANI_OK) {
82 IMAGE_LOGE("[GetPictureFromEnv] Object_GetField_Long fetch failed");
83 return nullptr;
84 }
85 PictureAni* pictureAni = reinterpret_cast<PictureAni*>(nativeObj);
86 if (!pictureAni) {
87 IMAGE_LOGE("[GetPictureFromEnv] pictureAni nullptr");
88 return nullptr;
89 }
90 return pictureAni->nativePicture_;
91 }
92
CreateAniImageInfo(ani_env * env)93 static ani_object CreateAniImageInfo(ani_env* env)
94 {
95 static const char* imageInfoClassName = "L@ohos/multimedia/image/image/ImageInfoInner;";
96 ani_class imageInfoCls;
97 if (ANI_OK != env->FindClass(imageInfoClassName, &imageInfoCls)) {
98 IMAGE_LOGE("Not found L@ohos/multimedia/image/image/ImageInfoInner;");
99 return nullptr;
100 }
101 ani_method imageInfoCtor;
102 if (ANI_OK != env->Class_FindMethod(imageInfoCls, "<ctor>", nullptr, &imageInfoCtor)) {
103 IMAGE_LOGE("Not found Class_FindMethod");
104 return nullptr;
105 }
106 ani_object imageInfoValue;
107 if (ANI_OK != env->Object_New(imageInfoCls, imageInfoCtor, &imageInfoValue)) {
108 IMAGE_LOGE("New Context Fail");
109 return nullptr;
110 }
111 return imageInfoValue;
112 }
113
SetImageInfoSize(ani_env * env,const ImageInfo & imgInfo,ani_object & imageInfoValue)114 static bool SetImageInfoSize(ani_env* env, const ImageInfo& imgInfo, ani_object& imageInfoValue)
115 {
116 ani_ref sizeref;
117 if (ANI_OK != env->Object_CallMethodByName_Ref(imageInfoValue, "<get>size",
118 ":L@ohos/multimedia/image/image/Size;", &sizeref)) {
119 IMAGE_LOGE("Object_CallMethodByName_Ref failed");
120 return false;
121 }
122 ani_object sizeObj = reinterpret_cast<ani_object>(sizeref);
123 if (ANI_OK != env->Object_CallMethodByName_Void(sizeObj, "<set>width", "I:V",
124 static_cast<ani_int>(imgInfo.size.width))) {
125 IMAGE_LOGE("Object_CallMethodByName_Void <set>width failed");
126 return false;
127 }
128 if (ANI_OK != env->Object_CallMethodByName_Void(sizeObj, "<set>height", "I:V",
129 static_cast<ani_int>(imgInfo.size.height))) {
130 IMAGE_LOGE("Object_CallMethodByName_Void <set>height failed");
131 return false;
132 }
133 return true;
134 }
135
getPixelFormatItemName(PixelFormat format)136 static string getPixelFormatItemName(PixelFormat format)
137 {
138 switch (format) {
139 case PixelFormat::ARGB_8888:
140 return "ARGB_8888";
141 case PixelFormat::RGB_565:
142 return "RGB_565";
143 case PixelFormat::RGBA_8888:
144 return "RGBA_8888";
145 case PixelFormat::BGRA_8888:
146 return "BGRA_8888";
147 case PixelFormat::RGB_888:
148 return "RGB_888";
149 case PixelFormat::ALPHA_8:
150 return "ALPHA_8";
151 case PixelFormat::RGBA_F16:
152 return "RGBA_F16";
153 case PixelFormat::NV21:
154 return "NV21";
155 case PixelFormat::NV12:
156 return "NV12";
157 case PixelFormat::RGBA_1010102:
158 return "RGBA_1010102";
159 case PixelFormat::YCBCR_P010:
160 return "YCBCR_P010";
161 case PixelFormat::YCRCB_P010:
162 return "YCRCB_P010";
163 case PixelFormat::ASTC_4x4:
164 return "ASTC_4x4";
165 default:
166 return "UNKNOWN";
167 }
168 }
169
findPixelFormatEnumItem(ani_env * env,PixelFormat format)170 static ani_enum_item findPixelFormatEnumItem([[maybe_unused]] ani_env* env, PixelFormat format)
171 {
172 ani_enum type;
173 if (ANI_OK != env->FindEnum("L@ohos/multimedia/image/image/PixelMapFormat;", &type)) {
174 IMAGE_LOGE("FindEnum for PixelMapFormat Failed");
175 return {};
176 }
177
178 string itemName = getPixelFormatItemName(format);
179
180 ani_enum_item enumItem;
181 if (ANI_OK != env->Enum_GetEnumItemByName(type, itemName.c_str(), &enumItem)) {
182 IMAGE_LOGE("Enum_GetEnumItemByName for PixelMapFormat Failed");
183 return {};
184 }
185
186 return enumItem;
187 }
188
getAlphaTypeItemName(AlphaType alphaType)189 static string getAlphaTypeItemName(AlphaType alphaType)
190 {
191 switch (alphaType) {
192 case AlphaType::IMAGE_ALPHA_TYPE_OPAQUE:
193 return "OPAQUE";
194 case AlphaType::IMAGE_ALPHA_TYPE_PREMUL:
195 return "PREMUL";
196 case AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL:
197 return "UNPREMUL";
198 default:
199 return "UNKNOWN";
200 }
201 }
202
findAlphaTypeEnumItem(ani_env * env,AlphaType alphaType)203 static ani_enum_item findAlphaTypeEnumItem([[maybe_unused]] ani_env* env, AlphaType alphaType)
204 {
205 ani_enum type;
206 if (ANI_OK != env->FindEnum("L@ohos/multimedia/image/image/AlphaType;", &type)) {
207 IMAGE_LOGE("FindEnum for AlphaType Failed");
208 return {};
209 }
210
211 string itemName = getAlphaTypeItemName(alphaType);
212
213 ani_enum_item enumItem;
214 if (ANI_OK != env->Enum_GetEnumItemByName(type, itemName.c_str(), &enumItem)) {
215 IMAGE_LOGE("Enum_GetEnumItemByName for AlphaType Failed");
216 return {};
217 }
218
219 return enumItem;
220 }
221
CreateImageInfoValueFromNative(ani_env * env,const ImageInfo & imgInfo,PixelMap * pixelmap)222 ani_object ImageAniUtils::CreateImageInfoValueFromNative(ani_env* env, const ImageInfo &imgInfo, PixelMap* pixelmap)
223 {
224 ani_object imageInfoValue = CreateAniImageInfo(env);
225 if (imageInfoValue == nullptr) {
226 return nullptr;
227 }
228
229 if (!SetImageInfoSize(env, imgInfo, imageInfoValue)) {
230 return nullptr;
231 }
232 if (ANI_OK != env->Object_CallMethodByName_Void(imageInfoValue, "<set>density", "I:V",
233 static_cast<ani_int>(imgInfo.baseDensity))) {
234 IMAGE_LOGE("Object_CallMethodByName_Void <set>density failed");
235 return nullptr;
236 }
237 if (ANI_OK != env->Object_CallMethodByName_Void(imageInfoValue, "<set>stride", "I:V",
238 static_cast<ani_int>(imgInfo.size.height))) {
239 IMAGE_LOGE("Object_CallMethodByName_Void <set>stride failed");
240 return nullptr;
241 }
242 if (ANI_OK != env->Object_CallMethodByName_Void(imageInfoValue, "<set>pixelFormat",
243 "L@ohos/multimedia/image/image/PixelMapFormat;:V", findPixelFormatEnumItem(env, imgInfo.pixelFormat))) {
244 IMAGE_LOGE("Object_CallMethodByName_Void <set>pixelFormat failed");
245 return nullptr;
246 }
247 if (ANI_OK != env->Object_CallMethodByName_Void(imageInfoValue, "<set>alphaType",
248 "L@ohos/multimedia/image/image/AlphaType;:V", findAlphaTypeEnumItem(env, imgInfo.alphaType))) {
249 IMAGE_LOGE("Object_CallMethodByName_Void <set>alphaType failed");
250 return nullptr;
251 }
252 ani_string encodeStr = ImageAniUtils::GetAniString(env, imgInfo.encodedFormat);
253 if (ANI_OK != env->Object_CallMethodByName_Void(imageInfoValue, "<set>mimeType",
254 "Lstd/core/String;:V", encodeStr)) {
255 IMAGE_LOGE("Object_CallMethodByName_Void <set>encodedFormat failed ");
256 return nullptr;
257 }
258
259 if (pixelmap != nullptr) {
260 if (ANI_OK != env->Object_CallMethodByName_Void(imageInfoValue, "<set>isHdr", "Z:V", pixelmap->IsHdr())) {
261 IMAGE_LOGE("Object_CallMethodByName_Void <set>isHdr failed ");
262 return nullptr;
263 }
264 }
265 return imageInfoValue;
266 }
267
CreateAniPixelMap(ani_env * env,std::unique_ptr<PixelMapAni> & pPixelMapAni)268 ani_object ImageAniUtils::CreateAniPixelMap(ani_env* env, std::unique_ptr<PixelMapAni>& pPixelMapAni)
269 {
270 static const char* className = "L@ohos/multimedia/image/image/PixelMapInner;";
271 ani_class cls;
272 if (ANI_OK != env->FindClass(className, &cls)) {
273 IMAGE_LOGE("Not found L@ohos/multimedia/image/image/PixelMapInner;");
274 return nullptr;
275 }
276 ani_method ctor;
277 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", "J:V", &ctor)) {
278 IMAGE_LOGE("Not found <ctor>");
279 return nullptr;
280 }
281 ani_object aniValue;
282 if (ANI_OK != env->Object_New(cls, ctor, &aniValue, reinterpret_cast<ani_long>(pPixelMapAni.release()))) {
283 IMAGE_LOGE("New Context Fail");
284 }
285 return aniValue;
286 }
287
CreateAniImageSource(ani_env * env,std::unique_ptr<ImageSourceAni> & pImageSourceAni)288 ani_object ImageAniUtils::CreateAniImageSource(ani_env* env, std::unique_ptr<ImageSourceAni>& pImageSourceAni)
289 {
290 static const char* className = "L@ohos/multimedia/image/image/ImageSourceInner;";
291 ani_class cls;
292 if (ANI_OK != env->FindClass(className, &cls)) {
293 IMAGE_LOGE("Not found L@ohos/multimedia/image/image/ImageSourceInner;");
294 return nullptr;
295 }
296
297 ani_method ctor;
298 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", "J:V", &ctor)) {
299 IMAGE_LOGE("Not found <ctor>");
300 return nullptr;
301 }
302
303 ani_object aniValue;
304 if (ANI_OK != env->Object_New(cls, ctor, &aniValue, reinterpret_cast<ani_long>(pImageSourceAni.release()))) {
305 IMAGE_LOGE("New Context Fail");
306 }
307 return aniValue;
308 }
309
CreateAniPicture(ani_env * env,std::unique_ptr<PictureAni> & pPictureAni)310 ani_object ImageAniUtils::CreateAniPicture(ani_env* env, std::unique_ptr<PictureAni>& pPictureAni)
311 {
312 static const char* className = "L@ohos/multimedia/image/image/PictureInner;";
313 ani_class cls;
314 if (ANI_OK != env->FindClass(className, &cls)) {
315 IMAGE_LOGE("Not found L@ohos/multimedia/image/image/PictureInner;");
316 return nullptr;
317 }
318 ani_method ctor;
319 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", "J:V", &ctor)) {
320 IMAGE_LOGE("Not found <ctor>");
321 return nullptr;
322 }
323 ani_object aniValue;
324 if (ANI_OK != env->Object_New(cls, ctor, &aniValue, reinterpret_cast<ani_long>(pPictureAni.release()))) {
325 IMAGE_LOGE("New Context Fail");
326 }
327 return aniValue;
328 }
329
GetAniString(ani_env * env,const string & str)330 ani_string ImageAniUtils::GetAniString(ani_env *env, const string &str)
331 {
332 ani_string aniMimeType = nullptr;
333 const char *utf8String = str.c_str();
334 const ani_size stringLength = strlen(utf8String);
335 env->String_NewUTF8(utf8String, stringLength, &aniMimeType);
336 return aniMimeType;
337 }
338
GetRecordSetMethod(ani_env * env,ani_object & argumentObj)339 ani_method ImageAniUtils::GetRecordSetMethod(ani_env* env, ani_object &argumentObj)
340 {
341 ani_status status;
342 ani_class recordCls;
343 status = env->FindClass("Lescompat/Record;", &recordCls);
344 if (status != ANI_OK) {
345 IMAGE_LOGE("FindClass failed status :%{public}u", status);
346 return nullptr;
347 }
348 ani_method ctor;
349 status = env->Class_FindMethod(recordCls, "<ctor>", nullptr, &ctor);
350 if (status != ANI_OK) {
351 IMAGE_LOGE("Class_FindMethod failed status :%{public}u", status);
352 return nullptr;
353 }
354 if (ANI_OK != env->Object_New(recordCls, ctor, &argumentObj)) {
355 IMAGE_LOGE("Object_New Failed");
356 return nullptr;
357 }
358 ani_method recordSetMethod;
359 status = env->Class_FindMethod(recordCls, "$_set",
360 "Lstd/core/Object;Lstd/core/Object;:V", &recordSetMethod);
361 if (status != ANI_OK) {
362 IMAGE_LOGE("Class_FindMethod recordSetMethod Failed");
363 return nullptr;
364 }
365 return recordSetMethod;
366 }
367 } // Meida
368 } // OHOS