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