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