1 /*
2  * Copyright (C) 2021 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_utils.h"
17 
18 #include <sys/stat.h>
19 #include <cerrno>
20 #include <charconv>
21 #include <climits>
22 #include <cmath>
23 #include <cstdint>
24 #include <cstdlib>
25 #include <string>
26 #include <fstream>
27 #include <sstream>
28 #include <chrono>
29 
30 #include "__config"
31 #include "image_log.h"
32 #include "ios"
33 #include "istream"
34 #include "media_errors.h"
35 #include "new"
36 #include "plugin_server.h"
37 #include "singleton.h"
38 #include "string"
39 #include "type_traits"
40 #include "vector"
41 #include "image_trace.h"
42 #include "hitrace_meter.h"
43 #include "image_system_properties.h"
44 #include "image/abs_image_decoder.h"
45 #include "pixel_map.h"
46 #ifdef IOS_PLATFORM
47 #include <sys/syscall.h>
48 #endif
49 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
50 #include "surface_buffer.h"
51 #include "bundle_mgr_interface.h"
52 #include "iservice_registry.h"
53 #include "ipc_skeleton.h"
54 #include "system_ability_definition.h"
55 #include "os_account_manager.h"
56 #else
57 #include "refbase.h"
58 #endif
59 
60 #undef LOG_DOMAIN
61 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
62 
63 #undef LOG_TAG
64 #define LOG_TAG "imageUtils"
65 
66 namespace OHOS {
67 namespace Media {
68 using namespace std;
69 using namespace MultimediaPlugin;
70 
71 constexpr int32_t ALPHA8_BYTES = 1;
72 constexpr int32_t RGB565_BYTES = 2;
73 constexpr int32_t RGB888_BYTES = 3;
74 constexpr int32_t ARGB8888_BYTES = 4;
75 constexpr int32_t RGBA_F16_BYTES = 8;
76 constexpr int32_t NV21_BYTES = 2;  // Each pixel is sorted on 3/2 bytes.
77 constexpr uint8_t MOVE_BITS_8 = 8;
78 constexpr uint8_t MOVE_BITS_16 = 16;
79 constexpr uint8_t MOVE_BITS_24 = 24;
80 constexpr int32_t NV21P010_BYTES = 3;
81 constexpr int32_t ASTC_4X4_BYTES = 1;
82 constexpr int32_t ASTC_4X4_BLOCK = 4;
83 constexpr int32_t ASTC_6X6_BLOCK = 6;
84 constexpr int32_t ASTC_8X8_BLOCK = 8;
85 constexpr int32_t ASTC_BLOCK_SIZE = 16;
86 constexpr int32_t ASTC_HEADER_SIZE = 16;
87 constexpr uint8_t FILL_NUMBER = 3;
88 constexpr uint8_t ALIGN_NUMBER = 4;
89 constexpr int32_t FAULT_API_VERSION = -1;
90 constexpr int32_t BUNDLE_MGR_SERVICE_SYS_ABILITY_ID = 401;
91 constexpr float EPSILON = 1e-6;
92 constexpr int MAX_DIMENSION = INT32_MAX >> 2;
93 constexpr int32_t DMA_SIZE = 512 * 512;
94 static bool g_pluginRegistered = false;
95 static const uint8_t NUM_0 = 0;
96 static const uint8_t NUM_1 = 1;
97 static const uint8_t NUM_2 = 2;
98 static const uint8_t NUM_3 = 3;
99 static const uint8_t NUM_4 = 4;
100 static const uint8_t NUM_5 = 5;
101 static const uint8_t NUM_6 = 6;
102 static const uint8_t NUM_7 = 7;
103 static const string FILE_DIR_IN_THE_SANDBOX = "/data/storage/el2/base/files/";
104 
GetFileSize(const string & pathName,size_t & size)105 bool ImageUtils::GetFileSize(const string &pathName, size_t &size)
106 {
107     if (pathName.empty()) {
108         IMAGE_LOGE("[ImageUtil]input parameter exception.");
109         return false;
110     }
111     struct stat statbuf;
112     int ret = stat(pathName.c_str(), &statbuf);
113     if (ret != 0) {
114         IMAGE_LOGE("[ImageUtil]get the file size failed, ret:%{public}d, errno:%{public}d.", ret, errno);
115         return false;
116     }
117     size = statbuf.st_size;
118     return true;
119 }
120 
GetFileSize(const int fd,size_t & size)121 bool ImageUtils::GetFileSize(const int fd, size_t &size)
122 {
123     struct stat statbuf;
124 
125     if (fd < 0) {
126         return false;
127     }
128 
129     int ret = fstat(fd, &statbuf);
130     if (ret != 0) {
131         IMAGE_LOGE("[ImageUtil]get the file size failed, ret:%{public}d, errno:%{public}d.", ret, errno);
132         return false;
133     }
134     size = statbuf.st_size;
135     return true;
136 }
137 
GetInputStreamSize(istream & inputStream,size_t & size)138 bool ImageUtils::GetInputStreamSize(istream &inputStream, size_t &size)
139 {
140     if (inputStream.rdbuf() == nullptr) {
141         IMAGE_LOGE("[ImageUtil]input parameter exception.");
142         return false;
143     }
144     size_t original = inputStream.tellg();
145     inputStream.seekg(0, ios_base::end);
146     size = inputStream.tellg();
147     inputStream.seekg(original);
148     return true;
149 }
150 
GetPixelBytes(const PixelFormat & pixelFormat)151 int32_t ImageUtils::GetPixelBytes(const PixelFormat &pixelFormat)
152 {
153     int pixelBytes = 0;
154     switch (pixelFormat) {
155         case PixelFormat::ARGB_8888:
156         case PixelFormat::BGRA_8888:
157         case PixelFormat::RGBA_8888:
158         case PixelFormat::RGBA_1010102:
159         case PixelFormat::CMYK:
160             pixelBytes = ARGB8888_BYTES;
161             break;
162         case PixelFormat::ALPHA_8:
163             pixelBytes = ALPHA8_BYTES;
164             break;
165         case PixelFormat::RGB_888:
166             pixelBytes = RGB888_BYTES;
167             break;
168         case PixelFormat::RGB_565:
169             pixelBytes = RGB565_BYTES;
170             break;
171         case PixelFormat::RGBA_F16:
172         case PixelFormat::RGBA_U16:
173             pixelBytes = RGBA_F16_BYTES;
174             break;
175         case PixelFormat::NV21:
176         case PixelFormat::NV12:
177             pixelBytes = NV21_BYTES;  // perl pixel 1.5 Bytes but return int so return 2
178             break;
179         case PixelFormat::ASTC_4x4:
180         case PixelFormat::ASTC_6x6:
181         case PixelFormat::ASTC_8x8:
182             pixelBytes = ASTC_4X4_BYTES;
183             break;
184         case PixelFormat::YCBCR_P010:
185         case PixelFormat::YCRCB_P010:
186             pixelBytes = NV21P010_BYTES;
187             break;
188         default:
189             IMAGE_LOGE("[ImageUtil]get pixel bytes failed, pixelFormat:%{public}d.",
190                 static_cast<int32_t>(pixelFormat));
191             break;
192     }
193     return pixelBytes;
194 }
195 
GetRowDataSizeByPixelFormat(const int32_t & width,const PixelFormat & format)196 int32_t ImageUtils::GetRowDataSizeByPixelFormat(const int32_t &width, const PixelFormat &format)
197 {
198     uint64_t uWidth = static_cast<uint64_t>(width);
199     uint64_t pixelBytes = static_cast<uint64_t>(GetPixelBytes(format));
200     uint64_t rowDataSize = 0;
201     switch (format) {
202         case PixelFormat::ALPHA_8:
203             rowDataSize = pixelBytes * ((uWidth + FILL_NUMBER) / ALIGN_NUMBER * ALIGN_NUMBER);
204             break;
205         case PixelFormat::ASTC_4x4:
206             rowDataSize = pixelBytes * (((uWidth + NUM_3) >> NUM_2) << NUM_2);
207             break;
208         case PixelFormat::ASTC_6x6:
209             rowDataSize = pixelBytes * (((uWidth + NUM_5) / NUM_6) * NUM_6);
210             break;
211         case PixelFormat::ASTC_8x8:
212             rowDataSize = pixelBytes * (((uWidth + NUM_7) >> NUM_3) << NUM_3);
213             break;
214         default:
215             rowDataSize = pixelBytes * uWidth;
216     }
217     if (rowDataSize > INT32_MAX) {
218         IMAGE_LOGE("GetRowDataSizeByPixelFormat failed: rowDataSize overflowed");
219         return -1;
220     }
221     return static_cast<int32_t>(rowDataSize);
222 }
223 
RegisterPluginServer()224 uint32_t ImageUtils::RegisterPluginServer()
225 {
226 #ifdef _WIN32
227     vector<string> pluginPaths = { "" };
228 #elif defined(_APPLE)
229     vector<string> pluginPaths = { "./" };
230 #elif defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
231     vector<string> pluginPaths = {};
232 #else
233     vector<string> pluginPaths = { "/system/etc/multimediaplugin/image" };
234 #endif
235     PluginServer &pluginServer = DelayedRefSingleton<PluginServer>::GetInstance();
236     uint32_t result = pluginServer.Register(std::move(pluginPaths));
237     if (result != SUCCESS) {
238         IMAGE_LOGE("[ImageUtil]failed to register plugin server, ERRNO: %{public}u.", result);
239     } else {
240         g_pluginRegistered = true;
241         IMAGE_LOGD("[ImageUtil]success to register plugin server");
242     }
243     return result;
244 }
245 
GetPluginServer()246 PluginServer& ImageUtils::GetPluginServer()
247 {
248     if (!g_pluginRegistered) {
249         uint32_t result = RegisterPluginServer();
250         if (result != SUCCESS) {
251             IMAGE_LOGI("[ImageUtil]failed to register plugin server, ERRNO: %{public}u.", result);
252         }
253     }
254     return DelayedRefSingleton<PluginServer>::GetInstance();
255 }
256 
PathToRealPath(const string & path,string & realPath)257 bool ImageUtils::PathToRealPath(const string &path, string &realPath)
258 {
259     if (path.empty()) {
260         IMAGE_LOGE("path is empty!");
261         return false;
262     }
263 
264     if ((path.length() >= PATH_MAX)) {
265         IMAGE_LOGE("path len is error, the len is: [%{public}lu]", static_cast<unsigned long>(path.length()));
266         return false;
267     }
268 
269     char tmpPath[PATH_MAX] = { 0 };
270 
271 #ifdef _WIN32
272     if (_fullpath(tmpPath, path.c_str(), path.length()) == nullptr) {
273         IMAGE_LOGW("path to _fullpath error");
274     }
275 #else
276     if (realpath(path.c_str(), tmpPath) == nullptr) {
277         IMAGE_LOGE("path to realpath is nullptr");
278         return false;
279     }
280 #endif
281 
282     realPath = tmpPath;
283     return true;
284 }
285 
FloatCompareZero(float src)286 bool ImageUtils::FloatCompareZero(float src)
287 {
288     return fabs(src - 0) < EPSILON;
289 }
290 
GetValidAlphaTypeByFormat(const AlphaType & dstType,const PixelFormat & format)291 AlphaType ImageUtils::GetValidAlphaTypeByFormat(const AlphaType &dstType, const PixelFormat &format)
292 {
293     switch (format) {
294         case PixelFormat::RGBA_8888:
295         case PixelFormat::BGRA_8888:
296         case PixelFormat::ARGB_8888:
297         case PixelFormat::RGBA_1010102:
298         case PixelFormat::RGBA_F16: {
299             break;
300         }
301         case PixelFormat::ALPHA_8: {
302             if (dstType != AlphaType::IMAGE_ALPHA_TYPE_PREMUL) {
303                 return AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
304             }
305             break;
306         }
307         case PixelFormat::RGB_888:
308         case PixelFormat::RGB_565: {
309             if (dstType != AlphaType::IMAGE_ALPHA_TYPE_OPAQUE) {
310                 return AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
311             }
312             break;
313         }
314         case PixelFormat::NV21:
315         case PixelFormat::NV12:
316         case PixelFormat::YCBCR_P010:
317         case PixelFormat::YCRCB_P010: {
318             if (dstType != AlphaType::IMAGE_ALPHA_TYPE_OPAQUE) {
319                 return AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
320             }
321             break;
322         }
323         case PixelFormat::CMYK:
324         default: {
325             IMAGE_LOGE("GetValidAlphaTypeByFormat unsupport the format(%{public}d).", format);
326             return AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
327         }
328     }
329     return dstType;
330 }
331 
GetPixelMapAllocatorType(const Size & size,const PixelFormat & format,bool useDMA)332 AllocatorType ImageUtils::GetPixelMapAllocatorType(const Size &size, const PixelFormat &format, bool useDMA)
333 {
334 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
335     return useDMA && (format == PixelFormat::RGBA_8888 || (format == PixelFormat::RGBA_1010102 ||
336         format == PixelFormat::YCRCB_P010 ||
337         format == PixelFormat::YCBCR_P010)) &&
338         size.width * size.height >= DMA_SIZE ?
339         AllocatorType::DMA_ALLOC : AllocatorType::SHARE_MEM_ALLOC;
340 #else
341     return AllocatorType::HEAP_ALLOC;
342 #endif
343 }
344 
IsValidImageInfo(const ImageInfo & info)345 bool ImageUtils::IsValidImageInfo(const ImageInfo &info)
346 {
347     if (info.size.width <= 0 || info.size.height <= 0 || info.size.width > MAX_DIMENSION ||
348         info.size.height > MAX_DIMENSION) {
349         IMAGE_LOGE("width(%{public}d) or height(%{public}d) is invalid.", info.size.width, info.size.height);
350         return false;
351     }
352     if (info.pixelFormat == PixelFormat::UNKNOWN || info.alphaType == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
353         IMAGE_LOGE("check pixelformat and alphatype is invalid.");
354         return false;
355     }
356     return true;
357 }
358 
IsValidAuxiliaryInfo(const std::shared_ptr<PixelMap> & pixelMap,const AuxiliaryPictureInfo & info)359 bool ImageUtils::IsValidAuxiliaryInfo(const std::shared_ptr<PixelMap> &pixelMap, const AuxiliaryPictureInfo &info)
360 {
361     int32_t rowSize = ImageUtils::GetRowDataSizeByPixelFormat(info.size.width, info.pixelFormat);
362     if (rowSize <= 0 || info.size.height <= 0 || rowSize > std::numeric_limits<int32_t>::max() / info.size.height) {
363         IMAGE_LOGE("%{public}s rowSize: %{public}d, height: %{public}d may overflowed",
364             __func__, rowSize, info.size.height);
365         return false;
366     }
367     uint32_t infoSize = static_cast<uint32_t>(rowSize * info.size.height);
368     uint32_t pixelsSize = pixelMap->GetCapacity();
369     if (infoSize > pixelsSize) {
370         IMAGE_LOGE("%{public}s invalid infoSize: %{public}u, pixelsSize: %{public}u", __func__, infoSize, pixelsSize);
371         return false;
372     }
373     return true;
374 }
375 
IsAstc(PixelFormat format)376 bool ImageUtils::IsAstc(PixelFormat format)
377 {
378     return format == PixelFormat::ASTC_4x4 || format == PixelFormat::ASTC_6x6 || format == PixelFormat::ASTC_8x8;
379 }
380 
CheckMulOverflow(int32_t width,int32_t bytesPerPixel)381 bool ImageUtils::CheckMulOverflow(int32_t width, int32_t bytesPerPixel)
382 {
383     if (width == 0 || bytesPerPixel == 0) {
384         IMAGE_LOGE("param is 0");
385         return true;
386     }
387     int32_t rowSize = width * bytesPerPixel;
388     if ((rowSize / width) != bytesPerPixel) {
389         IMAGE_LOGE("width * bytesPerPixel overflow!");
390         return true;
391     }
392     return false;
393 }
394 
CheckMulOverflow(int32_t width,int32_t height,int32_t bytesPerPixel)395 bool ImageUtils::CheckMulOverflow(int32_t width, int32_t height, int32_t bytesPerPixel)
396 {
397     if (width == 0 || height == 0 || bytesPerPixel == 0) {
398         IMAGE_LOGE("param is 0");
399         return true;
400     }
401     int32_t rectSize = width * height;
402     if ((rectSize / width) != height) {
403         IMAGE_LOGE("width * height overflow!");
404         return true;
405     }
406     int32_t bufferSize = rectSize * bytesPerPixel;
407     if ((bufferSize / bytesPerPixel) != rectSize) {
408         IMAGE_LOGE("bytesPerPixel overflow!");
409         return true;
410     }
411     return false;
412 }
413 
ReversePixels(uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)414 static void ReversePixels(uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
415 {
416     if (byteCount % NUM_4 != NUM_0) {
417         IMAGE_LOGE("Pixel count must multiple of 4.");
418         return;
419     }
420     uint8_t *src = srcPixels;
421     uint8_t *dst = dstPixels;
422     for (uint32_t i = NUM_0 ; i < byteCount; i += NUM_4) {
423         // 0-B 1-G 2-R 3-A
424         dst[NUM_0] = src[NUM_3];
425         dst[NUM_1] = src[NUM_2];
426         dst[NUM_2] = src[NUM_1];
427         dst[NUM_3] = src[NUM_0];
428         src += NUM_4;
429         dst += NUM_4;
430     }
431 }
432 
BGRAToARGB(uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)433 void ImageUtils::BGRAToARGB(uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
434 {
435     ImageTrace imageTrace("BGRAToARGB");
436     ReversePixels(srcPixels, dstPixels, byteCount);
437 }
438 
ARGBToBGRA(uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)439 void ImageUtils::ARGBToBGRA(uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
440 {
441     ReversePixels(srcPixels, dstPixels, byteCount);
442 }
443 
SurfaceBuffer_Reference(void * buffer)444 int32_t ImageUtils::SurfaceBuffer_Reference(void* buffer)
445 {
446     if (buffer == nullptr) {
447         IMAGE_LOGE("parameter error, please check input parameter");
448         return ERR_SURFACEBUFFER_REFERENCE_FAILED;
449     }
450     OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(buffer);
451     ref->IncStrongRef(ref);
452     return SUCCESS;
453 }
454 
SurfaceBuffer_Unreference(void * buffer)455 int32_t ImageUtils::SurfaceBuffer_Unreference(void* buffer)
456 {
457     if (buffer == nullptr) {
458         IMAGE_LOGE("parameter error, please check input parameter");
459         return ERR_SURFACEBUFFER_UNREFERENCE_FAILED;
460     }
461     OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(buffer);
462     ref->DecStrongRef(ref);
463     return SUCCESS;
464 }
465 
DumpPixelMap(PixelMap * pixelMap,std::string customFileName,uint64_t imageId)466 void ImageUtils::DumpPixelMap(PixelMap* pixelMap, std::string customFileName, uint64_t imageId)
467 {
468     IMAGE_LOGI("ImageUtils::DumpPixelMap start");
469     std::string fileName = FILE_DIR_IN_THE_SANDBOX + GetLocalTime() + customFileName + std::to_string(imageId) +
470         GetPixelMapName(pixelMap) + ".dat";
471     int32_t totalSize = pixelMap->GetRowStride() * pixelMap->GetHeight();
472     PixelFormat pixelFormat = pixelMap->GetPixelFormat();
473     if (pixelFormat == PixelFormat::NV12 || pixelFormat == PixelFormat::NV21 ||
474         pixelFormat == PixelFormat::YCBCR_P010 || pixelFormat == PixelFormat::YCRCB_P010) {
475 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
476         if (pixelMap->GetAllocatorType() == AllocatorType::DMA_ALLOC) {
477             auto sbBuffer = reinterpret_cast<SurfaceBuffer*>(pixelMap->GetFd());
478             if (!sbBuffer) {
479                 return;
480             }
481             totalSize = static_cast<int32_t>(sbBuffer->GetSize());
482         } else {
483             totalSize = static_cast<int32_t>(pixelMap->GetCapacity());
484         }
485 #else
486         totalSize = static_cast<int32_t>(pixelMap->GetCapacity());
487 #endif
488         IMAGE_LOGI("ImageUtils::DumpPixelMap YUV420 totalSize is %{public}d", totalSize);
489     }
490     if (SUCCESS != SaveDataToFile(fileName, reinterpret_cast<const char*>(pixelMap->GetPixels()), totalSize)) {
491         IMAGE_LOGI("ImageUtils::DumpPixelMap failed");
492         return;
493     }
494     IMAGE_LOGI("ImageUtils::DumpPixelMap success, path = %{public}s", fileName.c_str());
495 }
496 
DumpPixelMapIfDumpEnabled(std::unique_ptr<PixelMap> & pixelMap,uint64_t imageId)497 void ImageUtils::DumpPixelMapIfDumpEnabled(std::unique_ptr<PixelMap>& pixelMap, uint64_t imageId)
498 {
499     if (!ImageSystemProperties::GetDumpImageEnabled()) {
500         return;
501     }
502     if (pixelMap == nullptr) {
503         IMAGE_LOGI("ImageUtils::DumpPixelMapIfDumpEnabled pixelMap is null");
504         return;
505     }
506     DumpPixelMap(pixelMap.get(), "_imageId", imageId);
507 }
508 
DumpPixelMapBeforeEncode(PixelMap & pixelMap)509 void ImageUtils::DumpPixelMapBeforeEncode(PixelMap& pixelMap)
510 {
511     if (!ImageSystemProperties::GetDumpImageEnabled()) {
512         return;
513     }
514     DumpPixelMap(&pixelMap, "_beforeEncode");
515 }
516 
DumpDataIfDumpEnabled(const char * data,const size_t & totalSize,const std::string & fileSuffix,uint64_t imageId)517 void ImageUtils::DumpDataIfDumpEnabled(const char* data, const size_t& totalSize,
518     const std::string& fileSuffix, uint64_t imageId)
519 {
520     if (!ImageSystemProperties::GetDumpImageEnabled()) {
521         return;
522     }
523     std::string fileName = FILE_DIR_IN_THE_SANDBOX + GetLocalTime() + "_imageId" + std::to_string(imageId) +
524         "_data_total" + std::to_string(totalSize) + "." + fileSuffix;
525     if (SUCCESS != SaveDataToFile(fileName, data, totalSize)) {
526         IMAGE_LOGI("ImageUtils::DumpDataIfDumpEnabled failed");
527         return;
528     }
529     IMAGE_LOGI("ImageUtils::DumpDataIfDumpEnabled success, path = %{public}s", fileName.c_str());
530 }
531 
GetNowTimeMilliSeconds()532 uint64_t ImageUtils::GetNowTimeMilliSeconds()
533 {
534     auto now = std::chrono::system_clock::now();
535     return std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
536 }
537 
GetNowTimeMicroSeconds()538 uint64_t ImageUtils::GetNowTimeMicroSeconds()
539 {
540     auto now = std::chrono::system_clock::now();
541     return std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
542 }
543 
GetCurrentProcessName()544 std::string ImageUtils::GetCurrentProcessName()
545 {
546     std::string processName;
547     std::ifstream cmdlineFile("/proc/self/cmdline");
548     if (cmdlineFile.is_open()) {
549         std::ostringstream oss;
550         oss << cmdlineFile.rdbuf();
551         cmdlineFile.close();
552 
553         //Extrace process name from the command line
554         std::string cmdline = oss.str();
555         size_t pos = cmdline.find_first_of('\0');
556         if (pos != std::string::npos) {
557             processName = cmdline.substr(0, pos);
558         }
559     }
560     return processName;
561 }
562 
SaveDataToFile(const std::string & fileName,const char * data,const size_t & totalSize)563 uint32_t ImageUtils::SaveDataToFile(const std::string& fileName, const char* data, const size_t& totalSize)
564 {
565     std::ofstream outFile(fileName, std::ofstream::out);
566     if (!outFile.is_open()) {
567         IMAGE_LOGI("ImageUtils::SaveDataToFile write error, path=%{public}s", fileName.c_str());
568         return IMAGE_RESULT_SAVE_DATA_TO_FILE_FAILED;
569     }
570     if (data == nullptr) {
571         IMAGE_LOGE("ImageUtils::SaveDataToFile data is nullptr");
572         return IMAGE_RESULT_SAVE_DATA_TO_FILE_FAILED;
573     }
574     outFile.write(data, totalSize);
575     return SUCCESS;
576 }
577 
GetLocalTime()578 std::string ImageUtils::GetLocalTime()
579 {
580     // time string : "year-month-day hour_minute_second.millisecond", ':' is not supported in windows file name
581     auto now = std::chrono::system_clock::now();
582     auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
583     std::time_t t = std::chrono::system_clock::to_time_t(now);
584     std::tm tm = *std::localtime(&t);
585 
586     std::stringstream ss;
587     int millSecondWidth = 3;
588     ss << std::put_time(&tm, "%Y-%m-%d %H_%M_%S.") << std::setfill('0') << std::setw(millSecondWidth) << ms.count();
589     return ss.str();
590 }
591 
GetPixelMapName(PixelMap * pixelMap)592 std::string ImageUtils::GetPixelMapName(PixelMap* pixelMap)
593 {
594     if (!pixelMap) {
595         IMAGE_LOGE("ImageUtils::GetPixelMapName error, pixelMap is null");
596         return "";
597     }
598 #ifdef IOS_PLATFORM
599     std::string pixelMapStr = "_pixelMap_w" + std::to_string(pixelMap->GetWidth()) +
600         "_h" + std::to_string(pixelMap->GetHeight()) +
601         "_rowStride" + std::to_string(pixelMap->GetRowStride()) +
602         "_total" + std::to_string(pixelMap->GetRowStride() * pixelMap->GetHeight()) +
603         "_pid" + std::to_string(getpid()) +
604         "_tid" + std::to_string(syscall(SYS_thread_selfid)) +
605         "_uniqueId" + std::to_string(pixelMap->GetUniqueId());
606 #else
607     std::string yuvInfoStr = "";
608     if (pixelMap->GetPixelFormat() == PixelFormat::NV12 || pixelMap->GetPixelFormat() == PixelFormat::NV21) {
609         YUVDataInfo yuvInfo;
610         pixelMap->GetImageYUVInfo(yuvInfo);
611         yuvInfoStr += "_yWidth" + std::to_string(yuvInfo.yWidth) +
612             "_yHeight" + std::to_string(yuvInfo.yHeight) +
613             "_yStride" + std::to_string(yuvInfo.yStride) +
614             "_yOffset" + std::to_string(yuvInfo.yOffset) +
615             "_uvWidth" + std::to_string(yuvInfo.uvWidth) +
616             "_uvHeight" + std::to_string(yuvInfo.uvHeight) +
617             "_uvStride" + std::to_string(yuvInfo.uvStride) +
618             "_uvOffset" + std::to_string(yuvInfo.uvOffset);
619     }
620     std::string pixelMapStr = "_pixelMap_w" + std::to_string(pixelMap->GetWidth()) +
621         "_h" + std::to_string(pixelMap->GetHeight()) +
622         "_rowStride" + std::to_string(pixelMap->GetRowStride()) +
623         "_pixelFormat" + std::to_string((int32_t)pixelMap->GetPixelFormat()) +
624         yuvInfoStr +
625         "_total" + std::to_string(pixelMap->GetRowStride() * pixelMap->GetHeight()) +
626         "_pid" + std::to_string(getpid()) +
627         "_tid" + std::to_string(gettid()) +
628         "_uniqueId" + std::to_string(pixelMap->GetUniqueId());
629 #endif
630     return pixelMapStr;
631 }
632 
633  // BytesToUint16 function will modify the offset value.
BytesToUint16(uint8_t * bytes,uint32_t & offset,bool isBigEndian)634 uint16_t ImageUtils::BytesToUint16(uint8_t* bytes, uint32_t& offset, bool isBigEndian)
635 {
636     uint16_t data = 0;
637     if (bytes == nullptr) {
638         return data;
639     }
640     if (isBigEndian) {
641         data = (bytes[offset] << MOVE_BITS_8) | bytes[offset + NUM_1];
642     } else {
643         data = (bytes[offset + NUM_1] << MOVE_BITS_8) | bytes[offset];
644     }
645     offset += NUM_2;
646     return data;
647 }
648 
649 // BytesToUint32 function will modify the offset value.
BytesToUint32(uint8_t * bytes,uint32_t & offset,bool isBigEndian)650 uint32_t ImageUtils::BytesToUint32(uint8_t* bytes, uint32_t& offset, bool isBigEndian)
651 {
652     uint32_t data = 0;
653     if (bytes == nullptr) {
654         return data;
655     }
656     if (isBigEndian) {
657         data = (bytes[offset] << MOVE_BITS_24) | (bytes[offset + NUM_1] << MOVE_BITS_16) |
658                 (bytes[offset + NUM_2] << MOVE_BITS_8) | (bytes[offset + NUM_3]);
659     } else {
660         data = (bytes[offset + NUM_3] << MOVE_BITS_24) | (bytes[offset + NUM_2] << MOVE_BITS_16) |
661                 (bytes[offset + NUM_1] << MOVE_BITS_8) | bytes[offset];
662     }
663     offset += NUM_4;
664     return data;
665 }
666 
667 // BytesToInt32 function will modify the offset value.
BytesToInt32(uint8_t * bytes,uint32_t & offset,bool isBigEndian)668 int32_t ImageUtils::BytesToInt32(uint8_t* bytes, uint32_t& offset, bool isBigEndian)
669 {
670     int32_t data = 0;
671     if (bytes == nullptr) {
672         return data;
673     }
674     if (isBigEndian) {
675         data = (bytes[offset] << MOVE_BITS_24) | (bytes[offset + NUM_1] << MOVE_BITS_16) |
676                 (bytes[offset + NUM_2] << MOVE_BITS_8) | (bytes[offset + NUM_3]);
677     } else {
678         data = (bytes[offset + NUM_3] << MOVE_BITS_24) | (bytes[offset + NUM_2] << MOVE_BITS_16) |
679                 (bytes[offset + NUM_1] << MOVE_BITS_8) | bytes[offset];
680     }
681     offset += NUM_4;
682     return data;
683 }
684 
685 // BytesToFloat function will modify the offset value.
BytesToFloat(uint8_t * bytes,uint32_t & offset,bool isBigEndian)686 float ImageUtils::BytesToFloat(uint8_t* bytes, uint32_t& offset, bool isBigEndian)
687 {
688     uint32_t data = BytesToUint32(bytes, offset, isBigEndian);
689     union {
690         uint32_t i;
691         float f;
692     } u;
693     u.i = data;
694     return u.f;
695 }
696 
Uint16ToBytes(uint16_t data,vector<uint8_t> & bytes,uint32_t & offset,bool isBigEndian)697 void ImageUtils::Uint16ToBytes(uint16_t data, vector<uint8_t>& bytes, uint32_t& offset, bool isBigEndian)
698 {
699     uint8_t BYTE_ONE = (data >> MOVE_BITS_8) & 0xFF;
700     uint8_t BYTE_TWO = data & 0xFF;
701     if (isBigEndian) {
702         bytes[offset++] = BYTE_ONE;
703         bytes[offset++] = BYTE_TWO;
704     } else {
705         bytes[offset++] = BYTE_TWO;
706         bytes[offset++] = BYTE_ONE;
707     }
708 }
709 
Uint32ToBytes(uint32_t data,vector<uint8_t> & bytes,uint32_t & offset,bool isBigEndian)710 void ImageUtils::Uint32ToBytes(uint32_t data, vector<uint8_t>& bytes, uint32_t& offset, bool isBigEndian)
711 {
712     uint8_t BYTE_ONE = (data >> MOVE_BITS_24) & 0xFF;
713     uint8_t BYTE_TWO = (data >> MOVE_BITS_16) & 0xFF;
714     uint8_t BYTE_THREE = (data >> MOVE_BITS_8) & 0xFF;
715     uint8_t BYTE_FOUR = data & 0xFF;
716     if (isBigEndian) {
717         bytes[offset++] = BYTE_ONE;
718         bytes[offset++] = BYTE_TWO;
719         bytes[offset++] = BYTE_THREE;
720         bytes[offset++] = BYTE_FOUR;
721     } else {
722         bytes[offset++] = BYTE_FOUR;
723         bytes[offset++] = BYTE_THREE;
724         bytes[offset++] = BYTE_TWO;
725         bytes[offset++] = BYTE_ONE;
726     }
727 }
728 
FloatToBytes(float data,vector<uint8_t> & bytes,uint32_t & offset,bool isBigEndian)729 void ImageUtils::FloatToBytes(float data, vector<uint8_t>& bytes, uint32_t& offset, bool isBigEndian)
730 {
731     union {
732         uint32_t i;
733         float f;
734     } u;
735     u.f = data;
736     Uint32ToBytes(u.i, bytes, offset, isBigEndian);
737 }
738 
Int32ToBytes(int32_t data,vector<uint8_t> & bytes,uint32_t & offset,bool isBigEndian)739 void ImageUtils::Int32ToBytes(int32_t data, vector<uint8_t>& bytes, uint32_t& offset, bool isBigEndian)
740 {
741     union {
742         uint32_t uit;
743         int32_t it;
744     } u;
745     u.it = data;
746     Uint32ToBytes(u.uit, bytes, offset, isBigEndian);
747 }
748 
ArrayToBytes(const uint8_t * data,uint32_t length,vector<uint8_t> & bytes,uint32_t & offset)749 void ImageUtils::ArrayToBytes(const uint8_t* data, uint32_t length, vector<uint8_t>& bytes, uint32_t& offset)
750 {
751     for (uint32_t i = 0; i < length; i++) {
752         bytes[offset++] = data[i] & 0xFF;
753     }
754 }
755 
FlushSurfaceBuffer(PixelMap * pixelMap)756 void ImageUtils::FlushSurfaceBuffer(PixelMap* pixelMap)
757 {
758 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
759     if (!pixelMap || pixelMap->GetAllocatorType() != AllocatorType::DMA_ALLOC) {
760         return;
761     }
762     SurfaceBuffer* surfaceBuffer = static_cast<SurfaceBuffer*>(pixelMap->GetFd());
763     if (surfaceBuffer && (surfaceBuffer->GetUsage() & BUFFER_USAGE_MEM_MMZ_CACHE)) {
764         GSError err = surfaceBuffer->Map();
765         if (err != GSERROR_OK) {
766             IMAGE_LOGE("ImageUtils Map failed, GSError=%{public}d", err);
767             return;
768         }
769         err = surfaceBuffer->FlushCache();
770         if (err != GSERROR_OK) {
771             IMAGE_LOGE("ImageUtils FlushCache failed, GSError=%{public}d", err);
772         }
773     }
774 #else
775     return;
776 #endif
777 }
778 
FlushContextSurfaceBuffer(ImagePlugin::DecodeContext & context)779 void ImageUtils::FlushContextSurfaceBuffer(ImagePlugin::DecodeContext& context)
780 {
781 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
782     if (context.pixelsBuffer.context == nullptr || context.allocatorType != AllocatorType::DMA_ALLOC) {
783         return;
784     }
785     SurfaceBuffer* surfaceBuffer = static_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
786     if (surfaceBuffer && (surfaceBuffer->GetUsage() & BUFFER_USAGE_MEM_MMZ_CACHE)) {
787         GSError err = surfaceBuffer->Map();
788         if (err != GSERROR_OK) {
789             IMAGE_LOGE("ImageUtils Map failed, GSError=%{public}d", err);
790             return;
791         }
792         err = surfaceBuffer->FlushCache();
793         if (err != GSERROR_OK) {
794             IMAGE_LOGE("ImageUtils FlushCache failed, GSError=%{public}d", err);
795         }
796     }
797 #else
798     return;
799 #endif
800 }
801 
InvalidateContextSurfaceBuffer(ImagePlugin::DecodeContext & context)802 void ImageUtils::InvalidateContextSurfaceBuffer(ImagePlugin::DecodeContext& context)
803 {
804 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
805     if (context.pixelsBuffer.context == nullptr || context.allocatorType != AllocatorType::DMA_ALLOC) {
806         return;
807     }
808     SurfaceBuffer* surfaceBuffer = static_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
809     if (surfaceBuffer && (surfaceBuffer->GetUsage() & BUFFER_USAGE_MEM_MMZ_CACHE)) {
810         GSError err = surfaceBuffer->InvalidateCache();
811         if (err != GSERROR_OK) {
812             IMAGE_LOGE("ImageUtils FlushCache failed, GSError=%{public}d", err);
813         }
814     }
815 #else
816     return;
817 #endif
818 }
819 
GetAstcBytesCount(const ImageInfo & imageInfo)820 size_t ImageUtils::GetAstcBytesCount(const ImageInfo& imageInfo)
821 {
822     size_t astcBytesCount = 0;
823     uint32_t blockWidth = 0;
824     uint32_t blockHeight = 0;
825 
826     switch (imageInfo.pixelFormat) {
827         case PixelFormat::ASTC_4x4:
828             blockWidth = ASTC_4X4_BLOCK;
829             blockHeight = ASTC_4X4_BLOCK;
830             break;
831         case PixelFormat::ASTC_6x6:
832             blockWidth = ASTC_6X6_BLOCK;
833             blockHeight = ASTC_6X6_BLOCK;
834             break;
835         case PixelFormat::ASTC_8x8:
836             blockWidth = ASTC_8X8_BLOCK;
837             blockHeight = ASTC_8X8_BLOCK;
838             break;
839         default:
840             IMAGE_LOGE("ImageUtils GetAstcBytesCount failed, format is not supported %{public}d",
841                 imageInfo.pixelFormat);
842             return 0;
843     }
844     if ((blockWidth >= ASTC_4X4_BLOCK) && (blockHeight >= ASTC_4X4_BLOCK)) {
845         astcBytesCount = ((imageInfo.size.width + blockWidth - 1) / blockWidth) *
846             ((imageInfo.size.height + blockHeight - 1) / blockHeight) * ASTC_BLOCK_SIZE + ASTC_HEADER_SIZE;
847     }
848     return astcBytesCount;
849 }
850 
IsAuxiliaryPictureTypeSupported(AuxiliaryPictureType type)851 bool ImageUtils::IsAuxiliaryPictureTypeSupported(AuxiliaryPictureType type)
852 {
853     auto auxTypes = GetAllAuxiliaryPictureType();
854     return (auxTypes.find(type) != auxTypes.end());
855 }
856 
IsAuxiliaryPictureEncoded(AuxiliaryPictureType type)857 bool ImageUtils::IsAuxiliaryPictureEncoded(AuxiliaryPictureType type)
858 {
859     return AuxiliaryPictureType::GAINMAP == type || AuxiliaryPictureType::UNREFOCUS_MAP == type ||
860         AuxiliaryPictureType::FRAGMENT_MAP == type;
861 }
862 
IsMetadataTypeSupported(MetadataType metadataType)863 bool ImageUtils::IsMetadataTypeSupported(MetadataType metadataType)
864 {
865     if (metadataType == MetadataType::EXIF || metadataType == MetadataType::FRAGMENT) {
866         return true;
867     } else {
868         return false;
869     }
870 }
871 
GetAllAuxiliaryPictureType()872 const std::set<AuxiliaryPictureType> ImageUtils::GetAllAuxiliaryPictureType()
873 {
874     static const std::set<AuxiliaryPictureType> auxTypes = {
875         AuxiliaryPictureType::GAINMAP,
876         AuxiliaryPictureType::DEPTH_MAP,
877         AuxiliaryPictureType::UNREFOCUS_MAP,
878         AuxiliaryPictureType::LINEAR_MAP,
879         AuxiliaryPictureType::FRAGMENT_MAP};
880     return auxTypes;
881 }
882 
StrToUint32(const std::string & str,uint32_t & value)883 bool ImageUtils::StrToUint32(const std::string& str, uint32_t& value)
884 {
885     auto [ptr, errCode] = std::from_chars(str.data(), str.data() + str.size(), value);
886     bool ret = errCode == std::errc{} && (ptr == str.data() + str.size());
887     return ret;
888 }
889 
IsInRange(uint32_t value,uint32_t minValue,uint32_t maxValue)890 bool ImageUtils::IsInRange(uint32_t value, uint32_t minValue, uint32_t maxValue)
891 {
892     return (value >= minValue) && (value <= maxValue);
893 }
894 
HasOverflowed(uint32_t num1,uint32_t num2)895 bool ImageUtils::HasOverflowed(uint32_t num1, uint32_t num2)
896 {
897     return num1 > std::numeric_limits<uint32_t>::max() - num2;
898 }
899 
GetEncodedHeifFormat()900 std::string ImageUtils::GetEncodedHeifFormat()
901 {
902     if (GetAPIVersion() > APIVERSION_13) {
903         return "image/heic";
904     } else {
905         return "image/heif";
906     }
907 }
908 
GetAPIVersion()909 int32_t ImageUtils::GetAPIVersion()
910 {
911 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
912     uint32_t targetVersion = 0;
913     auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
914     if (samgr == nullptr) {
915         IMAGE_LOGE("Get ability manager failed");
916         return FAULT_API_VERSION;
917     }
918     sptr<IRemoteObject> object = samgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
919     if (object == nullptr) {
920         IMAGE_LOGE("Object is NULL");
921         return FAULT_API_VERSION;
922     }
923 
924     sptr<OHOS::AppExecFwk::IBundleMgr> bms = iface_cast<OHOS::AppExecFwk::IBundleMgr>(object);
925     if (bms == nullptr) {
926         IMAGE_LOGE("Bundle manager service is NULL.");
927         return FAULT_API_VERSION;
928     }
929     AppExecFwk::BundleInfo bundleInfo;
930     if (bms->GetBundleInfoForSelf(0, bundleInfo) != ERR_OK) {
931         IMAGE_LOGE("Get bundle info for self failed");
932         return FAULT_API_VERSION;
933     }
934     targetVersion = bundleInfo.targetVersion;
935     int32_t apiVersionResult = static_cast<int32_t>(targetVersion % 100);
936     return apiVersionResult;
937 #else
938     return FAULT_API_VERSION;
939 #endif
940 }
941 } // namespace Media
942 } // namespace OHOS
943