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