• 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 #ifndef _WIN32
28 #include "securec.h"
29 #else
30 #include "memory.h"
31 #endif
32 
33 #if !defined(_WIN32) && !defined(_APPLE)
34 #include <sys/mman.h>
35 #include "ashmem.h"
36 #include "ipc_file_descriptor.h"
37 #endif
38 
39 namespace OHOS {
40 namespace Media {
41 using namespace OHOS::HiviewDFX;
42 using namespace std;
43 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_IMAGE, "PixelMap" };
44 constexpr int32_t MAX_DIMENSION = INT32_MAX >> 2;
45 constexpr uint8_t FOUR_BYTE_SHIFT = 2;
46 constexpr uint8_t BGRA_ALPHA_INDEX = 3;
47 constexpr uint8_t BGRA_BYTES = 4;
48 constexpr uint8_t PER_PIXEL_LEN = 1;
49 
50 constexpr uint8_t FILL_NUMBER = 3;
51 constexpr uint8_t ALIGN_NUMBER = 4;
52 
~PixelMap()53 PixelMap::~PixelMap()
54 {
55     FreePixelMap();
56 }
57 
FreePixelMap()58 void PixelMap::FreePixelMap()
59 {
60     if (data_ == nullptr) {
61         return;
62     }
63     switch (allocatorType_) {
64         case AllocatorType::HEAP_ALLOC: {
65             free(data_);
66             data_ = nullptr;
67             break;
68         }
69         case AllocatorType::CUSTOM_ALLOC: {
70             if (custFreePixelMap_ != nullptr) {
71                 custFreePixelMap_(data_, context_, pixelsSize_);
72             }
73             data_ = nullptr;
74             context_ = nullptr;
75             break;
76         }
77         case AllocatorType::SHARE_MEM_ALLOC: {
78             ReleaseSharedMemory(data_, context_, pixelsSize_);
79             data_ = nullptr;
80             context_ = nullptr;
81             break;
82         }
83         default: {
84             HiLog::Error(LABEL, "unknown allocator type:[%{public}d].", allocatorType_);
85             return;
86         }
87     }
88 }
89 
ReleaseSharedMemory(void * addr,void * context,uint32_t size)90 void PixelMap::ReleaseSharedMemory(void *addr, void *context, uint32_t size)
91 {
92 #if !defined(_WIN32) && !defined(_APPLE)
93     int *fd = static_cast<int *>(context);
94     if (addr != nullptr) {
95         ::munmap(addr, size);
96     }
97     if (fd != nullptr) {
98         ::close(*fd);
99         delete fd;
100     }
101 #endif
102 }
103 
SetPixelsAddr(void * addr,void * context,uint32_t size,AllocatorType type,CustomFreePixelMap func)104 void PixelMap::SetPixelsAddr(void *addr, void *context, uint32_t size, AllocatorType type, CustomFreePixelMap func)
105 {
106     FreePixelMap();
107     data_ = static_cast<uint8_t *>(addr);
108     context_ = context;
109     pixelsSize_ = size;
110     allocatorType_ = type;
111     custFreePixelMap_ = func;
112 }
113 
Create(const uint32_t * colors,uint32_t colorLength,const InitializationOptions & opts)114 unique_ptr<PixelMap> PixelMap::Create(const uint32_t *colors, uint32_t colorLength, const InitializationOptions &opts)
115 {
116     HiLog::Info(LABEL, "PixelMap::Create1 enter");
117     return Create(colors, colorLength, 0, opts.size.width, opts);
118 }
119 
Create(const uint32_t * colors,uint32_t colorLength,int32_t offset,int32_t stride,const InitializationOptions & opts)120 unique_ptr<PixelMap> PixelMap::Create(const uint32_t *colors, uint32_t colorLength, int32_t offset, int32_t stride,
121                                       const InitializationOptions &opts)
122 {
123     HiLog::Info(LABEL, "PixelMap::Create2 enter");
124     if (!CheckParams(colors, colorLength, offset, stride, opts)) {
125         return nullptr;
126     }
127     unique_ptr<PixelMap> dstPixelMap = make_unique<PixelMap>();
128     if (dstPixelMap == nullptr) {
129         HiLog::Error(LABEL, "create pixelMap pointer fail");
130         return nullptr;
131     }
132 
133     ImageInfo srcImageInfo =
134         MakeImageInfo(stride, opts.size.height, PixelFormat::BGRA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
135     PixelFormat dstPixelFormat = (opts.pixelFormat == PixelFormat::UNKNOWN ? PixelFormat::RGBA_8888 : opts.pixelFormat);
136     AlphaType dstAlphaType =
137         (opts.alphaType == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) ? AlphaType::IMAGE_ALPHA_TYPE_PREMUL : opts.alphaType;
138     dstAlphaType = ImageUtils::GetValidAlphaTypeByFormat(dstAlphaType, dstPixelFormat);
139     ImageInfo dstImageInfo = MakeImageInfo(opts.size.width, opts.size.height, dstPixelFormat, dstAlphaType);
140     if (dstPixelMap->SetImageInfo(dstImageInfo) != SUCCESS) {
141         HiLog::Error(LABEL, "set image info fail");
142         return nullptr;
143     }
144     uint32_t bufferSize = dstPixelMap->GetByteCount();
145     if (bufferSize == 0) {
146         HiLog::Error(LABEL, "malloc parameter is zero");
147         return nullptr;
148     }
149     void *dstPixels = malloc(bufferSize);
150     if (dstPixels == nullptr) {
151         HiLog::Error(LABEL, "allocate memory size %{public}u fail", bufferSize);
152         return nullptr;
153     }
154 
155     Position dstPosition;
156     if (!PixelConvertAdapter::WritePixelsConvert(reinterpret_cast<const void *>(colors + offset),
157         static_cast<uint32_t>(stride) << FOUR_BYTE_SHIFT, srcImageInfo,
158         dstPixels, dstPosition, dstPixelMap->GetRowBytes(), dstImageInfo)) {
159         HiLog::Error(LABEL, "pixel convert in adapter failed.");
160         free(dstPixels);
161         dstPixels = nullptr;
162         return nullptr;
163     }
164     dstPixelMap->SetEditable(opts.editable);
165     dstPixelMap->SetPixelsAddr(dstPixels, nullptr, bufferSize, AllocatorType::HEAP_ALLOC, nullptr);
166     return dstPixelMap;
167 }
168 
CheckParams(const uint32_t * colors,uint32_t colorLength,int32_t offset,int32_t stride,const InitializationOptions & opts)169 bool PixelMap::CheckParams(const uint32_t *colors, uint32_t colorLength, int32_t offset, int32_t stride,
170                            const InitializationOptions &opts)
171 {
172     if (colors == nullptr || colorLength <= 0 || colorLength > PIXEL_MAP_MAX_RAM_SIZE) {
173         HiLog::Error(LABEL, "colors invalid");
174         return false;
175     }
176     int32_t dstWidth = opts.size.width;
177     int32_t dstHeight = opts.size.height;
178     if (dstWidth <= 0 || dstHeight <= 0) {
179         HiLog::Error(LABEL, "initial options size invalid");
180         return false;
181     }
182     if (stride < dstWidth) {
183         HiLog::Error(LABEL, "stride: %{public}d must >= width: %{public}d", stride, dstWidth);
184         return false;
185     }
186     if (stride > MAX_DIMENSION) {
187         HiLog::Error(LABEL, "stride %{public}d is out of range", stride);
188         return false;
189     }
190     int64_t lastLine = static_cast<int64_t>(dstHeight - 1) * stride + offset;
191     if (offset < 0 || static_cast<int64_t>(offset) + dstWidth > colorLength || lastLine + dstWidth > colorLength) {
192         HiLog::Error(LABEL, "colors length: %{public}u, offset: %{public}d, stride: %{public}d  is invalid",
193                      colorLength, offset, stride);
194         return false;
195     }
196     return true;
197 }
198 
Create(const InitializationOptions & opts)199 unique_ptr<PixelMap> PixelMap::Create(const InitializationOptions &opts)
200 {
201     HiLog::Info(LABEL, "PixelMap::Create3 enter");
202     unique_ptr<PixelMap> dstPixelMap = make_unique<PixelMap>();
203     if (dstPixelMap == nullptr) {
204         HiLog::Error(LABEL, "create pixelMap pointer fail");
205         return nullptr;
206     }
207     PixelFormat dstPixelFormat = (opts.pixelFormat == PixelFormat::UNKNOWN ? PixelFormat::RGBA_8888 : opts.pixelFormat);
208     AlphaType dstAlphaType =
209         (opts.alphaType == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) ? AlphaType::IMAGE_ALPHA_TYPE_PREMUL : opts.alphaType;
210     dstAlphaType = ImageUtils::GetValidAlphaTypeByFormat(dstAlphaType, dstPixelFormat);
211     ImageInfo dstImageInfo = MakeImageInfo(opts.size.width, opts.size.height, dstPixelFormat, dstAlphaType);
212     if (dstPixelMap->SetImageInfo(dstImageInfo) != SUCCESS) {
213         HiLog::Error(LABEL, "set image info fail");
214         return nullptr;
215     }
216     uint32_t bufferSize = dstPixelMap->GetByteCount();
217     if (bufferSize <= 0) {
218         HiLog::Error(LABEL, "calloc parameter bufferSize:[%{public}d] error.", bufferSize);
219         return nullptr;
220     }
221     uint8_t *dstPixels = static_cast<uint8_t *>(calloc(bufferSize, 1));
222     if (dstPixels == nullptr) {
223         HiLog::Error(LABEL, "allocate memory size %{public}u fail", bufferSize);
224         return nullptr;
225     }
226     // update alpha opaque
227     UpdatePixelsAlpha(dstImageInfo.alphaType, dstImageInfo.pixelFormat, dstPixels, *dstPixelMap.get());
228     dstPixelMap->SetPixelsAddr(dstPixels, nullptr, bufferSize, AllocatorType::HEAP_ALLOC, nullptr);
229     dstPixelMap->SetEditable(opts.editable);
230     return dstPixelMap;
231 }
232 
UpdatePixelsAlpha(const AlphaType & alphaType,const PixelFormat & pixelFormat,uint8_t * dstPixels,PixelMap dstPixelMap)233 void PixelMap::UpdatePixelsAlpha(const AlphaType &alphaType, const PixelFormat &pixelFormat, uint8_t *dstPixels,
234                                  PixelMap dstPixelMap)
235 {
236     if (alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE) {
237         int8_t alphaIndex = -1;
238         if (pixelFormat == PixelFormat::RGBA_8888 || pixelFormat == PixelFormat::BGRA_8888) {
239             alphaIndex = BGRA_ALPHA_INDEX;
240         } else if (pixelFormat == PixelFormat::ARGB_8888) {
241             alphaIndex = 0;
242         }
243         if (alphaIndex != -1) {
244             uint8_t pixelBytes = dstPixelMap.GetPixelBytes();
245             uint32_t bufferSize = dstPixelMap.GetByteCount();
246             uint32_t i = alphaIndex;
247             while (i < bufferSize) {
248                 dstPixels[i] = ALPHA_OPAQUE;
249                 i += pixelBytes;
250             }
251         }
252     }
253 }
254 
Create(PixelMap & source,const InitializationOptions & opts)255 unique_ptr<PixelMap> PixelMap::Create(PixelMap &source, const InitializationOptions &opts)
256 {
257     HiLog::Info(LABEL, "PixelMap::Create4 enter");
258     Rect rect;
259     return Create(source, rect, opts);
260 }
261 
Create(PixelMap & source,const Rect & srcRect,const InitializationOptions & opts)262 unique_ptr<PixelMap> PixelMap::Create(PixelMap &source, const Rect &srcRect, const InitializationOptions &opts)
263 {
264     HiLog::Info(LABEL, "PixelMap::Create5 enter");
265     ImageInfo srcImageInfo;
266     source.GetImageInfo(srcImageInfo);
267     PostProc postProc;
268     Rect sRect = srcRect;
269     CropValue cropType = PostProc::ValidCropValue(sRect, srcImageInfo.size);
270     if (cropType == CropValue::INVALID) {
271         HiLog::Error(LABEL, "src crop range is invalid");
272         return nullptr;
273     }
274     ImageInfo dstImageInfo;
275     InitDstImageInfo(opts, srcImageInfo, dstImageInfo);
276     Size targetSize = dstImageInfo.size;
277     // use source if match
278     bool isHasConvert = postProc.HasPixelConvert(srcImageInfo, dstImageInfo);
279     if (opts.useSourceIfMatch && !source.IsEditable() && !opts.editable && (cropType == CropValue::NOCROP) &&
280         !isHasConvert && IsSameSize(srcImageInfo.size, dstImageInfo.size)) {
281         source.useSourceAsResponse_ = true;
282         return unique_ptr<PixelMap>(&source);
283     }
284     unique_ptr<PixelMap> dstPixelMap = make_unique<PixelMap>();
285     if (dstPixelMap == nullptr) {
286         HiLog::Error(LABEL, "create pixelmap pointer fail");
287         return nullptr;
288     }
289     if (cropType == CropValue::VALID) {
290         dstImageInfo.size.width = sRect.width;
291         dstImageInfo.size.height = sRect.height;
292     } else {
293         dstImageInfo.size = srcImageInfo.size;
294     }
295     if (dstPixelMap->SetImageInfo(dstImageInfo) != SUCCESS) {
296         return nullptr;
297     }
298     // dst pixelmap is source crop and convert pixelmap
299     if ((cropType == CropValue::VALID) || isHasConvert) {
300         if (!SourceCropAndConvert(source, srcImageInfo, dstImageInfo, sRect, *dstPixelMap.get())) {
301             return nullptr;
302         }
303     } else {
304         // only maybe size changed, copy source as scale operation
305         if (!CopyPixelMap(source, *dstPixelMap.get())) {
306             return nullptr;
307         }
308     }
309     if (!ScalePixelMap(targetSize, dstImageInfo.size, opts.scaleMode, *dstPixelMap.get())) {
310         return nullptr;
311     }
312     dstPixelMap->SetEditable(opts.editable);
313     return dstPixelMap;
314 }
315 
SourceCropAndConvert(PixelMap & source,const ImageInfo & srcImageInfo,const ImageInfo & dstImageInfo,const Rect & srcRect,PixelMap & dstPixelMap)316 bool PixelMap::SourceCropAndConvert(PixelMap &source, const ImageInfo &srcImageInfo, const ImageInfo &dstImageInfo,
317                                     const Rect &srcRect, PixelMap &dstPixelMap)
318 {
319     uint32_t bufferSize = dstPixelMap.GetByteCount();
320     if (bufferSize <= 0) {
321         HiLog::Error(LABEL, "malloc parameter bufferSize:[%{public}d] error.", bufferSize);
322         return false;
323     }
324     void *dstPixels = malloc(bufferSize);
325     if (dstPixels == nullptr) {
326         HiLog::Error(LABEL, "allocate memory size %{public}u fail", bufferSize);
327         return false;
328     }
329 
330     Position srcPosition{ srcRect.left, srcRect.top };
331     if (!PixelConvertAdapter::ReadPixelsConvert(source.GetPixels(), srcPosition, source.GetRowBytes(), srcImageInfo,
332         dstPixels, dstPixelMap.GetRowBytes(), dstImageInfo)) {
333         HiLog::Error(LABEL, "pixel convert in adapter failed.");
334         free(dstPixels);
335         dstPixels = nullptr;
336         return false;
337     }
338     dstPixelMap.SetPixelsAddr(dstPixels, nullptr, bufferSize, AllocatorType::HEAP_ALLOC, nullptr);
339     return true;
340 }
341 
ScalePixelMap(const Size & targetSize,const Size & dstSize,const ScaleMode & scaleMode,PixelMap & dstPixelMap)342 bool PixelMap::ScalePixelMap(const Size &targetSize, const Size &dstSize, const ScaleMode &scaleMode,
343                              PixelMap &dstPixelMap)
344 {
345     if (dstSize.width == targetSize.width && dstSize.height == targetSize.height) {
346         return true;
347     }
348     PostProc postProc;
349     if (scaleMode == ScaleMode::FIT_TARGET_SIZE) {
350         if (!postProc.ScalePixelMap(targetSize, dstPixelMap)) {
351             HiLog::Error(LABEL, "scale FIT_TARGET_SIZE fail");
352             return false;
353         }
354     }
355     if (scaleMode == ScaleMode::CENTER_CROP) {
356         if (!postProc.CenterScale(targetSize, dstPixelMap)) {
357             HiLog::Error(LABEL, "scale CENTER_CROP fail");
358             return false;
359         }
360     }
361     return true;
362 }
363 
InitDstImageInfo(const InitializationOptions & opts,const ImageInfo & srcImageInfo,ImageInfo & dstImageInfo)364 void PixelMap::InitDstImageInfo(const InitializationOptions &opts, const ImageInfo &srcImageInfo,
365                                 ImageInfo &dstImageInfo)
366 {
367     dstImageInfo.size = opts.size;
368     if (dstImageInfo.size.width == 0 && dstImageInfo.size.height == 0) {
369         dstImageInfo.size = srcImageInfo.size;
370     }
371     dstImageInfo.pixelFormat = opts.pixelFormat;
372     if (dstImageInfo.pixelFormat == PixelFormat::UNKNOWN) {
373         dstImageInfo.pixelFormat = srcImageInfo.pixelFormat;
374     }
375     dstImageInfo.alphaType = opts.alphaType;
376     if (dstImageInfo.alphaType == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
377         dstImageInfo.alphaType = srcImageInfo.alphaType;
378     }
379 }
380 
CopyPixelMap(PixelMap & source,PixelMap & dstPixelMap)381 bool PixelMap::CopyPixelMap(PixelMap &source, PixelMap &dstPixelMap)
382 {
383     uint32_t bufferSize = source.GetByteCount();
384     if (source.GetPixels() == nullptr) {
385         HiLog::Error(LABEL, "source pixelMap data invalid");
386         return false;
387     }
388     if (bufferSize <= 0) {
389         HiLog::Error(LABEL, "malloc parameter bufferSize:[%{public}d] error.", bufferSize);
390         return false;
391     }
392     uint8_t *dstPixels = static_cast<uint8_t *>(malloc(bufferSize));
393     if (dstPixels == nullptr) {
394         HiLog::Error(LABEL, "allocate memory size %{public}u fail", bufferSize);
395         return false;
396     }
397     errno_t errRet = memcpy_s(dstPixels, bufferSize, source.GetPixels(), bufferSize);
398     if (errRet != 0) {
399         HiLog::Error(LABEL, "copy source memory size %{public}u fail, errorCode = %{public}d", bufferSize, errRet);
400         free(dstPixels);
401         dstPixels = nullptr;
402         return false;
403     }
404     dstPixelMap.SetPixelsAddr(dstPixels, nullptr, bufferSize, AllocatorType::HEAP_ALLOC, nullptr);
405     return true;
406 }
407 
IsSameSize(const Size & src,const Size & dst)408 bool PixelMap::IsSameSize(const Size &src, const Size &dst)
409 {
410     return (src.width == dst.width) && (src.height == dst.height);
411 }
412 
GetPixelFormatDetail(const PixelFormat format)413 bool PixelMap::GetPixelFormatDetail(const PixelFormat format)
414 {
415     switch (format) {
416         case PixelFormat::RGBA_8888: {
417             pixelBytes_ = ARGB_8888_BYTES;
418             colorProc_ = RGBA8888ToARGB;
419             break;
420         }
421         case PixelFormat::BGRA_8888: {
422             pixelBytes_ = ARGB_8888_BYTES;
423             colorProc_ = BGRA8888ToARGB;
424             break;
425         }
426         case PixelFormat::ARGB_8888: {
427             pixelBytes_ = ARGB_8888_BYTES;
428             colorProc_ = ARGB8888ToARGB;
429             break;
430         }
431         case PixelFormat::ALPHA_8: {
432             pixelBytes_ = ALPHA_8_BYTES;
433             colorProc_ = ALPHA8ToARGB;
434             break;
435         }
436         case PixelFormat::RGB_565: {
437             pixelBytes_ = RGB_565_BYTES;
438             colorProc_ = RGB565ToARGB;
439             break;
440         }
441         case PixelFormat::RGB_888: {
442             pixelBytes_ = RGB_888_BYTES;
443             colorProc_ = RGB888ToARGB;
444             break;
445         }
446         case PixelFormat::NV12:
447         case PixelFormat::NV21: {
448             pixelBytes_ = YUV420_BYTES;
449             break;
450         }
451         case PixelFormat::CMYK:
452             pixelBytes_ = ARGB_8888_BYTES;
453             break;
454         default: {
455             HiLog::Error(LABEL, "pixel format:[%{public}d] not supported.", format);
456             return false;
457         }
458     }
459     return true;
460 }
461 
SetImageInfo(ImageInfo & info)462 uint32_t PixelMap::SetImageInfo(ImageInfo &info)
463 {
464     return SetImageInfo(info, false);
465 }
466 
SetImageInfo(ImageInfo & info,bool isReused)467 uint32_t PixelMap::SetImageInfo(ImageInfo &info, bool isReused)
468 {
469     if (info.size.width <= 0 || info.size.height <= 0) {
470         HiLog::Error(LABEL, "pixel map image info invalid.");
471         return ERR_IMAGE_DATA_ABNORMAL;
472     }
473     if (!GetPixelFormatDetail(info.pixelFormat)) {
474         return ERR_IMAGE_DATA_UNSUPPORT;
475     }
476 
477     if (pixelBytes_ <= 0) {
478         ResetPixelMap();
479         HiLog::Error(LABEL, "pixel map bytes is invalid.");
480         return ERR_IMAGE_DATA_ABNORMAL;
481     }
482 
483     if ((static_cast<uint64_t>(pixelBytes_) * info.size.width) > PIXEL_MAP_MAX_RAM_SIZE) {
484         ResetPixelMap();
485         HiLog::Error(LABEL, "image size is out of range.");
486         return ERR_IMAGE_TOO_LARGE;
487     }
488     if (info.pixelFormat == PixelFormat::ALPHA_8) {
489         rowDataSize_ = pixelBytes_ * ((info.size.width + FILL_NUMBER) / ALIGN_NUMBER * ALIGN_NUMBER);
490         HiLog::Info(LABEL, "ALPHA_8 rowDataSize_ %{public}d.", rowDataSize_);
491     } else {
492         rowDataSize_ = pixelBytes_ * info.size.width;
493     }
494     if (info.size.height > (PIXEL_MAP_MAX_RAM_SIZE / rowDataSize_)) {
495         ResetPixelMap();
496         HiLog::Error(LABEL, "pixel map byte count out of range.");
497         return ERR_IMAGE_TOO_LARGE;
498     }
499     if (!isReused) {
500         FreePixelMap();
501     }
502     imageInfo_ = info;
503     return SUCCESS;
504 }
505 
GetPixel8(int32_t x,int32_t y)506 const uint8_t *PixelMap::GetPixel8(int32_t x, int32_t y)
507 {
508     if (!CheckValidParam(x, y) || (pixelBytes_ != ALPHA_8_BYTES)) {
509         HiLog::Error(LABEL, "get addr8 pixel position:(%{public}d, %{public}d) pixel bytes:%{public}d invalid.", x, y,
510                      pixelBytes_);
511         return nullptr;
512     }
513     return (data_ + y * rowDataSize_ + x);
514 }
515 
GetPixel16(int32_t x,int32_t y)516 const uint16_t *PixelMap::GetPixel16(int32_t x, int32_t y)
517 {
518     if (!CheckValidParam(x, y) || (pixelBytes_ != RGB_565_BYTES)) {
519         HiLog::Error(LABEL, "get addr16 pixel position:(%{public}d, %{public}d) pixel bytes:%{public}d invalid.", x, y,
520                      pixelBytes_);
521         return nullptr;
522     }
523     // convert uint8_t* to uint16_t*
524     return reinterpret_cast<uint16_t *>(data_ + y * rowDataSize_ + (static_cast<uint32_t>(x) << RGB_565_SHIFT));
525 }
526 
GetPixel32(int32_t x,int32_t y)527 const uint32_t *PixelMap::GetPixel32(int32_t x, int32_t y)
528 {
529     if (!CheckValidParam(x, y) || (pixelBytes_ != ARGB_8888_BYTES)) {
530         HiLog::Error(LABEL, "get addr32 pixel position:(%{public}d, %{public}d) pixel bytes:%{public}d invalid.", x, y,
531                      pixelBytes_);
532         return nullptr;
533     }
534     // convert uint8_t* to uint32_t*
535     return reinterpret_cast<uint32_t *>(data_ + y * rowDataSize_ + (static_cast<uint32_t>(x) << ARGB_8888_SHIFT));
536 }
537 
GetPixel(int32_t x,int32_t y)538 const uint8_t *PixelMap::GetPixel(int32_t x, int32_t y)
539 {
540     if (!CheckValidParam(x, y)) {
541         HiLog::Error(LABEL, "input pixel position:(%{public}d, %{public}d) invalid.", x, y);
542         return nullptr;
543     }
544     return (data_ + y * rowDataSize_ + (static_cast<uint32_t>(x) * pixelBytes_));
545 }
546 
GetARGB32Color(int32_t x,int32_t y,uint32_t & color)547 bool PixelMap::GetARGB32Color(int32_t x, int32_t y, uint32_t &color)
548 {
549     if (colorProc_ == nullptr) {
550         HiLog::Error(LABEL, "pixel format not supported.");
551         return false;
552     }
553     const uint8_t *src = GetPixel(x, y);
554     if (src == nullptr) {
555         HiLog::Error(LABEL, "get pixel color error.");
556         return false;
557     }
558     // use founction point for frequently called interface
559     return colorProc_(src, ONE_PIXEL_SIZE * pixelBytes_, &color, ONE_PIXEL_SIZE);
560 }
561 
ALPHA8ToARGB(const uint8_t * in,uint32_t inCount,uint32_t * out,uint32_t outCount)562 bool PixelMap::ALPHA8ToARGB(const uint8_t *in, uint32_t inCount, uint32_t *out, uint32_t outCount)
563 {
564     if (inCount != outCount) {
565         HiLog::Error(LABEL, "input count:%{public}u is not match to output count:%{public}u.", inCount, outCount);
566         return false;
567     }
568     const uint8_t *src = in;
569     for (uint32_t i = 0; i < outCount; i++) {
570         *out++ = GetColorARGB(*src++, BYTE_ZERO, BYTE_ZERO, BYTE_ZERO);
571     }
572     return true;
573 }
574 
RGB565ToARGB(const uint8_t * in,uint32_t inCount,uint32_t * out,uint32_t outCount)575 bool PixelMap::RGB565ToARGB(const uint8_t *in, uint32_t inCount, uint32_t *out, uint32_t outCount)
576 {
577     if (((inCount / RGB_565_BYTES) != outCount) && ((inCount % RGB_565_BYTES) != 0)) {
578         HiLog::Error(LABEL, "input count:%{public}u is not match to output count:%{public}u.", inCount, outCount);
579         return false;
580     }
581     const uint16_t *src = reinterpret_cast<const uint16_t *>(in);
582     for (uint32_t i = 0; i < outCount; i++) {
583         uint16_t color = *src++;
584         *out++ = GetColorARGB(BYTE_FULL, RGB565ToR32(color), RGB565ToG32(color), RGB565ToB32(color));
585     }
586     return true;
587 }
588 
ARGB8888ToARGB(const uint8_t * in,uint32_t inCount,uint32_t * out,uint32_t outCount)589 bool PixelMap::ARGB8888ToARGB(const uint8_t *in, uint32_t inCount, uint32_t *out, uint32_t outCount)
590 {
591     if (((inCount / ARGB_8888_BYTES) != outCount) && ((inCount % ARGB_8888_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 uint32_t *src = reinterpret_cast<const uint32_t *>(in);
596     for (uint32_t i = 0; i < outCount; i++) {
597         uint32_t color = *src++;
598         *out++ = GetColorARGB(GetColorComp(color, ARGB32_A_SHIFT), GetColorComp(color, ARGB32_R_SHIFT),
599                               GetColorComp(color, ARGB32_G_SHIFT), GetColorComp(color, ARGB32_B_SHIFT));
600     }
601     return true;
602 }
603 
RGBA8888ToARGB(const uint8_t * in,uint32_t inCount,uint32_t * out,uint32_t outCount)604 bool PixelMap::RGBA8888ToARGB(const uint8_t *in, uint32_t inCount, uint32_t *out, uint32_t outCount)
605 {
606     if (((inCount / ARGB_8888_BYTES) != outCount) && ((inCount % ARGB_8888_BYTES) != 0)) {
607         HiLog::Error(LABEL, "input count:%{public}u is not match to output count:%{public}u.", inCount, outCount);
608         return false;
609     }
610     const uint32_t *src = reinterpret_cast<const uint32_t *>(in);
611     for (uint32_t i = 0; i < outCount; i++) {
612         uint32_t color = *src++;
613         *out++ = GetColorARGB(GetColorComp(color, RGBA32_A_SHIFT), GetColorComp(color, RGBA32_R_SHIFT),
614                               GetColorComp(color, RGBA32_G_SHIFT), GetColorComp(color, RGBA32_B_SHIFT));
615     }
616     return true;
617 }
618 
BGRA8888ToARGB(const uint8_t * in,uint32_t inCount,uint32_t * out,uint32_t outCount)619 bool PixelMap::BGRA8888ToARGB(const uint8_t *in, uint32_t inCount, uint32_t *out, uint32_t outCount)
620 {
621     if (((inCount / ARGB_8888_BYTES) != outCount) && ((inCount % ARGB_8888_BYTES) != 0)) {
622         HiLog::Error(LABEL, "input count:%{public}u is not match to output count:%{public}u.", inCount, outCount);
623         return false;
624     }
625     const uint32_t *src = reinterpret_cast<const uint32_t *>(in);
626     for (uint32_t i = 0; i < outCount; i++) {
627         uint32_t color = *src++;
628         *out++ = GetColorARGB(GetColorComp(color, BGRA32_A_SHIFT), GetColorComp(color, BGRA32_R_SHIFT),
629                               GetColorComp(color, BGRA32_G_SHIFT), GetColorComp(color, BGRA32_B_SHIFT));
630     }
631     return true;
632 }
633 
RGB888ToARGB(const uint8_t * in,uint32_t inCount,uint32_t * out,uint32_t outCount)634 bool PixelMap::RGB888ToARGB(const uint8_t *in, uint32_t inCount, uint32_t *out, uint32_t outCount)
635 {
636     if (((inCount / RGB_888_BYTES) != outCount) && ((inCount % RGB_888_BYTES) != 0)) {
637         HiLog::Error(LABEL, "input count:%{public}u is not match to output count:%{public}u.", inCount, outCount);
638         return false;
639     }
640     const uint8_t *src = in;
641     for (uint32_t i = 0; i < outCount; i++) {
642         uint8_t colorR = *src++;
643         uint8_t colorG = *src++;
644         uint8_t colorB = *src++;
645         *out++ = GetColorARGB(BYTE_FULL, colorR, colorG, colorB);
646     }
647     return true;
648 }
649 
GetPixelBytes()650 int32_t PixelMap::GetPixelBytes()
651 {
652     return pixelBytes_;
653 }
654 
GetRowBytes()655 int32_t PixelMap::GetRowBytes()
656 {
657     return rowDataSize_;
658 }
659 
GetByteCount()660 int32_t PixelMap::GetByteCount()
661 {
662     HiLog::Debug(LABEL, "GetByteCount");
663     return rowDataSize_ * imageInfo_.size.height;
664 }
665 
GetWidth()666 int32_t PixelMap::GetWidth()
667 {
668     return imageInfo_.size.width;
669 }
670 
GetHeight()671 int32_t PixelMap::GetHeight()
672 {
673     return imageInfo_.size.height;
674 }
675 
GetBaseDensity()676 int32_t PixelMap::GetBaseDensity()
677 {
678     return imageInfo_.baseDensity;
679 }
680 
GetImageInfo(ImageInfo & imageInfo)681 void PixelMap::GetImageInfo(ImageInfo &imageInfo)
682 {
683     imageInfo = imageInfo_;
684 }
685 
GetPixelFormat()686 PixelFormat PixelMap::GetPixelFormat()
687 {
688     return imageInfo_.pixelFormat;
689 }
690 
GetColorSpace()691 ColorSpace PixelMap::GetColorSpace()
692 {
693     return imageInfo_.colorSpace;
694 }
695 
GetAlphaType()696 AlphaType PixelMap::GetAlphaType()
697 {
698     return imageInfo_.alphaType;
699 }
700 
GetPixels()701 const uint8_t *PixelMap::GetPixels()
702 {
703     return data_;
704 }
705 
GetARGB32ColorA(uint32_t color)706 uint8_t PixelMap::GetARGB32ColorA(uint32_t color)
707 {
708     return (color >> ARGB_A_SHIFT) & ARGB_MASK;
709 }
710 
GetARGB32ColorR(uint32_t color)711 uint8_t PixelMap::GetARGB32ColorR(uint32_t color)
712 {
713     return (color >> ARGB_R_SHIFT) & ARGB_MASK;
714 }
715 
GetARGB32ColorG(uint32_t color)716 uint8_t PixelMap::GetARGB32ColorG(uint32_t color)
717 {
718     return (color >> ARGB_G_SHIFT) & ARGB_MASK;
719 }
720 
GetARGB32ColorB(uint32_t color)721 uint8_t PixelMap::GetARGB32ColorB(uint32_t color)
722 {
723     return (color >> ARGB_B_SHIFT) & ARGB_MASK;
724 }
725 
IsSameImage(const PixelMap & other)726 bool PixelMap::IsSameImage(const PixelMap &other)
727 {
728     if (data_ == nullptr || other.data_ == nullptr) {
729         HiLog::Error(LABEL, "IsSameImage data_ is nullptr.");
730         return false;
731     }
732     if (imageInfo_.size.width != other.imageInfo_.size.width ||
733         imageInfo_.size.height != other.imageInfo_.size.height ||
734         imageInfo_.pixelFormat != other.imageInfo_.pixelFormat || imageInfo_.alphaType != other.imageInfo_.alphaType) {
735         HiLog::Error(LABEL, "IsSameImage imageInfo check not OK.");
736         return false;
737     }
738     uint64_t size = static_cast<uint64_t>(rowDataSize_) * imageInfo_.size.height;
739     if (memcmp(data_, other.data_, size) != 0) {
740         HiLog::Error(LABEL, "IsSameImage mmemcmp check not OK.");
741         return false;
742     }
743     return true;
744 }
745 
ReadPixels(const uint64_t & bufferSize,uint8_t * dst)746 uint32_t PixelMap::ReadPixels(const uint64_t &bufferSize, uint8_t *dst)
747 {
748     if (dst == nullptr) {
749         HiLog::Error(LABEL, "read pixels by buffer input dst address is null.");
750         return ERR_IMAGE_READ_PIXELMAP_FAILED;
751     }
752     if (data_ == nullptr) {
753         HiLog::Error(LABEL, "read pixels by buffer current PixelMap data is null.");
754         return ERR_IMAGE_READ_PIXELMAP_FAILED;
755     }
756     if (bufferSize < static_cast<uint64_t>(pixelsSize_)) {
757         HiLog::Error(LABEL, "read pixels by buffer input dst buffer(%{public}llu) < current pixelmap size(%{public}u).",
758                      static_cast<unsigned long long>(bufferSize), pixelsSize_);
759         return ERR_IMAGE_INVALID_PARAMETER;
760     }
761     errno_t ret = memcpy_s(dst, bufferSize, data_, pixelsSize_);
762     if (ret != 0) {
763         HiLog::Error(LABEL, "read pixels by buffer memcpy the pixelmap data to dst fail, error:%{public}d", ret);
764         return ERR_IMAGE_READ_PIXELMAP_FAILED;
765     }
766     return SUCCESS;
767 }
768 
CheckPixelsInput(const uint8_t * dst,const uint64_t & bufferSize,const uint32_t & offset,const uint32_t & stride,const Rect & region)769 bool PixelMap::CheckPixelsInput(const uint8_t *dst, const uint64_t &bufferSize, const uint32_t &offset,
770                                 const uint32_t &stride, const Rect &region)
771 {
772     if (dst == nullptr) {
773         HiLog::Error(LABEL, "CheckPixelsInput input dst address is null.");
774         return false;
775     }
776 
777     if (bufferSize == 0) {
778         HiLog::Error(LABEL, "CheckPixelsInput input buffer size is 0.");
779         return false;
780     }
781 
782     if (region.left < 0 || region.top < 0 || stride > numeric_limits<int32_t>::max() ||
783         static_cast<uint64_t>(offset) > bufferSize) {
784         HiLog::Error(
785             LABEL,
786             "CheckPixelsInput left(%{public}d) or top(%{public}d) or stride(%{public}u) or offset(%{public}u) < 0.",
787             region.left, region.top, stride, offset);
788         return false;
789     }
790     if (region.width <= 0 || region.height <= 0 || region.width > MAX_DIMENSION || region.height > MAX_DIMENSION) {
791         HiLog::Error(LABEL, "CheckPixelsInput width(%{public}d) or height(%{public}d) is < 0.", region.width,
792                      region.height);
793         return false;
794     }
795     if (region.left > GetWidth() - region.width) {
796         HiLog::Error(LABEL, "CheckPixelsInput left(%{public}d) + width(%{public}d) is > pixelmap width(%{public}d).",
797                      region.left, region.width, GetWidth());
798         return false;
799     }
800     if (region.top > GetHeight() - region.height) {
801         HiLog::Error(LABEL, "CheckPixelsInput top(%{public}d) + height(%{public}d) is > pixelmap height(%{public}d).",
802                      region.top, region.height, GetHeight());
803         return false;
804     }
805     uint32_t regionStride = static_cast<uint32_t>(region.width) * 4;  // bytes count, need multiply by 4
806     if (stride < regionStride) {
807         HiLog::Error(LABEL, "CheckPixelsInput stride(%{public}d) < width*4 (%{public}d).", stride, regionStride);
808         return false;
809     }
810 
811     if (bufferSize < regionStride) {
812         HiLog::Error(LABEL, "CheckPixelsInput input buffer size is < width * 4.");
813         return false;
814     }
815     uint64_t lastLinePos = offset + static_cast<uint64_t>(region.height - 1) * stride;  // "1" is except the last line.
816     if (static_cast<uint64_t>(offset) > (bufferSize - regionStride) || lastLinePos > (bufferSize - regionStride)) {
817         HiLog::Error(LABEL,
818                      "CheckPixelsInput fail, height(%{public}d), width(%{public}d), lastLine(%{public}llu), "
819                      "offset(%{public}u), bufferSize:%{public}llu.",
820                      region.height, region.width, static_cast<unsigned long long>(lastLinePos), offset,
821                      static_cast<unsigned long long>(bufferSize));
822         return false;
823     }
824     return true;
825 }
826 
ReadPixels(const uint64_t & bufferSize,const uint32_t & offset,const uint32_t & stride,const Rect & region,uint8_t * dst)827 uint32_t PixelMap::ReadPixels(const uint64_t &bufferSize, const uint32_t &offset, const uint32_t &stride,
828                               const Rect &region, uint8_t *dst)
829 {
830     if (!CheckPixelsInput(dst, bufferSize, offset, stride, region)) {
831         HiLog::Error(LABEL, "read pixels by rect input parameter fail.");
832         return ERR_IMAGE_INVALID_PARAMETER;
833     }
834     if (data_ == nullptr) {
835         HiLog::Error(LABEL, "read pixels by rect this pixel data is null.");
836         return ERR_IMAGE_READ_PIXELMAP_FAILED;
837     }
838     ImageInfo dstImageInfo =
839         MakeImageInfo(region.width, region.height, PixelFormat::BGRA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
840     Position srcPosition{ region.left, region.top };
841     if (!PixelConvertAdapter::ReadPixelsConvert(data_, srcPosition, rowDataSize_, imageInfo_, dst + offset, stride,
842         dstImageInfo)) {
843         HiLog::Error(LABEL, "read pixels by rect call ReadPixelsConvert fail.");
844         return ERR_IMAGE_READ_PIXELMAP_FAILED;
845     }
846     return SUCCESS;
847 }
848 
ReadPixel(const Position & pos,uint32_t & dst)849 uint32_t PixelMap::ReadPixel(const Position &pos, uint32_t &dst)
850 {
851     if (pos.x < 0 || pos.y < 0 || pos.x >= GetWidth() || pos.y >= GetHeight()) {
852         HiLog::Error(LABEL, "read pixel by pos input invalid exception. [x(%{public}d), y(%{public}d)]", pos.x, pos.y);
853         return ERR_IMAGE_INVALID_PARAMETER;
854     }
855     if (data_ == nullptr) {
856         HiLog::Error(LABEL, "read pixel by pos source data is null.");
857         return ERR_IMAGE_READ_PIXELMAP_FAILED;
858     }
859     ImageInfo dstImageInfo =
860         MakeImageInfo(PER_PIXEL_LEN, PER_PIXEL_LEN, PixelFormat::BGRA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
861     uint32_t dstRowBytes = BGRA_BYTES;
862     Position srcPosition{ pos.x, pos.y };
863     if (!PixelConvertAdapter::ReadPixelsConvert(data_, srcPosition, rowDataSize_, imageInfo_, &dst, dstRowBytes,
864         dstImageInfo)) {
865         HiLog::Error(LABEL, "read pixel by pos call ReadPixelsConvert fail.");
866         return ERR_IMAGE_READ_PIXELMAP_FAILED;
867     }
868     return SUCCESS;
869 }
870 
ResetConfig(const Size & size,const PixelFormat & format)871 uint32_t PixelMap::ResetConfig(const Size &size, const PixelFormat &format)
872 {
873     if (size.width <= 0 || size.height <= 0) {
874         HiLog::Error(LABEL, "ResetConfig reset input width(%{public}d) or height(%{public}d) is < 0.", size.width,
875                      size.height);
876         return ERR_IMAGE_INVALID_PARAMETER;
877     }
878     uint32_t bytesPerPixel = ImageUtils::GetPixelBytes(format);
879     if (bytesPerPixel == 0) {
880         HiLog::Error(LABEL, "ResetConfig get bytes by per pixel fail.");
881         return ERR_IMAGE_INVALID_PARAMETER;
882     }
883     uint64_t dstSize = static_cast<uint64_t>(size.width) * size.height * bytesPerPixel;
884     if (dstSize > static_cast<uint64_t>(pixelsSize_)) {
885         HiLog::Error(LABEL, "ResetConfig reset dstSize(%{public}llu) > current(%{public}u).",
886                      static_cast<unsigned long long>(dstSize), pixelsSize_);
887         return ERR_IMAGE_INVALID_PARAMETER;
888     }
889     AlphaType dstAlphaType = ImageUtils::GetValidAlphaTypeByFormat(GetAlphaType(), format);
890     if (dstAlphaType == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
891         HiLog::Error(LABEL, "ResetConfig Failed to get validate alpha type.");
892         return ERR_IMAGE_INVALID_PARAMETER;
893     }
894     ImageInfo dstInfo = MakeImageInfo(size.width, size.height, format, dstAlphaType);
895     uint32_t ret = SetImageInfo(dstInfo, true);
896     if (ret != SUCCESS) {
897         HiLog::Error(LABEL, "ResetConfig call SetImageInfo Failed. ret:%{public}u", ret);
898         return ERR_IMAGE_CONFIG_FAILED;
899     }
900     return SUCCESS;
901 }
902 
SetAlphaType(const AlphaType & alphaType)903 bool PixelMap::SetAlphaType(const AlphaType &alphaType)
904 {
905     AlphaType type = ImageUtils::GetValidAlphaTypeByFormat(alphaType, imageInfo_.pixelFormat);
906     if (type == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
907         HiLog::Error(LABEL, "SetAlphaType Failed to get validate alpha type.");
908         return false;
909     }
910     ImageInfo dstInfo = imageInfo_;
911     dstInfo.alphaType = type;
912     uint32_t ret = SetImageInfo(dstInfo, true);
913     if (ret != SUCCESS) {
914         HiLog::Error(LABEL, "SetAlphaType call SetImageInfo Failed. ret:%{public}u", ret);
915         return false;
916     }
917     return true;
918 }
919 
WritePixel(const Position & pos,const uint32_t & color)920 uint32_t PixelMap::WritePixel(const Position &pos, const uint32_t &color)
921 {
922     if (pos.x < 0 || pos.y < 0 || pos.x >= GetWidth() || pos.y >= GetHeight()) {
923         HiLog::Error(LABEL,
924                      "write pixel by pos but input position is invalid. [x(%{public}d), y(%{public}d)]"\
925                      "Width() %{public}d,  Height() %{public}d, ",
926                      pos.x, pos.y, GetWidth(), GetHeight());
927         return ERR_IMAGE_INVALID_PARAMETER;
928     }
929     if (!IsEditable()) {
930         HiLog::Error(LABEL, "write pixel by pos pixelmap is not editable.");
931         return ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY;
932     }
933     if (!ImageUtils::IsValidImageInfo(imageInfo_)) {
934         HiLog::Error(LABEL, "write pixel by pos current pixelmap image info is invalid.");
935         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
936     }
937     if (data_ == nullptr) {
938         HiLog::Error(LABEL, "write pixel by pos but current pixelmap data is nullptr.");
939         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
940     }
941     ImageInfo srcImageInfo =
942         MakeImageInfo(PER_PIXEL_LEN, PER_PIXEL_LEN, PixelFormat::BGRA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
943     uint32_t srcRowBytes = BGRA_BYTES;
944     Position dstPosition{ pos.x, pos.y };  // source is per pixel.
945     if (!PixelConvertAdapter::WritePixelsConvert(&color, srcRowBytes, srcImageInfo, data_, dstPosition, rowDataSize_,
946         imageInfo_)) {
947         HiLog::Error(LABEL, "write pixel by pos call WritePixelsConvert fail.");
948         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
949     }
950     return SUCCESS;
951 }
952 
WritePixels(const uint8_t * source,const uint64_t & bufferSize,const uint32_t & offset,const uint32_t & stride,const Rect & region)953 uint32_t PixelMap::WritePixels(const uint8_t *source, const uint64_t &bufferSize, const uint32_t &offset,
954                                const uint32_t &stride, const Rect &region)
955 {
956     if (!CheckPixelsInput(source, bufferSize, offset, stride, region)) {
957         HiLog::Error(LABEL, "write pixel by rect input parameter fail.");
958         return ERR_IMAGE_INVALID_PARAMETER;
959     }
960     if (!IsEditable()) {
961         HiLog::Error(LABEL, "write pixel by rect pixelmap data is not editable.");
962         return ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY;
963     }
964     if (!ImageUtils::IsValidImageInfo(imageInfo_)) {
965         HiLog::Error(LABEL, "write pixel by rect current pixelmap image info is invalid.");
966         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
967     }
968     if (data_ == nullptr) {
969         HiLog::Error(LABEL, "write pixel by rect current pixel map data is null.");
970         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
971     }
972     uint32_t bytesPerPixel = ImageUtils::GetPixelBytes(imageInfo_.pixelFormat);
973     if (bytesPerPixel == 0) {
974         HiLog::Error(LABEL, "write pixel by rect get bytes by per pixel fail.");
975         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
976     }
977     Position dstPosition{ region.left, region.top };
978     ImageInfo srcInfo =
979         MakeImageInfo(region.width, region.height, PixelFormat::BGRA_8888, AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
980     if (!PixelConvertAdapter::WritePixelsConvert(source + offset, stride, srcInfo, data_, dstPosition, rowDataSize_,
981         imageInfo_)) {
982         HiLog::Error(LABEL, "write pixel by rect call WritePixelsConvert fail.");
983         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
984     }
985     return SUCCESS;
986 }
987 
WritePixels(const uint8_t * source,const uint64_t & bufferSize)988 uint32_t PixelMap::WritePixels(const uint8_t *source, const uint64_t &bufferSize)
989 {
990     if (source == nullptr || bufferSize < static_cast<uint64_t>(pixelsSize_)) {
991         HiLog::Error(LABEL, "write pixels by buffer source is nullptr or size(%{public}llu) < pixelSize(%{public}u).",
992                      static_cast<unsigned long long>(bufferSize), pixelsSize_);
993         return ERR_IMAGE_INVALID_PARAMETER;
994     }
995     if (!IsEditable()) {
996         HiLog::Error(LABEL, "write pixels by buffer pixelmap data is not editable.");
997         return ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY;
998     }
999     if (!ImageUtils::IsValidImageInfo(imageInfo_)) {
1000         HiLog::Error(LABEL, "write pixels by buffer current pixelmap image info is invalid.");
1001         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
1002     }
1003     if (data_ == nullptr) {
1004         HiLog::Error(LABEL, "write pixels by buffer current pixelmap data is nullptr.");
1005         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
1006     }
1007     errno_t ret = memcpy_s(data_, pixelsSize_, source, pixelsSize_);
1008     if (ret != 0) {
1009         HiLog::Error(LABEL, "write pixels by buffer memcpy to pixelmap data from source fail, error:%{public}d", ret);
1010         return ERR_IMAGE_WRITE_PIXELMAP_FAILED;
1011     }
1012     return SUCCESS;
1013 }
1014 
WritePixels(const uint32_t & color)1015 bool PixelMap::WritePixels(const uint32_t &color)
1016 {
1017     if (!IsEditable()) {
1018         HiLog::Error(LABEL, "erase pixels by color pixelmap data is not editable.");
1019         return false;
1020     }
1021     if (!ImageUtils::IsValidImageInfo(imageInfo_)) {
1022         HiLog::Error(LABEL, "erase pixels by color current pixelmap image info is invalid.");
1023         return false;
1024     }
1025     if (data_ == nullptr) {
1026         HiLog::Error(LABEL, "erase pixels by color current pixel map data is null.");
1027         return false;
1028     }
1029     ImageInfo srcInfo =
1030         MakeImageInfo(imageInfo_.size.width, imageInfo_.size.height, imageInfo_.pixelFormat, imageInfo_.alphaType);
1031     if (!PixelConvertAdapter::EraseBitmap(data_, rowDataSize_, srcInfo, color)) {
1032         HiLog::Error(LABEL, "erase pixels by color call EraseBitmap fail.");
1033         return false;
1034     }
1035     return true;
1036 }
1037 
GetAllocatorType()1038 AllocatorType PixelMap::GetAllocatorType()
1039 {
1040     return allocatorType_;
1041 }
1042 
GetFd() const1043 void *PixelMap::GetFd() const
1044 {
1045     return context_;
1046 }
1047 
ReleaseMemory(AllocatorType allocType,void * addr,void * context,uint32_t size)1048 void PixelMap::ReleaseMemory(AllocatorType allocType, void *addr, void *context, uint32_t size)
1049 {
1050     if (allocType == AllocatorType::SHARE_MEM_ALLOC) {
1051 #if !defined(_WIN32) && !defined(_APPLE)
1052         int *fd = static_cast<int *>(context);
1053         if (addr != nullptr) {
1054             ::munmap(addr, size);
1055         }
1056         if (fd != nullptr) {
1057             ::close(*fd);
1058         }
1059 #endif
1060     } else if (allocType == AllocatorType::HEAP_ALLOC) {
1061         if (addr != nullptr) {
1062             free(addr);
1063             addr = nullptr;
1064         }
1065     }
1066 }
1067 
WriteImageData(Parcel & parcel,size_t size) const1068 bool PixelMap::WriteImageData(Parcel &parcel, size_t size) const
1069 {
1070     const uint8_t *data = data_;
1071     if (data == nullptr) {
1072         HiLog::Error(LABEL, "write to parcel failed, pixel memory is null.");
1073         return false;
1074     }
1075     if (data == nullptr || size > MAX_IMAGEDATA_SIZE) {
1076         return false;
1077     }
1078 
1079     if (!parcel.WriteInt32(size)) {
1080         return false;
1081     }
1082     if (size <= MIN_IMAGEDATA_SIZE) {
1083         return parcel.WriteUnpadBuffer(data, size);
1084     }
1085 #if !defined(_WIN32) && !defined(_APPLE)
1086     int fd = AshmemCreate("Parcel ImageData", size);
1087     HiLog::Info(LABEL, "AshmemCreate:[%{public}d].", fd);
1088     if (fd < 0) {
1089         return false;
1090     }
1091 
1092     int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
1093     HiLog::Info(LABEL, "AshmemSetProt:[%{public}d].", result);
1094     if (result < 0) {
1095         ::close(fd);
1096         return false;
1097     }
1098     void *ptr = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1099 
1100     if (ptr == MAP_FAILED) {
1101         ::close(fd);
1102         return false;
1103     }
1104     HiLog::Info(LABEL, "mmap success");
1105 
1106     if (memcpy_s(ptr, size, data, size) != EOK) {
1107         ::munmap(ptr, size);
1108         ::close(fd);
1109         HiLog::Error(LABEL, "WriteImageData memcpy_s error");
1110         return false;
1111     }
1112 
1113     if (!WriteFileDescriptor(parcel, fd)) {
1114         ::munmap(ptr, size);
1115         ::close(fd);
1116         HiLog::Error(LABEL, "WriteImageData WriteFileDescriptor error");
1117         return false;
1118     }
1119     HiLog::Debug(LABEL, "WriteImageData WriteFileDescriptor success");
1120     ::munmap(ptr, size);
1121     ::close(fd);
1122     HiLog::Debug(LABEL, "WriteImageData End");
1123 #endif
1124     return true;
1125 }
1126 
ReadImageData(Parcel & parcel,int32_t bufferSize)1127 uint8_t *PixelMap::ReadImageData(Parcel &parcel, int32_t bufferSize)
1128 {
1129     uint8_t *base = nullptr;
1130     int fd = -1;
1131 
1132     if (static_cast<unsigned int>(bufferSize) <= MIN_IMAGEDATA_SIZE) {
1133         const uint8_t *ptr = parcel.ReadUnpadBuffer(bufferSize);
1134         if (bufferSize <= 0) {
1135             HiLog::Error(LABEL, "malloc parameter bufferSize:[%{public}d] error.", bufferSize);
1136             return nullptr;
1137         }
1138         base = static_cast<uint8_t *>(malloc(bufferSize));
1139         if (base == nullptr) {
1140             HiLog::Error(LABEL, "alloc output pixel memory size:[%{public}d] error.", bufferSize);
1141             return nullptr;
1142         }
1143         if (memcpy_s(base, bufferSize, ptr, bufferSize) != 0) {
1144             free(base);
1145             base = nullptr;
1146             HiLog::Error(LABEL, "memcpy pixel data size:[%{public}d] error.", bufferSize);
1147             return nullptr;
1148         }
1149     } else {
1150 #if !defined(_WIN32) && !defined(_APPLE)
1151         fd = ReadFileDescriptor(parcel);
1152         if (fd < 0) {
1153             HiLog::Error(LABEL, "read fd :[%{public}d] error", fd);
1154             return nullptr;
1155         }
1156         void *ptr = ::mmap(nullptr, bufferSize, PROT_READ, MAP_SHARED, fd, 0);
1157         if (ptr == MAP_FAILED) {
1158             // do not close fd here. fd will be closed in FileDescriptor, ::close(fd)
1159             HiLog::Error(LABEL, "mmap error");
1160             return nullptr;
1161         }
1162         if (bufferSize <= 0) {
1163             HiLog::Error(LABEL, "malloc parameter bufferSize:[%{public}d] error.", bufferSize);
1164             return nullptr;
1165         }
1166         base = static_cast<uint8_t *>(malloc(bufferSize));
1167         if (base == nullptr) {
1168             HiLog::Error(LABEL, "alloc output pixel memory size:[%{public}d] error.", bufferSize);
1169             return nullptr;
1170         }
1171         if (memcpy_s(base, bufferSize, ptr, bufferSize) != 0) {
1172             free(base);
1173             base = nullptr;
1174             HiLog::Error(LABEL, "memcpy pixel data size:[%{public}d] error.", bufferSize);
1175             return nullptr;
1176         }
1177 
1178         ReleaseMemory(AllocatorType::SHARE_MEM_ALLOC, ptr, &fd, bufferSize);
1179 #endif
1180     }
1181     return base;
1182 }
1183 
WriteFileDescriptor(Parcel & parcel,int fd)1184 bool PixelMap::WriteFileDescriptor(Parcel &parcel, int fd)
1185 {
1186     if (fd < 0) {
1187         return false;
1188     }
1189     int dupFd = dup(fd);
1190     if (dupFd < 0) {
1191         return false;
1192     }
1193     sptr<IPCFileDescriptor> descriptor = new IPCFileDescriptor(dupFd);
1194     return parcel.WriteObject<IPCFileDescriptor>(descriptor);
1195 }
1196 
ReadFileDescriptor(Parcel & parcel)1197 int PixelMap::ReadFileDescriptor(Parcel &parcel)
1198 {
1199     sptr<IPCFileDescriptor> descriptor = parcel.ReadObject<IPCFileDescriptor>();
1200     if (descriptor == nullptr) {
1201         return -1;
1202     }
1203     int fd = descriptor->GetFd();
1204     if (fd < 0) {
1205         return -1;
1206     }
1207     return dup(fd);
1208 }
1209 
WriteImageInfo(Parcel & parcel) const1210 bool PixelMap::WriteImageInfo(Parcel &parcel) const
1211 {
1212     if (!parcel.WriteInt32(imageInfo_.size.width)) {
1213         HiLog::Error(LABEL, "write image info width:[%{public}d] to parcel failed.", imageInfo_.size.width);
1214         return false;
1215     }
1216     if (!parcel.WriteInt32(imageInfo_.size.height)) {
1217         HiLog::Error(LABEL, "write image info height:[%{public}d] to parcel failed.", imageInfo_.size.height);
1218         return false;
1219     }
1220     if (!parcel.WriteInt32(static_cast<int32_t>(imageInfo_.pixelFormat))) {
1221         HiLog::Error(LABEL, "write image info pixel format:[%{public}d] to parcel failed.", imageInfo_.pixelFormat);
1222         return false;
1223     }
1224     if (!parcel.WriteInt32(static_cast<int32_t>(imageInfo_.colorSpace))) {
1225         HiLog::Error(LABEL, "write image info color space:[%{public}d] to parcel failed.", imageInfo_.colorSpace);
1226         return false;
1227     }
1228     if (!parcel.WriteInt32(static_cast<int32_t>(imageInfo_.alphaType))) {
1229         HiLog::Error(LABEL, "write image info alpha type:[%{public}d] to parcel failed.", imageInfo_.alphaType);
1230         return false;
1231     }
1232     if (!parcel.WriteInt32(imageInfo_.baseDensity)) {
1233         HiLog::Error(LABEL, "write image info base density:[%{public}d] to parcel failed.", imageInfo_.baseDensity);
1234         return false;
1235     }
1236     return true;
1237 }
1238 
Marshalling(Parcel & parcel) const1239 bool PixelMap::Marshalling(Parcel &parcel) const
1240 {
1241     int32_t PIXEL_MAP_INFO_MAX_LENGTH = 128;
1242     int32_t bufferSize = rowDataSize_ * imageInfo_.size.height;
1243     if (static_cast<size_t>(bufferSize) <= MIN_IMAGEDATA_SIZE &&
1244         static_cast<size_t>(bufferSize + PIXEL_MAP_INFO_MAX_LENGTH) > parcel.GetDataCapacity() &&
1245         !parcel.SetDataCapacity(bufferSize + PIXEL_MAP_INFO_MAX_LENGTH)) {
1246         HiLog::Error(LABEL, "set parcel max capacity:[%{public}d] failed.", bufferSize + PIXEL_MAP_INFO_MAX_LENGTH);
1247         return false;
1248     }
1249     if (!WriteImageInfo(parcel)) {
1250         HiLog::Error(LABEL, "write image info to parcel failed.");
1251         return false;
1252     }
1253 
1254     if (!parcel.WriteInt32(static_cast<int32_t>(allocatorType_))) {
1255         HiLog::Error(LABEL, "write pixel map allocator type:[%{public}d] to parcel failed.",
1256                      allocatorType_);
1257         return false;
1258     }
1259     if (allocatorType_ == AllocatorType::SHARE_MEM_ALLOC) {
1260 #if !defined(_WIN32) && !defined(_APPLE)
1261         if (!parcel.WriteInt32(bufferSize)) {
1262             return false;
1263         }
1264 
1265         int *fd = static_cast<int *>(context_);
1266         if (*fd < 0) {
1267             HiLog::Error(LABEL, "write pixel map failed, fd < 0.");
1268             return false;
1269         }
1270 
1271         if (!WriteFileDescriptor(parcel, *fd)) {
1272             HiLog::Error(LABEL, "write pixel map fd:[%{public}d] to parcel failed.", *fd);
1273             return false;
1274         }
1275 #endif
1276     } else {
1277         if (!WriteImageData(parcel, bufferSize)) {
1278             HiLog::Error(LABEL, "write pixel map buffer to parcel failed.");
1279             return false;
1280         }
1281     }
1282     return true;
1283 }
1284 
ReadImageInfo(Parcel & parcel,ImageInfo & imgInfo)1285 bool PixelMap::ReadImageInfo(Parcel &parcel, ImageInfo &imgInfo)
1286 {
1287     imgInfo.size.width = parcel.ReadInt32();
1288     HiLog::Debug(LABEL, "read pixel map width:[%{public}d] to parcel.", imgInfo.size.width);
1289     imgInfo.size.height = parcel.ReadInt32();
1290     HiLog::Debug(LABEL, "read pixel map height:[%{public}d] to parcel.", imgInfo.size.height);
1291     imgInfo.pixelFormat = static_cast<PixelFormat>(parcel.ReadInt32());
1292     HiLog::Debug(LABEL, "read pixel map pixelFormat:[%{public}d] to parcel.", imgInfo.pixelFormat);
1293     imgInfo.colorSpace = static_cast<ColorSpace>(parcel.ReadInt32());
1294     HiLog::Debug(LABEL, "read pixel map colorSpace:[%{public}d] to parcel.", imgInfo.colorSpace);
1295     imgInfo.alphaType = static_cast<AlphaType>(parcel.ReadInt32());
1296     HiLog::Debug(LABEL, "read pixel map alphaType:[%{public}d] to parcel.", imgInfo.alphaType);
1297     imgInfo.baseDensity = parcel.ReadInt32();
1298     return true;
1299 }
1300 
Unmarshalling(Parcel & parcel)1301 PixelMap *PixelMap::Unmarshalling(Parcel &parcel)
1302 {
1303     PixelMap *pixelMap = new PixelMap();
1304     if (pixelMap == nullptr) {
1305         return nullptr;
1306     }
1307 
1308     ImageInfo imgInfo;
1309     if (!pixelMap->ReadImageInfo(parcel, imgInfo)) {
1310         HiLog::Error(LABEL, "read imageInfo fail");
1311         delete pixelMap;
1312         return nullptr;
1313     }
1314 
1315     AllocatorType allocType = static_cast<AllocatorType>(parcel.ReadInt32());
1316     int32_t bufferSize = parcel.ReadInt32();
1317     uint8_t *base = nullptr;
1318     void *context = nullptr;
1319     if (allocType == AllocatorType::SHARE_MEM_ALLOC) {
1320 #if !defined(_WIN32) && !defined(_APPLE)
1321         int fd = ReadFileDescriptor(parcel);
1322         if (fd < 0) {
1323             HiLog::Error(LABEL, "fd < 0");
1324             delete pixelMap;
1325             return nullptr;
1326         }
1327         void* ptr = ::mmap(nullptr, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1328         if (ptr == MAP_FAILED) {
1329             ::close(fd);
1330             delete pixelMap;
1331             HiLog::Error(LABEL, "shared memory map failed");
1332             return nullptr;
1333         }
1334         context = new int32_t();
1335         if (context == nullptr) {
1336             ::munmap(ptr, bufferSize);
1337             ::close(fd);
1338             delete pixelMap;
1339             return nullptr;
1340         }
1341         *static_cast<int32_t *>(context) = fd;
1342         base = static_cast<uint8_t *>(ptr);
1343 #endif
1344     } else {
1345         base = ReadImageData(parcel, bufferSize);
1346         if (base == nullptr) {
1347             HiLog::Error(LABEL, "get pixel memory size:[%{public}d] error.", bufferSize);
1348             delete pixelMap;
1349             return nullptr;
1350         }
1351     }
1352 
1353     uint32_t ret = pixelMap->SetImageInfo(imgInfo);
1354     if (ret != SUCCESS) {
1355         ReleaseMemory(allocType, base, context, bufferSize);
1356         if (context != nullptr) {
1357             delete static_cast<int32_t *>(context);
1358         }
1359         delete pixelMap;
1360         HiLog::Error(LABEL, "create pixel map from parcel failed, set image info error.");
1361         return nullptr;
1362     }
1363     pixelMap->SetPixelsAddr(base, context, bufferSize, allocType, nullptr);
1364     return pixelMap;
1365 }
1366 } // namespace Media
1367 } // namespace OHOS
1368