• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_type.h"
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 DMA_SIZE = 512 * 512; // DMA minimum effective size
90 constexpr int32_t FAULT_API_VERSION = -1;
91 constexpr int32_t BUNDLE_MGR_SERVICE_SYS_ABILITY_ID = 401;
92 constexpr int32_t BASE_EVEN_DIVISOR = 2;
93 constexpr float EPSILON = 1e-6;
94 constexpr int MAX_DIMENSION = INT32_MAX >> 2;
95 static bool g_pluginRegistered = false;
96 static const uint8_t NUM_0 = 0;
97 static const uint8_t NUM_1 = 1;
98 static const uint8_t NUM_2 = 2;
99 static const uint8_t NUM_3 = 3;
100 static const uint8_t NUM_4 = 4;
101 static const uint8_t NUM_5 = 5;
102 static const uint8_t NUM_6 = 6;
103 static const uint8_t NUM_7 = 7;
104 static const uint8_t INT_255 = 255;
105 static const string FILE_DIR_IN_THE_SANDBOX = "/data/storage/el2/base/files/";
106 static constexpr int32_t PLANE_Y = 0;
107 static constexpr int32_t PLANE_U = 1;
108 static constexpr int32_t PLANE_V = 2;
109 
GetFileSize(const string & pathName,size_t & size)110 bool ImageUtils::GetFileSize(const string &pathName, size_t &size)
111 {
112     if (pathName.empty()) {
113         IMAGE_LOGE("[ImageUtil]input parameter exception.");
114         return false;
115     }
116     struct stat statbuf;
117     int ret = stat(pathName.c_str(), &statbuf);
118     if (ret != 0) {
119         IMAGE_LOGE("[ImageUtil]get the file size failed, ret:%{public}d, errno:%{public}d.", ret, errno);
120         return false;
121     }
122     size = statbuf.st_size;
123     return true;
124 }
125 
GetFileSize(const int fd,size_t & size)126 bool ImageUtils::GetFileSize(const int fd, size_t &size)
127 {
128     struct stat statbuf;
129 
130     if (fd < 0) {
131         return false;
132     }
133 
134     int ret = fstat(fd, &statbuf);
135     if (ret != 0) {
136         IMAGE_LOGE("[ImageUtil]get the file size failed, ret:%{public}d, errno:%{public}d.", ret, errno);
137         return false;
138     }
139     size = statbuf.st_size;
140     return true;
141 }
142 
GetInputStreamSize(istream & inputStream,size_t & size)143 bool ImageUtils::GetInputStreamSize(istream &inputStream, size_t &size)
144 {
145     if (inputStream.rdbuf() == nullptr) {
146         IMAGE_LOGE("[ImageUtil]input parameter exception.");
147         return false;
148     }
149     size_t original = inputStream.tellg();
150     inputStream.seekg(0, ios_base::end);
151     size = inputStream.tellg();
152     inputStream.seekg(original);
153     return true;
154 }
155 
GetPixelBytes(const PixelFormat & pixelFormat)156 int32_t ImageUtils::GetPixelBytes(const PixelFormat &pixelFormat)
157 {
158     int pixelBytes = 0;
159     switch (pixelFormat) {
160         case PixelFormat::ARGB_8888:
161         case PixelFormat::BGRA_8888:
162         case PixelFormat::RGBA_8888:
163         case PixelFormat::RGBA_1010102:
164         case PixelFormat::CMYK:
165             pixelBytes = ARGB8888_BYTES;
166             break;
167         case PixelFormat::ALPHA_8:
168             pixelBytes = ALPHA8_BYTES;
169             break;
170         case PixelFormat::RGB_888:
171             pixelBytes = RGB888_BYTES;
172             break;
173         case PixelFormat::RGB_565:
174             pixelBytes = RGB565_BYTES;
175             break;
176         case PixelFormat::RGBA_F16:
177         case PixelFormat::RGBA_U16:
178             pixelBytes = RGBA_F16_BYTES;
179             break;
180         case PixelFormat::NV21:
181         case PixelFormat::NV12:
182             pixelBytes = NV21_BYTES;  // perl pixel 1.5 Bytes but return int so return 2
183             break;
184         case PixelFormat::ASTC_4x4:
185         case PixelFormat::ASTC_6x6:
186         case PixelFormat::ASTC_8x8:
187             pixelBytes = ASTC_4X4_BYTES;
188             break;
189         case PixelFormat::YCBCR_P010:
190         case PixelFormat::YCRCB_P010:
191             pixelBytes = NV21P010_BYTES;
192             break;
193         default:
194             IMAGE_LOGE("[ImageUtil]get pixel bytes failed, pixelFormat:%{public}d.",
195                 static_cast<int32_t>(pixelFormat));
196             break;
197     }
198     return pixelBytes;
199 }
200 
GetRowDataSizeByPixelFormat(const int32_t & width,const PixelFormat & format)201 int32_t ImageUtils::GetRowDataSizeByPixelFormat(const int32_t &width, const PixelFormat &format)
202 {
203     uint64_t uWidth = static_cast<uint64_t>(width);
204     uint64_t pixelBytes = static_cast<uint64_t>(GetPixelBytes(format));
205     uint64_t rowDataSize = 0;
206     switch (format) {
207         case PixelFormat::ALPHA_8:
208             rowDataSize = pixelBytes * ((uWidth + FILL_NUMBER) / ALIGN_NUMBER * ALIGN_NUMBER);
209             break;
210         case PixelFormat::ASTC_4x4:
211             rowDataSize = pixelBytes * (((uWidth + NUM_3) >> NUM_2) << NUM_2);
212             break;
213         case PixelFormat::ASTC_6x6:
214             rowDataSize = pixelBytes * (((uWidth + NUM_5) / NUM_6) * NUM_6);
215             break;
216         case PixelFormat::ASTC_8x8:
217             rowDataSize = pixelBytes * (((uWidth + NUM_7) >> NUM_3) << NUM_3);
218             break;
219         default:
220             rowDataSize = pixelBytes * uWidth;
221     }
222     if (rowDataSize > INT32_MAX) {
223         IMAGE_LOGE("GetRowDataSizeByPixelFormat failed: rowDataSize overflowed");
224         return -1;
225     }
226     return static_cast<int32_t>(rowDataSize);
227 }
228 
RegisterPluginServer()229 uint32_t ImageUtils::RegisterPluginServer()
230 {
231 #ifdef _WIN32
232     vector<string> pluginPaths = { "" };
233 #elif defined(_APPLE)
234     vector<string> pluginPaths = { "./" };
235 #elif defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
236     vector<string> pluginPaths = {};
237 #else
238     vector<string> pluginPaths = { "/system/etc/multimediaplugin/image" };
239 #endif
240     PluginServer &pluginServer = DelayedRefSingleton<PluginServer>::GetInstance();
241     uint32_t result = pluginServer.Register(std::move(pluginPaths));
242     if (result != SUCCESS) {
243         IMAGE_LOGE("[ImageUtil]failed to register plugin server, ERRNO: %{public}u.", result);
244     } else {
245         g_pluginRegistered = true;
246         IMAGE_LOGD("[ImageUtil]success to register plugin server");
247     }
248     return result;
249 }
250 
GetPluginServer()251 PluginServer& ImageUtils::GetPluginServer()
252 {
253     if (!g_pluginRegistered) {
254         uint32_t result = RegisterPluginServer();
255         if (result != SUCCESS) {
256             IMAGE_LOGI("[ImageUtil]failed to register plugin server, ERRNO: %{public}u.", result);
257         }
258     }
259     return DelayedRefSingleton<PluginServer>::GetInstance();
260 }
261 
PathToRealPath(const string & path,string & realPath)262 bool ImageUtils::PathToRealPath(const string &path, string &realPath)
263 {
264     if (path.empty()) {
265         IMAGE_LOGE("path is empty!");
266         return false;
267     }
268 
269     if ((path.length() >= PATH_MAX)) {
270         IMAGE_LOGE("path len is error, the len is: [%{public}lu]", static_cast<unsigned long>(path.length()));
271         return false;
272     }
273 
274     char tmpPath[PATH_MAX] = { 0 };
275 
276 #ifdef _WIN32
277     if (_fullpath(tmpPath, path.c_str(), path.length()) == nullptr) {
278         IMAGE_LOGW("path to _fullpath error");
279     }
280 #else
281     if (realpath(path.c_str(), tmpPath) == nullptr) {
282         IMAGE_LOGE("path to realpath is nullptr");
283         return false;
284     }
285 #endif
286 
287     realPath = tmpPath;
288     return true;
289 }
290 
FloatCompareZero(float src)291 bool ImageUtils::FloatCompareZero(float src)
292 {
293     return fabs(src - 0) < EPSILON;
294 }
295 
GetValidAlphaTypeByFormat(const AlphaType & dstType,const PixelFormat & format)296 AlphaType ImageUtils::GetValidAlphaTypeByFormat(const AlphaType &dstType, const PixelFormat &format)
297 {
298     switch (format) {
299         case PixelFormat::RGBA_8888:
300         case PixelFormat::BGRA_8888:
301         case PixelFormat::ARGB_8888:
302         case PixelFormat::RGBA_1010102:
303         case PixelFormat::RGBA_F16: {
304             break;
305         }
306         case PixelFormat::ALPHA_8: {
307             if (dstType != AlphaType::IMAGE_ALPHA_TYPE_PREMUL) {
308                 return AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
309             }
310             break;
311         }
312         case PixelFormat::RGB_888:
313         case PixelFormat::RGB_565: {
314             if (dstType != AlphaType::IMAGE_ALPHA_TYPE_OPAQUE) {
315                 return AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
316             }
317             break;
318         }
319         case PixelFormat::NV21:
320         case PixelFormat::NV12:
321         case PixelFormat::YCBCR_P010:
322         case PixelFormat::YCRCB_P010: {
323             if (dstType != AlphaType::IMAGE_ALPHA_TYPE_OPAQUE) {
324                 return AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
325             }
326             break;
327         }
328         case PixelFormat::CMYK:
329         default: {
330             IMAGE_LOGE("GetValidAlphaTypeByFormat unsupport the format(%{public}d).", format);
331             return AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
332         }
333     }
334     return dstType;
335 }
336 
GetPixelMapAllocatorType(const Size & size,const PixelFormat & format,bool preferDma)337 AllocatorType ImageUtils::GetPixelMapAllocatorType(const Size &size, const PixelFormat &format, bool preferDma)
338 {
339 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
340     return IsSizeSupportDma(size) && (preferDma || (IsWidthAligned(size.width) && IsFormatSupportDma(format))) &&
341         (format == PixelFormat::RGBA_8888 || Is10Bit(format)) ?
342         AllocatorType::DMA_ALLOC : AllocatorType::SHARE_MEM_ALLOC;
343 #else
344     return AllocatorType::HEAP_ALLOC;
345 #endif
346 }
347 
IsValidImageInfo(const ImageInfo & info)348 bool ImageUtils::IsValidImageInfo(const ImageInfo &info)
349 {
350     if (info.size.width <= 0 || info.size.height <= 0 || info.size.width > MAX_DIMENSION ||
351         info.size.height > MAX_DIMENSION) {
352         IMAGE_LOGE("width(%{public}d) or height(%{public}d) is invalid.", info.size.width, info.size.height);
353         return false;
354     }
355     if (info.pixelFormat == PixelFormat::UNKNOWN || info.alphaType == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
356         IMAGE_LOGE("check pixelformat and alphatype is invalid.");
357         return false;
358     }
359     return true;
360 }
361 
IsValidAuxiliaryInfo(const std::shared_ptr<PixelMap> & pixelMap,const AuxiliaryPictureInfo & info)362 bool ImageUtils::IsValidAuxiliaryInfo(const std::shared_ptr<PixelMap> &pixelMap, const AuxiliaryPictureInfo &info)
363 {
364     int32_t rowSize = ImageUtils::GetRowDataSizeByPixelFormat(info.size.width, info.pixelFormat);
365     bool cond = rowSize <= 0 || info.size.height <= 0 ||
366                 rowSize > std::numeric_limits<int32_t>::max() / info.size.height;
367     CHECK_ERROR_RETURN_RET_LOG(cond, false, "%{public}s rowSize: %{public}d, height: %{public}d may overflowed",
368                                __func__, rowSize, info.size.height);
369     uint32_t infoSize = static_cast<uint32_t>(rowSize * info.size.height);
370     uint32_t pixelsSize = pixelMap->GetCapacity();
371     cond = infoSize > pixelsSize;
372     CHECK_ERROR_RETURN_RET_LOG(cond, false, "%{public}s invalid infoSize: %{public}u, pixelsSize: %{public}u",
373                                __func__, infoSize, pixelsSize);
374     return true;
375 }
376 
IsAstc(PixelFormat format)377 bool ImageUtils::IsAstc(PixelFormat format)
378 {
379     return format == PixelFormat::ASTC_4x4 || format == PixelFormat::ASTC_6x6 || format == PixelFormat::ASTC_8x8;
380 }
381 
IsYUV8Bit(PixelFormat & format)382 bool IsYUV8Bit(PixelFormat &format)
383 {
384     return format == PixelFormat::NV12 || format == PixelFormat::NV21;
385 }
386 
IsYUV10Bit(PixelFormat & format)387 bool IsYUV10Bit(PixelFormat &format)
388 {
389     return format == PixelFormat::YCBCR_P010 || format == PixelFormat::YCRCB_P010;
390 }
391 
IsYUV(PixelFormat format)392 bool ImageUtils::IsYUV(PixelFormat format)
393 {
394     return IsYUV8Bit(format) || IsYUV10Bit(format);
395 }
396 
IsRGBX(PixelFormat format)397 bool ImageUtils::IsRGBX(PixelFormat format)
398 {
399     return format == PixelFormat::ARGB_8888 || format == PixelFormat::RGB_565 ||
400         format == PixelFormat::RGBA_8888 || format == PixelFormat::BGRA_8888 ||
401         format == PixelFormat::RGB_888 || format == PixelFormat::ALPHA_8 ||
402         format == PixelFormat::RGBA_F16 || format == PixelFormat::RGBA_1010102 ||
403         format == PixelFormat::RGBA_U16 || format == PixelFormat::UNKNOWN;
404 }
405 
PixelMapCreateCheckFormat(PixelFormat format)406 bool ImageUtils::PixelMapCreateCheckFormat(PixelFormat format)
407 {
408     if (IsRGBX(format)) {
409         return true;
410     }
411     if (IsYUV(format)) {
412         return true;
413     }
414     return false;
415 }
416 
CheckTlvSupportedFormat(PixelFormat format)417 bool ImageUtils::CheckTlvSupportedFormat(PixelFormat format)
418 {
419     if (format == PixelFormat::UNKNOWN || format == PixelFormat::RGBA_U16 ||
420         IsYUV8Bit(format)) {
421         return false;
422     }
423     if (IsRGBX(format)) {
424         return true;
425     }
426     if (IsYUV10Bit(format)) {
427         return true;
428     }
429     return false;
430 }
431 
IsWidthAligned(const int32_t & width)432 bool ImageUtils::IsWidthAligned(const int32_t &width)
433 {
434     return ((static_cast<uint32_t>(width) * NUM_4) & INT_255) == 0;
435 }
436 
IsSizeSupportDma(const Size & size)437 bool ImageUtils::IsSizeSupportDma(const Size &size)
438 {
439     // Check for overflow risk
440     if (size.width > 0 && size.height > INT_MAX / size.width) {
441         return false;
442     }
443     return size.width * size.height >= DMA_SIZE;
444 }
445 
IsFormatSupportDma(const PixelFormat & format)446 bool ImageUtils::IsFormatSupportDma(const PixelFormat &format)
447 {
448     return format == PixelFormat::UNKNOWN || format == PixelFormat::RGBA_8888;
449 }
450 
Is10Bit(const PixelFormat & format)451 bool ImageUtils::Is10Bit(const PixelFormat &format)
452 {
453     return format == PixelFormat::RGBA_1010102 ||
454         format == PixelFormat::YCRCB_P010 || format == PixelFormat::YCBCR_P010;
455 }
456 
CheckMulOverflow(int32_t width,int32_t bytesPerPixel)457 bool ImageUtils::CheckMulOverflow(int32_t width, int32_t bytesPerPixel)
458 {
459     if (width == 0 || bytesPerPixel == 0) {
460         IMAGE_LOGE("param is 0");
461         return true;
462     }
463     int32_t rowSize = width * bytesPerPixel;
464     if ((rowSize / width) != bytesPerPixel) {
465         IMAGE_LOGE("width * bytesPerPixel overflow!");
466         return true;
467     }
468     return false;
469 }
470 
CheckMulOverflow(int32_t width,int32_t height,int32_t bytesPerPixel)471 bool ImageUtils::CheckMulOverflow(int32_t width, int32_t height, int32_t bytesPerPixel)
472 {
473     if (width == 0 || height == 0 || bytesPerPixel == 0) {
474         IMAGE_LOGE("param is 0");
475         return true;
476     }
477     int32_t rectSize = width * height;
478     if ((rectSize / width) != height) {
479         IMAGE_LOGE("width * height overflow!");
480         return true;
481     }
482     int32_t bufferSize = rectSize * bytesPerPixel;
483     if ((bufferSize / bytesPerPixel) != rectSize) {
484         IMAGE_LOGE("bytesPerPixel overflow!");
485         return true;
486     }
487     return false;
488 }
489 
ReversePixels(uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)490 static void ReversePixels(uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
491 {
492     if (byteCount % NUM_4 != NUM_0) {
493         IMAGE_LOGE("Pixel count must multiple of 4.");
494         return;
495     }
496     uint8_t *src = srcPixels;
497     uint8_t *dst = dstPixels;
498     for (uint32_t i = NUM_0 ; i < byteCount; i += NUM_4) {
499         // 0-B 1-G 2-R 3-A
500         dst[NUM_0] = src[NUM_3];
501         dst[NUM_1] = src[NUM_2];
502         dst[NUM_2] = src[NUM_1];
503         dst[NUM_3] = src[NUM_0];
504         src += NUM_4;
505         dst += NUM_4;
506     }
507 }
508 
BGRAToARGB(uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)509 void ImageUtils::BGRAToARGB(uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
510 {
511     ImageTrace imageTrace("BGRAToARGB");
512     ReversePixels(srcPixels, dstPixels, byteCount);
513 }
514 
ARGBToBGRA(uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)515 void ImageUtils::ARGBToBGRA(uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
516 {
517     ReversePixels(srcPixels, dstPixels, byteCount);
518 }
519 
SurfaceBuffer_Reference(void * buffer)520 int32_t ImageUtils::SurfaceBuffer_Reference(void* buffer)
521 {
522     if (buffer == nullptr) {
523         IMAGE_LOGE("parameter error, please check input parameter");
524         return ERR_SURFACEBUFFER_REFERENCE_FAILED;
525     }
526     OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(buffer);
527     ref->IncStrongRef(ref);
528     return SUCCESS;
529 }
530 
SurfaceBuffer_Unreference(void * buffer)531 int32_t ImageUtils::SurfaceBuffer_Unreference(void* buffer)
532 {
533     if (buffer == nullptr) {
534         IMAGE_LOGE("parameter error, please check input parameter");
535         return ERR_SURFACEBUFFER_UNREFERENCE_FAILED;
536     }
537     OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(buffer);
538     ref->DecStrongRef(ref);
539     return SUCCESS;
540 }
541 
DumpPixelMap(PixelMap * pixelMap,std::string customFileName,uint64_t imageId)542 void ImageUtils::DumpPixelMap(PixelMap* pixelMap, std::string customFileName, uint64_t imageId)
543 {
544     IMAGE_LOGI("ImageUtils::DumpPixelMap start");
545     std::string fileName = FILE_DIR_IN_THE_SANDBOX + GetLocalTime() + customFileName + std::to_string(imageId) +
546         GetPixelMapName(pixelMap) + ".dat";
547     int32_t totalSize = pixelMap->GetRowStride() * pixelMap->GetHeight();
548     PixelFormat pixelFormat = pixelMap->GetPixelFormat();
549     if (pixelFormat == PixelFormat::NV12 || pixelFormat == PixelFormat::NV21 ||
550         pixelFormat == PixelFormat::YCBCR_P010 || pixelFormat == PixelFormat::YCRCB_P010) {
551 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
552         if (pixelMap->GetAllocatorType() == AllocatorType::DMA_ALLOC) {
553             auto sbBuffer = reinterpret_cast<SurfaceBuffer*>(pixelMap->GetFd());
554             if (!sbBuffer) {
555                 return;
556             }
557             totalSize = static_cast<int32_t>(sbBuffer->GetSize());
558         } else {
559             totalSize = static_cast<int32_t>(pixelMap->GetCapacity());
560         }
561 #else
562         totalSize = static_cast<int32_t>(pixelMap->GetCapacity());
563 #endif
564         IMAGE_LOGI("ImageUtils::DumpPixelMapIfDumpEnabled YUV420 totalSize is %{public}d", totalSize);
565     }
566     if (SUCCESS != SaveDataToFile(fileName, reinterpret_cast<const char*>(pixelMap->GetPixels()), totalSize)) {
567         IMAGE_LOGI("ImageUtils::DumpPixelMap failed");
568         return;
569     }
570     IMAGE_LOGI("ImageUtils::DumpPixelMap success, path = %{public}s", fileName.c_str());
571 }
572 
DumpPixelMapIfDumpEnabled(std::unique_ptr<PixelMap> & pixelMap,uint64_t imageId)573 void ImageUtils::DumpPixelMapIfDumpEnabled(std::unique_ptr<PixelMap>& pixelMap, uint64_t imageId)
574 {
575     if (!ImageSystemProperties::GetDumpImageEnabled()) {
576         return;
577     }
578     if (pixelMap == nullptr) {
579         IMAGE_LOGI("ImageUtils::DumpPixelMapIfDumpEnabled pixelMap is null");
580         return;
581     }
582     DumpPixelMap(pixelMap.get(), "_imageId", imageId);
583 }
584 
DumpPixelMapBeforeEncode(PixelMap & pixelMap)585 void ImageUtils::DumpPixelMapBeforeEncode(PixelMap& pixelMap)
586 {
587     if (!ImageSystemProperties::GetDumpImageEnabled()) {
588         return;
589     }
590     DumpPixelMap(&pixelMap, "_beforeEncode");
591 }
592 
DumpDataIfDumpEnabled(const char * data,const size_t & totalSize,const std::string & fileSuffix,uint64_t imageId)593 void ImageUtils::DumpDataIfDumpEnabled(const char* data, const size_t& totalSize,
594     const std::string& fileSuffix, uint64_t imageId)
595 {
596     if (!ImageSystemProperties::GetDumpImageEnabled()) {
597         return;
598     }
599     std::string fileName = FILE_DIR_IN_THE_SANDBOX + GetLocalTime() + "_imageId" + std::to_string(imageId) +
600         "_data_total" + std::to_string(totalSize) + "." + fileSuffix;
601     if (SUCCESS != SaveDataToFile(fileName, data, totalSize)) {
602         IMAGE_LOGI("ImageUtils::DumpDataIfDumpEnabled failed");
603         return;
604     }
605     IMAGE_LOGI("ImageUtils::DumpDataIfDumpEnabled success, path = %{public}s", fileName.c_str());
606 }
607 
GetNowTimeMilliSeconds()608 uint64_t ImageUtils::GetNowTimeMilliSeconds()
609 {
610     auto now = std::chrono::system_clock::now();
611     return std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
612 }
613 
GetNowTimeMicroSeconds()614 uint64_t ImageUtils::GetNowTimeMicroSeconds()
615 {
616     auto now = std::chrono::system_clock::now();
617     return std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
618 }
619 
GetCurrentProcessName()620 std::string ImageUtils::GetCurrentProcessName()
621 {
622     std::string processName;
623     std::ifstream cmdlineFile("/proc/self/cmdline");
624     if (cmdlineFile.is_open()) {
625         std::ostringstream oss;
626         oss << cmdlineFile.rdbuf();
627         cmdlineFile.close();
628 
629         //Extrace process name from the command line
630         std::string cmdline = oss.str();
631         size_t pos = cmdline.find_first_of('\0');
632         if (pos != std::string::npos) {
633             processName = cmdline.substr(0, pos);
634         }
635     }
636     return processName;
637 }
638 
SaveDataToFile(const std::string & fileName,const char * data,const size_t & totalSize)639 uint32_t ImageUtils::SaveDataToFile(const std::string& fileName, const char* data, const size_t& totalSize)
640 {
641     std::ofstream outFile(fileName, std::ofstream::out);
642     if (!outFile.is_open()) {
643         IMAGE_LOGI("ImageUtils::SaveDataToFile write error, path=%{public}s", fileName.c_str());
644         return IMAGE_RESULT_SAVE_DATA_TO_FILE_FAILED;
645     }
646     if (data == nullptr) {
647         IMAGE_LOGE("ImageUtils::SaveDataToFile data is nullptr");
648         return IMAGE_RESULT_SAVE_DATA_TO_FILE_FAILED;
649     }
650     outFile.write(data, totalSize);
651     return SUCCESS;
652 }
653 
GetLocalTime()654 std::string ImageUtils::GetLocalTime()
655 {
656     // time string : "year-month-day hour_minute_second.millisecond", ':' is not supported in windows file name
657     auto now = std::chrono::system_clock::now();
658     auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
659     std::time_t t = std::chrono::system_clock::to_time_t(now);
660     std::tm tm = *std::localtime(&t);
661 
662     std::stringstream ss;
663     int millSecondWidth = 3;
664     ss << std::put_time(&tm, "%Y-%m-%d %H_%M_%S.") << std::setfill('0') << std::setw(millSecondWidth) << ms.count();
665     return ss.str();
666 }
667 
GetPixelMapName(PixelMap * pixelMap)668 std::string ImageUtils::GetPixelMapName(PixelMap* pixelMap)
669 {
670     if (!pixelMap) {
671         IMAGE_LOGE("ImageUtils::GetPixelMapName error, pixelMap is null");
672         return "";
673     }
674 #ifdef IOS_PLATFORM
675     std::string pixelMapStr = "_pixelMap_w" + std::to_string(pixelMap->GetWidth()) +
676         "_h" + std::to_string(pixelMap->GetHeight()) +
677         "_rowStride" + std::to_string(pixelMap->GetRowStride()) +
678         "_pixelFormat" + std::to_string((int32_t)pixelMap->GetPixelFormat()) +
679         "_total" + std::to_string(pixelMap->GetRowStride() * pixelMap->GetHeight()) +
680         "_pid" + std::to_string(getpid()) +
681         "_tid" + std::to_string(syscall(SYS_thread_selfid)) +
682         "_uniqueId" + std::to_string(pixelMap->GetUniqueId());
683 #else
684     std::string yuvInfoStr = "";
685     if (pixelMap->GetPixelFormat() == PixelFormat::NV12 || pixelMap->GetPixelFormat() == PixelFormat::NV21) {
686         YUVDataInfo yuvInfo;
687         pixelMap->GetImageYUVInfo(yuvInfo);
688         yuvInfoStr += "_yWidth" + std::to_string(yuvInfo.yWidth) +
689             "_yHeight" + std::to_string(yuvInfo.yHeight) +
690             "_yStride" + std::to_string(yuvInfo.yStride) +
691             "_yOffset" + std::to_string(yuvInfo.yOffset) +
692             "_uvWidth" + std::to_string(yuvInfo.uvWidth) +
693             "_uvHeight" + std::to_string(yuvInfo.uvHeight) +
694             "_uvStride" + std::to_string(yuvInfo.uvStride) +
695             "_uvOffset" + std::to_string(yuvInfo.uvOffset);
696     }
697     std::string pixelMapStr = "_pixelMap_w" + std::to_string(pixelMap->GetWidth()) +
698         "_h" + std::to_string(pixelMap->GetHeight()) +
699         "_rowStride" + std::to_string(pixelMap->GetRowStride()) +
700         "_pixelFormat" + std::to_string((int32_t)pixelMap->GetPixelFormat()) +
701         "_total" + std::to_string(pixelMap->GetRowStride() * pixelMap->GetHeight()) +
702         "_pid" + std::to_string(getpid()) +
703         "_tid" + std::to_string(gettid()) +
704         "_uniqueId" + std::to_string(pixelMap->GetUniqueId());
705 #endif
706     return pixelMapStr;
707 }
708 
709  // BytesToUint16 function will modify the offset value.
BytesToUint16(uint8_t * bytes,uint32_t & offset,uint32_t size,bool isBigEndian)710 uint16_t ImageUtils::BytesToUint16(uint8_t* bytes, uint32_t& offset, uint32_t size, bool isBigEndian)
711 {
712     uint16_t data = 0;
713     if (bytes == nullptr || offset + NUM_2 >= size) {
714         return data;
715     }
716     if (isBigEndian) {
717         data = (bytes[offset] << MOVE_BITS_8) | bytes[offset + NUM_1];
718     } else {
719         data = (bytes[offset + NUM_1] << MOVE_BITS_8) | bytes[offset];
720     }
721     offset += NUM_2;
722     return data;
723 }
724 
725 // BytesToUint32 function will modify the offset value.
BytesToUint32(uint8_t * bytes,uint32_t & offset,uint32_t size,bool isBigEndian)726 uint32_t ImageUtils::BytesToUint32(uint8_t* bytes, uint32_t& offset, uint32_t size, bool isBigEndian)
727 {
728     uint32_t data = 0;
729     if (bytes == nullptr || offset + NUM_4 >= size) {
730         return data;
731     }
732     if (isBigEndian) {
733         data = (bytes[offset] << MOVE_BITS_24) | (bytes[offset + NUM_1] << MOVE_BITS_16) |
734                 (bytes[offset + NUM_2] << MOVE_BITS_8) | (bytes[offset + NUM_3]);
735     } else {
736         data = (bytes[offset + NUM_3] << MOVE_BITS_24) | (bytes[offset + NUM_2] << MOVE_BITS_16) |
737                 (bytes[offset + NUM_1] << MOVE_BITS_8) | bytes[offset];
738     }
739     offset += NUM_4;
740     return data;
741 }
742 
743 // BytesToInt32 function will modify the offset value.
BytesToInt32(uint8_t * bytes,uint32_t & offset,uint32_t size,bool isBigEndian)744 int32_t ImageUtils::BytesToInt32(uint8_t* bytes, uint32_t& offset, uint32_t size, bool isBigEndian)
745 {
746     int32_t data = 0;
747     if (bytes == nullptr || offset + NUM_4 >= size) {
748         return data;
749     }
750     if (isBigEndian) {
751         data = (bytes[offset] << MOVE_BITS_24) | (bytes[offset + NUM_1] << MOVE_BITS_16) |
752                 (bytes[offset + NUM_2] << MOVE_BITS_8) | (bytes[offset + NUM_3]);
753     } else {
754         data = (bytes[offset + NUM_3] << MOVE_BITS_24) | (bytes[offset + NUM_2] << MOVE_BITS_16) |
755                 (bytes[offset + NUM_1] << MOVE_BITS_8) | bytes[offset];
756     }
757     offset += NUM_4;
758     return data;
759 }
760 
761 // BytesToFloat function will modify the offset value.
BytesToFloat(uint8_t * bytes,uint32_t & offset,uint32_t size,bool isBigEndian)762 float ImageUtils::BytesToFloat(uint8_t* bytes, uint32_t& offset, uint32_t size, bool isBigEndian)
763 {
764     uint32_t data = BytesToUint32(bytes, offset, size, isBigEndian);
765     union {
766         uint32_t i;
767         float f;
768     } u;
769     u.i = data;
770     return u.f;
771 }
772 
Uint16ToBytes(uint16_t data,vector<uint8_t> & bytes,uint32_t & offset,bool isBigEndian)773 void ImageUtils::Uint16ToBytes(uint16_t data, vector<uint8_t>& bytes, uint32_t& offset, bool isBigEndian)
774 {
775     uint8_t BYTE_ONE = (data >> MOVE_BITS_8) & 0xFF;
776     uint8_t BYTE_TWO = data & 0xFF;
777     if (isBigEndian) {
778         bytes[offset++] = BYTE_ONE;
779         bytes[offset++] = BYTE_TWO;
780     } else {
781         bytes[offset++] = BYTE_TWO;
782         bytes[offset++] = BYTE_ONE;
783     }
784 }
785 
Uint32ToBytes(uint32_t data,vector<uint8_t> & bytes,uint32_t & offset,bool isBigEndian)786 void ImageUtils::Uint32ToBytes(uint32_t data, vector<uint8_t>& bytes, uint32_t& offset, bool isBigEndian)
787 {
788     uint8_t BYTE_ONE = (data >> MOVE_BITS_24) & 0xFF;
789     uint8_t BYTE_TWO = (data >> MOVE_BITS_16) & 0xFF;
790     uint8_t BYTE_THREE = (data >> MOVE_BITS_8) & 0xFF;
791     uint8_t BYTE_FOUR = data & 0xFF;
792     if (isBigEndian) {
793         bytes[offset++] = BYTE_ONE;
794         bytes[offset++] = BYTE_TWO;
795         bytes[offset++] = BYTE_THREE;
796         bytes[offset++] = BYTE_FOUR;
797     } else {
798         bytes[offset++] = BYTE_FOUR;
799         bytes[offset++] = BYTE_THREE;
800         bytes[offset++] = BYTE_TWO;
801         bytes[offset++] = BYTE_ONE;
802     }
803 }
804 
FloatToBytes(float data,vector<uint8_t> & bytes,uint32_t & offset,bool isBigEndian)805 void ImageUtils::FloatToBytes(float data, vector<uint8_t>& bytes, uint32_t& offset, bool isBigEndian)
806 {
807     union {
808         uint32_t i;
809         float f;
810     } u;
811     u.f = data;
812     Uint32ToBytes(u.i, bytes, offset, isBigEndian);
813 }
814 
Int32ToBytes(int32_t data,vector<uint8_t> & bytes,uint32_t & offset,bool isBigEndian)815 void ImageUtils::Int32ToBytes(int32_t data, vector<uint8_t>& bytes, uint32_t& offset, bool isBigEndian)
816 {
817     union {
818         uint32_t uit;
819         int32_t it;
820     } u;
821     u.it = data;
822     Uint32ToBytes(u.uit, bytes, offset, isBigEndian);
823 }
824 
ArrayToBytes(const uint8_t * data,uint32_t length,vector<uint8_t> & bytes,uint32_t & offset)825 void ImageUtils::ArrayToBytes(const uint8_t* data, uint32_t length, vector<uint8_t>& bytes, uint32_t& offset)
826 {
827     for (uint32_t i = 0; i < length; i++) {
828         bytes[offset++] = data[i] & 0xFF;
829     }
830 }
831 
FlushSurfaceBuffer(PixelMap * pixelMap)832 void ImageUtils::FlushSurfaceBuffer(PixelMap* pixelMap)
833 {
834 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
835     if (!pixelMap || pixelMap->GetAllocatorType() != AllocatorType::DMA_ALLOC) {
836         return;
837     }
838     SurfaceBuffer* surfaceBuffer = static_cast<SurfaceBuffer*>(pixelMap->GetFd());
839     if (surfaceBuffer && (surfaceBuffer->GetUsage() & BUFFER_USAGE_MEM_MMZ_CACHE)) {
840         GSError err = surfaceBuffer->Map();
841         if (err != GSERROR_OK) {
842             IMAGE_LOGE("ImageUtils Map failed, GSError=%{public}d", err);
843             return;
844         }
845         err = surfaceBuffer->FlushCache();
846         if (err != GSERROR_OK) {
847             IMAGE_LOGE("ImageUtils FlushCache failed, GSError=%{public}d", err);
848         }
849     }
850 #else
851     return;
852 #endif
853 }
854 
FlushContextSurfaceBuffer(ImagePlugin::DecodeContext & context)855 void ImageUtils::FlushContextSurfaceBuffer(ImagePlugin::DecodeContext& context)
856 {
857 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
858     if (context.pixelsBuffer.context == nullptr || context.allocatorType != AllocatorType::DMA_ALLOC) {
859         return;
860     }
861     SurfaceBuffer* surfaceBuffer = static_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
862     if (surfaceBuffer && (surfaceBuffer->GetUsage() & BUFFER_USAGE_MEM_MMZ_CACHE)) {
863         GSError err = surfaceBuffer->Map();
864         if (err != GSERROR_OK) {
865             IMAGE_LOGE("ImageUtils Map failed, GSError=%{public}d", err);
866             return;
867         }
868         err = surfaceBuffer->FlushCache();
869         if (err != GSERROR_OK) {
870             IMAGE_LOGE("ImageUtils FlushCache failed, GSError=%{public}d", err);
871         }
872     }
873 #else
874     return;
875 #endif
876 }
877 
InvalidateContextSurfaceBuffer(ImagePlugin::DecodeContext & context)878 void ImageUtils::InvalidateContextSurfaceBuffer(ImagePlugin::DecodeContext& context)
879 {
880 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
881     bool cond = context.pixelsBuffer.context == nullptr || context.allocatorType != AllocatorType::DMA_ALLOC;
882     CHECK_ERROR_RETURN(cond);
883     SurfaceBuffer* surfaceBuffer = static_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
884     if (surfaceBuffer && (surfaceBuffer->GetUsage() & BUFFER_USAGE_MEM_MMZ_CACHE)) {
885         GSError err = surfaceBuffer->InvalidateCache();
886         cond = err != GSERROR_OK;
887         CHECK_ERROR_PRINT_LOG(cond, "ImageUtils FlushCache failed, GSError=%{public}d", err);
888     }
889 #else
890     return;
891 #endif
892 }
893 
IsAuxiliaryPictureTypeSupported(AuxiliaryPictureType type)894 bool ImageUtils::IsAuxiliaryPictureTypeSupported(AuxiliaryPictureType type)
895 {
896     auto auxTypes = GetAllAuxiliaryPictureType();
897     return (auxTypes.find(type) != auxTypes.end());
898 }
899 
IsAuxiliaryPictureEncoded(AuxiliaryPictureType type)900 bool ImageUtils::IsAuxiliaryPictureEncoded(AuxiliaryPictureType type)
901 {
902     return AuxiliaryPictureType::GAINMAP == type || AuxiliaryPictureType::UNREFOCUS_MAP == type ||
903         AuxiliaryPictureType::FRAGMENT_MAP == type;
904 }
905 
IsMetadataTypeSupported(MetadataType metadataType)906 bool ImageUtils::IsMetadataTypeSupported(MetadataType metadataType)
907 {
908     if (metadataType == MetadataType::EXIF || metadataType == MetadataType::FRAGMENT) {
909         return true;
910     } else {
911         return false;
912     }
913 }
914 
GetAllAuxiliaryPictureType()915 const std::set<AuxiliaryPictureType> ImageUtils::GetAllAuxiliaryPictureType()
916 {
917     static const std::set<AuxiliaryPictureType> auxTypes = {
918         AuxiliaryPictureType::GAINMAP,
919         AuxiliaryPictureType::DEPTH_MAP,
920         AuxiliaryPictureType::UNREFOCUS_MAP,
921         AuxiliaryPictureType::LINEAR_MAP,
922         AuxiliaryPictureType::FRAGMENT_MAP};
923     return auxTypes;
924 }
925 
GetAstcBytesCount(const ImageInfo & imageInfo)926 size_t ImageUtils::GetAstcBytesCount(const ImageInfo& imageInfo)
927 {
928     size_t astcBytesCount = 0;
929     uint32_t blockWidth = 0;
930     uint32_t blockHeight = 0;
931 
932     switch (imageInfo.pixelFormat) {
933         case PixelFormat::ASTC_4x4:
934             blockWidth = ASTC_4X4_BLOCK;
935             blockHeight = ASTC_4X4_BLOCK;
936             break;
937         case PixelFormat::ASTC_6x6:
938             blockWidth = ASTC_6X6_BLOCK;
939             blockHeight = ASTC_6X6_BLOCK;
940             break;
941         case PixelFormat::ASTC_8x8:
942             blockWidth = ASTC_8X8_BLOCK;
943             blockHeight = ASTC_8X8_BLOCK;
944             break;
945         default:
946             IMAGE_LOGE("ImageUtils GetAstcBytesCount failed, format is not supported %{public}d",
947                 imageInfo.pixelFormat);
948             return 0;
949     }
950     if ((blockWidth >= ASTC_4X4_BLOCK) && (blockHeight >= ASTC_4X4_BLOCK)) {
951         astcBytesCount = ((imageInfo.size.width + blockWidth - 1) / blockWidth) *
952             ((imageInfo.size.height + blockHeight - 1) / blockHeight) * ASTC_BLOCK_SIZE + ASTC_HEADER_SIZE;
953     }
954     return astcBytesCount;
955 }
956 
StrToUint32(const std::string & str,uint32_t & value)957 bool ImageUtils::StrToUint32(const std::string& str, uint32_t& value)
958 {
959     if (str.empty() || !isdigit(str.front())) {
960         return false;
961     }
962 
963     char* end = nullptr;
964     errno = 0;
965     auto addr = str.c_str();
966     auto result = strtoul(addr, &end, 10); /* 10 means decimal */
967     if ((end == addr) || (end[0] != '\0') || (errno == ERANGE) ||
968         (result > UINT32_MAX)) {
969         return false;
970     }
971     value = static_cast<uint32_t>(result);
972     return true;
973 }
974 
IsInRange(uint32_t value,uint32_t minValue,uint32_t maxValue)975 bool ImageUtils::IsInRange(uint32_t value, uint32_t minValue, uint32_t maxValue)
976 {
977     return (value >= minValue) && (value <= maxValue);
978 }
979 
IsInRange(int32_t value,int32_t minValue,int32_t maxValue)980 bool ImageUtils::IsInRange(int32_t value, int32_t minValue, int32_t maxValue)
981 {
982     return (value >= minValue) && (value <= maxValue);
983 }
984 
IsEven(int32_t value)985 bool ImageUtils::IsEven(int32_t value)
986 {
987     return value % BASE_EVEN_DIVISOR == 0;
988 }
989 
HasOverflowed(uint32_t num1,uint32_t num2)990 bool ImageUtils::HasOverflowed(uint32_t num1, uint32_t num2)
991 {
992     return num1 > std::numeric_limits<uint32_t>::max() - num2;
993 }
994 
GetEncodedHeifFormat()995 std::string ImageUtils::GetEncodedHeifFormat()
996 {
997     if (GetAPIVersion() > APIVERSION_13) {
998         return "image/heic";
999     } else {
1000         return "image/heif";
1001     }
1002 }
1003 
GetAPIVersion()1004 int32_t ImageUtils::GetAPIVersion()
1005 {
1006 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1007     uint32_t targetVersion = 0;
1008     auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1009     if (samgr == nullptr) {
1010         IMAGE_LOGE("Get ability manager failed");
1011         return FAULT_API_VERSION;
1012     }
1013     sptr<IRemoteObject> object = samgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
1014     if (object == nullptr) {
1015         IMAGE_LOGE("Object is NULL");
1016         return FAULT_API_VERSION;
1017     }
1018 
1019     sptr<OHOS::AppExecFwk::IBundleMgr> bms = iface_cast<OHOS::AppExecFwk::IBundleMgr>(object);
1020     if (bms == nullptr) {
1021         IMAGE_LOGE("Bundle manager service is NULL.");
1022         return FAULT_API_VERSION;
1023     }
1024     AppExecFwk::BundleInfo bundleInfo;
1025     if (bms->GetBundleInfoForSelf(0, bundleInfo) != ERR_OK) {
1026         IMAGE_LOGE("Get bundle info for self failed");
1027         return FAULT_API_VERSION;
1028     }
1029     targetVersion = bundleInfo.targetVersion;
1030     int32_t apiVersionResult = static_cast<int32_t>(targetVersion % 100);
1031     return apiVersionResult;
1032 #else
1033     return FAULT_API_VERSION;
1034 #endif
1035 }
1036 
1037 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
GetYUVStrideInfo(int32_t pixelFmt,OH_NativeBuffer_Planes * planes,YUVStrideInfo & dstStrides)1038 static void GetYUVStrideInfo(int32_t pixelFmt, OH_NativeBuffer_Planes *planes, YUVStrideInfo &dstStrides)
1039 {
1040     if (pixelFmt == GRAPHIC_PIXEL_FMT_YCBCR_420_SP) {
1041         auto yStride = planes->planes[PLANE_Y].columnStride;
1042         auto uvStride = planes->planes[PLANE_U].columnStride;
1043         auto yOffset = planes->planes[PLANE_Y].offset;
1044         auto uvOffset = planes->planes[PLANE_U].offset;
1045         dstStrides = {yStride, uvStride, yOffset, uvOffset};
1046     } else if (pixelFmt == GRAPHIC_PIXEL_FMT_YCRCB_420_SP) {
1047         auto yStride = planes->planes[PLANE_Y].columnStride;
1048         auto uvStride = planes->planes[PLANE_V].columnStride;
1049         auto yOffset = planes->planes[PLANE_Y].offset;
1050         auto uvOffset = planes->planes[PLANE_V].offset;
1051         dstStrides = {yStride, uvStride, yOffset, uvOffset};
1052     } else if (pixelFmt == GRAPHIC_PIXEL_FMT_YCBCR_P010) {
1053         auto yStride = planes->planes[PLANE_Y].columnStride / 2;
1054         auto uvStride = planes->planes[PLANE_U].columnStride / 2;
1055         auto yOffset = planes->planes[PLANE_Y].offset / 2;
1056         auto uvOffset = planes->planes[PLANE_U].offset / 2;
1057         dstStrides = {yStride, uvStride, yOffset, uvOffset};
1058     } else if (pixelFmt == GRAPHIC_PIXEL_FMT_YCRCB_P010) {
1059         auto yStride = planes->planes[PLANE_Y].columnStride / 2;
1060         auto uvStride = planes->planes[PLANE_V].columnStride / 2;
1061         auto yOffset = planes->planes[PLANE_Y].offset / 2;
1062         auto uvOffset = planes->planes[PLANE_V].offset / 2;
1063         dstStrides = {yStride, uvStride, yOffset, uvOffset};
1064     }
1065 }
1066 #endif
1067 
UpdateSdrYuvStrides(const ImageInfo & imageInfo,YUVStrideInfo & dstStrides,void * context,AllocatorType dstType)1068 void ImageUtils::UpdateSdrYuvStrides(const ImageInfo &imageInfo, YUVStrideInfo &dstStrides,
1069     void *context, AllocatorType dstType)
1070 {
1071     int32_t dstWidth = imageInfo.size.width;
1072     int32_t dstHeight = imageInfo.size.height;
1073     int32_t dstYStride = dstWidth;
1074     int32_t dstUvStride = (dstWidth + 1) / NUM_2 * NUM_2;
1075     int32_t dstYOffset = 0;
1076     int32_t dstUvOffset = dstYStride * dstHeight;
1077     dstStrides = {dstYStride, dstUvStride, dstYOffset, dstUvOffset};
1078 
1079 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1080     if (context == nullptr) {
1081         return;
1082     }
1083     if (dstType == AllocatorType::DMA_ALLOC) {
1084         auto sb = static_cast<SurfaceBuffer*>(context);
1085         if (sb == nullptr) {
1086             IMAGE_LOGE("get SurfaceBuffer failed");
1087             return;
1088         }
1089         OH_NativeBuffer_Planes *planes = nullptr;
1090         GSError retVal = sb->GetPlanesInfo(reinterpret_cast<void**>(&planes));
1091         if (retVal != OHOS::GSERROR_OK || planes == nullptr) {
1092             IMAGE_LOGE("UpdateSdrYuvStrides Get planesInfo failed, retVal:%{public}d", retVal);
1093         } else if (planes->planeCount >= NUM_2) {
1094             int32_t pixelFmt = sb->GetFormat();
1095             GetYUVStrideInfo(pixelFmt, planes, dstStrides);
1096         }
1097     }
1098 #endif
1099 }
1100 
GetReusePixelRefCount(const std::shared_ptr<PixelMap> & reusePixelmap)1101 uint16_t ImageUtils::GetReusePixelRefCount(const std::shared_ptr<PixelMap> &reusePixelmap)
1102 {
1103 #if !defined(CROSS_PLATFORM)
1104     if (reusePixelmap->GetAllocatorType() != AllocatorType::DMA_ALLOC) {
1105         return 0;
1106     }
1107     void* sbBuffer = reusePixelmap->GetFd();
1108     if (sbBuffer != nullptr) {
1109         OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(sbBuffer);
1110         uint16_t reusePixelRefCount = static_cast<uint16_t>(ref->GetSptrRefCount());
1111         return reusePixelRefCount;
1112     }
1113     return 0;
1114 #else
1115     return 0;
1116 #endif
1117 }
1118 
CanReusePixelMap(ImagePlugin::DecodeContext & context,int width,int height,const std::shared_ptr<PixelMap> & reusePixelmap)1119 bool ImageUtils::CanReusePixelMap(ImagePlugin::DecodeContext& context, int width,
1120     int height, const std::shared_ptr<PixelMap> &reusePixelmap)
1121 {
1122     if (reusePixelmap == nullptr) {
1123         IMAGE_LOGD("reusePixelmap is nullptr");
1124         return false;
1125     }
1126     bool cond = GetReusePixelRefCount(reusePixelmap) != 1;
1127     CHECK_ERROR_RETURN_RET_LOG(cond, false, "reusePixelmap reference count is not equal to 1");
1128     cond = ((width != reusePixelmap->GetWidth()) || (height != reusePixelmap->GetHeight()));
1129     CHECK_ERROR_RETURN_RET_LOG(cond, false, "The height or width of image is not equal to reusePixelmap");
1130     cond = ((reusePixelmap->GetAllocatorType() != AllocatorType::DMA_ALLOC) ||
1131         (context.allocatorType != AllocatorType::DMA_ALLOC));
1132     CHECK_ERROR_RETURN_RET_LOG(cond, false, "Image allocatortype is not DMA");
1133     return true;
1134 }
1135 
CanReusePixelMapHdr(ImagePlugin::DecodeContext & context,int width,int height,const std::shared_ptr<PixelMap> & reusePixelmap)1136 bool ImageUtils::CanReusePixelMapHdr(ImagePlugin::DecodeContext& context, int width,
1137     int height, const std::shared_ptr<PixelMap> &reusePixelmap)
1138 {
1139 #if !defined(CROSS_PLATFORM)
1140     if (!CanReusePixelMap(context, width, height, reusePixelmap)) {
1141         return false;
1142     }
1143     auto hdrPixelFormat = GRAPHIC_PIXEL_FMT_RGBA_1010102;
1144     if (context.photoDesiredPixelFormat == PixelFormat::YCBCR_P010) {
1145         hdrPixelFormat = GRAPHIC_PIXEL_FMT_YCBCR_P010;
1146     }
1147     SetContextHdr(context, hdrPixelFormat);
1148     bool cond = ((reusePixelmap->GetPixelFormat() != PixelFormat::RGBA_1010102) ||
1149         (context.info.pixelFormat != PixelFormat::RGBA_1010102));
1150     CHECK_ERROR_RETURN_RET_LOG(cond, false, "PixelFormat of Hdrimage is not equal to reusePixelmap");
1151     return true;
1152 #else
1153     return false;
1154 #endif
1155 }
1156 
IsReuseYUVFormat(PixelFormat format)1157 bool IsReuseYUVFormat(PixelFormat format)
1158 {
1159     return format == PixelFormat::NV12 || format == PixelFormat::NV21;
1160 }
1161 
1162 // Determine whether the reusePixelmap and decoding image are both YUV format.
IsReuseYUV(ImagePlugin::DecodeContext & context,const std::shared_ptr<PixelMap> & reusePixelmap)1163 bool ImageUtils::IsReuseYUV(ImagePlugin::DecodeContext& context, const std::shared_ptr<PixelMap> &reusePixelmap)
1164 {
1165     return IsReuseYUVFormat(reusePixelmap->GetPixelFormat()) && IsReuseYUVFormat(context.info.pixelFormat);
1166 }
1167 
IsReuseRGBFormat(PixelFormat format)1168 bool IsReuseRGBFormat(PixelFormat format)
1169 {
1170     return format == PixelFormat::RGBA_8888 || format == PixelFormat::BGRA_8888;
1171 }
1172 
1173 // Determine whether the reusePixelmap and decoding image are both RGB format.
IsReuseRGB(ImagePlugin::DecodeContext & context,const std::shared_ptr<PixelMap> & reusePixelmap)1174 bool ImageUtils::IsReuseRGB(ImagePlugin::DecodeContext& context, const std::shared_ptr<PixelMap> &reusePixelmap)
1175 {
1176     return IsReuseRGBFormat(reusePixelmap->GetPixelFormat()) && IsReuseRGBFormat(context.info.pixelFormat);
1177 }
1178 
CanReusePixelMapSdr(ImagePlugin::DecodeContext & context,int width,int height,const std::shared_ptr<PixelMap> & reusePixelmap)1179 bool ImageUtils::CanReusePixelMapSdr(ImagePlugin::DecodeContext& context, int width,
1180     int height, const std::shared_ptr<PixelMap> &reusePixelmap)
1181 {
1182     if (!CanReusePixelMap(context, width, height, reusePixelmap)) {
1183         return false;
1184     }
1185     bool cond = ((reusePixelmap->GetPixelFormat() == PixelFormat::RGBA_1010102) ||
1186         (context.info.pixelFormat == PixelFormat::RGBA_1010102));
1187     CHECK_ERROR_RETURN_RET_LOG(cond, false, "Sdr image is not RGBA 10bit");
1188     cond = (!IsReuseYUV(context, reusePixelmap) && !IsReuseRGB(context, reusePixelmap));
1189     CHECK_ERROR_RETURN_RET_LOG(cond, false, "PixelFormat of Sdrimage is not equal to reusePixelmap");
1190     return true;
1191 }
1192 
CanApplyMemForReusePixel(ImagePlugin::DecodeContext & context,const std::shared_ptr<PixelMap> & reusePixelmap)1193 bool CanApplyMemForReusePixel(ImagePlugin::DecodeContext& context,
1194     const std::shared_ptr<PixelMap> &reusePixelmap)
1195 {
1196 #if !defined(CROSS_PLATFORM)
1197     uint8_t *reusePixelBuffer = const_cast<uint8_t *>(reusePixelmap->GetPixels());
1198     int32_t err = ImageUtils::SurfaceBuffer_Reference(reusePixelmap->GetFd());
1199     bool cond = err != OHOS::GSERROR_OK;
1200     CHECK_ERROR_RETURN_RET_LOG(cond, false, "reusePixelmapBuffer Reference failed");
1201     ImageUtils::SetReuseContextBuffer(context, AllocatorType::DMA_ALLOC, reusePixelBuffer,
1202         reusePixelmap->GetCapacity(), reusePixelmap->GetFd());
1203     return true;
1204 #else
1205     return false;
1206 #endif
1207 }
1208 
IsSdrPixelMapReuseSuccess(ImagePlugin::DecodeContext & context,int width,int height,const std::shared_ptr<PixelMap> & reusePixelmap)1209 bool ImageUtils::IsSdrPixelMapReuseSuccess(ImagePlugin::DecodeContext& context, int width,
1210     int height, const std::shared_ptr<PixelMap> &reusePixelmap)
1211 {
1212 #if !defined(CROSS_PLATFORM)
1213     if (!CanReusePixelMapSdr(context, width, height, reusePixelmap)) {
1214         return false;
1215     }
1216     return CanApplyMemForReusePixel(context, reusePixelmap);
1217 #else
1218     return false;
1219 #endif
1220 }
1221 
IsHdrPixelMapReuseSuccess(ImagePlugin::DecodeContext & context,int width,int height,const std::shared_ptr<PixelMap> & reusePixelmap)1222 bool ImageUtils::IsHdrPixelMapReuseSuccess(ImagePlugin::DecodeContext& context, int width,
1223     int height, const std::shared_ptr<PixelMap> &reusePixelmap)
1224 {
1225 #if !defined(CROSS_PLATFORM)
1226     if (!CanReusePixelMapHdr(context, width, height, reusePixelmap)) {
1227         return false;
1228     }
1229     return CanApplyMemForReusePixel(context, reusePixelmap);
1230 #else
1231     return false;
1232 #endif
1233 }
1234 
SetContextHdr(ImagePlugin::DecodeContext & context,uint32_t format)1235 void ImageUtils::SetContextHdr(ImagePlugin::DecodeContext& context, uint32_t format)
1236 {
1237 #if !defined(CROSS_PLATFORM)
1238     context.info.alphaType = AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL;
1239     if (format == GRAPHIC_PIXEL_FMT_RGBA_1010102) {
1240         context.pixelFormat = PixelFormat::RGBA_1010102;
1241         context.info.pixelFormat = PixelFormat::RGBA_1010102;
1242         context.grColorSpaceName = ColorManager::BT2020_HLG;
1243     } else if (format == GRAPHIC_PIXEL_FMT_YCBCR_P010) {
1244         context.pixelFormat = PixelFormat::YCBCR_P010;
1245         context.info.pixelFormat = PixelFormat::YCBCR_P010;
1246         context.grColorSpaceName = ColorManager::BT2020_HLG;
1247     }
1248 #endif
1249 }
1250 
SetReuseContextBuffer(ImagePlugin::DecodeContext & context,AllocatorType type,uint8_t * ptr,uint64_t count,void * fd)1251 void ImageUtils::SetReuseContextBuffer(ImagePlugin::DecodeContext& context,
1252     AllocatorType type, uint8_t* ptr, uint64_t count, void* fd)
1253 {
1254     context.allocatorType = type;
1255     context.freeFunc = nullptr;
1256     context.pixelsBuffer.buffer = ptr;
1257     context.pixelsBuffer.bufferSize = count;
1258     context.pixelsBuffer.context = fd;
1259 }
1260 } // namespace Media
1261 } // namespace OHOS
1262