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