• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &region)
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 &region, 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 &region)
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