1 /*
2 * Copyright (C) 2023 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_packer_mdk_kits.h"
17
18 #include <map>
19 #include "image_log.h"
20
21 #undef LOG_DOMAIN
22 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
23
24 #undef LOG_TAG
25 #define LOG_TAG "ImagePackerMdk"
26
27 namespace {
28 constexpr size_t SIZE_ZERO = 0;
29 constexpr int INVALID_FD = -1;
30 }
31
32 namespace OHOS {
33 namespace Media {
34 using ImagePackerNativeFunc = int32_t (*)(struct ImagePackerArgs* args);
35
36 enum class PackingSourceType : int32_t {
37 TYPE_INVALID = -1,
38 TYPE_IMAGE_SOURCE,
39 TYPE_PIXEL_MAP,
40 };
41
42 #ifdef __cplusplus
43 extern "C" {
44 #endif
45
IsInstanceOf(napi_env env,napi_value value,napi_value global,const char * type)46 static bool IsInstanceOf(napi_env env, napi_value value, napi_value global, const char* type)
47 {
48 napi_value constructor = nullptr;
49 if (napi_get_named_property(env, global, type, &constructor) != napi_ok) {
50 IMAGE_LOGE("Get constructor property failed!");
51 return false;
52 }
53
54 bool isInstance = false;
55 if (napi_instanceof(env, value, constructor, &isInstance) == napi_ok && isInstance) {
56 return true;
57 }
58 return false;
59 }
60
ParserPackingArgumentType(napi_env env,napi_value source)61 static PackingSourceType ParserPackingArgumentType(napi_env env, napi_value source)
62 {
63 napi_value global = nullptr;
64 if (napi_get_global(env, &global) != napi_ok) {
65 IMAGE_LOGE("Get global property failed!");
66 return PackingSourceType::TYPE_INVALID;
67 }
68
69 if (IsInstanceOf(env, source, global, "ImageSource")) {
70 IMAGE_LOGD("This is ImageSource!");
71 return PackingSourceType::TYPE_IMAGE_SOURCE;
72 } else if (IsInstanceOf(env, source, global, "PixelMap")) {
73 IMAGE_LOGD("This is PixelMap!");
74 return PackingSourceType::TYPE_PIXEL_MAP;
75 }
76
77 IMAGE_LOGE("Invalid type!");
78 return PackingSourceType::TYPE_INVALID;
79 }
80
ImagePackerNapiCreate(struct ImagePackerArgs * args)81 static int32_t ImagePackerNapiCreate(struct ImagePackerArgs* args)
82 {
83 if (args == nullptr || args->inEnv == nullptr || args->outVal == nullptr) {
84 IMAGE_LOGE("ImagePackerNapiCreate bad parameter");
85 return IMAGE_RESULT_BAD_PARAMETER;
86 }
87 *(args->outVal) = ImagePackerNapi::CreateImagePacker(args->inEnv, nullptr);
88 if (*(args->outVal) == nullptr) {
89 IMAGE_LOGE("ImageSourceNapiCreate native create failed");
90 return IMAGE_RESULT_BAD_PARAMETER;
91 }
92 IMAGE_LOGD("ImagePackerNapiCreate success");
93 return IMAGE_RESULT_SUCCESS;
94 }
95
GetNativeImageSouce(napi_env env,napi_value source)96 static std::shared_ptr<ImageSource> GetNativeImageSouce(napi_env env, napi_value source)
97 {
98 std::unique_ptr<ImageSourceNapi> napi = nullptr;
99 napi_status status = napi_unwrap(env, source, reinterpret_cast<void**>(&napi));
100 if ((status == napi_ok) && napi != nullptr) {
101 return napi.release()->nativeImgSrc;
102 }
103 return nullptr;
104 }
105
DoStartPacking(std::shared_ptr<ImagePacker> & packer,struct ImagePackerArgs * args)106 static int32_t DoStartPacking(std::shared_ptr<ImagePacker> &packer, struct ImagePackerArgs* args)
107 {
108 if (args == nullptr || args->inOpts == nullptr) {
109 return IMAGE_RESULT_BAD_PARAMETER;
110 }
111
112 PackOption option;
113 option.format = args->inOpts->format;
114 option.quality = args->inOpts->quality;
115 option.desiredDynamicRange = EncodeDynamicRange::SDR;
116 if (args->outData != nullptr && args->dataSize != nullptr && *(args->dataSize) != SIZE_ZERO) {
117 return packer->StartPacking(args->outData, *(args->dataSize), option);
118 } else if (args->inNum0 > INVALID_FD) {
119 return packer->StartPacking(args->inNum0, option);
120 }
121 IMAGE_LOGE("DoNativePacking StartPacking failed");
122 return IMAGE_RESULT_BAD_PARAMETER;
123 }
124
DoAddImage(std::shared_ptr<ImagePacker> & packer,PackingSourceType type,struct ImagePackerArgs * args)125 static int32_t DoAddImage(std::shared_ptr<ImagePacker> &packer,
126 PackingSourceType type, struct ImagePackerArgs* args)
127 {
128 if (args == nullptr || args->inOpts == nullptr) {
129 return IMAGE_RESULT_BAD_PARAMETER;
130 }
131
132 if (type == PackingSourceType::TYPE_IMAGE_SOURCE) {
133 auto image = GetNativeImageSouce(args->inEnv, args->inVal);
134 if (image != nullptr) {
135 return packer->AddImage(*image);
136 } else {
137 IMAGE_LOGE("DoNativePacking get image source native failed");
138 return IMAGE_RESULT_BAD_PARAMETER;
139 }
140 } else if (type == PackingSourceType::TYPE_PIXEL_MAP) {
141 auto pixel = PixelMapNapi::GetPixelMap(args->inEnv, args->inVal);
142 if (pixel != nullptr) {
143 return packer->AddImage(*pixel);
144 } else {
145 IMAGE_LOGE("DoNativePacking get pixelmap native failed");
146 return IMAGE_RESULT_BAD_PARAMETER;
147 }
148 }
149 IMAGE_LOGE("DoNativePacking unsupport packing source type %{public}d", type);
150 return IMAGE_RESULT_BAD_PARAMETER;
151 }
152
DoNativePacking(struct ImagePackerArgs * args)153 static int32_t DoNativePacking(struct ImagePackerArgs* args)
154 {
155 if (args == nullptr || args->inOpts == nullptr || args->inVal == nullptr) {
156 return IMAGE_RESULT_BAD_PARAMETER;
157 }
158
159 auto type = ParserPackingArgumentType(args->inEnv, args->inVal);
160 if (type == PackingSourceType::TYPE_INVALID) {
161 return IMAGE_RESULT_BAD_PARAMETER;
162 }
163 auto nativeImagePacker = ImagePackerNapi::GetNative(args->inNapi);
164 if (nativeImagePacker == nullptr) {
165 IMAGE_LOGE("DoNativePacking get native failed");
166 return IMAGE_RESULT_BAD_PARAMETER;
167 }
168 int32_t res = DoStartPacking(nativeImagePacker, args);
169 if (res != IMAGE_RESULT_SUCCESS) {
170 IMAGE_LOGE("DoNativePacking StartPacking failed");
171 return res;
172 }
173 res = DoAddImage(nativeImagePacker, type, args);
174 if (res != IMAGE_RESULT_SUCCESS) {
175 IMAGE_LOGE("DoNativePacking AddImage failed");
176 return res;
177 }
178 int64_t packedSize = SIZE_ZERO;
179 res = static_cast<int32_t>(nativeImagePacker->FinalizePacking(packedSize));
180 if (args->dataSize != nullptr) {
181 *args->dataSize = packedSize;
182 }
183 return res;
184 }
ImagePackerNapiPackToData(struct ImagePackerArgs * args)185 static int32_t ImagePackerNapiPackToData(struct ImagePackerArgs* args)
186 {
187 if (args == nullptr || args->inEnv == nullptr ||
188 args->inNapi == nullptr || args->inVal == nullptr ||
189 args->inOpts == nullptr || args->outData == nullptr ||
190 args->dataSize == nullptr || *(args->dataSize) == SIZE_ZERO) {
191 IMAGE_LOGE("ImagePackerNapiPackToData bad parameter");
192 return IMAGE_RESULT_BAD_PARAMETER;
193 }
194 return DoNativePacking(args);
195 }
196
ImagePackerNapiPackToFile(struct ImagePackerArgs * args)197 static int32_t ImagePackerNapiPackToFile(struct ImagePackerArgs* args)
198 {
199 if (args == nullptr || args->inEnv == nullptr ||
200 args->inNapi == nullptr || args->inVal == nullptr ||
201 args->inOpts == nullptr || args->inNum0 <= INVALID_FD) {
202 IMAGE_LOGE("ImagePackerNapiPackToFile bad parameter");
203 return IMAGE_RESULT_BAD_PARAMETER;
204 }
205 return DoNativePacking(args);
206 }
207
208 static const std::map<int32_t, ImagePackerNativeFunc> g_CtxFunctions = {
209 {ENV_FUNC_IMAGEPACKER_CREATE, ImagePackerNapiCreate},
210 {CTX_FUNC_IMAGEPACKER_PACKTODATA, ImagePackerNapiPackToData},
211 {CTX_FUNC_IMAGEPACKER_PACKTOFILE, ImagePackerNapiPackToFile},
212 };
213
214 MIDK_EXPORT
ImagePackerNativeCall(int32_t mode,struct ImagePackerArgs * args)215 int32_t ImagePackerNativeCall(int32_t mode, struct ImagePackerArgs* args)
216 {
217 auto funcSearch = g_CtxFunctions.find(mode);
218 if (funcSearch == g_CtxFunctions.end()) {
219 return IMAGE_RESULT_BAD_PARAMETER;
220 }
221 return funcSearch->second(args);
222 }
223
224 MIDK_EXPORT
ImagePackerNapi_Unwrap(napi_env env,napi_value value)225 ImagePackerNapi* ImagePackerNapi_Unwrap(napi_env env, napi_value value)
226 {
227 napi_valuetype valueType;
228 napi_typeof(env, value, &valueType);
229 if (valueType != napi_object) {
230 return nullptr;
231 }
232 std::unique_ptr<ImagePackerNapi> napi = nullptr;
233 napi_status status = napi_unwrap(env, value, reinterpret_cast<void**>(&napi));
234 if ((status == napi_ok) && napi != nullptr) {
235 return napi.release();
236 }
237 return nullptr;
238 }
239 #ifdef __cplusplus
240 };
241 #endif
242 } // namespace Media
243 } // namespace OHOS
244