• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "image_utils.h"
17 
18 #include <sys/stat.h>
19 #include <cerrno>
20 #include <climits>
21 #include <cmath>
22 #include <cstdint>
23 #include <cstdlib>
24 #include <string>
25 #include <fstream>
26 #include <sstream>
27 
28 #include "__config"
29 #include "image_log.h"
30 #include "ios"
31 #include "istream"
32 #include "media_errors.h"
33 #include "new"
34 #include "plugin_server.h"
35 #include "singleton.h"
36 #include "string"
37 #include "type_traits"
38 #include "vector"
39 #include "image_trace.h"
40 #include "hitrace_meter.h"
41 #include "image_system_properties.h"
42 #include "pixel_map.h"
43 #ifdef IOS_PLATFORM
44 #include <sys/syscall.h>
45 #endif
46 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
47 #include "surface_buffer.h"
48 #else
49 #include "refbase.h"
50 #endif
51 
52 #undef LOG_DOMAIN
53 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
54 
55 #undef LOG_TAG
56 #define LOG_TAG "imageUtils"
57 
58 namespace OHOS {
59 namespace Media {
60 using namespace std;
61 using namespace MultimediaPlugin;
62 
63 constexpr int32_t ALPHA8_BYTES = 1;
64 constexpr int32_t RGB565_BYTES = 2;
65 constexpr int32_t RGB888_BYTES = 3;
66 constexpr int32_t ARGB8888_BYTES = 4;
67 constexpr int32_t RGBA_F16_BYTES = 8;
68 constexpr int32_t NV21_BYTES = 2;  // Each pixel is sorted on 3/2 bytes.
69 constexpr int32_t ASTC_4X4_BYTES = 1;
70 constexpr float EPSILON = 1e-6;
71 constexpr int MAX_DIMENSION = INT32_MAX >> 2;
72 static bool g_pluginRegistered = false;
73 static const uint8_t NUM_0 = 0;
74 static const uint8_t NUM_1 = 1;
75 static const uint8_t NUM_2 = 2;
76 static const uint8_t NUM_3 = 3;
77 static const uint8_t NUM_4 = 4;
78 static const string FILE_DIR_IN_THE_SANDBOX = "/data/storage/el2/base/files/";
79 
GetFileSize(const string & pathName,size_t & size)80 bool ImageUtils::GetFileSize(const string &pathName, size_t &size)
81 {
82     if (pathName.empty()) {
83         IMAGE_LOGE("[ImageUtil]input parameter exception.");
84         return false;
85     }
86     struct stat statbuf;
87     int ret = stat(pathName.c_str(), &statbuf);
88     if (ret != 0) {
89         IMAGE_LOGE("[ImageUtil]get the file size failed, ret:%{public}d, errno:%{public}d.", ret, errno);
90         return false;
91     }
92     size = statbuf.st_size;
93     return true;
94 }
95 
GetFileSize(const int fd,size_t & size)96 bool ImageUtils::GetFileSize(const int fd, size_t &size)
97 {
98     struct stat statbuf;
99 
100     if (fd < 0) {
101         return false;
102     }
103 
104     int ret = fstat(fd, &statbuf);
105     if (ret != 0) {
106         IMAGE_LOGE("[ImageUtil]get the file size failed, ret:%{public}d, errno:%{public}d.", ret, errno);
107         return false;
108     }
109     size = statbuf.st_size;
110     return true;
111 }
112 
GetInputStreamSize(istream & inputStream,size_t & size)113 bool ImageUtils::GetInputStreamSize(istream &inputStream, size_t &size)
114 {
115     if (inputStream.rdbuf() == nullptr) {
116         IMAGE_LOGE("[ImageUtil]input parameter exception.");
117         return false;
118     }
119     size_t original = inputStream.tellg();
120     inputStream.seekg(0, ios_base::end);
121     size = inputStream.tellg();
122     inputStream.seekg(original);
123     return true;
124 }
125 
GetPixelBytes(const PixelFormat & pixelFormat)126 int32_t ImageUtils::GetPixelBytes(const PixelFormat &pixelFormat)
127 {
128     int pixelBytes = 0;
129     switch (pixelFormat) {
130         case PixelFormat::ARGB_8888:
131         case PixelFormat::BGRA_8888:
132         case PixelFormat::RGBA_8888:
133         case PixelFormat::CMYK:
134             pixelBytes = ARGB8888_BYTES;
135             break;
136         case PixelFormat::ALPHA_8:
137             pixelBytes = ALPHA8_BYTES;
138             break;
139         case PixelFormat::RGB_888:
140             pixelBytes = RGB888_BYTES;
141             break;
142         case PixelFormat::RGB_565:
143             pixelBytes = RGB565_BYTES;
144             break;
145         case PixelFormat::RGBA_F16:
146             pixelBytes = RGBA_F16_BYTES;
147             break;
148         case PixelFormat::NV21:
149         case PixelFormat::NV12:
150             pixelBytes = NV21_BYTES;  // perl pixel 1.5 Bytes but return int so return 2
151             break;
152         case PixelFormat::ASTC_4x4:
153         case PixelFormat::ASTC_6x6:
154         case PixelFormat::ASTC_8x8:
155             pixelBytes = ASTC_4X4_BYTES;
156             break;
157         default:
158             IMAGE_LOGE("[ImageUtil]get pixel bytes failed, pixelFormat:%{public}d.",
159                 static_cast<int32_t>(pixelFormat));
160             break;
161     }
162     return pixelBytes;
163 }
164 
RegisterPluginServer()165 uint32_t ImageUtils::RegisterPluginServer()
166 {
167 #ifdef _WIN32
168     vector<string> pluginPaths = { "" };
169 #elif defined(_APPLE)
170     vector<string> pluginPaths = { "./" };
171 #elif defined(A_PLATFORM) || defined(IOS_PLATFORM)
172     vector<string> pluginPaths = {};
173 #else
174     vector<string> pluginPaths = { "/system/etc/multimediaplugin/image" };
175 #endif
176     PluginServer &pluginServer = DelayedRefSingleton<PluginServer>::GetInstance();
177     uint32_t result = pluginServer.Register(std::move(pluginPaths));
178     if (result != SUCCESS) {
179         IMAGE_LOGE("[ImageUtil]failed to register plugin server, ERRNO: %{public}u.", result);
180     } else {
181         g_pluginRegistered = true;
182         IMAGE_LOGD("[ImageUtil]success to register plugin server");
183     }
184     return result;
185 }
186 
GetPluginServer()187 PluginServer& ImageUtils::GetPluginServer()
188 {
189     if (!g_pluginRegistered) {
190         uint32_t result = RegisterPluginServer();
191         if (result != SUCCESS) {
192             IMAGE_LOGI("[ImageUtil]failed to register plugin server, ERRNO: %{public}u.", result);
193         }
194     }
195     return DelayedRefSingleton<PluginServer>::GetInstance();
196 }
197 
PathToRealPath(const string & path,string & realPath)198 bool ImageUtils::PathToRealPath(const string &path, string &realPath)
199 {
200     if (path.empty()) {
201         IMAGE_LOGE("path is empty!");
202         return false;
203     }
204 
205     if ((path.length() >= PATH_MAX)) {
206         IMAGE_LOGE("path len is error, the len is: [%{public}lu]", static_cast<unsigned long>(path.length()));
207         return false;
208     }
209 
210     char tmpPath[PATH_MAX] = { 0 };
211 
212 #ifdef _WIN32
213     if (_fullpath(tmpPath, path.c_str(), path.length()) == nullptr) {
214         IMAGE_LOGW("path to _fullpath error");
215     }
216 #else
217     if (realpath(path.c_str(), tmpPath) == nullptr) {
218         IMAGE_LOGE("path to realpath is nullptr");
219         return false;
220     }
221 #endif
222 
223     realPath = tmpPath;
224     return true;
225 }
226 
FloatCompareZero(float src)227 bool ImageUtils::FloatCompareZero(float src)
228 {
229     return fabs(src - 0) < EPSILON;
230 }
231 
GetValidAlphaTypeByFormat(const AlphaType & dstType,const PixelFormat & format)232 AlphaType ImageUtils::GetValidAlphaTypeByFormat(const AlphaType &dstType, const PixelFormat &format)
233 {
234     switch (format) {
235         case PixelFormat::RGBA_8888:
236         case PixelFormat::BGRA_8888:
237         case PixelFormat::ARGB_8888:
238         case PixelFormat::RGBA_F16: {
239             break;
240         }
241         case PixelFormat::ALPHA_8: {
242             if (dstType != AlphaType::IMAGE_ALPHA_TYPE_PREMUL) {
243                 return AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
244             }
245             break;
246         }
247         case PixelFormat::RGB_888:
248         case PixelFormat::RGB_565: {
249             if (dstType != AlphaType::IMAGE_ALPHA_TYPE_OPAQUE) {
250                 return AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
251             }
252             break;
253         }
254         case PixelFormat::NV21:
255         case PixelFormat::NV12:
256         case PixelFormat::CMYK:
257         default: {
258             IMAGE_LOGE("GetValidAlphaTypeByFormat unsupport the format(%{public}d).", format);
259             return AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
260         }
261     }
262     return dstType;
263 }
264 
IsValidImageInfo(const ImageInfo & info)265 bool ImageUtils::IsValidImageInfo(const ImageInfo &info)
266 {
267     if (info.size.width <= 0 || info.size.height <= 0 || info.size.width > MAX_DIMENSION ||
268         info.size.height > MAX_DIMENSION) {
269         IMAGE_LOGE("width(%{public}d) or height(%{public}d) is invalid.", info.size.width, info.size.height);
270         return false;
271     }
272     if (info.pixelFormat == PixelFormat::UNKNOWN || info.alphaType == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
273         IMAGE_LOGE("check pixelformat and alphatype is invalid.");
274         return false;
275     }
276     return true;
277 }
278 
CheckMulOverflow(int32_t width,int32_t bytesPerPixel)279 bool ImageUtils::CheckMulOverflow(int32_t width, int32_t bytesPerPixel)
280 {
281     if (width == 0 || bytesPerPixel == 0) {
282         IMAGE_LOGE("param is 0");
283         return true;
284     }
285     int64_t rowSize = static_cast<int64_t>(width) * bytesPerPixel;
286     if ((rowSize / width) != bytesPerPixel) {
287         IMAGE_LOGE("width * bytesPerPixel overflow!");
288         return true;
289     }
290     return false;
291 }
292 
CheckMulOverflow(int32_t width,int32_t height,int32_t bytesPerPixel)293 bool ImageUtils::CheckMulOverflow(int32_t width, int32_t height, int32_t bytesPerPixel)
294 {
295     if (width == 0 || height == 0 || bytesPerPixel == 0) {
296         IMAGE_LOGE("param is 0");
297         return true;
298     }
299     int64_t rectSize = static_cast<int64_t>(width) * height;
300     if ((rectSize / width) != height) {
301         IMAGE_LOGE("width * height overflow!");
302         return true;
303     }
304     int64_t bufferSize = rectSize * bytesPerPixel;
305     if ((bufferSize / bytesPerPixel) != rectSize) {
306         IMAGE_LOGE("bytesPerPixel overflow!");
307         return true;
308     }
309     return false;
310 }
311 
ReversePixels(uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)312 static void ReversePixels(uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
313 {
314     if (byteCount % NUM_4 != NUM_0) {
315         IMAGE_LOGE("Pixel count must multiple of 4.");
316         return;
317     }
318     uint8_t *src = srcPixels;
319     uint8_t *dst = dstPixels;
320     for (uint32_t i = NUM_0 ; i < byteCount; i += NUM_4) {
321         // 0-B 1-G 2-R 3-A
322         dst[NUM_0] = src[NUM_3];
323         dst[NUM_1] = src[NUM_2];
324         dst[NUM_2] = src[NUM_1];
325         dst[NUM_3] = src[NUM_0];
326         src += NUM_4;
327         dst += NUM_4;
328     }
329 }
330 
BGRAToARGB(uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)331 void ImageUtils::BGRAToARGB(uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
332 {
333     ImageTrace imageTrace("BGRAToARGB");
334     ReversePixels(srcPixels, dstPixels, byteCount);
335 }
336 
ARGBToBGRA(uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)337 void ImageUtils::ARGBToBGRA(uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
338 {
339     ReversePixels(srcPixels, dstPixels, byteCount);
340 }
341 
SurfaceBuffer_Reference(void * buffer)342 int32_t ImageUtils::SurfaceBuffer_Reference(void* buffer)
343 {
344     if (buffer == nullptr) {
345         IMAGE_LOGE("parameter error, please check input parameter");
346         return ERR_SURFACEBUFFER_REFERENCE_FAILED;
347     }
348     OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(buffer);
349     ref->IncStrongRef(ref);
350     return SUCCESS;
351 }
352 
SurfaceBuffer_Unreference(void * buffer)353 int32_t ImageUtils::SurfaceBuffer_Unreference(void* buffer)
354 {
355     if (buffer == nullptr) {
356         IMAGE_LOGE("parameter error, please check input parameter");
357         return ERR_SURFACEBUFFER_UNREFERENCE_FAILED;
358     }
359     OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(buffer);
360     ref->DecStrongRef(ref);
361     return SUCCESS;
362 }
363 
DumpPixelMapIfDumpEnabled(std::unique_ptr<PixelMap> & pixelMap,uint64_t imageId)364 void ImageUtils::DumpPixelMapIfDumpEnabled(std::unique_ptr<PixelMap>& pixelMap, uint64_t imageId)
365 {
366     if (!ImageSystemProperties::GetDumpImageEnabled()) {
367         return;
368     }
369     if (pixelMap == nullptr) {
370         IMAGE_LOGI("ImageUtils::DumpPixelMapIfDumpEnabled pixelMap is null");
371         return;
372     }
373 
374     IMAGE_LOGI("ImageUtils::DumpPixelMapIfDumpEnabled start");
375     std::string fileName = FILE_DIR_IN_THE_SANDBOX + GetLocalTime() + "_imageId" + std::to_string(imageId) +
376         GetPixelMapName(pixelMap.get()) + ".dat";
377     int32_t totalSize = pixelMap->GetRowStride() * pixelMap->GetHeight();
378     if (SUCCESS != SaveDataToFile(fileName, reinterpret_cast<const char*>(pixelMap->GetPixels()), totalSize)) {
379         IMAGE_LOGI("ImageUtils::DumpPixelMapIfDumpEnabled failed");
380         return;
381     }
382     IMAGE_LOGI("ImageUtils::DumpPixelMapIfDumpEnabled success, path = %{public}s", fileName.c_str());
383 }
384 
DumpPixelMapBeforeEncode(PixelMap & pixelMap)385 void ImageUtils::DumpPixelMapBeforeEncode(PixelMap& pixelMap)
386 {
387     if (!ImageSystemProperties::GetDumpImageEnabled()) {
388         return;
389     }
390     IMAGE_LOGI("ImageUtils::DumpPixelMapBeforeEncode start");
391     std::string fileName = FILE_DIR_IN_THE_SANDBOX + GetLocalTime() + "_beforeEncode" + GetPixelMapName(&pixelMap) +
392         ".dat";
393     int32_t totalSize = pixelMap.GetRowStride() * pixelMap.GetHeight();
394     if (SUCCESS != SaveDataToFile(fileName, reinterpret_cast<const char*>(pixelMap.GetPixels()), totalSize)) {
395         IMAGE_LOGI("ImageUtils::DumpPixelMapBeforeEncode failed");
396         return;
397     }
398     IMAGE_LOGI("ImageUtils::DumpPixelMapBeforeEncode success, path = %{public}s", fileName.c_str());
399 }
400 
DumpDataIfDumpEnabled(const char * data,const size_t & totalSize,const std::string & fileSuffix,uint64_t imageId)401 void ImageUtils::DumpDataIfDumpEnabled(const char* data, const size_t& totalSize,
402     const std::string& fileSuffix, uint64_t imageId)
403 {
404     if (!ImageSystemProperties::GetDumpImageEnabled()) {
405         return;
406     }
407     std::string fileName = FILE_DIR_IN_THE_SANDBOX + GetLocalTime() + "_imageId" + std::to_string(imageId) +
408         "_data_total" + std::to_string(totalSize) + "." + fileSuffix;
409     if (SUCCESS != SaveDataToFile(fileName, data, totalSize)) {
410         IMAGE_LOGI("ImageUtils::DumpDataIfDumpEnabled failed");
411         return;
412     }
413     IMAGE_LOGI("ImageUtils::DumpDataIfDumpEnabled success, path = %{public}s", fileName.c_str());
414 }
415 
SaveDataToFile(const std::string & fileName,const char * data,const size_t & totalSize)416 uint32_t ImageUtils::SaveDataToFile(const std::string& fileName, const char* data, const size_t& totalSize)
417 {
418     std::ofstream outFile(fileName, std::ofstream::out);
419     if (!outFile.is_open()) {
420         IMAGE_LOGI("ImageUtils::SaveDataToFile write error, path=%{public}s", fileName.c_str());
421         return IMAGE_RESULT_SAVE_DATA_TO_FILE_FAILED;
422     }
423     outFile.write(data, totalSize);
424     return SUCCESS;
425 }
426 
GetLocalTime()427 std::string ImageUtils::GetLocalTime()
428 {
429     // time string : "year-month-day hour_minute_second.millisecond", ':' is not supported in windows file name
430     auto now = std::chrono::system_clock::now();
431     auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
432     std::time_t t = std::chrono::system_clock::to_time_t(now);
433     std::tm tm = *std::localtime(&t);
434 
435     std::stringstream ss;
436     int millSecondWidth = 3;
437     ss << std::put_time(&tm, "%Y-%m-%d %H_%M_%S.") << std::setfill('0') << std::setw(millSecondWidth) << ms.count();
438     return ss.str();
439 }
440 
GetPixelMapName(PixelMap * pixelMap)441 std::string ImageUtils::GetPixelMapName(PixelMap* pixelMap)
442 {
443     if (!pixelMap) {
444         IMAGE_LOGE("ImageUtils::GetPixelMapName error, pixelMap is null");
445         return "";
446     }
447 #ifdef IOS_PLATFORM
448     std::string pixelMapStr = "_pixelMap_w" + std::to_string(pixelMap->GetWidth()) +
449         "_h" + std::to_string(pixelMap->GetHeight()) +
450         "_rowStride" + std::to_string(pixelMap->GetRowStride()) +
451         "_total" + std::to_string(pixelMap->GetRowStride() * pixelMap->GetHeight()) +
452         "_pid" + std::to_string(getpid()) +
453         "_tid" + std::to_string(syscall(SYS_thread_selfid)) +
454         "_uniqueId" + std::to_string(pixelMap->GetUniqueId());
455 #else
456     std::string pixelMapStr = "_pixelMap_w" + std::to_string(pixelMap->GetWidth()) +
457         "_h" + std::to_string(pixelMap->GetHeight()) +
458         "_rowStride" + std::to_string(pixelMap->GetRowStride()) +
459         "_total" + std::to_string(pixelMap->GetRowStride() * pixelMap->GetHeight()) +
460         "_pid" + std::to_string(getpid()) +
461         "_tid" + std::to_string(gettid()) +
462         "_uniqueId" + std::to_string(pixelMap->GetUniqueId());
463 #endif
464     return pixelMapStr;
465 }
466 } // namespace Media
467 } // namespace OHOS
468