• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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_map.h"
17 #include <iostream>
18 #include <unistd.h>
19 #include "hilog/log.h"
20 #include "image_utils.h"
21 #include "log_tags.h"
22 #include "media_errors.h"
23 #include "pixel_convert_adapter.h"
24 #include "pixel_map_utils.h"
25 #include "post_proc.h"
26 #include "parcel.h"
27 #include "image_trace.h"
28 #include "hitrace_meter.h"
29 #ifndef _WIN32
30 #include "securec.h"
31 #else
32 #include "memory.h"
33 #endif
34 
35 #if !defined(_WIN32) && !defined(_APPLE) &&!defined(_IOS) &&!defined(_ANDROID)
36 #include <sys/mman.h>
37 #include "ashmem.h"
38 #include "ipc_file_descriptor.h"
39 #endif
40 
41 namespace OHOS {
42 namespace Media {
43 using namespace OHOS::HiviewDFX;
44 using namespace std;
45 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_IMAGE, "PixelMap" };
46 constexpr int32_t MAX_DIMENSION = INT32_MAX >> 2;
47 constexpr uint8_t FOUR_BYTE_SHIFT = 2;
48 constexpr int8_t INVALID_ALPHA_INDEX = -1;
49 constexpr uint8_t ARGB_ALPHA_INDEX = 0;
50 constexpr uint8_t BGRA_ALPHA_INDEX = 3;
51 constexpr uint8_t ALPHA_BYTES = 1;
52 constexpr uint8_t BGRA_BYTES = 4;
53 constexpr uint8_t RGBA_F16_BYTES = 8;
54 constexpr uint8_t PER_PIXEL_LEN = 1;
55 
56 constexpr uint8_t FILL_NUMBER = 3;
57 constexpr uint8_t ALIGN_NUMBER = 4;
58 
~PixelMap()59 PixelMap::~PixelMap()
60 {
61     FreePixelMap();
62 }
63 
FreePixelMap()64 void PixelMap::FreePixelMap() __attribute__((no_sanitize("cfi")))
65 {
66     if (data_ == nullptr) {
67         return;
68     }
69     switch (allocatorType_) {
70         case AllocatorType::HEAP_ALLOC: {
71             free(data_);
72             data_ = nullptr;
73             break;
74         }
75         case AllocatorType::CUSTOM_ALLOC: {
76             if (custFreePixelMap_ != nullptr) {
77                 custFreePixelMap_(data_, context_, pixelsSize_);
78             }
79             data_ = nullptr;
80             context_ = nullptr;
81             break;
82         }
83         case AllocatorType::SHARE_MEM_ALLOC: {
84             ReleaseSharedMemory(data_, context_, pixelsSize_);
85             data_ = nullptr;
86             context_ = nullptr;
87             break;
88         }
89         default: {
90             HiLog::Error(LABEL, "unknown allocator type:[%{public}d].", allocatorType_);
91             return;
92         }
93     }
94 }
95 
ReleaseSharedMemory(void * addr,void * context,uint32_t size)96 void PixelMap::ReleaseSharedMemory(void *addr, void *context, uint32_t size)
97 {
98 #if !defined(_WIN32) && !defined(_APPLE) && !defined(_IOS) &&!defined(_ANDROID)
99     int *fd = static_cast<int *>(context);
100     if (addr != nullptr) {
101         ::munmap(addr, size);
102     }
103     if (fd != nullptr) {
104         ::close(*fd);
105         delete fd;
106     }
107 #endif
108 }
109 
SetPixelsAddr(void * addr,void * context,uint32_t size,AllocatorType type,CustomFreePixelMap func)110 void PixelMap::SetPixelsAddr(void *addr, void *context, uint32_t size, AllocatorType type, CustomFreePixelMap func)
111 {
112     if (data_ != nullptr) {
113         FreePixelMap();
114     }
115     data_ = static_cast<uint8_t *>(addr);
116     context_ = context;
117     pixelsSize_ = size;
118     allocatorType_ = type;
119     custFreePixelMap_ = func;
120 }
121 
Create(const uint32_t * colors,uint32_t colorLength,const InitializationOptions & opts)122 unique_ptr<PixelMap> PixelMap::Create(const uint32_t *colors, uint32_t colorLength, const InitializationOptions &opts)
123 {
124     HiLog::Info(LABEL, "PixelMap::Create1 enter");
125     return Create(colors, colorLength, 0, opts.size.width, opts);
126 }
127 
Create(const uint32_t * colors,uint32_t colorLength,int32_t offset,int32_t stride,const InitializationOptions & opts)128 unique_ptr<PixelMap> PixelMap::Create(const uint32_t *colors, uint32_t colorLength, int32_t offset, int32_t stride,
129                                       const InitializationOptions &opts)
130 {
131     HiLog::Info(LABEL, "PixelMap::Create2 enter");
132     if (!CheckParams(colors, colorLength, offset, stride, opts)) {
133         return nullptr;
134     }
135     unique_ptr<PixelMap> dstPixelMap = make_unique<PixelMap>();
136     if (dstPixelMap == nullptr) {
137         HiLog::Error(LABEL, "create pixelMap pointer fail");
138         return nullptr;
139     }
140 
141     ImageInfo srcImageInfo =
142         MakeImageInfo(stride, opts.size.height, PixelFormat::BGRA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
143     PixelFormat dstPixelFormat = (opts.pixelFormat == PixelFormat::UNKNOWN ? PixelFormat::RGBA_8888 : opts.pixelFormat);
144     AlphaType dstAlphaType =
145         (opts.alphaType == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) ? AlphaType::IMAGE_ALPHA_TYPE_PREMUL : opts.alphaType;
146     dstAlphaType = ImageUtils::GetValidAlphaTypeByFormat(dstAlphaType, dstPixelFormat);
147     ImageInfo dstImageInfo = MakeImageInfo(opts.size.width, opts.size.height, dstPixelFormat, dstAlphaType);
148     if (dstPixelMap->SetImageInfo(dstImageInfo) != SUCCESS) {
149         HiLog::Error(LABEL, "set image info fail");
150         return nullptr;
151     }
152     uint32_t bufferSize = dstPixelMap->GetByteCount();
153     if (bufferSize == 0 || bufferSize > PIXEL_MAP_MAX_RAM_SIZE) {
154         HiLog::Error(LABEL, "malloc parameter is zero");
155         return nullptr;
156     }
157     void *dstPixels = malloc(bufferSize);
158     if (dstPixels == nullptr) {
159         HiLog::Error(LABEL, "allocate memory size %{public}u fail", bufferSize);
160         return nullptr;
161     }
162 
163     Position dstPosition;
164     if (!PixelConvertAdapter::WritePixelsConvert(reinterpret_cast<const void *>(colors + offset),
165         static_cast<uint32_t>(stride) << FOUR_BYTE_SHIFT, srcImageInfo,
166         dstPixels, dstPosition, dstPixelMap->GetRowBytes(), dstImageInfo)) {
167         HiLog::Error(LABEL, "pixel convert in adapter failed.");
168         free(dstPixels);
169         dstPixels = nullptr;
170         return nullptr;
171     }
172     dstPixelMap->SetEditable(opts.editable);
173     dstPixelMap->SetPixelsAddr(dstPixels, nullptr, bufferSize, AllocatorType::HEAP_ALLOC, nullptr);
174     return dstPixelMap;
175 }
176 
CheckParams(const uint32_t * colors,uint32_t colorLength,int32_t offset,int32_t stride,const InitializationOptions & opts)177 bool PixelMap::CheckParams(const uint32_t *colors, uint32_t colorLength, int32_t offset, int32_t stride,
178                            const InitializationOptions &opts)
179 {
180     if (colors == nullptr || colorLength <= 0 || colorLength > PIXEL_MAP_MAX_RAM_SIZE) {
181         HiLog::Error(LABEL, "colors invalid");
182         return false;
183     }
184     int32_t dstWidth = opts.size.width;
185     int32_t dstHeight = opts.size.height;
186     if (dstWidth <= 0 || dstHeight <= 0) {
187         HiLog::Error(LABEL, "initial options size invalid");
188         return false;
189     }
190     if (stride < dstWidth) {
191         HiLog::Error(LABEL, "stride: %{public}d must >= width: %{public}d", stride, dstWidth);
192         return false;
193     }
194     if (stride > MAX_DIMENSION) {
195         HiLog::Error(LABEL, "stride %{public}d is out of range", stride);
196         return false;
197     }
198     int64_t lastLine = static_cast<int64_t>(dstHeight - 1) * stride + offset;
199     if (offset < 0 || static_cast<int64_t>(offset) + dstWidth > colorLength || lastLine + dstWidth > colorLength) {
200         HiLog::Error(LABEL, "colors length: %{public}u, offset: %{public}d, stride: %{public}d  is invalid",
201                      colorLength, offset, stride);
202         return false;
203     }
204     return true;
205 }
206 
Create(const InitializationOptions & opts)207 unique_ptr<PixelMap> PixelMap::Create(const InitializationOptions &opts)
208 {
209     HiLog::Info(LABEL, "PixelMap::Create3 enter");
210     unique_ptr<PixelMap> dstPixelMap = make_unique<PixelMap>();
211     if (dstPixelMap == nullptr) {
212         HiLog::Error(LABEL, "create pixelMap pointer fail");
213         return nullptr;
214     }
215     PixelFormat dstPixelFormat = (opts.pixelFormat == PixelFormat::UNKNOWN ? PixelFormat::RGBA_8888 : opts.pixelFormat);
216     AlphaType dstAlphaType =
217         (opts.alphaType == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) ? AlphaType::IMAGE_ALPHA_TYPE_PREMUL : opts.alphaType;
218     dstAlphaType = ImageUtils::GetValidAlphaTypeByFormat(dstAlphaType, dstPixelFormat);
219     ImageInfo dstImageInfo = MakeImageInfo(opts.size.width, opts.size.height, dstPixelFormat, dstAlphaType);
220     if (dstPixelMap->SetImageInfo(dstImageInfo) != SUCCESS) {
221         HiLog::Error(LABEL, "set image info fail");
222         return nullptr;
223     }
224     uint32_t bufferSize = dstPixelMap->GetByteCount();
225     if (bufferSize == 0 || bufferSize > PIXEL_MAP_MAX_RAM_SIZE) {
226         HiLog::Error(LABEL, "calloc parameter bufferSize:[%{public}d] error.", bufferSize);
227         return nullptr;
228     }
229     uint8_t *dstPixels = static_cast<uint8_t *>(calloc(bufferSize, 1));
230     if (dstPixels == nullptr) {
231         HiLog::Error(LABEL, "allocate memory size %{public}u fail", bufferSize);
232         return nullptr;
233     }
234     // update alpha opaque
235     UpdatePixelsAlpha(dstImageInfo.alphaType, dstImageInfo.pixelFormat, dstPixels, *dstPixelMap.get());
236     dstPixelMap->SetPixelsAddr(dstPixels, nullptr, bufferSize, AllocatorType::HEAP_ALLOC, nullptr);
237     dstPixelMap->SetEditable(opts.editable);
238     return dstPixelMap;
239 }
240 
UpdatePixelsAlpha(const AlphaType & alphaType,const PixelFormat & pixelFormat,uint8_t * dstPixels,PixelMap dstPixelMap)241 void PixelMap::UpdatePixelsAlpha(const AlphaType &alphaType, const PixelFormat &pixelFormat, uint8_t *dstPixels,
242                                  PixelMap dstPixelMap)
243 {
244     if (alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE) {
245         int8_t alphaIndex = -1;
246         if (pixelFormat == PixelFormat::RGBA_8888 || pixelFormat == PixelFormat::BGRA_8888) {
247             alphaIndex = BGRA_ALPHA_INDEX;
248         } else if (pixelFormat == PixelFormat::ARGB_8888) {
249             alphaIndex = 0;
250         }
251         if (alphaIndex != -1) {
252             uint8_t pixelBytes = dstPixelMap.GetPixelBytes();
253             uint32_t bufferSize = dstPixelMap.GetByteCount();
254             uint32_t i = alphaIndex;
255             while (i < bufferSize) {
256                 dstPixels[i] = ALPHA_OPAQUE;
257                 i += pixelBytes;
258             }
259         }
260     }
261 }
262 
Create(PixelMap & source,const InitializationOptions & opts)263 unique_ptr<PixelMap> PixelMap::Create(PixelMap &source, const InitializationOptions &opts)
264 {
265     HiLog::Info(LABEL, "PixelMap::Create4 enter");
266     Rect rect;
267     return Create(source, rect, opts);
268 }
269 
Create(PixelMap & source,const Rect & srcRect,const InitializationOptions & opts)270 unique_ptr<PixelMap> PixelMap::Create(PixelMap &source, const Rect &srcRect, const InitializationOptions &opts)
271 {
272     HiLog::Info(LABEL, "PixelMap::Create5 enter");
273     ImageInfo srcImageInfo;
274     source.GetImageInfo(srcImageInfo);
275     PostProc postProc;
276     Rect sRect = srcRect;
277     CropValue cropType = PostProc::ValidCropValue(sRect, srcImageInfo.size);
278     if (cropType == CropValue::INVALID) {
279         HiLog::Error(LABEL, "src crop range is invalid");
280         return nullptr;
281     }
282     ImageInfo dstImageInfo;
283     InitDstImageInfo(opts, srcImageInfo, dstImageInfo);
284     Size targetSize = dstImageInfo.size;
285     // use source if match
286     bool isHasConvert = postProc.HasPixelConvert(srcImageInfo, dstImageInfo);
287     if (opts.useSourceIfMatch && !source.IsEditable() && !opts.editable && (cropType == CropValue::NOCROP) &&
288         !isHasConvert && IsSameSize(srcImageInfo.size, dstImageInfo.size)) {
289         source.useSourceAsResponse_ = true;
290         return unique_ptr<PixelMap>(&source);
291     }
292     unique_ptr<PixelMap> dstPixelMap = make_unique<PixelMap>();
293     if (dstPixelMap == nullptr) {
294         HiLog::Error(LABEL, "create pixelmap pointer fail");
295         return nullptr;
296     }
297     if (cropType == CropValue::VALID) {
298         dstImageInfo.size.width = sRect.width;
299         dstImageInfo.size.height = sRect.height;
300     } else {
301         dstImageInfo.size = srcImageInfo.size;
302     }
303     if (dstPixelMap->SetImageInfo(dstImageInfo) != SUCCESS) {
304         return nullptr;
305     }
306     // dst pixelmap is source crop and convert pixelmap
307     if ((cropType == CropValue::VALID) || isHasConvert) {
308         if (!SourceCropAndConvert(source, srcImageInfo, dstImageInfo, sRect, *dstPixelMap.get())) {
309             return nullptr;
310         }
311     } else {
312         // only maybe size changed, copy source as scale operation
313         if (!CopyPixelMap(source, *dstPixelMap.get())) {
314             return nullptr;
315         }
316     }
317     if (!ScalePixelMap(targetSize, dstImageInfo.size, opts.scaleMode, *dstPixelMap.get())) {
318         return nullptr;
319     }
320     dstPixelMap->SetEditable(opts.editable);
321     return dstPixelMap;
322 }
323 
SourceCropAndConvert(PixelMap & source,const ImageInfo & srcImageInfo,const ImageInfo & dstImageInfo,const Rect & srcRect,PixelMap & dstPixelMap)324 bool PixelMap::SourceCropAndConvert(PixelMap &source, const ImageInfo &srcImageInfo, const ImageInfo &dstImageInfo,
325                                     const Rect &srcRect, PixelMap &dstPixelMap)
326 {
327     uint32_t bufferSize = dstPixelMap.GetByteCount();
328     if (bufferSize == 0 || bufferSize > PIXEL_MAP_MAX_RAM_SIZE) {
329         HiLog::Error(LABEL, "malloc parameter bufferSize:[%{public}d] error.", bufferSize);
330         return false;
331     }
332     void *dstPixels = malloc(bufferSize);
333     if (dstPixels == nullptr) {
334         HiLog::Error(LABEL, "allocate memory size %{public}u fail", bufferSize);
335         return false;
336     }
337 
338     if (memset_s(dstPixels, bufferSize, 0, bufferSize) != EOK) {
339         HiLog::Error(LABEL, "dstPixels memset_s failed.");
340     }
341     Position srcPosition { srcRect.left, srcRect.top };
342     if (!PixelConvertAdapter::ReadPixelsConvert(source.GetPixels(), srcPosition, source.GetRowBytes(), srcImageInfo,
343         dstPixels, dstPixelMap.GetRowBytes(), dstImageInfo)) {
344         HiLog::Error(LABEL, "pixel convert in adapter failed.");
345         free(dstPixels);
346         dstPixels = nullptr;
347         return false;
348     }
349     dstPixelMap.SetPixelsAddr(dstPixels, nullptr, bufferSize, AllocatorType::HEAP_ALLOC, nullptr);
350     return true;
351 }
352 
ScalePixelMap(const Size & targetSize,const Size & dstSize,const ScaleMode & scaleMode,PixelMap & dstPixelMap)353 bool PixelMap::ScalePixelMap(const Size &targetSize, const Size &dstSize, const ScaleMode &scaleMode,
354                              PixelMap &dstPixelMap)
355 {
356     if (dstSize.width == targetSize.width && dstSize.height == targetSize.height) {
357         return true;
358     }
359     PostProc postProc;
360     if (scaleMode == ScaleMode::FIT_TARGET_SIZE) {
361         if (!postProc.ScalePixelMap(targetSize, dstPixelMap)) {
362             HiLog::Error(LABEL, "scale FIT_TARGET_SIZE fail");
363             return false;
364         }
365     }
366     if (scaleMode == ScaleMode::CENTER_CROP) {
367         if (!postProc.CenterScale(targetSize, dstPixelMap)) {
368             HiLog::Error(LABEL, "scale CENTER_CROP fail");
369             return false;
370         }
371     }
372     return true;
373 }
374 
InitDstImageInfo(const InitializationOptions & opts,const ImageInfo & srcImageInfo,ImageInfo & dstImageInfo)375 void PixelMap::InitDstImageInfo(const InitializationOptions &opts, const ImageInfo &srcImageInfo,
376                                 ImageInfo &dstImageInfo)
377 {
378     dstImageInfo.size = opts.size;
379     if (dstImageInfo.size.width == 0 && dstImageInfo.size.height == 0) {
380         dstImageInfo.size = srcImageInfo.size;
381     }
382     dstImageInfo.pixelFormat = opts.pixelFormat;
383     if (dstImageInfo.pixelFormat == PixelFormat::UNKNOWN) {
384         dstImageInfo.pixelFormat = srcImageInfo.pixelFormat;
385     }
386     dstImageInfo.alphaType = opts.alphaType;
387     if (dstImageInfo.alphaType == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
388         dstImageInfo.alphaType = srcImageInfo.alphaType;
389     }
390 }
391 
CopyPixelMap(PixelMap & source,PixelMap & dstPixelMap)392 bool PixelMap::CopyPixelMap(PixelMap &source, PixelMap &dstPixelMap)
393 {
394     uint32_t bufferSize = source.GetByteCount();
395     if (source.GetPixels() == nullptr) {
396         HiLog::Error(LABEL, "source pixelMap data invalid");
397         return false;
398     }
399     if (bufferSize == 0 || bufferSize > PIXEL_MAP_MAX_RAM_SIZE) {
400         HiLog::Error(LABEL, "malloc parameter bufferSize:[%{public}d] error.", bufferSize);
401         return false;
402     }
403     uint8_t *dstPixels = static_cast<uint8_t *>(malloc(bufferSize));
404     if (dstPixels == nullptr) {
405         HiLog::Error(LABEL, "allocate memory size %{public}u fail", bufferSize);
406         return false;
407     }
408     errno_t errRet = memcpy_s(dstPixels, bufferSize, source.GetPixels(), bufferSize);
409     if (errRet != 0) {
410         HiLog::Error(LABEL, "copy source memory size %{public}u fail, errorCode = %{public}d", bufferSize, errRet);
411         free(dstPixels);
412         dstPixels = nullptr;
413         return false;
414     }
415     dstPixelMap.SetPixelsAddr(dstPixels, nullptr, bufferSize, AllocatorType::HEAP_ALLOC, nullptr);
416     return true;
417 }
418 
IsSameSize(const Size & src,const Size & dst)419 bool PixelMap::IsSameSize(const Size &src, const Size &dst)
420 {
421     return (src.width == dst.width) && (src.height == dst.height);
422 }
423 
GetPixelFormatDetail(const PixelFormat format)424 bool PixelMap::GetPixelFormatDetail(const PixelFormat format)
425 {
426     switch (format) {
427         case PixelFormat::RGBA_8888: {
428             pixelBytes_ = ARGB_8888_BYTES;
429             colorProc_ = RGBA8888ToARGB;
430             break;
431         }
432         case PixelFormat::BGRA_8888: {
433             pixelBytes_ = ARGB_8888_BYTES;
434             colorProc_ = BGRA8888ToARGB;
435             break;
436         }
437         case PixelFormat::ARGB_8888: {
438             pixelBytes_ = ARGB_8888_BYTES;
439             colorProc_ = ARGB8888ToARGB;
440             break;
441         }
442         case PixelFormat::ALPHA_8: {
443             pixelBytes_ = ALPHA_8_BYTES;
444             colorProc_ = ALPHA8ToARGB;
445             break;
446         }
447         case PixelFormat::RGB_565: {
448             pixelBytes_ = RGB_565_BYTES;
449             colorProc_ = RGB565ToARGB;
450             break;
451         }
452         case PixelFormat::RGB_888: {
453             pixelBytes_ = RGB_888_BYTES;
454             colorProc_ = RGB888ToARGB;
455             break;
456         }
457         case PixelFormat::NV12:
458         case PixelFormat::NV21: {
459             pixelBytes_ = YUV420_BYTES;
460             break;
461         }
462         case PixelFormat::CMYK:
463             pixelBytes_ = ARGB_8888_BYTES;
464             break;
465         case PixelFormat::RGBA_F16:
466             pixelBytes_ = BGRA_F16_BYTES;
467             break;
468         default: {
469             HiLog::Error(LABEL, "pixel format:[%{public}d] not supported.", format);
470             return false;
471         }
472     }
473     return true;
474 }
475 
SetImageInfo(ImageInfo & info)476 uint32_t PixelMap::SetImageInfo(ImageInfo &info)
477 {
478     return SetImageInfo(info, false);
479 }
480 
SetImageInfo(ImageInfo & info,bool isReused)481 uint32_t PixelMap::SetImageInfo(ImageInfo &info, bool isReused)
482 {
483     if (info.size.width <= 0 || info.size.height <= 0) {
484         HiLog::Error(LABEL, "pixel map image info invalid.");
485         return ERR_IMAGE_DATA_ABNORMAL;
486     }
487     if (!GetPixelFormatDetail(info.pixelFormat)) {
488         return ERR_IMAGE_DATA_UNSUPPORT;
489     }
490 
491     if (pixelBytes_ <= 0) {
492         ResetPixelMap();
493         HiLog::Error(LABEL, "pixel map bytes is invalid.");
494         return ERR_IMAGE_DATA_ABNORMAL;
495     }
496 
497     if ((static_cast<uint64_t>(pixelBytes_) * info.size.width) > PIXEL_MAP_MAX_RAM_SIZE) {
498         ResetPixelMap();
499         HiLog::Error(LABEL, "image size is out of range.");
500         return ERR_IMAGE_TOO_LARGE;
501     }
502     if (info.pixelFormat == PixelFormat::ALPHA_8) {
503         rowDataSize_ = pixelBytes_ * ((info.size.width + FILL_NUMBER) / ALIGN_NUMBER * ALIGN_NUMBER);
504         HiLog::Info(LABEL, "ALPHA_8 rowDataSize_ %{public}d.", rowDataSize_);
505     } else {
506         rowDataSize_ = pixelBytes_ * info.size.width;
507     }
508     if (info.size.height > (PIXEL_MAP_MAX_RAM_SIZE / rowDataSize_)) {
509         ResetPixelMap();
510         HiLog::Error(LABEL, "pixel map byte count out of range.");
511         return ERR_IMAGE_TOO_LARGE;
512     }
513     if (!isReused) {
514         FreePixelMap();
515     }
516     imageInfo_ = info;
517     return SUCCESS;
518 }
519 
GetPixel8(int32_t x,int32_t y)520 const uint8_t *PixelMap::GetPixel8(int32_t x, int32_t y)
521 {
522     if (!CheckValidParam(x, y) || (pixelBytes_ != ALPHA_8_BYTES)) {
523         HiLog::Error(LABEL, "get addr8 pixel position:(%{public}d, %{public}d) pixel bytes:%{public}d invalid.", x, y,
524                      pixelBytes_);
525         return nullptr;
526     }
527     return (data_ + y * rowDataSize_ + x);
528 }
529 
GetPixel16(int32_t x,int32_t y)530 const uint16_t *PixelMap::GetPixel16(int32_t x, int32_t y)
531 {
532     if (!CheckValidParam(x, y) || (pixelBytes_ != RGB_565_BYTES)) {
533         HiLog::Error(LABEL, "get addr16 pixel position:(%{public}d, %{public}d) pixel bytes:%{public}d invalid.", x, y,
534                      pixelBytes_);
535         return nullptr;
536     }
537     // convert uint8_t* to uint16_t*
538     return reinterpret_cast<uint16_t *>(data_ + y * rowDataSize_ + (static_cast<uint32_t>(x) << RGB_565_SHIFT));
539 }
540 
GetPixel32(int32_t x,int32_t y)541 const uint32_t *PixelMap::GetPixel32(int32_t x, int32_t y)
542 {
543     if (!CheckValidParam(x, y) || (pixelBytes_ != ARGB_8888_BYTES)) {
544         HiLog::Error(LABEL, "get addr32 pixel position:(%{public}d, %{public}d) pixel bytes:%{public}d invalid.", x, y,
545                      pixelBytes_);
546         return nullptr;
547     }
548     // convert uint8_t* to uint32_t*
549     return reinterpret_cast<uint32_t *>(data_ + y * rowDataSize_ + (static_cast<uint32_t>(x) << ARGB_8888_SHIFT));
550 }
551 
GetPixel(int32_t x,int32_t y)552 const uint8_t *PixelMap::GetPixel(int32_t x, int32_t y)
553 {
554     if (!CheckValidParam(x, y)) {
555         HiLog::Error(LABEL, "input pixel position:(%{public}d, %{public}d) invalid.", x, y);
556         return nullptr;
557     }
558     return (data_ + y * rowDataSize_ + (static_cast<uint32_t>(x) * pixelBytes_));
559 }
560 
GetARGB32Color(int32_t x,int32_t y,uint32_t & color)561 bool PixelMap::GetARGB32Color(int32_t x, int32_t y, uint32_t &color)
562 {
563     if (colorProc_ == nullptr) {
564         HiLog::Error(LABEL, "pixel format not supported.");
565         return false;
566     }
567     const uint8_t *src = GetPixel(x, y);
568     if (src == nullptr) {
569         HiLog::Error(LABEL, "get pixel color error.");
570         return false;
571     }
572     // use founction point for frequently called interface
573     return colorProc_(src, ONE_PIXEL_SIZE * pixelBytes_, &color, ONE_PIXEL_SIZE);
574 }
575 
ALPHA8ToARGB(const uint8_t * in,uint32_t inCount,uint32_t * out,uint32_t outCount)576 bool PixelMap::ALPHA8ToARGB(const uint8_t *in, uint32_t inCount, uint32_t *out, uint32_t outCount)
577 {
578     if (inCount != outCount) {
579         HiLog::Error(LABEL, "input count:%{public}u is not match to output count:%{public}u.", inCount, outCount);
580         return false;
581     }
582     const uint8_t *src = in;
583     for (uint32_t i = 0; i < outCount; i++) {
584         *out++ = GetColorARGB(*src++, BYTE_ZERO, BYTE_ZERO, BYTE_ZERO);
585     }
586     return true;
587 }
588 
RGB565ToARGB(const uint8_t * in,uint32_t inCount,uint32_t * out,uint32_t outCount)589 bool PixelMap::RGB565ToARGB(const uint8_t *in, uint32_t inCount, uint32_t *out, uint32_t outCount)
590 {
591     if (((inCount / RGB_565_BYTES) != outCount) && ((inCount % RGB_565_BYTES) != 0)) {
592         HiLog::Error(LABEL, "input count:%{public}u is not match to output count:%{public}u.", inCount, outCount);
593         return false;
594     }
595     const uint16_t *src = reinterpret_cast<const uint16_t *>(in);
596     for (uint32_t i = 0; i < outCount; i++) {
597         uint16_t color = *src++;
598         *out++ = GetColorARGB(BYTE_FULL, RGB565ToR32(color), RGB565ToG32(color), RGB565ToB32(color));
599     }
600     return true;
601 }
602 
ARGB8888ToARGB(const uint8_t * in,uint32_t inCount,uint32_t * out,uint32_t outCount)603 bool PixelMap::ARGB8888ToARGB(const uint8_t *in, uint32_t inCount, uint32_t *out, uint32_t outCount)
604 {
605     if (((inCount / ARGB_8888_BYTES) != outCount) && ((inCount % ARGB_8888_BYTES) != 0)) {
606         HiLog::Error(LABEL, "input count:%{public}u is not match to output count:%{public}u.", inCount, outCount);
607         return false;
608     }
609     const uint32_t *src = reinterpret_cast<const uint32_t *>(in);
610     for (uint32_t i = 0; i < outCount; i++) {
611         uint32_t color = *src++;
612         *out++ = GetColorARGB(GetColorComp(color, ARGB32_A_SHIFT), GetColorComp(color, ARGB32_R_SHIFT),
613                               GetColorComp(color, ARGB32_G_SHIFT), GetColorComp(color, ARGB32_B_SHIFT));
614     }
615     return true;
616 }
617 
RGBA8888ToARGB(const uint8_t * in,uint32_t inCount,uint32_t * out,uint32_t outCount)618 bool PixelMap::RGBA8888ToARGB(const uint8_t *in, uint32_t inCount, uint32_t *out, uint32_t outCount)
619 {
620     if (((inCount / ARGB_8888_BYTES) != outCount) && ((inCount % ARGB_8888_BYTES) != 0)) {
621         HiLog::Error(LABEL, "input count:%{public}u is not match to output count:%{public}u.", inCount, outCount);
622         return false;
623     }
624     const uint32_t *src = reinterpret_cast<const uint32_t *>(in);
625     for (uint32_t i = 0; i < outCount; i++) {
626         uint32_t color = *src++;
627         *out++ = GetColorARGB(GetColorComp(color, RGBA32_A_SHIFT), GetColorComp(color, RGBA32_R_SHIFT),
628                               GetColorComp(color, RGBA32_G_SHIFT), GetColorComp(color, RGBA32_B_SHIFT));
629     }
630     return true;
631 }
632 
BGRA8888ToARGB(const uint8_t * in,uint32_t inCount,uint32_t * out,uint32_t outCount)633 bool PixelMap::BGRA8888ToARGB(const uint8_t *in, uint32_t inCount, uint32_t *out, uint32_t outCount)
634 {
635     if (((inCount / ARGB_8888_BYTES) != outCount) && ((inCount % ARGB_8888_BYTES) != 0)) {
636         HiLog::Error(LABEL, "input count:%{public}u is not match to output count:%{public}u.", inCount, outCount);
637         return false;
638     }
639     const uint32_t *src = reinterpret_cast<const uint32_t *>(in);
640     for (uint32_t i = 0; i < outCount; i++) {
641         uint32_t color = *src++;
642         *out++ = GetColorARGB(GetColorComp(color, BGRA32_A_SHIFT), GetColorComp(color, BGRA32_R_SHIFT),
643                               GetColorComp(color, BGRA32_G_SHIFT), GetColorComp(color, BGRA32_B_SHIFT));
644     }
645     return true;
646 }
647 
RGB888ToARGB(const uint8_t * in,uint32_t inCount,uint32_t * out,uint32_t outCount)648 bool PixelMap::RGB888ToARGB(const uint8_t *in, uint32_t inCount, uint32_t *out, uint32_t outCount)
649 {
650     if (((inCount / RGB_888_BYTES) != outCount) && ((inCount % RGB_888_BYTES) != 0)) {
651         HiLog::Error(LABEL, "input count:%{public}u is not match to output count:%{public}u.", inCount, outCount);
652         return false;
653     }
654     const uint8_t *src = in;
655     for (uint32_t i = 0; i < outCount; i++) {
656         uint8_t colorR = *src++;
657         uint8_t colorG = *src++;
658         uint8_t colorB = *src++;
659         *out++ = GetColorARGB(BYTE_FULL, colorR, colorG, colorB);
660     }
661     return true;
662 }
663 
GetPixelBytes()664 int32_t PixelMap::GetPixelBytes()
665 {
666     return pixelBytes_;
667 }
668 
GetRowBytes()669 int32_t PixelMap::GetRowBytes()
670 {
671     return rowDataSize_;
672 }
673 
GetByteCount()674 int32_t PixelMap::GetByteCount()
675 {
676     HiLog::Debug(LABEL, "GetByteCount");
677     return rowDataSize_ * imageInfo_.size.height;
678 }
679 
GetWidth()680 int32_t PixelMap::GetWidth()
681 {
682     return imageInfo_.size.width;
683 }
684 
GetHeight()685 int32_t PixelMap::GetHeight()
686 {
687     return imageInfo_.size.height;
688 }
689 
GetBaseDensity()690 int32_t PixelMap::GetBaseDensity()
691 {
692     return imageInfo_.baseDensity;
693 }
694 
GetImageInfo(ImageInfo & imageInfo)695 void PixelMap::GetImageInfo(ImageInfo &imageInfo)
696 {
697     imageInfo = imageInfo_;
698 }
699 
GetPixelFormat()700 PixelFormat PixelMap::GetPixelFormat()
701 {
702     return imageInfo_.pixelFormat;
703 }
704 
GetColorSpace()705 ColorSpace PixelMap::GetColorSpace()
706 {
707     return imageInfo_.colorSpace;
708 }
709 
GetAlphaType()710 AlphaType PixelMap::GetAlphaType()
711 {
712     return imageInfo_.alphaType;
713 }
714 
GetPixels()715 const uint8_t *PixelMap::GetPixels()
716 {
717     return data_;
718 }
719 
GetARGB32ColorA(uint32_t color)720 uint8_t PixelMap::GetARGB32ColorA(uint32_t color)
721 {
722     return (color >> ARGB_A_SHIFT) & ARGB_MASK;
723 }
724 
GetARGB32ColorR(uint32_t color)725 uint8_t PixelMap::GetARGB32ColorR(uint32_t color)
726 {
727     return (color >> ARGB_R_SHIFT) & ARGB_MASK;
728 }
729 
GetARGB32ColorG(uint32_t color)730 uint8_t PixelMap::GetARGB32ColorG(uint32_t color)
731 {
732     return (color >> ARGB_G_SHIFT) & ARGB_MASK;
733 }
734 
GetARGB32ColorB(uint32_t color)735 uint8_t PixelMap::GetARGB32ColorB(uint32_t color)
736 {
737     return (color >> ARGB_B_SHIFT) & ARGB_MASK;
738 }
739 
IsSameImage(const PixelMap & other)740 bool PixelMap::IsSameImage(const PixelMap &other)
741 {
742     if (data_ == nullptr || other.data_ == nullptr) {
743         HiLog::Error(LABEL, "IsSameImage data_ is nullptr.");
744         return false;
745     }
746     if (imageInfo_.size.width != other.imageInfo_.size.width ||
747         imageInfo_.size.height != other.imageInfo_.size.height ||
748         imageInfo_.pixelFormat != other.imageInfo_.pixelFormat || imageInfo_.alphaType != other.imageInfo_.alphaType) {
749         HiLog::Error(LABEL, "IsSameImage imageInfo check not OK.");
750         return false;
751     }
752     uint64_t size = static_cast<uint64_t>(rowDataSize_) * imageInfo_.size.height;
753     if (memcmp(data_, other.data_, size) != 0) {
754         HiLog::Error(LABEL, "IsSameImage mmemcmp check not OK.");
755         return false;
756     }
757     return true;
758 }
759 
ReadPixels(const uint64_t & bufferSize,uint8_t * dst)760 uint32_t PixelMap::ReadPixels(const uint64_t &bufferSize, uint8_t *dst)
761 {
762     StartTrace(HITRACE_TAG_ZIMAGE, "ReadPixels by bufferSize");
763     if (dst == nullptr) {
764         HiLog::Error(LABEL, "read pixels by buffer input dst address is null.");
765         return ERR_IMAGE_READ_PIXELMAP_FAILED;
766     }
767     if (data_ == nullptr) {
768         HiLog::Error(LABEL, "read pixels by buffer current PixelMap data is null.");
769         return ERR_IMAGE_READ_PIXELMAP_FAILED;
770     }
771     if (bufferSize < static_cast<uint64_t>(pixelsSize_)) {
772         HiLog::Error(LABEL, "read pixels by buffer input dst buffer(%{public}llu) < current pixelmap size(%{public}u).",
773                      static_cast<unsigned long long>(bufferSize), pixelsSize_);
774         return ERR_IMAGE_INVALID_PARAMETER;
775     }
776     errno_t ret = memcpy_s(dst, bufferSize, data_, pixelsSize_);
777     if (ret != 0) {
778         HiLog::Error(LABEL, "read pixels by buffer memcpy the pixelmap data to dst fail, error:%{public}d", ret);
779         return ERR_IMAGE_READ_PIXELMAP_FAILED;
780     }
781     FinishTrace(HITRACE_TAG_ZIMAGE);
782     return SUCCESS;
783 }
784 
CheckPixelsInput(const uint8_t * dst,const uint64_t & bufferSize,const uint32_t & offset,const uint32_t & stride,const Rect & region)785 bool PixelMap::CheckPixelsInput(const uint8_t *dst, const uint64_t &bufferSize, const uint32_t &offset,
786                                 const uint32_t &stride, const Rect &region)
787 {
788     if (dst == nullptr) {
789         HiLog::Error(LABEL, "CheckPixelsInput input dst address is null.");
790         return false;
791     }
792 
793     if (bufferSize == 0) {
794         HiLog::Error(LABEL, "CheckPixelsInput input buffer size is 0.");
795         return false;
796     }
797 
798     if (region.left < 0 || region.top < 0 || stride > numeric_limits<int32_t>::max() ||
799         static_cast<uint64_t>(offset) > bufferSize) {
800         HiLog::Error(
801             LABEL,
802             "CheckPixelsInput left(%{public}d) or top(%{public}d) or stride(%{public}u) or offset(%{public}u) < 0.",
803             region.left, region.top, stride, offset);
804         return false;
805     }
806     if (region.width <= 0 || region.height <= 0 || region.width > MAX_DIMENSION || region.height > MAX_DIMENSION) {
807         HiLog::Error(LABEL, "CheckPixelsInput width(%{public}d) or height(%{public}d) is < 0.", region.width,
808                      region.height);
809         return false;
810     }
811     if (region.left > GetWidth() - region.width) {
812         HiLog::Error(LABEL, "CheckPixelsInput left(%{public}d) + width(%{public}d) is > pixelmap width(%{public}d).",
813                      region.left, region.width, GetWidth());
814         return false;
815     }
816     if (region.top > GetHeight() - region.height) {
817         HiLog::Error(LABEL, "CheckPixelsInput top(%{public}d) + height(%{public}d) is > pixelmap height(%{public}d).",
818                      region.top, region.height, GetHeight());
819         return false;
820     }
821     uint32_t regionStride = static_cast<uint32_t>(region.width) * 4;  // bytes count, need multiply by 4
822     if (stride < regionStride) {
823         HiLog::Error(LABEL, "CheckPixelsInput stride(%{public}d) < width*4 (%{public}d).", stride, regionStride);
824         return false;
825     }
826 
827     if (bufferSize < regionStride) {
828         HiLog::Error(LABEL, "CheckPixelsInput input buffer size is < width * 4.");
829         return false;
830     }
831     uint64_t lastLinePos = offset + static_cast<uint64_t>(region.height - 1) * stride;  // "1" is except the last line.
832     if (static_cast<uint64_t>(offset) > (bufferSize - regionStride) || lastLinePos > (bufferSize - regionStride)) {
833         HiLog::Error(LABEL,
834                      "CheckPixelsInput fail, height(%{public}d), width(%{public}d), lastLine(%{public}llu), "
835                      "offset(%{public}u), bufferSize:%{public}llu.",
836                      region.height, region.width, static_cast<unsigned long long>(lastLinePos), offset,
837                      static_cast<unsigned long long>(bufferSize));
838         return false;
839     }
840     return true;
841 }
842 
ReadPixels(const uint64_t & bufferSize,const uint32_t & offset,const uint32_t & stride,const Rect & region,uint8_t * dst)843 uint32_t PixelMap::ReadPixels(const uint64_t &bufferSize, const uint32_t &offset, const uint32_t &stride,
844                               const Rect &region, uint8_t *dst)
845 {
846     if (!CheckPixelsInput(dst, bufferSize, offset, stride, region)) {
847         HiLog::Error(LABEL, "read pixels by rect input parameter fail.");
848         return ERR_IMAGE_INVALID_PARAMETER;
849     }
850     if (data_ == nullptr) {
851         HiLog::Error(LABEL, "read pixels by rect this pixel data is null.");
852         return ERR_IMAGE_READ_PIXELMAP_FAILED;
853     }
854     ImageInfo dstImageInfo =
855         MakeImageInfo(region.width, region.height, PixelFormat::BGRA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
856     Position srcPosition { region.left, region.top };
857     if (!PixelConvertAdapter::ReadPixelsConvert(data_, srcPosition, rowDataSize_, imageInfo_, dst + offset, stride,
858         dstImageInfo)) {
859         HiLog::Error(LABEL, "read pixels by rect call ReadPixelsConvert fail.");
860         return ERR_IMAGE_READ_PIXELMAP_FAILED;
861     }
862     return SUCCESS;
863 }
864 
ReadPixel(const Position & pos,uint32_t & dst)865 uint32_t PixelMap::ReadPixel(const Position &pos, uint32_t &dst)
866 {
867     if (pos.x < 0 || pos.y < 0 || pos.x >= GetWidth() || pos.y >= GetHeight()) {
868         HiLog::Error(LABEL, "read pixel by pos input invalid exception. [x(%{public}d), y(%{public}d)]", pos.x, pos.y);
869         return ERR_IMAGE_INVALID_PARAMETER;
870     }
871     if (data_ == nullptr) {
872         HiLog::Error(LABEL, "read pixel by pos source data is null.");
873         return ERR_IMAGE_READ_PIXELMAP_FAILED;
874     }
875     ImageInfo dstImageInfo =
876         MakeImageInfo(PER_PIXEL_LEN, PER_PIXEL_LEN, PixelFormat::BGRA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
877     uint32_t dstRowBytes = BGRA_BYTES;
878     Position srcPosition { pos.x, pos.y };
879     if (!PixelConvertAdapter::ReadPixelsConvert(data_, srcPosition, rowDataSize_, imageInfo_, &dst, dstRowBytes,
880         dstImageInfo)) {
881         HiLog::Error(LABEL, "read pixel by pos call ReadPixelsConvert fail.");
882         return ERR_IMAGE_READ_PIXELMAP_FAILED;
883     }
884     return SUCCESS;
885 }
886 
ResetConfig(const Size & size,const PixelFormat & format)887 uint32_t PixelMap::ResetConfig(const Size &size, const PixelFormat &format)
888 {
889     if (size.width <= 0 || size.height <= 0) {
890         HiLog::Error(LABEL, "ResetConfig reset input width(%{public}d) or height(%{public}d) is < 0.", size.width,
891                      size.height);
892         return ERR_IMAGE_INVALID_PARAMETER;
893     }
894     uint32_t bytesPerPixel = ImageUtils::GetPixelBytes(format);
895     if (bytesPerPixel == 0) {
896         HiLog::Error(LABEL, "ResetConfig get bytes by per pixel fail.");
897         return ERR_IMAGE_INVALID_PARAMETER;
898     }
899     uint64_t dstSize = static_cast<uint64_t>(size.width) * size.height * bytesPerPixel;
900     if (dstSize > static_cast<uint64_t>(pixelsSize_)) {
901         HiLog::Error(LABEL, "ResetConfig reset dstSize(%{public}llu) > current(%{public}u).",
902                      static_cast<unsigned long long>(dstSize), pixelsSize_);
903         return ERR_IMAGE_INVALID_PARAMETER;
904     }
905     AlphaType dstAlphaType = ImageUtils::GetValidAlphaTypeByFormat(GetAlphaType(), format);
906     if (dstAlphaType == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
907         HiLog::Error(LABEL, "ResetConfig Failed to get validate alpha type.");
908         return ERR_IMAGE_INVALID_PARAMETER;
909     }
910     ImageInfo dstInfo = MakeImageInfo(size.width, size.height, format, dstAlphaType);
911     uint32_t ret = SetImageInfo(dstInfo, true);
912     if (ret != SUCCESS) {
913         HiLog::Error(LABEL, "ResetConfig call SetImageInfo Failed. ret:%{public}u", ret);
914         return ERR_IMAGE_CONFIG_FAILED;
915     }
916     return SUCCESS;
917 }
918 
SetAlphaType(const AlphaType & alphaType)919 bool PixelMap::SetAlphaType(const AlphaType &alphaType)
920 {
921     AlphaType type = ImageUtils::GetValidAlphaTypeByFormat(alphaType, imageInfo_.pixelFormat);
922     if (type == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
923         HiLog::Error(LABEL, "SetAlphaType Failed to get validate alpha type.");
924         return false;
925     }
926     ImageInfo dstInfo = imageInfo_;
927     dstInfo.alphaType = type;
928     uint32_t ret = SetImageInfo(dstInfo, true);
929     if (ret != SUCCESS) {
930         HiLog::Error(LABEL, "SetAlphaType call SetImageInfo Failed. ret:%{public}u", ret);
931         return false;
932     }
933     return true;
934 }
935 
WritePixel(const Position & pos,const uint32_t & color)936 uint32_t PixelMap::WritePixel(const Position &pos, const uint32_t &color)
937 {
938     if (pos.x < 0 || pos.y < 0 || pos.x >= GetWidth() || pos.y >= GetHeight()) {
939         HiLog::Error(LABEL,
940                      "write pixel by pos but input position is invalid. [x(%{public}d), y(%{public}d)]"\
941                      "Width() %{public}d,  Height() %{public}d, ",
942                      pos.x, pos.y, GetWidth(), GetHeight());
943         return ERR_IMAGE_INVALID_PARAMETER;
944     }
945     if (!IsEditable()) {
946         HiLog::Error(LABEL, "write pixel by pos pixelmap is not editable.");
947         return ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY;
948     }
949     if (!ImageUtils::IsValidImageInfo(imageInfo_)) {
950         HiLog::Error(LABEL, "write pixel by pos current pixelmap image info is invalid.");
951         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
952     }
953     if (data_ == nullptr) {
954         HiLog::Error(LABEL, "write pixel by pos but current pixelmap data is nullptr.");
955         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
956     }
957     ImageInfo srcImageInfo =
958         MakeImageInfo(PER_PIXEL_LEN, PER_PIXEL_LEN, PixelFormat::BGRA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
959     uint32_t srcRowBytes = BGRA_BYTES;
960     Position dstPosition { pos.x, pos.y };  // source is per pixel.
961     if (!PixelConvertAdapter::WritePixelsConvert(&color, srcRowBytes, srcImageInfo, data_, dstPosition, rowDataSize_,
962         imageInfo_)) {
963         HiLog::Error(LABEL, "write pixel by pos call WritePixelsConvert fail.");
964         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
965     }
966     return SUCCESS;
967 }
968 
WritePixels(const uint8_t * source,const uint64_t & bufferSize,const uint32_t & offset,const uint32_t & stride,const Rect & region)969 uint32_t PixelMap::WritePixels(const uint8_t *source, const uint64_t &bufferSize, const uint32_t &offset,
970                                const uint32_t &stride, const Rect &region)
971 {
972     if (!CheckPixelsInput(source, bufferSize, offset, stride, region)) {
973         HiLog::Error(LABEL, "write pixel by rect input parameter fail.");
974         return ERR_IMAGE_INVALID_PARAMETER;
975     }
976     if (!IsEditable()) {
977         HiLog::Error(LABEL, "write pixel by rect pixelmap data is not editable.");
978         return ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY;
979     }
980     if (!ImageUtils::IsValidImageInfo(imageInfo_)) {
981         HiLog::Error(LABEL, "write pixel by rect current pixelmap image info is invalid.");
982         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
983     }
984     if (data_ == nullptr) {
985         HiLog::Error(LABEL, "write pixel by rect current pixel map data is null.");
986         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
987     }
988     uint32_t bytesPerPixel = ImageUtils::GetPixelBytes(imageInfo_.pixelFormat);
989     if (bytesPerPixel == 0) {
990         HiLog::Error(LABEL, "write pixel by rect get bytes by per pixel fail.");
991         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
992     }
993     Position dstPosition { region.left, region.top };
994     ImageInfo srcInfo =
995         MakeImageInfo(region.width, region.height, PixelFormat::BGRA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
996     if (!PixelConvertAdapter::WritePixelsConvert(source + offset, stride, srcInfo, data_, dstPosition, rowDataSize_,
997         imageInfo_)) {
998         HiLog::Error(LABEL, "write pixel by rect call WritePixelsConvert fail.");
999         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
1000     }
1001     return SUCCESS;
1002 }
1003 
WritePixels(const uint8_t * source,const uint64_t & bufferSize)1004 uint32_t PixelMap::WritePixels(const uint8_t *source, const uint64_t &bufferSize)
1005 {
1006     StartTrace(HITRACE_TAG_ZIMAGE, "WritePixels");
1007     if (source == nullptr || bufferSize < static_cast<uint64_t>(pixelsSize_)) {
1008         HiLog::Error(LABEL, "write pixels by buffer source is nullptr or size(%{public}llu) < pixelSize(%{public}u).",
1009                      static_cast<unsigned long long>(bufferSize), pixelsSize_);
1010         return ERR_IMAGE_INVALID_PARAMETER;
1011     }
1012     if (!IsEditable()) {
1013         HiLog::Error(LABEL, "write pixels by buffer pixelmap data is not editable.");
1014         return ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY;
1015     }
1016     if (!ImageUtils::IsValidImageInfo(imageInfo_)) {
1017         HiLog::Error(LABEL, "write pixels by buffer current pixelmap image info is invalid.");
1018         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
1019     }
1020     if (data_ == nullptr) {
1021         HiLog::Error(LABEL, "write pixels by buffer current pixelmap data is nullptr.");
1022         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
1023     }
1024     errno_t ret = memcpy_s(data_, pixelsSize_, source, pixelsSize_);
1025     if (ret != 0) {
1026         HiLog::Error(LABEL, "write pixels by buffer memcpy to pixelmap data from source fail, error:%{public}d", ret);
1027         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
1028     }
1029     FinishTrace(HITRACE_TAG_ZIMAGE);
1030     return SUCCESS;
1031 }
1032 
WritePixels(const uint32_t & color)1033 bool PixelMap::WritePixels(const uint32_t &color)
1034 {
1035     if (!IsEditable()) {
1036         HiLog::Error(LABEL, "erase pixels by color pixelmap data is not editable.");
1037         return false;
1038     }
1039     if (!ImageUtils::IsValidImageInfo(imageInfo_)) {
1040         HiLog::Error(LABEL, "erase pixels by color current pixelmap image info is invalid.");
1041         return false;
1042     }
1043     if (data_ == nullptr) {
1044         HiLog::Error(LABEL, "erase pixels by color current pixel map data is null.");
1045         return false;
1046     }
1047     ImageInfo srcInfo =
1048         MakeImageInfo(imageInfo_.size.width, imageInfo_.size.height, imageInfo_.pixelFormat, imageInfo_.alphaType);
1049     if (!PixelConvertAdapter::EraseBitmap(data_, rowDataSize_, srcInfo, color)) {
1050         HiLog::Error(LABEL, "erase pixels by color call EraseBitmap fail.");
1051         return false;
1052     }
1053     return true;
1054 }
1055 
GetAllocatorType()1056 AllocatorType PixelMap::GetAllocatorType()
1057 {
1058     return allocatorType_;
1059 }
1060 
GetFd() const1061 void *PixelMap::GetFd() const
1062 {
1063     return context_;
1064 }
1065 
ReleaseMemory(AllocatorType allocType,void * addr,void * context,uint32_t size)1066 void PixelMap::ReleaseMemory(AllocatorType allocType, void *addr, void *context, uint32_t size)
1067 {
1068     if (allocType == AllocatorType::SHARE_MEM_ALLOC) {
1069 #if !defined(_WIN32) && !defined(_APPLE) && !defined(_IOS) &&!defined(_ANDROID)
1070         int *fd = static_cast<int *>(context);
1071         if (addr != nullptr) {
1072             ::munmap(addr, size);
1073         }
1074         if (fd != nullptr) {
1075             ::close(*fd);
1076         }
1077 #endif
1078     } else if (allocType == AllocatorType::HEAP_ALLOC) {
1079         if (addr != nullptr) {
1080             free(addr);
1081             addr = nullptr;
1082         }
1083     }
1084 }
1085 
WriteImageData(Parcel & parcel,size_t size) const1086 bool PixelMap::WriteImageData(Parcel &parcel, size_t size) const
1087 {
1088     const uint8_t *data = data_;
1089     if (data == nullptr) {
1090         HiLog::Error(LABEL, "write to parcel failed, pixel memory is null.");
1091         return false;
1092     }
1093     if (data == nullptr || size > MAX_IMAGEDATA_SIZE) {
1094         return false;
1095     }
1096 
1097     if (!parcel.WriteInt32(size)) {
1098         return false;
1099     }
1100     if (size <= MIN_IMAGEDATA_SIZE) {
1101         return parcel.WriteUnpadBuffer(data, size);
1102     }
1103 #if !defined(_WIN32) && !defined(_APPLE) && !defined(_IOS) &&!defined(_ANDROID)
1104     int fd = AshmemCreate("Parcel ImageData", size);
1105     HiLog::Info(LABEL, "AshmemCreate:[%{public}d].", fd);
1106     if (fd < 0) {
1107         return false;
1108     }
1109 
1110     int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
1111     HiLog::Info(LABEL, "AshmemSetProt:[%{public}d].", result);
1112     if (result < 0) {
1113         ::close(fd);
1114         return false;
1115     }
1116     void *ptr = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1117     if (ptr == MAP_FAILED) {
1118         ::close(fd);
1119         HiLog::Error(LABEL, "WriteImageData map failed, errno:%{public}d", errno);
1120         return false;
1121     }
1122     HiLog::Info(LABEL, "mmap success");
1123 
1124     if (memcpy_s(ptr, size, data, size) != EOK) {
1125         ::munmap(ptr, size);
1126         ::close(fd);
1127         HiLog::Error(LABEL, "WriteImageData memcpy_s error");
1128         return false;
1129     }
1130 
1131     if (!WriteFileDescriptor(parcel, fd)) {
1132         ::munmap(ptr, size);
1133         ::close(fd);
1134         HiLog::Error(LABEL, "WriteImageData WriteFileDescriptor error");
1135         return false;
1136     }
1137     HiLog::Debug(LABEL, "WriteImageData WriteFileDescriptor success");
1138     ::munmap(ptr, size);
1139     ::close(fd);
1140     HiLog::Debug(LABEL, "WriteImageData End");
1141 #endif
1142     return true;
1143 }
1144 
ReadImageData(Parcel & parcel,int32_t bufferSize)1145 uint8_t *PixelMap::ReadImageData(Parcel &parcel, int32_t bufferSize)
1146 {
1147     uint8_t *base = nullptr;
1148     if (static_cast<unsigned int>(bufferSize) <= MIN_IMAGEDATA_SIZE) {
1149         if (bufferSize <= 0) {
1150             HiLog::Error(LABEL, "malloc parameter bufferSize:[%{public}d] error.", bufferSize);
1151             return nullptr;
1152         }
1153 
1154         const uint8_t *ptr = parcel.ReadUnpadBuffer(bufferSize);
1155         if (ptr == nullptr) {
1156             HiLog::Error(LABEL, "read buffer from parcel failed, read buffer addr is null");
1157             return nullptr;
1158         }
1159 
1160         base = static_cast<uint8_t *>(malloc(bufferSize));
1161         if (base == nullptr) {
1162             HiLog::Error(LABEL, "alloc output pixel memory size:[%{public}d] error.", bufferSize);
1163             return nullptr;
1164         }
1165         if (memcpy_s(base, bufferSize, ptr, bufferSize) != 0) {
1166             free(base);
1167             base = nullptr;
1168             HiLog::Error(LABEL, "memcpy pixel data size:[%{public}d] error.", bufferSize);
1169             return nullptr;
1170         }
1171     } else {
1172 #if !defined(_WIN32) && !defined(_APPLE) &&!defined(_IOS) &&!defined(_ANDROID)
1173         int fd = ReadFileDescriptor(parcel);
1174         if (fd < 0) {
1175             HiLog::Error(LABEL, "read fd :[%{public}d] error", fd);
1176             return nullptr;
1177         }
1178         if (bufferSize <= 0 || bufferSize > PIXEL_MAP_MAX_RAM_SIZE) {
1179             HiLog::Error(LABEL, "malloc parameter bufferSize:[%{public}d] error.", bufferSize);
1180             return nullptr;
1181         }
1182 
1183         void *ptr = ::mmap(nullptr, bufferSize, PROT_READ, MAP_SHARED, fd, 0);
1184         if (ptr == MAP_FAILED) {
1185             // do not close fd here. fd will be closed in FileDescriptor, ::close(fd)
1186             HiLog::Error(LABEL, "ReadImageData map failed, errno:%{public}d", errno);
1187             return nullptr;
1188         }
1189 
1190         base = static_cast<uint8_t *>(malloc(bufferSize));
1191         if (base == nullptr) {
1192             ::munmap(ptr, bufferSize);
1193             HiLog::Error(LABEL, "alloc output pixel memory size:[%{public}d] error.", bufferSize);
1194             return nullptr;
1195         }
1196         if (memcpy_s(base, bufferSize, ptr, bufferSize) != 0) {
1197             ::munmap(ptr, bufferSize);
1198             free(base);
1199             base = nullptr;
1200             HiLog::Error(LABEL, "memcpy pixel data size:[%{public}d] error.", bufferSize);
1201             return nullptr;
1202         }
1203 
1204         ReleaseMemory(AllocatorType::SHARE_MEM_ALLOC, ptr, &fd, bufferSize);
1205 #endif
1206     }
1207     return base;
1208 }
1209 
WriteFileDescriptor(Parcel & parcel,int fd)1210 bool PixelMap::WriteFileDescriptor(Parcel &parcel, int fd)
1211 {
1212 #if !defined(_IOS) &&!defined(_ANDROID)
1213     if (fd < 0) {
1214         return false;
1215     }
1216     int dupFd = dup(fd);
1217     if (dupFd < 0) {
1218         return false;
1219     }
1220     sptr<IPCFileDescriptor> descriptor = new IPCFileDescriptor(dupFd);
1221     return parcel.WriteObject<IPCFileDescriptor>(descriptor);
1222 #endif
1223 }
1224 
ReadFileDescriptor(Parcel & parcel)1225 int PixelMap::ReadFileDescriptor(Parcel &parcel)
1226 {
1227 #if !defined(_IOS) &&!defined(_ANDROID)
1228     sptr<IPCFileDescriptor> descriptor = parcel.ReadObject<IPCFileDescriptor>();
1229     if (descriptor == nullptr) {
1230         return -1;
1231     }
1232     int fd = descriptor->GetFd();
1233     if (fd < 0) {
1234         return -1;
1235     }
1236     return dup(fd);
1237 #endif
1238 }
1239 
WriteImageInfo(Parcel & parcel) const1240 bool PixelMap::WriteImageInfo(Parcel &parcel) const
1241 {
1242     if (!parcel.WriteInt32(imageInfo_.size.width)) {
1243         HiLog::Error(LABEL, "write image info width:[%{public}d] to parcel failed.", imageInfo_.size.width);
1244         return false;
1245     }
1246     if (!parcel.WriteInt32(imageInfo_.size.height)) {
1247         HiLog::Error(LABEL, "write image info height:[%{public}d] to parcel failed.", imageInfo_.size.height);
1248         return false;
1249     }
1250     if (!parcel.WriteInt32(static_cast<int32_t>(imageInfo_.pixelFormat))) {
1251         HiLog::Error(LABEL, "write image info pixel format:[%{public}d] to parcel failed.", imageInfo_.pixelFormat);
1252         return false;
1253     }
1254     if (!parcel.WriteInt32(static_cast<int32_t>(imageInfo_.colorSpace))) {
1255         HiLog::Error(LABEL, "write image info color space:[%{public}d] to parcel failed.", imageInfo_.colorSpace);
1256         return false;
1257     }
1258     if (!parcel.WriteInt32(static_cast<int32_t>(imageInfo_.alphaType))) {
1259         HiLog::Error(LABEL, "write image info alpha type:[%{public}d] to parcel failed.", imageInfo_.alphaType);
1260         return false;
1261     }
1262     if (!parcel.WriteInt32(imageInfo_.baseDensity)) {
1263         HiLog::Error(LABEL, "write image info base density:[%{public}d] to parcel failed.", imageInfo_.baseDensity);
1264         return false;
1265     }
1266     return true;
1267 }
1268 
Marshalling(Parcel & parcel) const1269 bool PixelMap::Marshalling(Parcel &parcel) const
1270 {
1271     int32_t PIXEL_MAP_INFO_MAX_LENGTH = 128;
1272     int32_t bufferSize = rowDataSize_ * imageInfo_.size.height;
1273     if (static_cast<size_t>(bufferSize) <= MIN_IMAGEDATA_SIZE &&
1274         static_cast<size_t>(bufferSize + PIXEL_MAP_INFO_MAX_LENGTH) > parcel.GetDataCapacity() &&
1275         !parcel.SetDataCapacity(bufferSize + PIXEL_MAP_INFO_MAX_LENGTH)) {
1276         HiLog::Error(LABEL, "set parcel max capacity:[%{public}d] failed.", bufferSize + PIXEL_MAP_INFO_MAX_LENGTH);
1277         return false;
1278     }
1279     if (!WriteImageInfo(parcel)) {
1280         HiLog::Error(LABEL, "write image info to parcel failed.");
1281         return false;
1282     }
1283 
1284     if (!parcel.WriteInt32(static_cast<int32_t>(allocatorType_))) {
1285         HiLog::Error(LABEL, "write pixel map allocator type:[%{public}d] to parcel failed.",
1286                      allocatorType_);
1287         return false;
1288     }
1289     if (allocatorType_ == AllocatorType::SHARE_MEM_ALLOC) {
1290 #if !defined(_WIN32) && !defined(_APPLE) &&!defined(_IOS) &&!defined(_ANDROID)
1291         if (!parcel.WriteInt32(bufferSize)) {
1292             return false;
1293         }
1294 
1295         int *fd = static_cast<int *>(context_);
1296         if (*fd < 0) {
1297             HiLog::Error(LABEL, "write pixel map failed, fd < 0.");
1298             return false;
1299         }
1300 
1301         if (!WriteFileDescriptor(parcel, *fd)) {
1302             HiLog::Error(LABEL, "write pixel map fd:[%{public}d] to parcel failed.", *fd);
1303             return false;
1304         }
1305 #endif
1306     } else {
1307         if (!WriteImageData(parcel, bufferSize)) {
1308             HiLog::Error(LABEL, "write pixel map buffer to parcel failed.");
1309             return false;
1310         }
1311     }
1312     return true;
1313 }
1314 
ReadImageInfo(Parcel & parcel,ImageInfo & imgInfo)1315 bool PixelMap::ReadImageInfo(Parcel &parcel, ImageInfo &imgInfo)
1316 {
1317     imgInfo.size.width = parcel.ReadInt32();
1318     HiLog::Debug(LABEL, "read pixel map width:[%{public}d] to parcel.", imgInfo.size.width);
1319     imgInfo.size.height = parcel.ReadInt32();
1320     HiLog::Debug(LABEL, "read pixel map height:[%{public}d] to parcel.", imgInfo.size.height);
1321     imgInfo.pixelFormat = static_cast<PixelFormat>(parcel.ReadInt32());
1322     HiLog::Debug(LABEL, "read pixel map pixelFormat:[%{public}d] to parcel.", imgInfo.pixelFormat);
1323     imgInfo.colorSpace = static_cast<ColorSpace>(parcel.ReadInt32());
1324     HiLog::Debug(LABEL, "read pixel map colorSpace:[%{public}d] to parcel.", imgInfo.colorSpace);
1325     imgInfo.alphaType = static_cast<AlphaType>(parcel.ReadInt32());
1326     HiLog::Debug(LABEL, "read pixel map alphaType:[%{public}d] to parcel.", imgInfo.alphaType);
1327     imgInfo.baseDensity = parcel.ReadInt32();
1328     return true;
1329 }
1330 
Unmarshalling(Parcel & parcel)1331 PixelMap *PixelMap::Unmarshalling(Parcel &parcel)
1332 {
1333     PixelMap *pixelMap = new PixelMap();
1334     if (pixelMap == nullptr) {
1335         return nullptr;
1336     }
1337 
1338     ImageInfo imgInfo;
1339     if (!pixelMap->ReadImageInfo(parcel, imgInfo)) {
1340         HiLog::Error(LABEL, "read imageInfo fail");
1341         delete pixelMap;
1342         return nullptr;
1343     }
1344 
1345     AllocatorType allocType = static_cast<AllocatorType>(parcel.ReadInt32());
1346     int32_t bufferSize = parcel.ReadInt32();
1347     int32_t bytesPerPixel = ImageUtils::GetPixelBytes(imgInfo.pixelFormat);
1348     if (bytesPerPixel == 0) {
1349         HiLog::Error(LABEL, "unmarshalling get bytes by per pixel fail.");
1350         return nullptr;
1351     }
1352     int32_t rowDataSize = 0;
1353     if (imgInfo.pixelFormat == PixelFormat::ALPHA_8) {
1354         rowDataSize = bytesPerPixel * ((imgInfo.size.width + FILL_NUMBER) / ALIGN_NUMBER * ALIGN_NUMBER);
1355         HiLog::Info(LABEL, "ALPHA_8 rowDataSize_ %{public}d.", rowDataSize);
1356     } else {
1357         rowDataSize = bytesPerPixel * imgInfo.size.width;
1358     }
1359     if (bufferSize != rowDataSize * imgInfo.size.height) {
1360         HiLog::Error(LABEL, "unmarshalling bufferSize parcelling error");
1361         return nullptr;
1362     }
1363     uint8_t *base = nullptr;
1364     void *context = nullptr;
1365     if (allocType == AllocatorType::SHARE_MEM_ALLOC) {
1366 #if !defined(_WIN32) && !defined(_APPLE) && !defined(_IOS) &&!defined(_ANDROID)
1367         int fd = ReadFileDescriptor(parcel);
1368         if (fd < 0) {
1369             HiLog::Error(LABEL, "fd < 0");
1370             delete pixelMap;
1371             return nullptr;
1372         }
1373         void* ptr = ::mmap(nullptr, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1374         if (ptr == MAP_FAILED) {
1375             ptr = ::mmap(nullptr, bufferSize, PROT_READ, MAP_SHARED, fd, 0);
1376             if (ptr == MAP_FAILED) {
1377                 ::close(fd);
1378                 delete pixelMap;
1379                 HiLog::Error(LABEL, "shared memory map in memalloc failed, errno:%{public}d", errno);
1380                 return nullptr;
1381             }
1382         }
1383         context = new int32_t();
1384         if (context == nullptr) {
1385             ::munmap(ptr, bufferSize);
1386             ::close(fd);
1387             delete pixelMap;
1388             return nullptr;
1389         }
1390         *static_cast<int32_t *>(context) = fd;
1391         base = static_cast<uint8_t *>(ptr);
1392 #endif
1393     } else {
1394         base = ReadImageData(parcel, bufferSize);
1395         if (base == nullptr) {
1396             HiLog::Error(LABEL, "get pixel memory size:[%{public}d] error.", bufferSize);
1397             delete pixelMap;
1398             return nullptr;
1399         }
1400     }
1401 
1402     uint32_t ret = pixelMap->SetImageInfo(imgInfo);
1403     if (ret != SUCCESS) {
1404         ReleaseMemory(allocType, base, context, bufferSize);
1405         if (context != nullptr) {
1406             delete static_cast<int32_t *>(context);
1407         }
1408         delete pixelMap;
1409         HiLog::Error(LABEL, "create pixel map from parcel failed, set image info error.");
1410         return nullptr;
1411     }
1412     pixelMap->SetPixelsAddr(base, context, bufferSize, allocType, nullptr);
1413     return pixelMap;
1414 }
1415 
GetNamedAlphaType(const AlphaType alphaType)1416 static const string GetNamedAlphaType(const AlphaType alphaType)
1417 {
1418     switch (alphaType) {
1419         case AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN:
1420             return "Alpha Type Unknown";
1421         case AlphaType::IMAGE_ALPHA_TYPE_OPAQUE:
1422             return "Alpha Type Opaque";
1423         case AlphaType::IMAGE_ALPHA_TYPE_PREMUL:
1424             return "Alpha Type Premul";
1425         case AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL:
1426             return "Alpha Type Unpremul";
1427         default:
1428             return "Alpha Type Unknown";
1429     }
1430     return "Alpha Type Unknown";
1431 }
1432 
GetNamedPixelFormat(const PixelFormat pixelFormat)1433 static const string GetNamedPixelFormat(const PixelFormat pixelFormat)
1434 {
1435     switch (pixelFormat) {
1436         case PixelFormat::UNKNOWN:
1437             return "Pixel Format UNKNOWN";
1438         case PixelFormat::RGB_565:
1439             return "Pixel Format RGB_565";
1440         case PixelFormat::RGB_888:
1441             return "Pixel Format RGB_888";
1442         case PixelFormat::NV21:
1443             return "Pixel Format NV21";
1444         case PixelFormat::NV12:
1445             return "Pixel Format NV12";
1446         case PixelFormat::CMYK:
1447             return "Pixel Format CMYK";
1448         case PixelFormat::ARGB_8888:
1449             return "Pixel Format ARGB_8888";
1450         case PixelFormat::ALPHA_8:
1451             return "Pixel Format ALPHA_8";
1452         case PixelFormat::RGBA_8888:
1453             return "Pixel Format RGBA_8888";
1454         case PixelFormat::BGRA_8888:
1455             return "Pixel Format BGRA_8888";
1456         case PixelFormat::RGBA_F16:
1457             return "Pixel Format RGBA_F16";
1458         default:
1459             return "Pixel Format UNKNOWN";
1460     }
1461     return "Pixel Format UNKNOWN";
1462 }
1463 
1464 constexpr uint8_t HALF_LOW_BYTE = 0;
1465 constexpr uint8_t HALF_HIGH_BYTE = 1;
1466 
HalfTranslate(const uint8_t * ui)1467 static float HalfTranslate(const uint8_t* ui)
1468 {
1469     return HalfToFloat(U8ToU16(ui[HALF_HIGH_BYTE], ui[HALF_LOW_BYTE]));
1470 }
1471 
HalfTranslate(const float pixel,uint8_t * ui)1472 static void HalfTranslate(const float pixel, uint8_t* ui)
1473 {
1474     uint16_t val = FloatToHalf(pixel);
1475     ui[HALF_LOW_BYTE] = static_cast<uint8_t>((val >> SHIFT_8_BIT) & UINT8_MAX);
1476     ui[HALF_HIGH_BYTE] = static_cast<uint8_t>(val & UINT8_MAX);
1477 }
1478 constexpr uint8_t RGBA_F16_R_OFFSET = 0;
1479 constexpr uint8_t RGBA_F16_G_OFFSET = 2;
1480 constexpr uint8_t RGBA_F16_B_OFFSET = 4;
1481 constexpr uint8_t RGBA_F16_A_OFFSET = 6;
1482 
1483 static constexpr float FLOAT_NUMBER_NEAR_ZERO = 0.000001;
1484 static constexpr float FLOAT_ZERO = 0.0f;
ProcessPremulF16Pixel(float mulPixel,float alpha,const float percent)1485 static float ProcessPremulF16Pixel(float mulPixel, float alpha, const float percent)
1486 {
1487     if (alpha < FLOAT_NUMBER_NEAR_ZERO && alpha > -FLOAT_NUMBER_NEAR_ZERO) {
1488         return FLOAT_ZERO;
1489     }
1490     float res = mulPixel * percent / alpha;
1491     return res > MAX_HALF? MAX_HALF: res;
1492 }
1493 
SetF16PixelAlpha(uint8_t * pixel,const float percent,bool isPixelPremul)1494 static void SetF16PixelAlpha(uint8_t *pixel, const float percent, bool isPixelPremul)
1495 {
1496     float A = HalfTranslate(pixel + RGBA_F16_A_OFFSET);
1497     if (isPixelPremul) {
1498         float R = HalfTranslate(pixel + RGBA_F16_R_OFFSET);
1499         float G = HalfTranslate(pixel + RGBA_F16_G_OFFSET);
1500         float B = HalfTranslate(pixel + RGBA_F16_B_OFFSET);
1501         R = ProcessPremulF16Pixel(R, A, percent);
1502         G = ProcessPremulF16Pixel(G, A, percent);
1503         B = ProcessPremulF16Pixel(B, A, percent);
1504         HalfTranslate(R, pixel + RGBA_F16_R_OFFSET);
1505         HalfTranslate(G, pixel + RGBA_F16_G_OFFSET);
1506         HalfTranslate(B, pixel + RGBA_F16_B_OFFSET);
1507     }
1508     A = percent * MAX_HALF;
1509     HalfTranslate(A, pixel + RGBA_F16_A_OFFSET);
1510 }
1511 
1512 static constexpr uint8_t U_ZERO = 0;
ProcessPremulPixel(uint8_t mulPixel,uint8_t alpha,const float percent)1513 static uint8_t ProcessPremulPixel(uint8_t mulPixel, uint8_t alpha, const float percent)
1514 {
1515     // mP = oP * oAlpha / UINT8_MAX
1516     // => oP = mP * UINT8_MAX / oAlpha
1517     // nP = oP * percent
1518     // => nP = mP * UINT8_MAX * percent / oAlpha
1519     if (alpha == 0) {
1520         return U_ZERO;
1521     }
1522     float nPixel = mulPixel * percent * UINT8_MAX / alpha;
1523     if ((nPixel + HALF_ONE) >= UINT8_MAX) {
1524         return UINT8_MAX;
1525     }
1526     return static_cast<uint8_t>(nPixel + HALF_ONE);
1527 }
1528 
SetUintPixelAlpha(uint8_t * pixel,const float percent,uint8_t pixelByte,int8_t alphaIndex,bool isPixelPremul)1529 static void SetUintPixelAlpha(uint8_t *pixel, const float percent,
1530     uint8_t pixelByte, int8_t alphaIndex, bool isPixelPremul)
1531 {
1532     if (isPixelPremul) {
1533         for (int32_t pixelIndex = 0; pixelIndex < pixelByte; pixelIndex++) {
1534             if (pixelIndex != alphaIndex) {
1535                 pixel[pixelIndex] = ProcessPremulPixel(pixel[pixelIndex],
1536                     pixel[alphaIndex], percent);
1537             }
1538         }
1539     }
1540     pixel[alphaIndex] = static_cast<uint8_t>(UINT8_MAX * percent + HALF_ONE);
1541 }
1542 
DoSetAlpha(const PixelFormat pixelFormat,uint8_t * pixels,uint32_t pixelsSize,uint8_t pixelByte,int8_t alphaIndex,const float percent,bool isPixelPremul)1543 static uint32_t DoSetAlpha(const PixelFormat pixelFormat, uint8_t *pixels,
1544     uint32_t pixelsSize, uint8_t pixelByte, int8_t alphaIndex,
1545     const float percent, bool isPixelPremul)
1546 {
1547     if (alphaIndex == INVALID_ALPHA_INDEX) {
1548         HiLog::Error(LABEL, "Invaild alpha index");
1549         return ERR_IMAGE_INVALID_PARAMETER;
1550     }
1551 
1552     if ((pixelFormat == PixelFormat::ALPHA_8 && pixelByte != ALPHA_BYTES) ||
1553         (pixelFormat == PixelFormat::RGBA_F16 && pixelByte != RGBA_F16_BYTES)) {
1554         HiLog::Error(LABEL, "Pixel format %{public}s mismatch pixelByte %{public}d",
1555             GetNamedPixelFormat(pixelFormat).c_str(), pixelByte);
1556         return ERR_IMAGE_INVALID_PARAMETER;
1557     }
1558     for (uint32_t i = 0; i < pixelsSize;) {
1559         uint8_t* pixel = pixels + i;
1560         if (pixelFormat == PixelFormat::RGBA_F16) {
1561             SetF16PixelAlpha(pixel, percent, isPixelPremul);
1562         } else {
1563             SetUintPixelAlpha(pixel, percent, pixelByte, alphaIndex, isPixelPremul);
1564         }
1565         i += pixelByte;
1566     }
1567     return SUCCESS;
1568 }
1569 
SetAlpha(const float percent)1570 uint32_t PixelMap::SetAlpha(const float percent)
1571 {
1572     auto alphaType = GetAlphaType();
1573     if (AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN == alphaType ||
1574         AlphaType::IMAGE_ALPHA_TYPE_OPAQUE == alphaType) {
1575         HiLog::Error(LABEL,
1576             "Could not set alpha on %{public}s",
1577             GetNamedAlphaType(alphaType).c_str());
1578         return ERR_IMAGE_DATA_UNSUPPORT;
1579     }
1580 
1581     if (percent <= 0 || percent > 1) {
1582         HiLog::Error(LABEL,
1583             "Set alpha input should (0 < input <= 1). Current input %{public}f",
1584             percent);
1585         return ERR_IMAGE_INVALID_PARAMETER;
1586     }
1587 
1588     bool pixelPremul = alphaType == AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
1589     int8_t alphaIndex = INVALID_ALPHA_INDEX;
1590     auto pixelFormat = GetPixelFormat();
1591     switch (pixelFormat) {
1592         case PixelFormat::ARGB_8888:
1593         case PixelFormat::ALPHA_8: {
1594             alphaIndex = ARGB_ALPHA_INDEX;
1595             break;
1596         }
1597         case PixelFormat::RGBA_8888:
1598         case PixelFormat::BGRA_8888:
1599         case PixelFormat::RGBA_F16: {
1600             alphaIndex = BGRA_ALPHA_INDEX;
1601             break;
1602         }
1603         default: {
1604             HiLog::Error(LABEL,
1605                 "Could not set alpha on %{public}s",
1606                 GetNamedPixelFormat(pixelFormat).c_str());
1607             return ERR_IMAGE_DATA_UNSUPPORT;
1608         }
1609     }
1610     return DoSetAlpha(pixelFormat, data_,
1611         GetByteCount(), pixelBytes_,
1612         alphaIndex, percent, pixelPremul);
1613 }
1614 
scale(float xAxis,float yAxis)1615 void PixelMap::scale(float xAxis, float yAxis)
1616 {
1617     PostProc postProc;
1618     if (!postProc.ScalePixelMap(xAxis, yAxis, *this)) {
1619         HiLog::Error(LABEL, "scale fail");
1620     }
1621 }
translate(float xAxis,float yAxis)1622 void PixelMap::translate(float xAxis, float yAxis)
1623 {
1624     PostProc postProc;
1625     if (!postProc.TranslatePixelMap(xAxis, yAxis, *this)) {
1626         HiLog::Error(LABEL, "translate fail");
1627     }
1628 }
rotate(float degrees)1629 void PixelMap::rotate(float degrees)
1630 {
1631     PostProc postProc;
1632     if (!postProc.RotatePixelMap(degrees, *this)) {
1633         HiLog::Error(LABEL, "rotate fail");
1634     }
1635 }
flip(bool xAxis,bool yAxis)1636 void PixelMap::flip(bool xAxis, bool yAxis)
1637 {
1638     if (xAxis == false && yAxis == false) {
1639         return;
1640     }
1641     scale(xAxis?-1:1, yAxis?-1:1);
1642 }
crop(const Rect & rect)1643 uint32_t PixelMap::crop(const Rect &rect)
1644 {
1645     PostProc postProc;
1646     auto cropValue = PostProc::GetCropValue(rect, imageInfo_.size);
1647     if (cropValue == CropValue::NOCROP) {
1648         return SUCCESS;
1649     }
1650 
1651     if (cropValue == CropValue::INVALID) {
1652         HiLog::Error(LABEL, "Invalid crop rect");
1653         return ERR_IMAGE_CROP;
1654     }
1655 
1656     ImageInfo dstImageInfo = {
1657         .size = {
1658             .width = rect.width,
1659             .height = rect.height,
1660         },
1661         .pixelFormat = imageInfo_.pixelFormat,
1662         .colorSpace = imageInfo_.colorSpace,
1663         .alphaType = imageInfo_.alphaType,
1664         .baseDensity = imageInfo_.baseDensity,
1665     };
1666     return postProc.ConvertProc(rect, dstImageInfo, *this, imageInfo_);
1667 }
1668 
1669 #ifdef IMAGE_COLORSPACE_FLAG
InnerSetColorSpace(const OHOS::ColorManager::ColorSpace & grColorSpace)1670     void PixelMap::InnerSetColorSpace(const OHOS::ColorManager::ColorSpace &grColorSpace)
1671     {
1672         grColorSpace_ = std::make_shared<OHOS::ColorManager::ColorSpace>(grColorSpace.ToSkColorSpace());
1673     }
1674 
InnerGetGrColorSpace()1675     OHOS::ColorManager::ColorSpace PixelMap::InnerGetGrColorSpace()
1676     {
1677         if (grColorSpace_ == nullptr) {
1678             grColorSpace_ =
1679                 std::make_shared<OHOS::ColorManager::ColorSpace>(OHOS::ColorManager::ColorSpaceName::SRGB);
1680         }
1681         return *grColorSpace_;
1682     }
1683 #endif
1684 } // namespace Media
1685 } // namespace OHOS
1686