1 /*
2 * Copyright (C) 2024 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 #include <cmath>
16 #include "pixel_yuv.h"
17
18 #include "image_utils.h"
19 #include "image_trace.h"
20 #include "image_type_converter.h"
21 #include "memory_manager.h"
22 #include "hitrace_meter.h"
23 #include "media_errors.h"
24 #include "pubdef.h"
25 #include "pixel_yuv_utils.h"
26 #include "securec.h"
27 #include "vpe_utils.h"
28 #include "image_log.h"
29 #include "image_mdk_common.h"
30 #include "image_system_properties.h"
31 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
32 #include "surface_buffer.h"
33 #endif
34
35 #undef LOG_DOMAIN
36 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
37
38 #undef LOG_TAG
39 #define LOG_TAG "PixelYuv"
40
41 namespace OHOS {
42 namespace Media {
43 using namespace std;
44
45 static const uint8_t NUM_2 = 2;
46 static const uint8_t NUM_3 = 3;
47 static const uint8_t NUM_4 = 4;
48 static const uint8_t RGBA_BIT_DEPTH = 4;
49 static const uint32_t TWO_SLICES = 2;
50 static const uint8_t YUV420_MIN_PIXEL_UINTBYTES = 4;
51 static const uint8_t YUV420P010_MIN_PIXEL_UINTBYTES = 8;
52 static const int32_t DEGREES90 = 90;
53 static const int32_t DEGREES180 = 180;
54 static const int32_t DEGREES270 = 270;
55 static const int32_t DEGREES360 = 360;
56 static const int32_t PLANE_Y = 0;
57 static const int32_t PLANE_U = 1;
58 static const int32_t PLANE_V = 2;
59 constexpr uint8_t Y_SHIFT = 16;
60 constexpr uint8_t U_SHIFT = 8;
61 constexpr uint8_t V_SHIFT = 0;
62 constexpr int32_t MAX_DIMENSION = INT32_MAX >> NUM_2;
63
64 struct TransInfos {
65 SkMatrix matrix;
66 };
67
68 struct TransMemoryInfo {
69 AllocatorType allocType;
70 std::unique_ptr<AbsMemory> memory = nullptr;
71 };
72
ToSkImageInfo(ImageInfo & info,sk_sp<SkColorSpace> colorSpace)73 static SkImageInfo ToSkImageInfo(ImageInfo &info, sk_sp<SkColorSpace> colorSpace)
74 {
75 SkColorType colorType = ImageTypeConverter::ToSkColorType(info.pixelFormat);
76 SkAlphaType alphaType = ImageTypeConverter::ToSkAlphaType(info.alphaType);
77 IMAGE_LOGD("ToSkImageInfo w %{public}d, h %{public}d\n" \
78 "ToSkImageInfo pf %{public}s, at %{public}s, skpf %{public}s, skat %{public}s",
79 info.size.width, info.size.height,
80 ImageTypeConverter::ToName(info.pixelFormat).c_str(),
81 ImageTypeConverter::ToName(info.alphaType).c_str(),
82 ImageTypeConverter::ToName(colorType).c_str(),
83 ImageTypeConverter::ToName(alphaType).c_str());
84 return SkImageInfo::Make(info.size.width, info.size.height, colorType, alphaType, colorSpace);
85 }
86
ToSkColorSpace(PixelMap * pixelmap)87 static sk_sp<SkColorSpace> ToSkColorSpace(PixelMap *pixelmap)
88 {
89 #ifdef IMAGE_COLORSPACE_FLAG
90 if (pixelmap->InnerGetGrColorSpacePtr() == nullptr) {
91 return nullptr;
92 }
93 return pixelmap->InnerGetGrColorSpacePtr()->ToSkColorSpace();
94 #else
95 return nullptr;
96 #endif
97 }
98
isSameColorSpace(const OHOS::ColorManager::ColorSpace & src,const OHOS::ColorManager::ColorSpace & dst)99 static bool isSameColorSpace(const OHOS::ColorManager::ColorSpace &src,
100 const OHOS::ColorManager::ColorSpace &dst)
101 {
102 auto skSrc = src.ToSkColorSpace();
103 auto skDst = dst.ToSkColorSpace();
104 return SkColorSpace::Equals(skSrc.get(), skDst.get());
105 }
106
~PixelYuv()107 PixelYuv::~PixelYuv()
108 {
109 FreePixelMap();
110 }
111
GetPixel8(int32_t x,int32_t y)112 const uint8_t *PixelYuv::GetPixel8(int32_t x, int32_t y)
113 {
114 IMAGE_LOGE("GetPixel8 is not support on PixelYuv");
115 return nullptr;
116 }
117
GetPixel16(int32_t x,int32_t y)118 const uint16_t *PixelYuv::GetPixel16(int32_t x, int32_t y)
119 {
120 IMAGE_LOGE("GetPixel16 is not support on PixelYuv");
121 return nullptr;
122 }
123
GetPixel32(int32_t x,int32_t y)124 const uint32_t *PixelYuv::GetPixel32(int32_t x, int32_t y)
125 {
126 IMAGE_LOGE("GetPixel32 is not support on PixelYuv");
127 return nullptr;
128 }
129
GetARGB32Color(int32_t x,int32_t y,uint32_t & color)130 bool PixelYuv::GetARGB32Color(int32_t x, int32_t y, uint32_t &color)
131 {
132 IMAGE_LOGE("GetARGB32Color is not support on PixelYuv");
133 return false;
134 }
135
GetARGB32ColorA(uint32_t color)136 uint8_t PixelYuv::GetARGB32ColorA(uint32_t color)
137 {
138 IMAGE_LOGE("GetARGB32ColorA is not support on PixelYuv");
139 return 0;
140 }
141
GetARGB32ColorR(uint32_t color)142 uint8_t PixelYuv::GetARGB32ColorR(uint32_t color)
143 {
144 IMAGE_LOGE("GetARGB32ColorR is not support on PixelYuv");
145 return 0;
146 }
147
GetARGB32ColorG(uint32_t color)148 uint8_t PixelYuv::GetARGB32ColorG(uint32_t color)
149 {
150 IMAGE_LOGE("GetARGB32ColorG is not support on PixelYuv");
151 return 0;
152 }
153
GetARGB32ColorB(uint32_t color)154 uint8_t PixelYuv::GetARGB32ColorB(uint32_t color)
155 {
156 IMAGE_LOGE("GetARGB32ColorB is not support on PixelYuv");
157 return 0;
158 }
159
SetAlpha(const float percent)160 uint32_t PixelYuv::SetAlpha(const float percent)
161 {
162 IMAGE_LOGE("SetAlpha is not support on PixelYuv");
163 return ERR_IMAGE_DATA_UNSUPPORT;
164 }
165
getPixelBytesNumber()166 uint32_t PixelYuv::getPixelBytesNumber()
167 {
168 IMAGE_LOGE("getPixelBytesNumber is not support on PixelYuv");
169 return ERR_IMAGE_DATA_UNSUPPORT;
170 }
171
GetByteCount()172 int32_t PixelYuv::GetByteCount()
173 {
174 return PixelMap::GetByteCount();
175 }
176
GetYSize(int32_t width,int32_t height)177 static int32_t GetYSize(int32_t width, int32_t height)
178 {
179 return width * height;
180 }
181
GetUStride(int32_t width)182 static int32_t GetUStride(int32_t width)
183 {
184 return (width + 1) / NUM_2;
185 }
186
GetUVHeight(int32_t height)187 static int32_t GetUVHeight(int32_t height)
188 {
189 return (height + 1) / NUM_2;
190 }
191
YuvRotateConvert(Size & size,int32_t degrees,int32_t & dstWidth,int32_t & dstHeight,OpenSourceLibyuv::RotationMode & rotateNum)192 bool PixelYuv::YuvRotateConvert(Size &size, int32_t degrees, int32_t &dstWidth, int32_t &dstHeight,
193 OpenSourceLibyuv::RotationMode &rotateNum)
194 {
195 switch (degrees) {
196 case DEGREES90:
197 dstWidth = size.height;
198 dstHeight = size.width;
199 rotateNum = OpenSourceLibyuv::RotationMode::kRotate90;
200 return true;
201 case DEGREES180:
202 rotateNum = OpenSourceLibyuv::RotationMode::kRotate180;
203 return true;
204 case DEGREES270:
205 dstWidth = size.height;
206 dstHeight = size.width;
207 rotateNum = OpenSourceLibyuv::RotationMode::kRotate270;
208 return true;
209 default:
210 return false;
211 }
212 }
213
YuvRotateConvert(Size & srcSize,int32_t degrees,Size & dstSize,OpenSourceLibyuv::RotationMode & rotateNum,YUVDataInfo yuvDataInfo)214 bool PixelYuv::YuvRotateConvert(Size &srcSize, int32_t degrees, Size &dstSize,
215 OpenSourceLibyuv::RotationMode &rotateNum, YUVDataInfo yuvDataInfo)
216 {
217 switch (degrees) {
218 case DEGREES90:
219 dstSize.width = srcSize.height;
220 dstSize.height = std::max(static_cast<uint32_t>(srcSize.width), yuvDataInfo.yStride);
221 rotateNum = OpenSourceLibyuv::RotationMode::kRotate90;
222 return true;
223 case DEGREES180:
224 rotateNum = OpenSourceLibyuv::RotationMode::kRotate180;
225 return true;
226 case DEGREES270:
227 dstSize.width = srcSize.height;
228 dstSize.height = std::max(static_cast<uint32_t>(srcSize.width), yuvDataInfo.yStride);
229 rotateNum = OpenSourceLibyuv::RotationMode::kRotate270;
230 return true;
231 default:
232 return false;
233 }
234 }
235
236 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
GetYUVStrideInfo(int32_t pixelFmt,OH_NativeBuffer_Planes * planes,YUVStrideInfo & dstStrides)237 static void GetYUVStrideInfo(int32_t pixelFmt, OH_NativeBuffer_Planes *planes, YUVStrideInfo &dstStrides)
238 {
239 if (pixelFmt == GRAPHIC_PIXEL_FMT_YCBCR_420_SP) {
240 auto yStride = planes->planes[PLANE_Y].columnStride;
241 auto uvStride = planes->planes[PLANE_U].columnStride;
242 auto yOffset = planes->planes[PLANE_Y].offset;
243 auto uvOffset = planes->planes[PLANE_U].offset;
244 dstStrides = {yStride, uvStride, yOffset, uvOffset};
245 } else if (pixelFmt == GRAPHIC_PIXEL_FMT_YCRCB_420_SP) {
246 auto yStride = planes->planes[PLANE_Y].columnStride;
247 auto uvStride = planes->planes[PLANE_V].columnStride;
248 auto yOffset = planes->planes[PLANE_Y].offset;
249 auto uvOffset = planes->planes[PLANE_V].offset;
250 dstStrides = {yStride, uvStride, yOffset, uvOffset};
251 } else if (pixelFmt == GRAPHIC_PIXEL_FMT_YCBCR_P010) {
252 auto yStride = planes->planes[PLANE_Y].columnStride / 2;
253 auto uvStride = planes->planes[PLANE_U].columnStride / 2;
254 auto yOffset = planes->planes[PLANE_Y].offset / 2;
255 auto uvOffset = planes->planes[PLANE_U].offset / 2;
256 dstStrides = {yStride, uvStride, yOffset, uvOffset};
257 } else if (pixelFmt == GRAPHIC_PIXEL_FMT_YCRCB_P010) {
258 auto yStride = planes->planes[PLANE_Y].columnStride / 2;
259 auto uvStride = planes->planes[PLANE_V].columnStride / 2;
260 auto yOffset = planes->planes[PLANE_Y].offset / 2;
261 auto uvOffset = planes->planes[PLANE_V].offset / 2;
262 dstStrides = {yStride, uvStride, yOffset, uvOffset};
263 }
264 }
265 #endif
266
CreateMemory(PixelFormat pixelFormat,std::string memoryTag,int32_t dstWidth,int32_t dstHeight,YUVStrideInfo & dstStrides)267 std::unique_ptr<AbsMemory> PixelYuv::CreateMemory(PixelFormat pixelFormat, std::string memoryTag, int32_t dstWidth,
268 int32_t dstHeight, YUVStrideInfo &dstStrides)
269 {
270 uint32_t pictureSize = GetImageSize(dstWidth, dstHeight, pixelFormat);
271 int32_t dst_yStride = dstWidth;
272 int32_t dst_uvStride = (dstWidth + 1) / NUM_2 * NUM_2;
273 int32_t dst_yOffset = 0;
274 int32_t dst_uvOffset = dst_yStride * dstHeight;
275
276 dstStrides = {dst_yStride, dst_uvStride, dst_yOffset, dst_uvOffset};
277 MemoryData memoryData = {nullptr, pictureSize, memoryTag.c_str(), {dstWidth, dstHeight}, pixelFormat};
278 auto m = MemoryManager::CreateMemory(allocatorType_, memoryData);
279 if (m == nullptr) {
280 IMAGE_LOGE("CreateMemory failed");
281 return m;
282 }
283 IMAGE_LOGE("CreateMemory allocatorType: %{public}d", allocatorType_);
284 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
285 if (allocatorType_ == AllocatorType::DMA_ALLOC) {
286 if (m->extend.data == nullptr) {
287 IMAGE_LOGE("CreateMemory get surfacebuffer failed");
288 return m;
289 }
290 auto sb = reinterpret_cast<SurfaceBuffer*>(m->extend.data);
291 OH_NativeBuffer_Planes *planes = nullptr;
292 GSError retVal = sb->GetPlanesInfo(reinterpret_cast<void**>(&planes));
293 if (retVal != OHOS::GSERROR_OK || planes == nullptr) {
294 IMAGE_LOGE("CreateMemory Get planesInfo failed, retVal:%{public}d", retVal);
295 } else if (planes->planeCount >= NUM_2) {
296 int32_t pixelFmt = sb->GetFormat();
297 GetYUVStrideInfo(pixelFmt, planes, dstStrides);
298 }
299 sptr<SurfaceBuffer> sourceSurfaceBuffer(reinterpret_cast<SurfaceBuffer*>(GetFd()));
300 sptr<SurfaceBuffer> dstSurfaceBuffer(reinterpret_cast<SurfaceBuffer*>(sb));
301 VpeUtils::CopySurfaceBufferInfo(sourceSurfaceBuffer, dstSurfaceBuffer);
302 }
303 #endif
304 return m;
305 }
306
rotate(float degrees)307 void PixelYuv::rotate(float degrees)
308 {
309 if (!IsYuvFormat() || degrees == 0) {
310 return;
311 }
312 if (degrees < 0) {
313 int n = abs(degrees / DEGREES360);
314 degrees += DEGREES360 * (n + 1);
315 }
316 OpenSourceLibyuv::RotationMode rotateNum = OpenSourceLibyuv::RotationMode::kRotate0;
317 YUVDataInfo yuvDataInfo;
318 GetImageYUVInfo(yuvDataInfo);
319 Size dstSize;
320 dstSize.width = imageInfo_.size.width;
321 dstSize.height = imageInfo_.size.height;
322 if (!YuvRotateConvert(imageInfo_.size, degrees, dstSize, rotateNum, yuvDataInfo)) {
323 IMAGE_LOGI("rotate degress is invalid, don't need rotate");
324 return ;
325 }
326 YUVStrideInfo dstStrides;
327 auto dstMemory = CreateMemory(imageInfo_.pixelFormat, "Rotate ImageData",
328 dstSize.width, dstSize.height, dstStrides);
329 if (dstMemory == nullptr) {
330 IMAGE_LOGE("rotate CreateMemory failed");
331 return;
332 }
333
334 uint8_t *dst = reinterpret_cast<uint8_t *>(dstMemory->data.data);
335 YuvImageInfo srcInfo = {PixelYuvUtils::ConvertFormat(imageInfo_.pixelFormat),
336 imageInfo_.size.width, imageInfo_.size.height, imageInfo_.pixelFormat, yuvDataInfo};
337 YuvImageInfo dstInfo;
338 if (!PixelYuvUtils::YuvRotate(data_, srcInfo, dst, dstInfo, degrees)) {
339 IMAGE_LOGE("rotate failed");
340 dstMemory->Release();
341 return;
342 }
343 imageInfo_.size.width = dstInfo.width;
344 imageInfo_.size.height = dstInfo.height;
345 SetPixelsAddr(dstMemory->data.data, dstMemory->extend.data, dstMemory->data.size, dstMemory->GetType(), nullptr);
346 SetImageInfo(imageInfo_, true);
347 UpdateYUVDataInfo(imageInfo_.pixelFormat, imageInfo_.size.width, imageInfo_.size.height, dstStrides);
348 AddVersionId();
349 }
350
crop(const Rect & rect)351 uint32_t PixelYuv::crop(const Rect &rect)
352 {
353 int32_t rectSize = GetYSize(rect.width, rect.height);
354 int32_t pixelSize = GetYSize(imageInfo_.size.width, imageInfo_.size.height);
355 if (rect.top < 0 || rect.left < 0 || rectSize > pixelSize || rect.width <= 1 || rect.height <= 1 ||
356 !IsYuvFormat()) {
357 IMAGE_LOGE("crop invalid param");
358 return ERR_IMAGE_INVALID_PARAMETER;
359 }
360 YUVStrideInfo dstStrides;
361 auto dstMemory = CreateMemory(imageInfo_.pixelFormat, "crop ImageData", rect.width, rect.height, dstStrides);
362 if (dstMemory == nullptr) {
363 IMAGE_LOGE("crop CreateMemory failed");
364 return ERR_IMAGE_CROP;
365 }
366 YUVDataInfo yuvDataInfo;
367 GetImageYUVInfo(yuvDataInfo);
368 YuvImageInfo srcInfo = {PixelYuvUtils::ConvertFormat(imageInfo_.pixelFormat),
369 imageInfo_.size.width, imageInfo_.size.height, imageInfo_.pixelFormat, yuvDataInfo};
370 if (!PixelYuvUtils::YuvCrop(data_, srcInfo, (uint8_t *)dstMemory->data.data, rect, dstStrides)) {
371 dstMemory->Release();
372 return ERR_IMAGE_CROP;
373 }
374 SetPixelsAddr(dstMemory->data.data, dstMemory->extend.data,
375 GetImageSize(rect.width, rect.height, imageInfo_.pixelFormat), dstMemory->GetType(), nullptr);
376 imageInfo_.size.height = rect.height;
377 imageInfo_.size.width = rect.width;
378 SetImageInfo(imageInfo_, true);
379 UpdateYUVDataInfo(imageInfo_.pixelFormat, rect.width, rect.height, dstStrides);
380 AddVersionId();
381 return SUCCESS;
382 }
383
scale(float xAxis,float yAxis)384 void PixelYuv::scale(float xAxis, float yAxis)
385 {
386 ImageTrace imageTrace("PixelMap scale");
387 return scale(xAxis, yAxis, AntiAliasingOption::NONE);
388 }
389
scale(int32_t dstW,int32_t dstH)390 void PixelYuv::scale(int32_t dstW, int32_t dstH)
391 {
392 ImageTrace imageTrace("PixelMap scale");
393 return scale(dstW, dstH, AntiAliasingOption::NONE);
394 }
395
resize(int32_t dstW,int32_t dstH)396 bool PixelYuv::resize(int32_t dstW, int32_t dstH)
397 {
398 ImageTrace imageTrace("PixelMap resize");
399 scale(dstW, dstH, AntiAliasingOption::NONE);
400 return true;
401 }
402
resize(float xAxis,float yAxis)403 bool PixelYuv::resize(float xAxis, float yAxis)
404 {
405 ImageTrace imageTrace("PixelMap resize");
406 scale(xAxis, yAxis, AntiAliasingOption::NONE);
407 return true;
408 }
409
scale(float xAxis,float yAxis,const AntiAliasingOption & option)410 void PixelYuv::scale(float xAxis, float yAxis, const AntiAliasingOption &option)
411 {
412 if (!IsYuvFormat()) {
413 return;
414 }
415 ImageTrace imageTrace("PixelMap scale");
416 if (xAxis == 1 && yAxis == 1 && option == AntiAliasingOption::NONE) {
417 return;
418 }
419 ImageInfo imageInfo;
420 GetImageInfo(imageInfo);
421 int32_t dstW = imageInfo.size.width * xAxis;
422 int32_t dstH = imageInfo.size.height * yAxis;
423 YUVStrideInfo dstStrides;
424 auto dstMemory = CreateMemory(imageInfo.pixelFormat, "scale ImageData", dstW, dstH, dstStrides);
425 if (dstMemory == nullptr) {
426 IMAGE_LOGE("scale CreateMemory failed");
427 return;
428 }
429 uint8_t *yuvData = reinterpret_cast<uint8_t *>(dstMemory->data.data);
430 YUVDataInfo yuvDataInfo;
431 GetImageYUVInfo(yuvDataInfo);
432 YuvImageInfo srcInfo = {PixelYuvUtils::ConvertFormat(imageInfo.pixelFormat),
433 imageInfo.size.width, imageInfo.size.height, imageInfo_.pixelFormat, yuvDataInfo};
434 YuvImageInfo dstInfo = {PixelYuvUtils::ConvertFormat(imageInfo.pixelFormat),
435 dstW, dstH, imageInfo_.pixelFormat, yuvDataInfo};
436 if (PixelYuvUtils::YuvScale(data_, srcInfo, yuvData, dstInfo, PixelYuvUtils::YuvConvertOption(option)) != SUCCESS) {
437 IMAGE_LOGE("ScaleYuv failed");
438 dstMemory->Release();
439 return;
440 }
441 imageInfo.size.height = dstH;
442 imageInfo.size.width = dstW;
443
444 SetPixelsAddr(dstMemory->data.data, dstMemory->extend.data, dstMemory->data.size, dstMemory->GetType(), nullptr);
445 SetImageInfo(imageInfo, true);
446 UpdateYUVDataInfo(imageInfo.pixelFormat, imageInfo.size.width, imageInfo.size.height, dstStrides);
447 AddVersionId();
448 }
449
scale(int32_t dstW,int32_t dstH,const AntiAliasingOption & option)450 void PixelYuv::scale(int32_t dstW, int32_t dstH, const AntiAliasingOption &option)
451 {
452 if (!IsYuvFormat()) {
453 return;
454 }
455 ImageInfo imageInfo;
456 GetImageInfo(imageInfo);
457 ImageTrace imageTrace("PixelMap scale");
458 if (imageInfo.size.width == dstW && imageInfo.size.height == dstH && option == AntiAliasingOption::NONE) {
459 return;
460 }
461 YUVStrideInfo dstStrides;
462 auto dstMemory = CreateMemory(imageInfo.pixelFormat, "scale ImageData", dstW, dstH, dstStrides);
463 if (dstMemory == nullptr) {
464 IMAGE_LOGE("scale CreateMemory failed");
465 return;
466 }
467 uint8_t *yuvData = reinterpret_cast<uint8_t *>(dstMemory->data.data);
468 YUVDataInfo yuvDataInfo;
469 GetImageYUVInfo(yuvDataInfo);
470 YuvImageInfo srcInfo = {PixelYuvUtils::ConvertFormat(imageInfo.pixelFormat),
471 imageInfo.size.width, imageInfo.size.height, imageInfo_.pixelFormat, yuvDataInfo};
472 YuvImageInfo dstInfo = {PixelYuvUtils::ConvertFormat(imageInfo.pixelFormat),
473 dstW, dstH, imageInfo_.pixelFormat, yuvDataInfo};
474 if (PixelYuvUtils::YuvScale(data_, srcInfo, yuvData, dstInfo, PixelYuvUtils::YuvConvertOption(option)) != SUCCESS) {
475 IMAGE_LOGE("ScaleYuv failed");
476 dstMemory->Release();
477 return;
478 }
479 imageInfo.size.height = dstH;
480 imageInfo.size.width = dstW;
481 SetPixelsAddr(dstMemory->data.data, dstMemory->extend.data, dstMemory->data.size, dstMemory->GetType(), nullptr);
482 SetImageInfo(imageInfo, true);
483 UpdateYUVDataInfo(imageInfo.pixelFormat, imageInfo.size.width, imageInfo.size.height, dstStrides);
484 AddVersionId();
485 }
486
flip(bool xAxis,bool yAxis)487 void PixelYuv::flip(bool xAxis, bool yAxis)
488 {
489 if (!IsYuvFormat()) {
490 return;
491 }
492 if (xAxis == false && yAxis == false) {
493 return;
494 }
495 int32_t srcW = imageInfo_.size.width;
496 int32_t srcH = imageInfo_.size.height;
497 PixelFormat format = imageInfo_.pixelFormat;
498 const uint8_t *src = data_;
499 YUVStrideInfo dstStrides;
500 auto dstMemory = CreateMemory(imageInfo_.pixelFormat, "flip ImageData", srcW, srcH, dstStrides);
501 if (dstMemory == nullptr) {
502 IMAGE_LOGE("flip CreateMemory failed");
503 return;
504 }
505 uint8_t *dst = reinterpret_cast<uint8_t *>(dstMemory->data.data);
506 YUVDataInfo yuvDataInfo;
507 GetImageYUVInfo(yuvDataInfo);
508 YuvImageInfo srcInfo = {PixelYuvUtils::ConvertFormat(format), srcW, srcH, imageInfo_.pixelFormat, yuvDataInfo};
509 YuvImageInfo dstInfo = {PixelYuvUtils::ConvertFormat(format), srcW, srcH, imageInfo_.pixelFormat, yuvDataInfo};
510 if (xAxis && yAxis) {
511 if (!PixelYuvUtils::YuvReversal(const_cast<uint8_t *>(src), srcInfo, dst, dstInfo)) {
512 IMAGE_LOGE("flip yuv xAxis and yAxis failed");
513 dstMemory->Release();
514 return;
515 }
516 } else {
517 bool isXaxis = ((xAxis | yAxis) && xAxis) ? true : false;
518 if (!PixelYuvUtils::YuvFlip(const_cast<uint8_t *>(src), srcInfo, dst, isXaxis)) {
519 IMAGE_LOGE("flip yuv xAxis or yAxis failed");
520 dstMemory->Release();
521 return;
522 }
523 }
524 SetPixelsAddr(dst, dstMemory->extend.data, dstMemory->data.size, dstMemory->GetType(), nullptr);
525 UpdateYUVDataInfo(format, srcW, srcH, dstStrides);
526 AddVersionId();
527 }
528
WritePixels(const uint8_t * source,const uint64_t & bufferSize,const uint32_t & offset,const uint32_t & stride,const Rect & region)529 uint32_t PixelYuv::WritePixels(const uint8_t *source, const uint64_t &bufferSize, const uint32_t &offset,
530 const uint32_t &stride, const Rect ®ion)
531 {
532 if (!CheckPixelsInput(source, bufferSize, offset, region)) {
533 IMAGE_LOGE("write pixel by rect input parameter fail.");
534 return ERR_IMAGE_INVALID_PARAMETER;
535 }
536 if (!IsEditable()) {
537 IMAGE_LOGE("write pixel by rect PixelYuv data is not editable.");
538 return ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY;
539 }
540 if (!ImageUtils::IsValidImageInfo(imageInfo_)) {
541 IMAGE_LOGE("write pixel by rect current PixelYuv image info is invalid.");
542 return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
543 }
544 if (data_ == nullptr) {
545 IMAGE_LOGE("write pixel by rect current pixel map data is null.");
546 return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
547 }
548 int32_t bytesPerPixel = ImageUtils::GetPixelBytes(imageInfo_.pixelFormat);
549 if (bytesPerPixel == 0) {
550 IMAGE_LOGE("write pixel by rect get bytes by per pixel fail.");
551 return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
552 }
553 Position dstPosition{region.left, region.top};
554 ImageInfo srcInfo;
555 srcInfo.size.height = region.height;
556 srcInfo.size.width = region.width;
557 srcInfo.pixelFormat = imageInfo_.pixelFormat;
558 if (!PixelYuvUtils::WriteYuvConvert(source + offset, srcInfo, data_, dstPosition, yuvDataInfo_)) {
559 IMAGE_LOGE("write pixel by rect call WriteYuvConvert fail.");
560 return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
561 }
562 AddVersionId();
563 return SUCCESS;
564 }
565
GetYUVInfoForCopyPixels(YUVDataInfo & yuvDataInfo)566 void PixelYuv::GetYUVInfoForCopyPixels(YUVDataInfo &yuvDataInfo)
567 {
568 GetImageYUVInfo(yuvDataInfo);
569 yuvDataInfo.yWidth = static_cast<uint32_t>(imageInfo_.size.width);
570 yuvDataInfo.yHeight = static_cast<uint32_t>(imageInfo_.size.height);
571 yuvDataInfo.uvWidth = yuvDataInfo.uvWidth * NUM_2;
572 if (IsP010Yuv()) {
573 yuvDataInfo.yWidth = static_cast<uint32_t>(imageInfo_.size.width) * NUM_2;
574 yuvDataInfo.uvWidth = yuvDataInfo.yWidth;
575 yuvDataInfo.yOffset = yuvDataInfo.yOffset * NUM_2;
576 yuvDataInfo.yStride = yuvDataInfo.yStride * NUM_2;
577 yuvDataInfo.uvOffset = yuvDataInfo.uvOffset * NUM_2;
578 yuvDataInfo.uvStride = yuvDataInfo.uvStride * NUM_2;
579 }
580 }
581
WritePixels(const uint8_t * source,const uint64_t & bufferSize)582 uint32_t PixelYuv::WritePixels(const uint8_t *source, const uint64_t &bufferSize)
583 {
584 if (!IsYuvFormat()) {
585 IMAGE_LOGE("PixelYuv WritePixels Not YUV format");
586 return ERR_IMAGE_READ_PIXELMAP_FAILED;
587 }
588 if (source == nullptr || data_ == nullptr) {
589 IMAGE_LOGE("PixelYuv write pixels by buffer source or current pixelmap data is nullptr");
590 return ERR_IMAGE_INVALID_PARAMETER;
591 }
592 auto requiredBufferSize = GetByteCount();
593 if (bufferSize < requiredBufferSize) {
594 IMAGE_LOGE("PixelYuv write pixels by buffer bufferSize error.");
595 return ERR_IMAGE_INVALID_PARAMETER;
596 }
597 if (!IsEditable()) {
598 IMAGE_LOGE("PixelYuv write pixels by buffer pixelmap data is not editable.");
599 return ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY;
600 }
601 if (!ImageUtils::IsValidImageInfo(imageInfo_)) {
602 IMAGE_LOGE("PixelYuv write pixels by buffer current pixelmap image info is invalid.");
603 return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
604 }
605 YUVDataInfo yuvDataInfo;
606 GetYUVInfoForCopyPixels(yuvDataInfo);
607 auto srcY = source;
608 auto srcUV = source + yuvDataInfo.yWidth * yuvDataInfo.yHeight;
609 auto dstY = data_ + yuvDataInfo.yOffset;
610 auto dstUV = data_ + yuvDataInfo.uvOffset;
611 /* copy Y plane*/
612 for (int32_t y = 0; y < static_cast<int32_t>(yuvDataInfo.yHeight); y++) {
613 if (memcpy_s(dstY, yuvDataInfo.yWidth, srcY, yuvDataInfo.yWidth) != EOK) {
614 IMAGE_LOGE("PixelYuv write pixels yInfo failed.");
615 return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
616 }
617 dstY += yuvDataInfo.yStride;
618 srcY += yuvDataInfo.yWidth;
619 }
620 /* copy UV plane*/
621 for (int32_t y = 0; y < static_cast<int32_t>(yuvDataInfo.uvHeight); y++) {
622 if (memcpy_s(dstUV, yuvDataInfo.uvWidth, srcUV, yuvDataInfo.uvWidth) != EOK) {
623 IMAGE_LOGE("PixelYuv write pixels uvInfo failed.");
624 return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
625 }
626 dstUV += yuvDataInfo.uvStride;
627 srcUV += yuvDataInfo.uvWidth;
628 }
629 AddVersionId();
630 return SUCCESS;
631 }
632
ReadPixels(const uint64_t & bufferSize,const uint32_t & offset,const uint32_t & stride,const Rect & region,uint8_t * dst)633 uint32_t PixelYuv::ReadPixels(const uint64_t &bufferSize, const uint32_t &offset, const uint32_t &stride,
634 const Rect ®ion, uint8_t *dst)
635 {
636 if (!CheckPixelsInput(dst, bufferSize, offset, region)) {
637 IMAGE_LOGE("read pixels by rect input parameter fail.");
638 return ERR_IMAGE_INVALID_PARAMETER;
639 }
640
641 if (data_ == nullptr) {
642 IMAGE_LOGE("read pixels by rect this pixel data is null.");
643 return ERR_IMAGE_READ_PIXELMAP_FAILED;
644 }
645 ImageInfo dstImageInfo;
646 dstImageInfo.size.width = region.width;
647 dstImageInfo.size.height = region.height;
648 dstImageInfo.pixelFormat = imageInfo_.pixelFormat;
649
650 Position srcPosition{region.left, region.top};
651 YUVDataInfo yuvDataInfo;
652 GetImageYUVInfo(yuvDataInfo);
653 YuvImageInfo imageInfo = {PixelYuvUtils::ConvertFormat(imageInfo_.pixelFormat),
654 imageInfo_.size.width, imageInfo_.size.height, imageInfo_.pixelFormat, yuvDataInfo};
655 if (!PixelYuvUtils::ReadYuvConvert((void *)data_, srcPosition, imageInfo, dst + offset, dstImageInfo)) {
656 IMAGE_LOGE("read pixels by rect call ReadPixelsConvert fail.");
657 return ERR_IMAGE_READ_PIXELMAP_FAILED;
658 }
659 return SUCCESS;
660 }
661
IsP010Yuv()662 bool PixelYuv::IsP010Yuv()
663 {
664 if (imageInfo_.pixelFormat == PixelFormat::YCBCR_P010 || imageInfo_.pixelFormat == PixelFormat::YCRCB_P010) {
665 return true;
666 }
667 return false;
668 }
669
ReadPixels(const uint64_t & bufferSize,uint8_t * dst)670 uint32_t PixelYuv::ReadPixels(const uint64_t &bufferSize, uint8_t *dst)
671 {
672 if (!IsYuvFormat()) {
673 IMAGE_LOGE("PixelYuv ReadPixels Not YUV format");
674 return ERR_IMAGE_READ_PIXELMAP_FAILED;
675 }
676 IMAGE_LOGD("PixelYuv ReadPixels by bufferSize");
677 if (dst == nullptr) {
678 IMAGE_LOGE("PixelYuv read pixels by buffer input dst address is null.");
679 return ERR_IMAGE_READ_PIXELMAP_FAILED;
680 }
681 if (data_ == nullptr) {
682 IMAGE_LOGE("PixelYuv read pixels by buffer current PixelMap data is null.");
683 return ERR_IMAGE_READ_PIXELMAP_FAILED;
684 }
685 auto requiredBufferSize = GetByteCount();
686 IMAGE_LOGD("PixelYuv requiredBufferSize: %{public}d", requiredBufferSize);
687
688 if (bufferSize < static_cast<uint64_t>(requiredBufferSize)) {
689 IMAGE_LOGE("PixelYuv read pixels dst buffer(%{public}llu) < current pixelmap size(%{public}u).",
690 static_cast<unsigned long long>(bufferSize), requiredBufferSize);
691 return ERR_IMAGE_INVALID_PARAMETER;
692 }
693 YUVDataInfo yuvDataInfo;
694 GetYUVInfoForCopyPixels(yuvDataInfo);
695 uint8_t *srcUVPixels = data_ + yuvDataInfo.uvOffset;
696 uint8_t *srcYPixels = data_ + yuvDataInfo.yOffset;
697 /* copy Y plane*/
698 for (int32_t y = 0; y<static_cast<int32_t>(yuvDataInfo.yHeight); y++) {
699 if (memcpy_s(dst, yuvDataInfo.yWidth, srcYPixels, yuvDataInfo.yWidth) != EOK) {
700 IMAGE_LOGE("PixelYuv read pixels yInfo failed.");
701 return ERR_IMAGE_INVALID_PARAMETER;
702 }
703 dst += yuvDataInfo.yWidth;
704 srcYPixels += yuvDataInfo.yStride;
705 }
706 /* copy UV plane*/
707 for (int32_t y = 0; y<static_cast<int32_t>(yuvDataInfo.uvHeight); y++) {
708 if (memcpy_s(dst, yuvDataInfo.uvWidth, srcUVPixels, yuvDataInfo.uvWidth) != EOK) {
709 IMAGE_LOGE("PixelYuv read pixels uvInfo failed.");
710 return ERR_IMAGE_INVALID_PARAMETER;
711 }
712 dst += yuvDataInfo.uvWidth;
713 srcUVPixels += yuvDataInfo.uvStride;
714 }
715 return SUCCESS;
716 }
717
718 // To check the axis is legal
IsLegalAxis(float xAxis,float yAxis)719 bool PixelYuv::IsLegalAxis(float xAxis, float yAxis)
720 {
721 if (abs(xAxis) > static_cast<float>(INT32_MAX) ||
722 abs(yAxis) > static_cast<float>(INT32_MAX)) {
723 IMAGE_LOGE("translate axis overflow xAxis(%{public}f), yAxis(%{public}f)", xAxis, yAxis);
724 return false;
725 }
726 if (!std::isfinite(xAxis) || !std::isfinite(yAxis)) {
727 IMAGE_LOGE("translate axis not finite");
728 return false;
729 }
730 int32_t xOffset = static_cast<int32_t>(xAxis);
731 int32_t yOffset = static_cast<int32_t>(yAxis);
732 if (imageInfo_.size.width > INT32_MAX - xOffset) {
733 IMAGE_LOGE("translate width overflow width(%{public}d) + xOffset(%{public}d)",
734 imageInfo_.size.width, xOffset);
735 return false;
736 }
737 if (imageInfo_.size.height > INT32_MAX - yOffset) {
738 IMAGE_LOGE("translate height overflow height(%{public}d) + yOffset(%{public}d)",
739 imageInfo_.size.height, yOffset);
740 return false;
741 }
742 if (xOffset == 0 && yOffset == 0) {
743 return false;
744 }
745 int32_t width = imageInfo_.size.width + xOffset;
746 int32_t height = imageInfo_.size.height + yOffset;
747 if (width < 1 || height < 1 || width > MAX_DIMENSION || height > MAX_DIMENSION) {
748 IMAGE_LOGE("Checktranslate size overflow width(%{public}d), height(%{public}d)", width, height);
749 return false;
750 }
751 return true;
752 }
753
translate(float xAxis,float yAxis)754 void PixelYuv::translate(float xAxis, float yAxis)
755 {
756 if (!IsYuvFormat()) {
757 IMAGE_LOGE("translate not yuv format");
758 return;
759 }
760 if (!IsLegalAxis(xAxis, yAxis)) {
761 return;
762 }
763 int32_t width = imageInfo_.size.width + xAxis;
764 int32_t height = imageInfo_.size.height + yAxis;
765 PixelFormat format = imageInfo_.pixelFormat;
766 YUVStrideInfo dstStrides;
767 auto dstMemory = CreateMemory(imageInfo_.pixelFormat, "translate ImageData", width, height, dstStrides);
768 if (dstMemory == nullptr) {
769 IMAGE_LOGE("translate CreateMemory failed");
770 return;
771 }
772 YUVDataInfo yuvDataInfo;
773 GetImageYUVInfo(yuvDataInfo);
774 XYaxis xyAxis = {xAxis, yAxis};
775 uint8_t *dst = reinterpret_cast<uint8_t *>(dstMemory->data.data);
776 PixelYuvUtils::SetTranslateDataDefault(dst, width, height, format, dstStrides);
777
778 if (!PixelYuvUtils::YuvTranslate(data_, yuvDataInfo, dst, xyAxis, imageInfo_, dstStrides)) {
779 dstMemory->Release();
780 return;
781 }
782 imageInfo_.size.width = width;
783 imageInfo_.size.height = height;
784
785 uint32_t dstSize = GetImageSize(width, height, format);
786 SetPixelsAddr(dst, dstMemory->extend.data, dstSize, dstMemory->GetType(), nullptr);
787 UpdateYUVDataInfo(imageInfo_.pixelFormat, width, height, dstStrides);
788 AddVersionId();
789 }
790
ReadPixel(const Position & pos,uint32_t & dst)791 uint32_t PixelYuv::ReadPixel(const Position &pos, uint32_t &dst)
792 {
793 if (pos.x < 0 || pos.y < 0) {
794 IMAGE_LOGE("read pixel by pos input invalid exception. [x(%{public}d), y(%{public}d)]", pos.x, pos.y);
795 return ERR_IMAGE_INVALID_PARAMETER;
796 }
797 if (data_ == nullptr) {
798 IMAGE_LOGE("read pixel by pos source data is null.");
799 return ERR_IMAGE_READ_PIXELMAP_FAILED;
800 }
801 ColorYuv420 colorYuv = GetYuv420Color(abs(pos.x), abs(pos.y));
802 dst = (colorYuv.colorY << Y_SHIFT) | (colorYuv.colorU << U_SHIFT) | (colorYuv.colorV << V_SHIFT);
803 return SUCCESS;
804 }
805
WritePixels(const uint32_t & color)806 bool PixelYuv::WritePixels(const uint32_t &color)
807 {
808 if (!IsYuvFormat() || data_ == nullptr) {
809 IMAGE_LOGE("erase pixels by color current pixel map data is null.");
810 return false;
811 }
812
813 return PixelYuvUtils::Yuv420WritePixels(yuvDataInfo_, data_, imageInfo_, color);
814 }
815
WritePixel(const Position & pos,const uint32_t & color)816 uint32_t PixelYuv::WritePixel(const Position &pos, const uint32_t &color)
817 {
818 if (!IsYuvFormat() || (pos.x < 0 || pos.y < 0)) {
819 IMAGE_LOGE("write pixel by pos but input position is invalid. [x(%{public}d), y(%{public}d)]", pos.x, pos.y);
820 return ERR_IMAGE_INVALID_PARAMETER;
821 }
822 if (data_ == nullptr) {
823 IMAGE_LOGE("write pixel by pos but current pixelmap data is nullptr.");
824 return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
825 }
826 return PixelYuvUtils::YuvWritePixel(data_, yuvDataInfo_, imageInfo_.pixelFormat, pos, color);
827 }
828
GetYuv420Color(uint32_t x,uint32_t y)829 ColorYuv420 PixelYuv::GetYuv420Color(uint32_t x, uint32_t y)
830 {
831 ColorYuv420 colorYuv;
832 ImageInfo imageInfo;
833 GetImageInfo(imageInfo);
834 PixelFormat format = imageInfo.pixelFormat;
835 YUVDataInfo yuvDataInfo;
836 GetImageYUVInfo(yuvDataInfo);
837 colorYuv.colorY = PixelYuvUtils::GetYuv420Y(x, y, yuvDataInfo, data_);
838 colorYuv.colorU = PixelYuvUtils::GetYuv420U(x, y, yuvDataInfo, format, data_);
839 colorYuv.colorV = PixelYuvUtils::GetYuv420V(x, y, yuvDataInfo, format, data_);
840 return colorYuv;
841 }
842
SetPixelsAddr(void * addr,void * context,uint32_t size,AllocatorType type,CustomFreePixelMap func)843 void PixelYuv::SetPixelsAddr(void *addr, void *context, uint32_t size, AllocatorType type, CustomFreePixelMap func)
844 {
845 if (data_ != nullptr) {
846 IMAGE_LOGE("SetPixelsAddr release the existed data first");
847 FreePixelMap();
848 }
849 if (type == AllocatorType::SHARE_MEM_ALLOC && context == nullptr) {
850 IMAGE_LOGE("SetPixelsAddr error type %{public}d ", type);
851 }
852 data_ = static_cast<uint8_t *>(addr);
853 context_ = context;
854 pixelsSize_ = size;
855 allocatorType_ = type;
856 custFreePixelMap_ = func;
857 if (type == AllocatorType::DMA_ALLOC && rowDataSize_ != 0) {
858 SetImageInfo(imageInfo_, true);
859 }
860 }
861
IsYUVP010Format(PixelFormat format)862 static bool IsYUVP010Format(PixelFormat format)
863 {
864 return format == PixelFormat::YCBCR_P010 || format == PixelFormat::YCRCB_P010;
865 }
866
CheckPixelsInput(const uint8_t * dst,const uint64_t & bufferSize,const uint32_t & offset,const Rect & region)867 bool PixelYuv::CheckPixelsInput(const uint8_t *dst, const uint64_t &bufferSize, const uint32_t &offset,
868 const Rect ®ion)
869 {
870 if (dst == nullptr) {
871 IMAGE_LOGE("CheckPixelsInput input dst address is null.");
872 return false;
873 }
874
875 if (bufferSize == 0) {
876 IMAGE_LOGE("CheckPixelsInput input buffer size is 0.");
877 return false;
878 }
879
880 if (region.left < 0 || region.top < 0 || static_cast<uint64_t>(offset) > bufferSize) {
881 IMAGE_LOGE("CheckPixelsInput left(%{public}d) or top(%{public}d) or offset(%{public}u) < 0.",
882 region.left, region.top, offset);
883 return false;
884 }
885 if (region.width <= 1 || region.height <= 1 || region.width > MAX_DIMENSION || region.height > MAX_DIMENSION) {
886 IMAGE_LOGE("CheckPixelsInput width(%{public}d) or height(%{public}d) is < 0.", region.width,
887 region.height);
888 return false;
889 }
890 if (region.left > GetWidth() - region.width) {
891 IMAGE_LOGE("CheckPixelsInput left(%{public}d) + width(%{public}d) is > PixelYuv width(%{public}d).",
892 region.left, region.width, GetWidth());
893 return false;
894 }
895 if (region.top > GetHeight() - region.height) {
896 IMAGE_LOGE("CheckPixelsInput top(%{public}d) + height(%{public}d) is > PixelYuv height(%{public}d).",
897 region.top, region.height, GetHeight());
898 return false;
899 }
900
901 if (IsYUVP010Format(imageInfo_.pixelFormat)) {
902 if (static_cast<uint64_t>(offset) >= (bufferSize - YUV420P010_MIN_PIXEL_UINTBYTES)) {
903 IMAGE_LOGE(
904 "CheckPixelsInput fail, height(%{public}d), width(%{public}d) "
905 "offset(%{public}u), bufferSize:%{public}llu.",
906 region.height, region.width, offset,
907 static_cast<unsigned long long>(bufferSize));
908 return false;
909 }
910 } else {
911 if (static_cast<uint64_t>(offset) >= (bufferSize - YUV420_MIN_PIXEL_UINTBYTES)) {
912 IMAGE_LOGE(
913 "CheckPixelsInput fail, height(%{public}d), width(%{public}d) "
914 "offset(%{public}u), bufferSize:%{public}llu.",
915 region.height, region.width, offset,
916 static_cast<unsigned long long>(bufferSize));
917 return false;
918 }
919 }
920 return true;
921 }
922
SetRowDataSizeForImageInfo(ImageInfo info)923 void PixelYuv::SetRowDataSizeForImageInfo(ImageInfo info)
924 {
925 rowDataSize_ = info.size.width * NUM_3 / NUM_2;
926 if (IsYUVP010Format(info.pixelFormat)) {
927 rowDataSize_ *= NUM_2;
928 }
929 return;
930 }
931
GetImageSize(int32_t width,int32_t height,PixelFormat format)932 uint32_t PixelYuv::GetImageSize(int32_t width, int32_t height, PixelFormat format)
933 {
934 uint32_t size = static_cast<uint32_t>(GetYSize(width, height) +
935 GetUStride(width) * GetUVHeight(height) * TWO_SLICES);
936 if (IsYUVP010Format(format)) {
937 size *= NUM_2;
938 }
939 return size;
940 }
941
942
943 #ifdef IMAGE_COLORSPACE_FLAG
SetColorSpace(const OHOS::ColorManager::ColorSpace & grColorSpace,SkTransYuvInfo & src,PixelFormat & format,uint64_t rowStride)944 uint32_t PixelYuv::SetColorSpace(const OHOS::ColorManager::ColorSpace &grColorSpace, SkTransYuvInfo &src,
945 PixelFormat &format, uint64_t rowStride)
946 {
947 int32_t width = static_cast<int32_t>(yuvDataInfo_.yStride);
948 int32_t height = static_cast<int32_t>(yuvDataInfo_.yHeight);
949 if (!PixelYuvUtils::CheckWidthAndHeightMult(width, height, RGBA_BIT_DEPTH)) {
950 IMAGE_LOGE("SetColorSpace size overflow width(%{public}d), height(%{public}d)", width, height);
951 return ERR_IMAGE_COLOR_CONVERT;
952 }
953 // Build sk target infomation
954 SkTransYuvInfo dst;
955 dst.info = ToSkImageInfo(imageInfo_, grColorSpace.ToSkColorSpace());
956 MemoryData memoryData = {nullptr, width * height * NUM_4, "ApplyColorSpace ImageData",
957 {dst.info.width(), dst.info.height()}};
958 auto dstMemory = MemoryManager::CreateMemory(allocatorType_, memoryData);
959 if (dstMemory == nullptr) {
960 IMAGE_LOGE("applyColorSpace CreateMemory failed");
961 return ERR_IMAGE_COLOR_CONVERT;
962 }
963 // Transfor pixels by readPixels
964 if (!src.bitmap.readPixels(dst.info, dstMemory->data.data, rowStride, 0, 0)) {
965 dstMemory->Release();
966 IMAGE_LOGE("ReadPixels failed");
967 return ERR_IMAGE_COLOR_CONVERT;
968 }
969
970 uint8_t *bgraData = reinterpret_cast<uint8_t *>(dstMemory->data.data);
971 if (ColorSpaceBGRAToYuv(bgraData, dst, imageInfo_, format, grColorSpace) != SUCCESS) {
972 dstMemory->Release();
973 IMAGE_LOGE("ColorSpaceBGRAToYuv failed");
974 return ERR_IMAGE_COLOR_CONVERT;
975 }
976 SetImageInfo(imageInfo_, true);
977 return SUCCESS;
978 }
979
ToImageInfo(ImageInfo & info,SkImageInfo & skInfo,bool sizeOnly=true)980 static void ToImageInfo(ImageInfo &info, SkImageInfo &skInfo, bool sizeOnly = true)
981 {
982 info.size.width = skInfo.width();
983 info.size.height = skInfo.height();
984 if (!sizeOnly) {
985 info.alphaType = ImageTypeConverter::ToAlphaType(skInfo.alphaType());
986 info.pixelFormat = ImageTypeConverter::ToPixelFormat(skInfo.colorType());
987 }
988 }
989
CheckColorSpace(const OHOS::ColorManager::ColorSpace & grColorSpace)990 bool PixelYuv::CheckColorSpace(const OHOS::ColorManager::ColorSpace &grColorSpace)
991 {
992 auto grName = grColorSpace.GetColorSpaceName();
993 if (grColorSpace_ != nullptr && isSameColorSpace(*grColorSpace_, grColorSpace)) {
994 if (grColorSpace_->GetColorSpaceName() != grName) {
995 InnerSetColorSpace(grColorSpace);
996 IMAGE_LOGI("applyColorSpace inner set");
997 }
998 return true;
999 }
1000 return false;
1001 }
1002
ColorSpaceBGRAToYuv(uint8_t * bgraData,SkTransYuvInfo & dst,ImageInfo & imageInfo,PixelFormat & format,const OHOS::ColorManager::ColorSpace & grColorSpace)1003 int32_t PixelYuv::ColorSpaceBGRAToYuv(uint8_t *bgraData, SkTransYuvInfo &dst, ImageInfo &imageInfo,
1004 PixelFormat &format, const OHOS::ColorManager::ColorSpace &grColorSpace)
1005 {
1006 int32_t dstWidth = dst.info.width();
1007 int32_t dstHeight = dst.info.height();
1008 uint32_t pictureSize = GetImageSize(dstWidth, dstHeight, format);
1009 MemoryData memoryYuvData = {nullptr, pictureSize, "Trans ImageData", {dstWidth, dstHeight}};
1010 auto yuvMemory = MemoryManager::CreateMemory(allocatorType_, memoryYuvData);
1011 if (yuvMemory == nullptr) {
1012 IMAGE_LOGE("applyColorSpace CreateYuvMemory failed");
1013 return ERR_IMAGE_COLOR_CONVERT;
1014 }
1015 YuvImageInfo srcInfo = {PixelYuvUtils::ConvertFormat(PixelFormat::BGRA_8888),
1016 imageInfo_.size.width, imageInfo_.size.height, imageInfo_.pixelFormat, yuvDataInfo_};
1017 YuvImageInfo dstInfo = {PixelYuvUtils::ConvertFormat(format),
1018 imageInfo_.size.width, imageInfo_.size.height, imageInfo_.pixelFormat, yuvDataInfo_};
1019 if (!PixelYuvUtils::BGRAToYuv420(bgraData, srcInfo, reinterpret_cast<uint8_t *>(yuvMemory->data.data), dstInfo)) {
1020 IMAGE_LOGE("applyColorSpace BGRAToYuv420 failed");
1021 yuvMemory->Release();
1022 return ERR_IMAGE_COLOR_CONVERT;
1023 }
1024 imageInfo.pixelFormat = format;
1025 dst.info = ToSkImageInfo(imageInfo, grColorSpace.ToSkColorSpace());
1026 ToImageInfo(imageInfo, dst.info);
1027 auto grName = grColorSpace.GetColorSpaceName();
1028 grColorSpace_ = std::make_shared<OHOS::ColorManager::ColorSpace>(dst.info.refColorSpace(), grName);
1029 SetPixelsAddr(reinterpret_cast<void *>(yuvMemory->data.data), yuvMemory->extend.data, pictureSize,
1030 yuvMemory->GetType(), nullptr);
1031 AddVersionId();
1032 return SUCCESS;
1033 }
1034
ApplyColorSpace(const OHOS::ColorManager::ColorSpace & grColorSpace)1035 uint32_t PixelYuv::ApplyColorSpace(const OHOS::ColorManager::ColorSpace &grColorSpace)
1036 {
1037 if (CheckColorSpace(grColorSpace)) {
1038 return SUCCESS;
1039 }
1040 PixelFormat format = imageInfo_.pixelFormat;
1041 imageInfo_.pixelFormat = PixelFormat::BGRA_8888;
1042 SkTransYuvInfo src;
1043 src.info = ToSkImageInfo(imageInfo_, ToSkColorSpace(this));
1044 uint64_t rowStride = src.info.minRowBytes();
1045 uint8_t *srcData = data_;
1046 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1047 if (GetAllocatorType() == AllocatorType::DMA_ALLOC && GetFd() != nullptr) {
1048 SurfaceBuffer *sbBuffer = reinterpret_cast<SurfaceBuffer *>(GetFd());
1049 rowStride = static_cast<uint64_t>(sbBuffer->GetStride());
1050 }
1051 srcData = static_cast<uint8_t *>(GetWritablePixels());
1052 #endif
1053
1054 YUVDataInfo yuvDataInfo;
1055 GetImageYUVInfo(yuvDataInfo);
1056 int32_t width = static_cast<int32_t>(yuvDataInfo.yStride);
1057 int32_t height = static_cast<int32_t>(yuvDataInfo.yHeight);
1058 if (!PixelYuvUtils::CheckWidthAndHeightMult(width, height, RGBA_BIT_DEPTH)) {
1059 IMAGE_LOGE("ApplyColorSpace size overflow width(%{public}d), height(%{public}d)", width, height);
1060 return ERR_IMAGE_COLOR_CONVERT;
1061 }
1062 YuvImageInfo srcInfo = {PixelYuvUtils::ConvertFormat(format),
1063 imageInfo_.size.width, imageInfo_.size.height, imageInfo_.pixelFormat, yuvDataInfo};
1064 YuvImageInfo dstInfo = {PixelYuvUtils::ConvertFormat(PixelFormat::BGRA_8888),
1065 imageInfo_.size.width, imageInfo_.size.height, imageInfo_.pixelFormat, yuvDataInfo};
1066 std::unique_ptr<uint8_t[]> RGBAdata = std::make_unique<uint8_t[]>(width * height * NUM_4);
1067 if (!PixelYuvUtils::Yuv420ToBGRA(srcData, srcInfo, RGBAdata.get(), dstInfo)) {
1068 IMAGE_LOGE("applyColorSpace Yuv420ToBGRA failed");
1069 return ERR_IMAGE_COLOR_CONVERT;
1070 }
1071 src.bitmap.installPixels(src.info, RGBAdata.get(), rowStride);
1072 return SetColorSpace(grColorSpace, src, format, rowStride);
1073 }
1074 #endif
1075 } // namespace Media
1076 } // namespace OHOS