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