• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 #include "image_ani_utils.h"
21 #include "image_log.h"
22 #include "log_tags.h"
23 #include "media_errors.h"
24 #include "pixel_map_ani.h"
25 
26 #undef LOG_DOMAIN
27 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
28 
29 #undef LOG_TAG
30 #define LOG_TAG "PixelMapAni"
31 
32 namespace OHOS {
33 namespace Media {
34 using namespace std;
35 
parseEnumFromStruct(ani_env * env,ani_object & param,string propertyGet,string enumType)36 static ani_int parseEnumFromStruct(ani_env* env, ani_object &param, string propertyGet, string enumType)
37 {
38     ani_status ret;
39     ani_ref enumRef;
40     if (ANI_OK != (ret = env->Object_CallMethodByName_Ref(param, propertyGet.c_str(), enumType.c_str(), &enumRef))) {
41         IMAGE_LOGE("Object_CallMethodByName_Int enumRef Failed: %{public}d", ret);
42         return 0;
43     }
44     ani_boolean undefined;
45     env->Reference_IsUndefined(enumRef, &undefined);
46     if (undefined) {
47         IMAGE_LOGI("Enum %{public}s is undefined", propertyGet.c_str());
48         return 0;
49     }
50 
51     ani_int enumIndex;
52     if (ANI_OK != env->EnumItem_GetValue_Int(static_cast<ani_enum_item>(enumRef), &enumIndex)) {
53         IMAGE_LOGE("EnumItem_GetValue_Int enumIndex Failed: %{public}d", ret);
54         return 0;
55     }
56     return enumIndex;
57 }
58 
ParseInitializationOptions(ani_env * env,ani_object param,InitializationOptions & opts)59 static bool ParseInitializationOptions([[maybe_unused]] ani_env* env, ani_object param, InitializationOptions &opts)
60 {
61     ani_boolean isUndefined;
62     env->Reference_IsUndefined(param, &isUndefined);
63     if (isUndefined) {
64         IMAGE_LOGE("ParseInitializationOptions isUndefined ");
65         return false;
66     }
67     ani_class dateCls;
68     const char *className = "L@ohos/multimedia/image/image/Size;";
69     if (ANI_OK != env->FindClass(className, &dateCls)) {
70         IMAGE_LOGE("Not found %{public}s", className);
71         return false;
72     }
73     ani_ref size;
74     if (ANI_OK != env->Object_CallMethodByName_Ref(param, "<get>size", ":L@ohos/multimedia/image/image/Size;", &size)) {
75         IMAGE_LOGE("Object_GetFieldByName_Ref Failed");
76     }
77     ani_status ret;
78     if (ANI_OK != env->Object_CallMethodByName_Int(reinterpret_cast<ani_object>(size),
79         "<get>width", ":I", &opts.size.width)) {
80         IMAGE_LOGE("Object_CallMethodByName_Int width Failed");
81     }
82     if ((ret = env->Object_CallMethodByName_Int(reinterpret_cast<ani_object>(size),
83         "<get>height", ":I", &opts.size.height)) != ANI_OK) {
84         IMAGE_LOGE("Object_CallMethodByName_Int height Failed");
85     }
86     opts.srcPixelFormat = PixelFormat(parseEnumFromStruct(env, param, "<get>srcPixelFormat",
87         ":L@ohos/multimedia/image/image/PixelMapFormat;"));
88     opts.pixelFormat = PixelFormat(parseEnumFromStruct(env, param, "<get>pixelFormat",
89         ":L@ohos/multimedia/image/image/PixelMapFormat;"));
90     ani_ref editableRef;
91     if (ANI_OK != (ret = env->Object_CallMethodByName_Ref(param,
92         "<get>editable", ":Lstd/core/Boolean;", &editableRef))) {
93         IMAGE_LOGE("Object_CallMethodByName_Int Failed editableRef:%{public}d", ret);
94     }
95     ani_boolean editable;
96     if ((ret = env->Object_CallMethodByName_Boolean(reinterpret_cast<ani_object>(editableRef),
97         "unboxed", ":Z", &editable)) != ANI_OK) {
98         IMAGE_LOGE("Object_CallMethodByName_Int Failed editable:%{public}d", ret);
99     }
100     opts.alphaType = AlphaType(parseEnumFromStruct(env, param, "<get>alphaType",
101         ":L@ohos/multimedia/image/image/AlphaType;"));
102     opts.scaleMode = ScaleMode(parseEnumFromStruct(env, param, "<get>scaleMode",
103         ":L@ohos/multimedia/image/image/ScaleMode;"));
104     return true;
105 }
106 
ParseRegion(ani_env * env,ani_object region,Rect & rect)107 static bool ParseRegion([[maybe_unused]] ani_env* env, ani_object region, Rect& rect)
108 {
109     ani_boolean undefined;
110     env->Reference_IsUndefined(region, &undefined);
111     if (undefined) {
112         IMAGE_LOGE("ParseRegion argument undefined");
113         return false;
114     }
115 
116     ani_ref size;
117     if (ANI_OK != env->Object_CallMethodByName_Ref(region, "<get>size", ":L@ohos/multimedia/image/image/Size;",
118         &size)) {
119         IMAGE_LOGE("Object_GetFieldByName_Ref Failed");
120         return false;
121     }
122     if (ANI_OK != env->Object_CallMethodByName_Int(reinterpret_cast<ani_object>(size), "<get>width", ":I",
123         &rect.width)) {
124         IMAGE_LOGE("Object_CallMethodByName_Int width Failed");
125         return false;
126     }
127     if (ANI_OK != env->Object_CallMethodByName_Int(reinterpret_cast<ani_object>(size), "<get>height", ":I",
128         &rect.height)) {
129         IMAGE_LOGE("Object_CallMethodByName_Int height Failed");
130         return false;
131     }
132 
133     if (ANI_OK != env->Object_CallMethodByName_Int(region, "<get>x", ":I", &rect.left)) {
134         IMAGE_LOGE("Object_CallMethodByName_Int x Failed");
135         return false;
136     }
137     if (ANI_OK != env->Object_CallMethodByName_Int(region, "<get>y", ":I", &rect.top)) {
138         IMAGE_LOGE("Object_CallMethodByName_Int y Failed");
139         return false;
140     }
141 
142     return true;
143 }
144 
CreatePixelMap(ani_env * env,std::shared_ptr<PixelMap> pixelMap)145 ani_object PixelMapAni::CreatePixelMap([[maybe_unused]] ani_env* env, std::shared_ptr<PixelMap> pixelMap)
146 {
147     unique_ptr<PixelMapAni> pPixelMapAni = make_unique<PixelMapAni>();
148     pPixelMapAni->nativePixelMap_ = pixelMap;
149     static const char* className = "L@ohos/multimedia/image/image/PixelMapInner;";
150     ani_class cls;
151     if (ANI_OK != env->FindClass(className, &cls)) {
152         IMAGE_LOGE("Not found L@ohos/multimedia/image/image/PixelMapInner");
153         return nullptr;
154     }
155     ani_method ctor;
156     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", "J:V", &ctor)) {
157         IMAGE_LOGE("Not found ani_method");
158         return nullptr;
159     }
160     ani_object aniValue;
161     if (ANI_OK != env->Object_New(cls, ctor, &aniValue, reinterpret_cast<ani_long>(pPixelMapAni.release()))) {
162         IMAGE_LOGE("New Context Fail");
163     }
164     return aniValue;
165 }
166 
CreatePixelMapAni(ani_env * env,ani_object obj)167 ani_object PixelMapAni::CreatePixelMapAni([[maybe_unused]] ani_env* env, ani_object obj)
168 {
169     unique_ptr<PixelMapAni> pPixelMapAni = make_unique<PixelMapAni>();
170     InitializationOptions opts;
171     if (!ParseInitializationOptions(env, obj, opts)) {
172         IMAGE_LOGE("ParseInitializationOptions failed '");
173         return nullptr;
174     }
175 
176     pPixelMapAni->nativePixelMap_ = PixelMap::Create(opts);
177     return ImageAniUtils::CreateAniPixelMap(env, pPixelMapAni);
178 }
179 
CreateAlphaPixelmap(ani_env * env,ani_object obj)180 static ani_object CreateAlphaPixelmap([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj)
181 {
182     PixelMap* pixelMap = ImageAniUtils::GetPixelMapFromEnv(env, obj);
183     if (pixelMap == nullptr) {
184         IMAGE_LOGE("[GetPixelMapFromEnv] pixelMap nullptr");
185         return nullptr;
186     }
187 
188     std::unique_ptr<PixelMapAni> pPixelMapAni = std::make_unique<PixelMapAni>();
189     InitializationOptions opts;
190     opts.pixelFormat = PixelFormat::ALPHA_8;
191     pPixelMapAni->nativePixelMap_ = PixelMap::Create(*pixelMap, opts);
192     return ImageAniUtils::CreateAniPixelMap(env, pPixelMapAni);
193 }
194 
GetImageInfo(ani_env * env,ani_object obj)195 static ani_object GetImageInfo([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj)
196 {
197     PixelMap* pixelmap = ImageAniUtils::GetPixelMapFromEnv(env, obj);
198     if (pixelmap == nullptr) {
199         IMAGE_LOGE("[GetPixelMapFromEnv] pixelmap nullptr ");
200         return nullptr;
201     }
202     ImageInfo imgInfo;
203     pixelmap->GetImageInfo(imgInfo);
204     return ImageAniUtils::CreateImageInfoValueFromNative(env, imgInfo, pixelmap);
205 }
206 
GetBytesNumberPerRow(ani_env * env,ani_object obj)207 static ani_int GetBytesNumberPerRow([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj)
208 {
209     PixelMap* pixelmap = ImageAniUtils::GetPixelMapFromEnv(env, obj);
210     if (pixelmap == nullptr) {
211         IMAGE_LOGE("[GetPixelMapFromEnv] pixelmap nullptr");
212         return 0;
213     }
214     return pixelmap->GetRowBytes();
215 }
216 
GetPixelBytesNumber(ani_env * env,ani_object obj)217 static ani_int GetPixelBytesNumber([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj)
218 {
219     PixelMap* pixelmap = ImageAniUtils::GetPixelMapFromEnv(env, obj);
220     if (pixelmap == nullptr) {
221         IMAGE_LOGE("[GetPixelMapFromEnv] pixelmap nullptr");
222         return 0;
223     }
224     return pixelmap->GetByteCount();
225 }
226 
Release(ani_env * env,ani_object obj)227 static void Release([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj)
228 {
229     ani_status ret;
230     ani_long nativeObj {};
231     if ((ret = env->Object_GetFieldByName_Long(obj, "nativeObj", &nativeObj)) != ANI_OK) {
232         IMAGE_LOGE("[Release] Object_GetField_Long fetch field");
233         return;
234     }
235     PixelMapAni* pixelmapAni = reinterpret_cast<PixelMapAni*>(nativeObj);
236     pixelmapAni->nativePixelMap_ = nullptr;
237 }
238 
ReadPixelsToBuffer(ani_env * env,ani_object obj,ani_object param0)239 static void ReadPixelsToBuffer(ani_env* env, ani_object obj, ani_object param0)
240 {
241     PixelMap* pixelmap = ImageAniUtils::GetPixelMapFromEnv(env, obj);
242     if (pixelmap == nullptr) {
243         IMAGE_LOGE("[ReadPixelsToBuffer] pixelmap nullptr ");
244         return;
245     }
246     size_t bufferLength = 0;
247     void *dstbuffer = nullptr;
248     ani_arraybuffer arraybuffer = static_cast<ani_arraybuffer>(param0);
249     if (ANI_OK != env->ArrayBuffer_GetInfo(arraybuffer, &dstbuffer, &bufferLength)) {
250         IMAGE_LOGE("[ReadPixelsToBuffer] ArrayBuffer_GetInfo failed");
251     }
252     uint32_t ret = pixelmap->ReadPixels(bufferLength, static_cast<uint8_t*>(dstbuffer));
253     if (ret != 0) {
254         IMAGE_LOGE("[ReadPixelsToBuffer] failed");
255     }
256 }
257 
Scale(ani_env * env,ani_object obj,ani_double x,ani_double y,ani_int level)258 static void Scale([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj, ani_double x, ani_double y,
259     ani_int level)
260 {
261     PixelMap* pixelmap = ImageAniUtils::GetPixelMapFromEnv(env, obj);
262     if (pixelmap == nullptr) {
263         IMAGE_LOGE("[GetPixelMapFromEnv] pixelmap nullptr");
264         return;
265     }
266 
267     ani_int levelIntValue = 0;
268     ani_enum enumType;
269     if (ANI_OK != env->FindEnum("L@ohos/multimedia/image/image/AntiAliasingLevel;", &enumType)) {
270         IMAGE_LOGI("Find Enum AntiAliasingLevel Failed");
271     }
272     ani_enum_item enumItem;
273     if (ANI_OK != env->Enum_GetEnumItemByIndex(enumType, level, &enumItem)) {
274         IMAGE_LOGI("Enum_GetEnumItemByIndex AntiAliasingLevel Failed");
275     }
276     if (ANI_OK != env->EnumItem_GetValue_Int(enumItem, &levelIntValue)) {
277         IMAGE_LOGI("EnumItem_GetValue_Int AntiAliasingLevel Failed");
278     }
279 
280     pixelmap->scale(static_cast<float>(x), static_cast<float>(y), AntiAliasingOption(levelIntValue));
281 }
282 
Crop(ani_env * env,ani_object obj,ani_object region)283 static void Crop([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj, ani_object region)
284 {
285     PixelMap* pixelmap = ImageAniUtils::GetPixelMapFromEnv(env, obj);
286     if (pixelmap == nullptr) {
287         IMAGE_LOGE("[GetPixelMapFromEnv] pixelmap nullptr");
288         return;
289     }
290 
291     Rect rect;
292     if (!ParseRegion(env, region, rect)) {
293         IMAGE_LOGE("ParseRegion failed");
294         return;
295     }
296 
297     pixelmap->crop(rect);
298 }
299 
Flip(ani_env * env,ani_object obj,ani_boolean horizontal,ani_boolean vertical)300 static void Flip([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object obj, ani_boolean horizontal,
301     ani_boolean vertical)
302 {
303     PixelMap* pixelmap = ImageAniUtils::GetPixelMapFromEnv(env, obj);
304     if (pixelmap == nullptr) {
305         IMAGE_LOGE("[GetPixelMapFromEnv] pixelmap nullptr");
306         return;
307     }
308 
309     pixelmap->flip(static_cast<bool>(horizontal), static_cast<bool>(vertical));
310 }
311 
Init(ani_env * env)312 ani_status PixelMapAni::Init(ani_env* env)
313 {
314     static const char *className = "L@ohos/multimedia/image/image/PixelMapInner;";
315     ani_class cls;
316     if (ANI_OK != env->FindClass(className, &cls)) {
317         IMAGE_LOGE("Not found L@ohos/multimedia/image/image/PixelMapInner;");
318         return ANI_ERROR;
319     }
320     std::array methods = {
321         ani_native_function {"nativeCreateAlphaPixelmap", ":L@ohos/multimedia/image/image/PixelMap;",
322             reinterpret_cast<void*>(OHOS::Media::CreateAlphaPixelmap)},
323         ani_native_function {"nativeGetImageInfo", ":L@ohos/multimedia/image/image/ImageInfo;",
324             reinterpret_cast<void*>(OHOS::Media::GetImageInfo)},
325         ani_native_function {"getBytesNumberPerRow", ":I", reinterpret_cast<void*>(OHOS::Media::GetBytesNumberPerRow)},
326         ani_native_function {"getPixelBytesNumber", ":I", reinterpret_cast<void*>(OHOS::Media::GetPixelBytesNumber)},
327         ani_native_function {"nativeRelease", ":V", reinterpret_cast<void*>(OHOS::Media::Release)},
328         ani_native_function {"nativeReadPixelsToBuffer", "Lescompat/ArrayBuffer;:V",
329             reinterpret_cast<void*>(OHOS::Media::ReadPixelsToBuffer)},
330         ani_native_function {"nativeScale", "DDL@ohos/multimedia/image/image/AntiAliasingLevel;:V",
331             reinterpret_cast<void*>(OHOS::Media::Scale)},
332         ani_native_function {"nativeCrop", "L@ohos/multimedia/image/image/Region;:V",
333             reinterpret_cast<void*>(OHOS::Media::Crop)},
334         ani_native_function {"nativeFlip", "ZZ:V", reinterpret_cast<void*>(OHOS::Media::Flip)},
335     };
336     ani_status ret = env->Class_BindNativeMethods(cls, methods.data(), methods.size());
337     if (ANI_OK != ret) {
338         IMAGE_LOGE("[Init] Class_BindNativeMethods failed :%{public}d", ret);
339         return ANI_ERROR;
340     };
341     return ANI_OK;
342 }
343 } // Media
344 } // OHOS