1 /*
2  * Copyright (C) 2022 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_pixel_map_napi_kits.h"
17 
18 #include <map>
19 #include <set>
20 #include "pixel_map_napi.h"
21 
22 namespace {
23     constexpr uint32_t NUM_0 = 0;
24     constexpr uint32_t NUM_1 = 1;
25 }
26 
27 namespace OHOS {
28 namespace Media {
29 using PixelMapNapiEnvFunc = int32_t (*)(napi_env env, PixelMapNapiArgs* args);
30 using PixelMapNapiCtxFunc = int32_t (*)(PixelMapNapi* native, PixelMapNapiArgs* args);
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
makeUndefined(napi_env env,napi_value * value)35 static bool makeUndefined(napi_env env, napi_value* value)
36 {
37     if (env != nullptr) {
38         napi_get_undefined(env, value);
39         return true;
40     }
41     return false;
42 }
43 
isUndefine(napi_env env,napi_value value)44 static bool isUndefine(napi_env env, napi_value value)
45 {
46     napi_valuetype res = napi_undefined;
47     napi_typeof(env, value, &res);
48     return (res == napi_undefined);
49 }
50 
GetPixelMap(PixelMapNapi * napi,PixelMapNapiArgs * args,int32_t & error)51 static std::shared_ptr<PixelMap> GetPixelMap(PixelMapNapi* napi, PixelMapNapiArgs* args,
52     int32_t &error)
53 {
54     if (napi == nullptr || napi->GetPixelNapiInner() == nullptr) {
55         error = IMAGE_RESULT_DATA_ABNORMAL;
56         return nullptr;
57     }
58     return napi->GetPixelNapiInner();
59 }
60 
ParsePixelForamt(int32_t val)61 static PixelFormat ParsePixelForamt(int32_t val)
62 {
63     if (val < static_cast<int32_t>(PixelFormat::EXTERNAL_MAX)) {
64         return PixelFormat(val);
65     }
66 
67     return PixelFormat::UNKNOWN;
68 }
ParseAlphaType(int32_t val)69 static AlphaType ParseAlphaType(int32_t val)
70 {
71     if (val <= static_cast<int32_t>(AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL)) {
72         return AlphaType(val);
73     }
74 
75     return AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
76 }
77 
ParseScaleMode(int32_t val)78 static ScaleMode ParseScaleMode(int32_t val)
79 {
80     if (val <= static_cast<int32_t>(ScaleMode::CENTER_CROP)) {
81         return ScaleMode(val);
82     }
83 
84     return ScaleMode::FIT_TARGET_SIZE;
85 }
86 
ParseAntiAliasingOption(int32_t val)87 static AntiAliasingOption ParseAntiAliasingOption(int32_t val)
88 {
89     if (val <= static_cast<int32_t>(AntiAliasingOption::SPLINE)) {
90         return AntiAliasingOption(val);
91     }
92 
93     return AntiAliasingOption::NONE;
94 }
95 
PixelMapNapiCreate(napi_env env,PixelMapNapiArgs * args)96 static int32_t PixelMapNapiCreate(napi_env env, PixelMapNapiArgs* args)
97 {
98     if (args == nullptr || args->outValue == nullptr) {
99         return IMAGE_RESULT_INVALID_PARAMETER;
100     }
101     napi_value undefinedValue = nullptr;
102     if ((!makeUndefined(env, &undefinedValue)) || args->inBuffer == nullptr || args->bufferLen <= NUM_0) {
103         *(args->outValue) = undefinedValue;
104         return IMAGE_RESULT_GET_DATA_ABNORMAL;
105     }
106 
107     *(args->outValue) = undefinedValue;
108     InitializationOptions info;
109     info.alphaType = ParseAlphaType(args->createOptions.alphaType);
110     info.editable = args->createOptions.editable != NUM_0;
111     info.pixelFormat = ParsePixelForamt(args->createOptions.pixelFormat);
112     info.scaleMode = ParseScaleMode(args->createOptions.scaleMode);
113     info.srcRowStride = args->rowStride;
114     info.useDMA = args->useDMA;
115     info.size.height = static_cast<int32_t>(args->createOptions.height);
116     info.size.width = static_cast<int32_t>(args->createOptions.width);
117 
118     BUILD_PARAM pam;
119     pam.offset_ = 0;
120     pam.width_ = info.size.width;
121     pam.flag_ = false;
122     int32_t error = IMAGE_RESULT_SUCCESS;
123     if (info.pixelFormat == PixelFormat::RGBA_1010102 ||
124         info.pixelFormat == PixelFormat::YCBCR_P010 ||
125         info.pixelFormat == PixelFormat::YCRCB_P010) {
126         error = IMAGE_RESULT_BAD_PARAMETER;
127         return error;
128     }
129     auto pixelmap = PixelMap::Create(static_cast<uint32_t*>(args->inBuffer), args->bufferLen, pam, info, error);
130     if (pixelmap == nullptr) {
131         return error;
132     }
133 
134     *(args->outValue) = PixelMapNapi::CreatePixelMap(env, std::move(pixelmap));
135     return isUndefine(env, *(args->outValue))?IMAGE_RESULT_BAD_PARAMETER:IMAGE_RESULT_SUCCESS;
136 }
137 
PixelMapNapiCreateAlpha(napi_env env,PixelMapNapiArgs * args)138 static int32_t PixelMapNapiCreateAlpha(napi_env env, PixelMapNapiArgs* args)
139 {
140     if (args == nullptr || args->outValue == nullptr) {
141         return IMAGE_RESULT_INVALID_PARAMETER;
142     }
143     napi_value undefinedValue = nullptr;
144     if ((!makeUndefined(env, &undefinedValue)) || args->inValue == nullptr) {
145         *(args->outValue) = undefinedValue;
146         return IMAGE_RESULT_GET_DATA_ABNORMAL;
147     }
148     *(args->outValue) = undefinedValue;
149 
150     auto pixelmap = PixelMapNapi::GetPixelMap(env, args->inValue);
151     if (pixelmap == nullptr) {
152         return IMAGE_RESULT_BAD_PARAMETER;
153     }
154 
155     InitializationOptions opts;
156     opts.pixelFormat = PixelFormat::ALPHA_8;
157     Rect rect;
158     int32_t error = IMAGE_RESULT_SUCCESS;
159     auto alphaPixelMap = PixelMap::Create(*pixelmap, rect, opts, error);
160     if (alphaPixelMap == nullptr) {
161         return error;
162     }
163 
164     *(args->outValue) = PixelMapNapi::CreatePixelMap(env, std::move(alphaPixelMap));
165     return isUndefine(env, *(args->outValue))?IMAGE_RESULT_BAD_PARAMETER:IMAGE_RESULT_SUCCESS;
166 }
167 
CheckAndGetPixelMap(PixelMapNapi * native,PixelMapNapiArgs * args,int32_t error)168 static std::shared_ptr<PixelMap> CheckAndGetPixelMap(PixelMapNapi* native, PixelMapNapiArgs* args,
169     int32_t error)
170 {
171     return args == nullptr ? nullptr : GetPixelMap(native, args, error);
172 }
173 
PixelMapNapiGetRowBytes(PixelMapNapi * native,PixelMapNapiArgs * args)174 static int32_t PixelMapNapiGetRowBytes(PixelMapNapi* native, PixelMapNapiArgs* args)
175 {
176     int32_t error = IMAGE_RESULT_SUCCESS;
177     auto pixelmap = CheckAndGetPixelMap(native, args, error);
178     if (pixelmap == nullptr) {
179         return error != 0 ? error : IMAGE_RESULT_INVALID_PARAMETER;
180     }
181     *(args->outNum) = pixelmap->GetRowBytes();
182     return IMAGE_RESULT_SUCCESS;
183 }
184 
PixelMapNapiIsEditable(PixelMapNapi * native,PixelMapNapiArgs * args)185 static int32_t PixelMapNapiIsEditable(PixelMapNapi* native, PixelMapNapiArgs* args)
186 {
187     int32_t error = IMAGE_RESULT_SUCCESS;
188     auto pixelmap = CheckAndGetPixelMap(native, args, error);
189     if (pixelmap == nullptr) {
190         return error != 0 ? error : IMAGE_RESULT_INVALID_PARAMETER;
191     }
192 
193     *(args->outNum) = pixelmap->IsEditable();
194     return IMAGE_RESULT_SUCCESS;
195 }
196 
PixelMapNapiIsSupportAlpha(PixelMapNapi * native,PixelMapNapiArgs * args)197 static int32_t PixelMapNapiIsSupportAlpha(PixelMapNapi* native, PixelMapNapiArgs* args)
198 {
199     int32_t error = IMAGE_RESULT_SUCCESS;
200     auto pixelmap = CheckAndGetPixelMap(native, args, error);
201     if (pixelmap == nullptr) {
202         return error != 0 ? error : IMAGE_RESULT_INVALID_PARAMETER;
203     }
204 
205     *(args->outNum) = pixelmap->GetAlphaType() != AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
206     return IMAGE_RESULT_SUCCESS;
207 }
208 
PixelMapNapiSetAlphaAble(PixelMapNapi * native,PixelMapNapiArgs * args)209 static int32_t PixelMapNapiSetAlphaAble(PixelMapNapi* native, PixelMapNapiArgs* args)
210 {
211     int32_t error = IMAGE_RESULT_SUCCESS;
212     auto pixelmap = CheckAndGetPixelMap(native, args, error);
213     if (pixelmap == nullptr) {
214         return error != 0 ? error : IMAGE_RESULT_INVALID_PARAMETER;
215     }
216 
217     auto alphaType = pixelmap->GetAlphaType();
218     if ((args->inNum0 != NUM_0) && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE)) {
219         pixelmap->SetAlphaType(AlphaType::IMAGE_ALPHA_TYPE_PREMUL);
220     } else if ((args->inNum0 == NUM_0) && !(alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE)) {
221         pixelmap->SetAlphaType(AlphaType::IMAGE_ALPHA_TYPE_OPAQUE);
222     } else {
223         return IMAGE_RESULT_BAD_PARAMETER;
224     }
225 
226     return IMAGE_RESULT_SUCCESS;
227 }
228 
PixelMapNapiGetDensity(PixelMapNapi * native,PixelMapNapiArgs * args)229 static int32_t PixelMapNapiGetDensity(PixelMapNapi* native, PixelMapNapiArgs* args)
230 {
231     int32_t error = IMAGE_RESULT_SUCCESS;
232     auto pixelmap = CheckAndGetPixelMap(native, args, error);
233     if (pixelmap == nullptr) {
234         return error != 0 ? error : IMAGE_RESULT_INVALID_PARAMETER;
235     }
236 
237     *(args->outNum) = pixelmap->GetBaseDensity();
238     return IMAGE_RESULT_SUCCESS;
239 }
240 
PixelMapNapiSetDensity(PixelMapNapi * native,PixelMapNapiArgs * args)241 static int32_t PixelMapNapiSetDensity(PixelMapNapi* native, PixelMapNapiArgs* args)
242 {
243     int32_t error = IMAGE_RESULT_SUCCESS;
244     auto pixelmap = CheckAndGetPixelMap(native, args, error);
245     if (pixelmap == nullptr) {
246         return error != 0 ? error : IMAGE_RESULT_INVALID_PARAMETER;
247     }
248 
249     ImageInfo imageinfo;
250     pixelmap->GetImageInfo(imageinfo);
251     if (imageinfo.baseDensity != args->inNum0) {
252         imageinfo.baseDensity = args->inNum0;
253         if (pixelmap->SetImageInfo(imageinfo, true) != IMAGE_RESULT_SUCCESS) {
254             return IMAGE_RESULT_INDEX_INVALID;
255         }
256     }
257     return IMAGE_RESULT_SUCCESS;
258 }
259 
PixelMapNapiSetOpacity(PixelMapNapi * native,PixelMapNapiArgs * args)260 static int32_t PixelMapNapiSetOpacity(PixelMapNapi* native, PixelMapNapiArgs* args)
261 {
262     int32_t error = IMAGE_RESULT_SUCCESS;
263     auto pixelmap = CheckAndGetPixelMap(native, args, error);
264     if (pixelmap == nullptr) {
265         return error != 0 ? error : IMAGE_RESULT_INVALID_PARAMETER;
266     }
267 
268     if (pixelmap->SetAlpha(args->inFloat0) != IMAGE_RESULT_SUCCESS) {
269         return IMAGE_RESULT_BAD_PARAMETER;
270     }
271     return IMAGE_RESULT_SUCCESS;
272 }
273 
PixelMapNapiScale(PixelMapNapi * native,PixelMapNapiArgs * args)274 static int32_t PixelMapNapiScale(PixelMapNapi* native, PixelMapNapiArgs* args)
275 {
276     int32_t error = IMAGE_RESULT_SUCCESS;
277     auto pixelmap = CheckAndGetPixelMap(native, args, error);
278     if (pixelmap == nullptr) {
279         return error != 0 ? error : IMAGE_RESULT_INVALID_PARAMETER;
280     }
281 
282     if (args->inNum0 == static_cast<int32_t>(AntiAliasingOption::NONE)) {
283         pixelmap->scale(args->inFloat0, args->inFloat1);
284     } else {
285         pixelmap->scale(args->inFloat0, args->inFloat1, ParseAntiAliasingOption(args->inNum0));
286     }
287     return pixelmap->errorCode == 0 ? IMAGE_RESULT_SUCCESS : pixelmap->errorCode;
288 }
289 
PixelMapNapiTranslate(PixelMapNapi * native,PixelMapNapiArgs * args)290 static int32_t PixelMapNapiTranslate(PixelMapNapi* native, PixelMapNapiArgs* args)
291 {
292     int32_t error = IMAGE_RESULT_SUCCESS;
293     auto pixelmap = CheckAndGetPixelMap(native, args, error);
294     if (pixelmap == nullptr) {
295         return error != 0 ? error : IMAGE_RESULT_INVALID_PARAMETER;
296     }
297 
298     pixelmap->translate(args->inFloat0, args->inFloat1);
299     return pixelmap->errorCode == 0 ? IMAGE_RESULT_SUCCESS : pixelmap->errorCode;
300 }
301 
PixelMapNapiRotate(PixelMapNapi * native,PixelMapNapiArgs * args)302 static int32_t PixelMapNapiRotate(PixelMapNapi* native, PixelMapNapiArgs* args)
303 {
304     int32_t error = IMAGE_RESULT_SUCCESS;
305     auto pixelmap = CheckAndGetPixelMap(native, args, error);
306     if (pixelmap == nullptr) {
307         return error != 0 ? error : IMAGE_RESULT_INVALID_PARAMETER;
308     }
309 
310     pixelmap->rotate(args->inFloat0);
311     return pixelmap->errorCode == 0 ? IMAGE_RESULT_SUCCESS : pixelmap->errorCode;
312 }
313 
PixelMapNapiFlip(PixelMapNapi * native,PixelMapNapiArgs * args)314 static int32_t PixelMapNapiFlip(PixelMapNapi* native, PixelMapNapiArgs* args)
315 {
316     int32_t error = IMAGE_RESULT_SUCCESS;
317     auto pixelmap = CheckAndGetPixelMap(native, args, error);
318     if (pixelmap == nullptr) {
319         return error != 0 ? error : IMAGE_RESULT_INVALID_PARAMETER;
320     }
321 
322     pixelmap->flip((args->inNum0 == NUM_1), (args->inNum1 == NUM_1));
323     return pixelmap->errorCode == 0 ? IMAGE_RESULT_SUCCESS : pixelmap->errorCode;
324 }
325 
PixelMapNapiCrop(PixelMapNapi * native,PixelMapNapiArgs * args)326 static int32_t PixelMapNapiCrop(PixelMapNapi* native, PixelMapNapiArgs* args)
327 {
328     int32_t error = IMAGE_RESULT_SUCCESS;
329     auto pixelmap = CheckAndGetPixelMap(native, args, error);
330     if (pixelmap == nullptr) {
331         return error != 0 ? error : IMAGE_RESULT_INVALID_PARAMETER;
332     }
333     Rect region;
334     region.left = args->inNum0;
335     region.top = args->inNum1;
336     region.width = args->inNum2;
337     region.height = args->inNum3;
338     pixelmap->crop(region);
339     return pixelmap->errorCode == 0 ? IMAGE_RESULT_SUCCESS : pixelmap->errorCode;
340 }
341 
PixelMapNapiGetImageInfo(PixelMapNapi * native,PixelMapNapiArgs * args)342 static int32_t PixelMapNapiGetImageInfo(PixelMapNapi* native, PixelMapNapiArgs* args)
343 {
344     int32_t error = IMAGE_RESULT_SUCCESS;
345     auto pixelmap = CheckAndGetPixelMap(native, args, error);
346     if (pixelmap == nullptr || args->outInfo == nullptr) {
347         return error != 0 ? error : IMAGE_RESULT_INVALID_PARAMETER;
348     }
349 
350     ImageInfo srcInfo;
351     pixelmap->GetImageInfo(srcInfo);
352     args->outInfo->width = static_cast<uint32_t>(srcInfo.size.width);
353     args->outInfo->height = static_cast<uint32_t>(srcInfo.size.height);
354     args->outInfo->rowSize = static_cast<uint32_t>(pixelmap->GetRowStride());
355     args->outInfo->pixelFormat = static_cast<int32_t>(srcInfo.pixelFormat);
356     return pixelmap->errorCode == 0 ? IMAGE_RESULT_SUCCESS : pixelmap->errorCode;
357 }
358 
PixelMapNapiAccessPixels(PixelMapNapi * native,PixelMapNapiArgs * args)359 static int32_t PixelMapNapiAccessPixels(PixelMapNapi* native, PixelMapNapiArgs* args)
360 {
361     int32_t error = IMAGE_RESULT_SUCCESS;
362     auto pixelmap = CheckAndGetPixelMap(native, args, error);
363     if (pixelmap == nullptr) {
364         return error != 0 ? error : IMAGE_RESULT_INVALID_PARAMETER;
365     }
366     native->LockPixelMap();
367     *(args->outAddr) = static_cast<uint8_t*>(pixelmap->GetWritablePixels());
368     return pixelmap->errorCode == 0 ? IMAGE_RESULT_SUCCESS : pixelmap->errorCode;
369 }
370 
PixelMapNapiUnAccessPixels(PixelMapNapi * native,PixelMapNapiArgs * args)371 static int32_t PixelMapNapiUnAccessPixels(PixelMapNapi* native, PixelMapNapiArgs* args)
372 {
373     if (native != nullptr) {
374         native->UnlockPixelMap();
375         return IMAGE_RESULT_SUCCESS;
376     } else {
377         return IMAGE_RESULT_INVALID_PARAMETER;
378     }
379 }
380 
381 static const std::map<int32_t, PixelMapNapiEnvFunc> g_EnvFunctions = {
382     {ENV_FUNC_CREATE, PixelMapNapiCreate},
383     {ENV_FUNC_CREATE_ALPHA, PixelMapNapiCreateAlpha},
384 };
385 static const std::map<int32_t, PixelMapNapiCtxFunc> g_CtxFunctions = {
386     {CTX_FUNC_GET_ROW_BYTES, PixelMapNapiGetRowBytes},
387     {CTX_FUNC_IS_EDITABLE, PixelMapNapiIsEditable},
388     {CTX_FUNC_IS_SUPPORT_ALPHA, PixelMapNapiIsSupportAlpha},
389     {CTX_FUNC_GET_DENSITY, PixelMapNapiGetDensity},
390     {CTX_FUNC_SET_ALPHAABLE, PixelMapNapiSetAlphaAble},
391     {CTX_FUNC_SET_DENSITY, PixelMapNapiSetDensity},
392     {CTX_FUNC_SET_OPACITY, PixelMapNapiSetOpacity},
393     {CTX_FUNC_SCALE, PixelMapNapiScale},
394     {CTX_FUNC_TRANSLATE, PixelMapNapiTranslate},
395     {CTX_FUNC_ROTATE, PixelMapNapiRotate},
396     {CTX_FUNC_FLIP, PixelMapNapiFlip},
397     {CTX_FUNC_CROP, PixelMapNapiCrop},
398     {CTX_FUNC_GET_IMAGE_INFO, PixelMapNapiGetImageInfo},
399     {CTX_FUNC_ACCESS_PIXELS, PixelMapNapiAccessPixels},
400     {CTX_FUNC_UNACCESS_PIXELS, PixelMapNapiUnAccessPixels},
401 };
402 
403 MIDK_EXPORT
PixelMapNapiNativeEnvCall(int32_t mode,napi_env env,PixelMapNapiArgs * args)404 int32_t PixelMapNapiNativeEnvCall(int32_t mode, napi_env env, PixelMapNapiArgs* args)
405 {
406     auto funcSearch = g_EnvFunctions.find(mode);
407     if (funcSearch == g_EnvFunctions.end()) {
408         return IMAGE_RESULT_JNI_ENV_ABNORMAL;
409     }
410     return funcSearch->second(env, args);
411 }
412 
413 MIDK_EXPORT
PixelMapNapiNativeCtxCall(int32_t mode,PixelMapNapi * native,PixelMapNapiArgs * args)414 int32_t PixelMapNapiNativeCtxCall(int32_t mode, PixelMapNapi* native, PixelMapNapiArgs* args)
415 {
416     auto funcSearch = g_CtxFunctions.find(mode);
417     if (funcSearch == g_CtxFunctions.end()) {
418         return IMAGE_RESULT_JNI_ENV_ABNORMAL;
419     }
420     return funcSearch->second(native, args);
421 }
422 
423 MIDK_EXPORT
PixelMapNapi_Unwrap(napi_env env,napi_value value)424 PixelMapNapi* PixelMapNapi_Unwrap(napi_env env, napi_value value)
425 {
426     napi_valuetype valueType;
427     napi_typeof(env, value, &valueType);
428     if (valueType != napi_object) {
429         return nullptr;
430     }
431     std::unique_ptr<PixelMapNapi> pixelMapNapi = nullptr;
432     napi_status status = napi_unwrap(env, value, reinterpret_cast<void**>(&pixelMapNapi));
433     if ((status == napi_ok) && pixelMapNapi != nullptr) {
434         return pixelMapNapi.release();
435     }
436     return nullptr;
437 }
438 #ifdef __cplusplus
439 };
440 #endif
441 }  // namespace Media
442 }  // namespace OHOS
443