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