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