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_packer_native.h"
17 
18 #include "common_utils.h"
19 #include "image_packer.h"
20 #include "image_packer_native_impl.h"
21 #include "image_source_native_impl.h"
22 #include "pixelmap_native_impl.h"
23 #ifndef _WIN32
24 #include "securec.h"
25 #else
26 #include "memory.h"
27 #endif
28 
29 using namespace OHOS;
30 using namespace Media;
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 constexpr size_t SIZE_ZERO = 0;
36 constexpr int32_t IMAGE_BASE = 62980096;
37 static constexpr int32_t IMAGE_BASE_19 = 19;
38 static constexpr int32_t IMAGE_BASE_16 = 16;
39 static constexpr int32_t IMAGE_BASE_17 = 17;
40 static constexpr int32_t IMAGE_BASE_26 = 26;
41 static constexpr int32_t IMAGE_BASE_31 = 31;
42 static constexpr int32_t IMAGE_BASE_152 = 152;
43 static constexpr int32_t IMAGE_BASE_27 = 27;
44 static constexpr int32_t IMAGE_BASE_12 = 12;
45 static constexpr int32_t IMAGE_BASE_13 = 13;
46 static constexpr int32_t IMAGE_BASE_6 = 6;
47 static constexpr int32_t IMAGE_BASE_14 = 14;
48 static constexpr int32_t IMAGE_BASE_4 = 4;
49 static constexpr int32_t IMAGE_BASE_9 = 9;
50 static constexpr int32_t IMAGE_BASE_20 = 20;
51 static constexpr int32_t IMAGE_BASE_22 = 22;
52 static constexpr int32_t IMAGE_BASE_23 = 23;
53 
54 struct OH_PackingOptions {
55     Image_MimeType mimeType;
56     int quality;
57     int32_t desiredDynamicRange = IMAGE_PACKER_DYNAMIC_RANGE_SDR;
58     uint16_t loop;
59     uint16_t* delayTimes;
60     uint32_t delayTimesSize;
61     uint16_t* disposalTypes;
62     uint32_t disposalTypesSize;
63     bool needsPackProperties = false;
64 };
65 
ToNewErrorCode(int code)66 static Image_ErrorCode ToNewErrorCode(int code)
67 {
68     switch (code) {
69         case 0:
70             return IMAGE_SUCCESS;
71         case IMAGE_BASE + IMAGE_BASE_19:
72             return IMAGE_BAD_PARAMETER;
73         case IMAGE_BASE + IMAGE_BASE_16:
74         case IMAGE_BASE + IMAGE_BASE_17:
75         case IMAGE_BASE + IMAGE_BASE_26:
76             return IMAGE_UNKNOWN_MIME_TYPE;
77         case IMAGE_BASE + IMAGE_BASE_31:
78             return IMAGE_TOO_LARGE;
79         case IMAGE_BASE + IMAGE_BASE_152:
80             return IMAGE_UNSUPPORTED_OPERATION;
81         case IMAGE_BASE + IMAGE_BASE_27:
82             return IMAGE_UNSUPPORTED_METADATA;
83         case IMAGE_BASE + IMAGE_BASE_12:
84             return IMAGE_UNSUPPORTED_CONVERSION;
85         case IMAGE_BASE + IMAGE_BASE_13:
86             return IMAGE_INVALID_REGION;
87         case IMAGE_BASE + IMAGE_BASE_6:
88             return IMAGE_ALLOC_FAILED;
89         case IMAGE_BASE + IMAGE_BASE_14:
90             return IMAGE_BAD_SOURCE;
91         case IMAGE_BASE + IMAGE_BASE_4:
92         case IMAGE_BASE + IMAGE_BASE_9:
93         case IMAGE_BASE + IMAGE_BASE_20:
94         case IMAGE_BASE + IMAGE_BASE_22:
95             return IMAGE_DECODE_FAILED;
96         case IMAGE_BASE + IMAGE_BASE_23:
97             return IMAGE_ENCODE_FAILED;
98         default:
99             return IMAGE_UNKNOWN_ERROR;
100     }
101 };
102 
ParseDynamicRange(int32_t val)103 static EncodeDynamicRange ParseDynamicRange(int32_t val)
104 {
105     if (val <= static_cast<int32_t>(EncodeDynamicRange::SDR)) {
106         return EncodeDynamicRange(val);
107     }
108 
109     return EncodeDynamicRange::SDR;
110 }
111 
CopyPackingOptions(const OH_PackingOptions * options,PackOption & packOption)112 static Image_ErrorCode CopyPackingOptions(const OH_PackingOptions *options, PackOption &packOption)
113 {
114     if (options == nullptr) {
115         return IMAGE_BAD_PARAMETER;
116     }
117 
118     std::string format(options->mimeType.data, options->mimeType.size);
119     if (format.empty()) {
120         return IMAGE_BAD_PARAMETER;
121     }
122     packOption.format = format;
123     packOption.quality = options->quality;
124     packOption.needsPackProperties = options->needsPackProperties;
125     packOption.desiredDynamicRange = ParseDynamicRange(options->desiredDynamicRange);
126     return IMAGE_SUCCESS;
127 }
128 
129 MIDK_EXPORT
OH_PackingOptions_Create(OH_PackingOptions ** options)130 Image_ErrorCode OH_PackingOptions_Create(OH_PackingOptions **options)
131 {
132     *options = new OH_PackingOptions();
133     if (*options == nullptr) {
134         return IMAGE_BAD_PARAMETER;
135     }
136     return IMAGE_SUCCESS;
137 }
138 
139 MIDK_EXPORT
OH_PackingOptions_GetMimeType(OH_PackingOptions * options,Image_MimeType * format)140 Image_ErrorCode OH_PackingOptions_GetMimeType(OH_PackingOptions *options,
141     Image_MimeType *format)
142 {
143     if (options == nullptr || format == nullptr) {
144         return IMAGE_BAD_PARAMETER;
145     }
146 
147     if (format->size != SIZE_ZERO && format->size < options->mimeType.size) {
148         return IMAGE_BAD_PARAMETER;
149     }
150 
151     format->size = (format->size == SIZE_ZERO) ? options->mimeType.size : format->size;
152     format->data = static_cast<char *>(malloc(format->size));
153     if (format->data == nullptr) {
154         return IMAGE_ALLOC_FAILED;
155     }
156 
157     if (memcpy_s(format->data, format->size, options->mimeType.data, options->mimeType.size) != 0) {
158         free(format->data);
159         format->data = nullptr;
160         format->size = 0;
161         return IMAGE_COPY_FAILED;
162     }
163     return IMAGE_SUCCESS;
164 }
165 
166 MIDK_EXPORT
OH_PackingOptions_SetMimeType(OH_PackingOptions * options,Image_MimeType * format)167 Image_ErrorCode OH_PackingOptions_SetMimeType(OH_PackingOptions *options,
168     Image_MimeType *format)
169 {
170     if (options == nullptr || format->data == nullptr || format->size == 0) {
171         return IMAGE_BAD_PARAMETER;
172     }
173     if (options->mimeType.data != nullptr) {
174         free(options->mimeType.data);
175         options->mimeType.data = nullptr;
176     }
177     options->mimeType.size = format->size;
178     options->mimeType.data = static_cast<char *>(malloc(options->mimeType.size));
179     if (options->mimeType.data == nullptr) {
180         return IMAGE_ALLOC_FAILED;
181     }
182     if (memcpy_s(options->mimeType.data, options->mimeType.size, format->data, format->size) != 0) {
183         free(options->mimeType.data);
184         options->mimeType.data = nullptr;
185         options->mimeType.size = 0;
186         return IMAGE_COPY_FAILED;
187     }
188     return IMAGE_SUCCESS;
189 }
190 
191 MIDK_EXPORT
OH_PackingOptions_GetQuality(OH_PackingOptions * options,uint32_t * quality)192 Image_ErrorCode OH_PackingOptions_GetQuality(OH_PackingOptions *options, uint32_t *quality)
193 {
194     if (options == nullptr || quality == nullptr) {
195         return IMAGE_BAD_PARAMETER;
196     }
197     *quality = options->quality;
198     return IMAGE_SUCCESS;
199 }
200 
201 MIDK_EXPORT
OH_PackingOptions_SetQuality(OH_PackingOptions * options,uint32_t quality)202 Image_ErrorCode OH_PackingOptions_SetQuality(OH_PackingOptions *options, uint32_t quality)
203 {
204     if (options == nullptr) {
205         return IMAGE_BAD_PARAMETER;
206     }
207     options->quality = static_cast<int>(quality);
208     return IMAGE_SUCCESS;
209 }
210 
211 MIDK_EXPORT
OH_PackingOptions_GetNeedsPackProperties(OH_PackingOptions * options,bool * needsPackProperties)212 Image_ErrorCode OH_PackingOptions_GetNeedsPackProperties(OH_PackingOptions *options, bool *needsPackProperties)
213 {
214     if (options == nullptr || needsPackProperties == nullptr) {
215         return IMAGE_BAD_PARAMETER;
216     }
217     *needsPackProperties = options->needsPackProperties;
218     return IMAGE_SUCCESS;
219 }
220 
221 MIDK_EXPORT
OH_PackingOptions_SetNeedsPackProperties(OH_PackingOptions * options,bool needsPackProperties)222 Image_ErrorCode OH_PackingOptions_SetNeedsPackProperties(OH_PackingOptions *options, bool needsPackProperties)
223 {
224     if (options == nullptr) {
225         return IMAGE_BAD_PARAMETER;
226     }
227     options->needsPackProperties = needsPackProperties;
228     return IMAGE_SUCCESS;
229 }
230 
231 MIDK_EXPORT
OH_PackingOptions_GetDesiredDynamicRange(OH_PackingOptions * options,int32_t * desiredDynamicRange)232 Image_ErrorCode OH_PackingOptions_GetDesiredDynamicRange(OH_PackingOptions *options, int32_t* desiredDynamicRange)
233 {
234     if (options == nullptr || desiredDynamicRange == nullptr) {
235         return IMAGE_BAD_PARAMETER;
236     }
237     *desiredDynamicRange = options->desiredDynamicRange;
238     return IMAGE_SUCCESS;
239 }
240 
241 MIDK_EXPORT
OH_PackingOptions_SetDesiredDynamicRange(OH_PackingOptions * options,int32_t desiredDynamicRange)242 Image_ErrorCode OH_PackingOptions_SetDesiredDynamicRange(OH_PackingOptions *options, int32_t desiredDynamicRange)
243 {
244     if (options == nullptr) {
245         return IMAGE_BAD_PARAMETER;
246     }
247     options->desiredDynamicRange = desiredDynamicRange;
248     return IMAGE_SUCCESS;
249 }
250 
251 MIDK_EXPORT
OH_PackingOptions_SetLoop(OH_PackingOptions * options,uint16_t loop)252 Image_ErrorCode OH_PackingOptions_SetLoop(OH_PackingOptions *options, uint16_t loop)
253 {
254     if (options == nullptr) {
255         return IMAGE_BAD_PARAMETER;
256     }
257     options->loop = loop;
258     return IMAGE_SUCCESS;
259 }
260 
261 MIDK_EXPORT
OH_PackingOptions_GetLoop(OH_PackingOptions * options,uint16_t * loop)262 Image_ErrorCode OH_PackingOptions_GetLoop(OH_PackingOptions *options, uint16_t* loop)
263 {
264     if (options == nullptr || loop == nullptr) {
265         return IMAGE_BAD_PARAMETER;
266     }
267     *loop = options->loop;
268     return IMAGE_SUCCESS;
269 }
270 
271 MIDK_EXPORT
OH_PackingOptions_SetDelayTimes(OH_PackingOptions * options,uint16_t * delayTimes,uint32_t delayTimesSize)272 Image_ErrorCode OH_PackingOptions_SetDelayTimes(OH_PackingOptions *options, uint16_t* delayTimes,
273     uint32_t delayTimesSize)
274 {
275     if (options == nullptr) {
276         return IMAGE_BAD_PARAMETER;
277     }
278     options->delayTimes = delayTimes;
279     options->delayTimesSize = delayTimesSize;
280     return IMAGE_SUCCESS;
281 }
282 
283 MIDK_EXPORT
OH_PackingOptions_GetDelayTimes(OH_PackingOptions * options,uint16_t * delayTimes,uint32_t * delayTimesSize)284 Image_ErrorCode OH_PackingOptions_GetDelayTimes(OH_PackingOptions *options, uint16_t* delayTimes,
285     uint32_t* delayTimesSize)
286 {
287     if (options == nullptr || delayTimes == nullptr || delayTimesSize == nullptr) {
288         return IMAGE_BAD_PARAMETER;
289     }
290     delayTimes = options->delayTimes;
291     *delayTimesSize = options->delayTimesSize;
292     return IMAGE_SUCCESS;
293 }
294 
295 MIDK_EXPORT
OH_PackingOptions_SetDisposalTypes(OH_PackingOptions * options,uint16_t * disposalTypes,uint32_t disposalTypesSize)296 Image_ErrorCode OH_PackingOptions_SetDisposalTypes(OH_PackingOptions *options, uint16_t* disposalTypes,
297     uint32_t disposalTypesSize)
298 {
299     if (options == nullptr) {
300         return IMAGE_BAD_PARAMETER;
301     }
302     options->disposalTypes = disposalTypes;
303     options->disposalTypesSize = disposalTypesSize;
304     return IMAGE_SUCCESS;
305 }
306 
307 MIDK_EXPORT
OH_PackingOptions_GetDisposalTypes(OH_PackingOptions * options,uint16_t * disposalTypes,uint32_t * disposalTypesSize)308 Image_ErrorCode OH_PackingOptions_GetDisposalTypes(OH_PackingOptions *options, uint16_t* disposalTypes,
309     uint32_t* disposalTypesSize)
310 {
311     if (options == nullptr || disposalTypes == nullptr || disposalTypesSize == nullptr) {
312         return IMAGE_BAD_PARAMETER;
313     }
314     disposalTypes = options->disposalTypes;
315     *disposalTypesSize = options->disposalTypesSize;
316     return IMAGE_SUCCESS;
317 }
318 
319 MIDK_EXPORT
OH_PackingOptions_Release(OH_PackingOptions * options)320 Image_ErrorCode OH_PackingOptions_Release(OH_PackingOptions *options)
321 {
322     if (options == nullptr) {
323         return IMAGE_BAD_PARAMETER;
324     }
325     if (options->mimeType.data) {
326         free(options->mimeType.data);
327         options->mimeType.data = nullptr;
328     }
329     delete options;
330     return IMAGE_SUCCESS;
331 }
332 
333 MIDK_EXPORT
OH_ImagePackerNative_Create(OH_ImagePackerNative ** imagePacker)334 Image_ErrorCode OH_ImagePackerNative_Create(OH_ImagePackerNative **imagePacker)
335 {
336     auto imagePacker2 = new OH_ImagePackerNative();
337     if (imagePacker2 == nullptr || imagePacker2->GetInnerImagePacker() == nullptr) {
338         if (imagePacker2) {
339             delete imagePacker2;
340         }
341         return IMAGE_BAD_PARAMETER;
342     }
343     *imagePacker = imagePacker2;
344     return IMAGE_SUCCESS;
345 }
346 
347 MIDK_EXPORT
OH_ImagePackerNative_PackToDataFromImageSource(OH_ImagePackerNative * imagePacker,OH_PackingOptions * options,OH_ImageSourceNative * imageSource,uint8_t * outData,size_t * size)348 Image_ErrorCode OH_ImagePackerNative_PackToDataFromImageSource(OH_ImagePackerNative *imagePacker,
349     OH_PackingOptions *options, OH_ImageSourceNative *imageSource, uint8_t *outData, size_t *size)
350 {
351     if (imagePacker == nullptr || options == nullptr || imageSource == nullptr || outData == nullptr) {
352         return IMAGE_BAD_PARAMETER;
353     }
354 
355     PackOption packOption;
356     Image_ErrorCode errorCode = CopyPackingOptions(options, packOption);
357     if (errorCode != IMAGE_SUCCESS) {
358         return errorCode;
359     }
360     return ToNewErrorCode(imagePacker->PackingFromImageSource(&packOption, imageSource,
361         outData, reinterpret_cast<int64_t*>(size)));
362 }
363 
364 MIDK_EXPORT
OH_ImagePackerNative_PackToDataFromPixelmap(OH_ImagePackerNative * imagePacker,OH_PackingOptions * options,OH_PixelmapNative * pixelmap,uint8_t * outData,size_t * size)365 Image_ErrorCode OH_ImagePackerNative_PackToDataFromPixelmap(OH_ImagePackerNative *imagePacker,
366     OH_PackingOptions *options, OH_PixelmapNative *pixelmap, uint8_t *outData, size_t *size)
367 {
368     if (imagePacker == nullptr || options == nullptr || pixelmap == nullptr || outData == nullptr) {
369         return IMAGE_BAD_PARAMETER;
370     }
371 
372     PackOption packOption;
373     Image_ErrorCode errorCode = CopyPackingOptions(options, packOption);
374     if (errorCode != IMAGE_SUCCESS) {
375         return errorCode;
376     }
377     return ToNewErrorCode(imagePacker->PackingFromPixelmap(&packOption, pixelmap, outData,
378         reinterpret_cast<int64_t*>(size)));
379 }
380 
381 MIDK_EXPORT
OH_ImagePackerNative_PackToDataFromPicture(OH_ImagePackerNative * imagePacker,OH_PackingOptions * options,OH_PictureNative * picture,uint8_t * outData,size_t * size)382 Image_ErrorCode OH_ImagePackerNative_PackToDataFromPicture(OH_ImagePackerNative *imagePacker,
383     OH_PackingOptions *options, OH_PictureNative *picture, uint8_t *outData, size_t *size)
384 {
385     if (imagePacker == nullptr || options == nullptr || picture == nullptr || outData == nullptr) {
386         return IMAGE_BAD_PARAMETER;
387     }
388 
389     PackOption packOption;
390     Image_ErrorCode errorCode = CopyPackingOptions(options, packOption);
391     if (errorCode != IMAGE_SUCCESS) {
392         return errorCode;
393     }
394     return ToNewErrorCode(imagePacker->PackToDataFromPicture(&packOption, picture, outData,
395         reinterpret_cast<int64_t*>(size)));
396 }
397 
398 MIDK_EXPORT
OH_ImagePackerNative_PackToFileFromImageSource(OH_ImagePackerNative * imagePacker,OH_PackingOptions * options,OH_ImageSourceNative * imageSource,int32_t fd)399 Image_ErrorCode OH_ImagePackerNative_PackToFileFromImageSource(OH_ImagePackerNative *imagePacker,
400     OH_PackingOptions *options, OH_ImageSourceNative *imageSource, int32_t fd)
401 {
402     if (imagePacker == nullptr || options == nullptr || imageSource == nullptr) {
403         return IMAGE_BAD_PARAMETER;
404     }
405 
406     PackOption packOption;
407     Image_ErrorCode errorCode = CopyPackingOptions(options, packOption);
408     if (errorCode != IMAGE_SUCCESS) {
409         return errorCode;
410     }
411     return ToNewErrorCode(imagePacker->PackToFileFromImageSource(&packOption, imageSource, fd));
412 }
413 
414 MIDK_EXPORT
OH_ImagePackerNative_PackToFileFromPixelmap(OH_ImagePackerNative * imagePacker,OH_PackingOptions * options,OH_PixelmapNative * pixelmap,int32_t fd)415 Image_ErrorCode OH_ImagePackerNative_PackToFileFromPixelmap(OH_ImagePackerNative *imagePacker,
416     OH_PackingOptions *options, OH_PixelmapNative *pixelmap, int32_t fd)
417 {
418     if (imagePacker == nullptr || options == nullptr || pixelmap == nullptr) {
419         return IMAGE_BAD_PARAMETER;
420     }
421 
422     PackOption packOption;
423     Image_ErrorCode errorCode = CopyPackingOptions(options, packOption);
424     if (errorCode != IMAGE_SUCCESS) {
425         return errorCode;
426     }
427     return ToNewErrorCode(imagePacker->PackToFileFromPixelmap(&packOption, pixelmap, fd));
428 }
429 
430 MIDK_EXPORT
OH_ImagePackerNative_PackToFileFromPicture(OH_ImagePackerNative * imagePacker,OH_PackingOptions * options,OH_PictureNative * picture,int32_t fd)431 Image_ErrorCode OH_ImagePackerNative_PackToFileFromPicture(OH_ImagePackerNative *imagePacker,
432     OH_PackingOptions *options, OH_PictureNative *picture, int32_t fd)
433 {
434     if (imagePacker == nullptr || options == nullptr || picture == nullptr) {
435         return IMAGE_BAD_PARAMETER;
436     }
437 
438     PackOption packOption;
439     Image_ErrorCode errorCode = CopyPackingOptions(options, packOption);
440     if (errorCode != IMAGE_SUCCESS) {
441         return errorCode;
442     }
443     return ToNewErrorCode(imagePacker->PackToFileFromPicture(&packOption, picture, fd));
444 }
445 
446 MIDK_EXPORT
OH_ImagePackerNative_Release(OH_ImagePackerNative * imagePacker)447 Image_ErrorCode OH_ImagePackerNative_Release(OH_ImagePackerNative *imagePacker)
448 {
449     if (imagePacker == nullptr) {
450         return IMAGE_BAD_PARAMETER;
451     }
452     delete imagePacker;
453     return IMAGE_SUCCESS;
454 }
455 
456 #ifdef __cplusplus
457 };
458 #endif