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