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 &region)504 uint32_t PixelYuv::WritePixels(const uint8_t *source, const uint64_t &bufferSize, const uint32_t &offset,
505     const uint32_t &stride, const Rect &region)
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 &region, uint8_t *dst)602 uint32_t PixelYuv::ReadPixels(const uint64_t &bufferSize, const uint32_t &offset, const uint32_t &stride,
603     const Rect &region, 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 &region)791 bool PixelYuv::CheckPixelsInput(const uint8_t *dst, const uint64_t &bufferSize, const uint32_t &offset,
792     const Rect &region)
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