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 ®ion)
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 ®ion, 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 ®ion)
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