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