• 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 #ifndef FRAMEWORKS_INNERKITSIMPL_COMMON_INCLUDE_PIXEL_MAP_UTILS_H
17 #define FRAMEWORKS_INNERKITSIMPL_COMMON_INCLUDE_PIXEL_MAP_UTILS_H
18 
19 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
20 #include "ashmem.h"
21 #endif
22 
23 #include "image_type.h"
24 #include "log_tags.h"
25 #include "memory_manager.h"
26 #include "pixel_convert.h"
27 #include "pixel_convert_adapter.h"
28 #include "pixel_map.h"
29 
30 namespace OHOS {
31 namespace Media {
32 // Define bytes per pixel
33 constexpr int8_t ALPHA_8_BYTES = 1;
34 constexpr int8_t RGB_565_BYTES = 2;
35 constexpr int8_t RGB_888_BYTES = 3;
36 constexpr int8_t ARGB_8888_BYTES = 4;
37 constexpr int8_t BGRA_F16_BYTES = 8;
38 constexpr int8_t YUV420_BYTES = 2;  // in fact NV21 one pixel used 1.5 bytes.
39 constexpr int8_t YUV420_P010_BYTES = 3;
40 constexpr int8_t ASTC_4x4_BYTES = 1;
41 
42 // Define shift bits of bytes per pixel
43 constexpr int8_t ALPHA_8_SHIFT = 0;
44 constexpr int8_t RGB_565_SHIFT = 1;
45 constexpr int8_t ARGB_8888_SHIFT = 2;
46 
47 // Convert RGB565 16bit pixel to 32bit pixel
48 constexpr uint8_t RGB565_R_BITS = 5;
49 constexpr uint8_t RGB565_G_BITS = 6;
50 constexpr uint8_t RGB565_B_BITS = 5;
51 
52 #if __BYTE_ORDER == __LITTLE_ENDIAN
53 constexpr uint8_t RGB565_R_SHIFT = 0;
54 constexpr uint8_t RGB565_G_SHIFT = RGB565_R_BITS;
55 constexpr uint8_t RGB565_B_SHIFT = RGB565_R_BITS + RGB565_G_BITS;
56 constexpr uint16_t RGB565_R_MASK = 0x001F;
57 constexpr uint16_t RGB565_G_MASK = 0x07E0;
58 constexpr uint16_t RGB565_B_MASK = 0xF800;
59 #else
60 constexpr uint8_t RGB565_R_SHIFT = RGB565_B_BITS + RGB565_G_BITS;
61 constexpr uint8_t RGB565_G_SHIFT = RGB565_B_BITS;
62 constexpr uint8_t RGB565_B_SHIFT = 0;
63 constexpr uint16_t RGB565_R_MASK = 0xF800;
64 constexpr uint16_t RGB565_G_MASK = 0x07E0;
65 constexpr uint16_t RGB565_B_MASK = 0x001F;
66 #endif
67 constexpr uint8_t BYTE_BITS = 8;
68 constexpr uint8_t RGB565_CONVERT_BIT = 2;
69 constexpr uint8_t ARGB8888_CONVERT_BIT = 24;
70 
71 // Convert for ARGB_8888 32bit pixel
72 #if __BYTE_ORDER == __LITTLE_ENDIAN
73 constexpr uint8_t ARGB32_A_SHIFT = 0;
74 constexpr uint8_t ARGB32_R_SHIFT = 8;
75 constexpr uint8_t ARGB32_G_SHIFT = 16;
76 constexpr uint8_t ARGB32_B_SHIFT = 24;
77 #else
78 constexpr uint8_t ARGB32_A_SHIFT = 24;
79 constexpr uint8_t ARGB32_R_SHIFT = 16;
80 constexpr uint8_t ARGB32_G_SHIFT = 8;
81 constexpr uint8_t ARGB32_B_SHIFT = 0;
82 #endif
83 
84 // Convert for RGBA_8888 32bit pixel
85 #if __BYTE_ORDER == __LITTLE_ENDIAN
86 constexpr uint8_t RGBA32_R_SHIFT = 0;
87 constexpr uint8_t RGBA32_G_SHIFT = 8;
88 constexpr uint8_t RGBA32_B_SHIFT = 16;
89 constexpr uint8_t RGBA32_A_SHIFT = 24;
90 #else
91 constexpr uint8_t RGBA32_R_SHIFT = 24;
92 constexpr uint8_t RGBA32_G_SHIFT = 16;
93 constexpr uint8_t RGBA32_B_SHIFT = 8;
94 constexpr uint8_t RGBA32_A_SHIFT = 0;
95 #endif
96 
97 // Convert for BGRA_8888 32bit pixel
98 #if __BYTE_ORDER == __LITTLE_ENDIAN
99 constexpr uint8_t BGRA32_B_SHIFT = 0;
100 constexpr uint8_t BGRA32_G_SHIFT = 8;
101 constexpr uint8_t BGRA32_R_SHIFT = 16;
102 constexpr uint8_t BGRA32_A_SHIFT = 24;
103 #else
104 constexpr uint8_t BGRA32_B_SHIFT = 24;
105 constexpr uint8_t BGRA32_G_SHIFT = 16;
106 constexpr uint8_t BGRA32_R_SHIFT = 8;
107 constexpr uint8_t BGRA32_A_SHIFT = 0;
108 #endif
109 
110 constexpr uint8_t BYTE_FULL = 0xFF;
111 constexpr uint8_t BYTE_ZERO = 0;
112 constexpr uint8_t ONE_PIXEL_SIZE = 1;
113 
114 /*
115  * For RGB_565
116  * 1. get R(5-bits)/G(6-bits)/B(5-bits) channel value form color value(uint16_t)
117  * 2. convert R(5-bits)/G(6-bits)/B(5-bits) value to R(8-bits)/G(8-bits)/B(8-bits)
118  * 3. construct normalized color value with A(255)/R(8-bits)/G(8-bits)/B(8-bits)
119  * 4. the normalized color format: (A << 24 | R << 16 | G << 8 | B << 0)
120  */
GetRGB565Channel(uint16_t color,uint16_t mask,uint8_t shift)121 static uint8_t GetRGB565Channel(uint16_t color, uint16_t mask, uint8_t shift)
122 {
123     return (color & mask) >> shift;
124 }
125 
RGB565To32(uint8_t channel,uint8_t bits)126 static uint8_t RGB565To32(uint8_t channel, uint8_t bits)
127 {
128     return (channel << (BYTE_BITS - bits)) | (channel >> (RGB565_CONVERT_BIT * bits - BYTE_BITS));
129 }
130 
RGB565ToR32(uint16_t color)131 static uint8_t RGB565ToR32(uint16_t color)
132 {
133     return RGB565To32(GetRGB565Channel(color, RGB565_R_MASK, RGB565_R_SHIFT), RGB565_R_BITS);
134 }
135 
RGB565ToG32(uint16_t color)136 static uint8_t RGB565ToG32(uint16_t color)
137 {
138     return RGB565To32(GetRGB565Channel(color, RGB565_G_MASK, RGB565_G_SHIFT), RGB565_G_BITS);
139 }
140 
RGB565ToB32(uint16_t color)141 static uint8_t RGB565ToB32(uint16_t color)
142 {
143     return RGB565To32(GetRGB565Channel(color, RGB565_B_MASK, RGB565_B_SHIFT), RGB565_B_BITS);
144 }
145 
146 /*
147  * For ARGB_8888
148  * 1. get A(8-bits)/R(8-bits)/G(8-bits)/B(8-bits) channel value form color value(uint32_t)
149  * 2. construct normalized color value with A(8-bits)/R(8-bits)/G(8-bits)/B(8-bits)
150  * 3. the normalized color format: (A << 24 | R << 16 | G << 8 | B << 0)
151  */
GetColorComp(uint32_t color,uint8_t shift)152 static uint8_t GetColorComp(uint32_t color, uint8_t shift)
153 {
154     return ((color) << (ARGB8888_CONVERT_BIT - shift)) >> ARGB8888_CONVERT_BIT;
155 }
156 
GetColorARGB(uint8_t a,uint8_t r,uint8_t g,uint8_t b)157 static uint32_t GetColorARGB(uint8_t a, uint8_t r, uint8_t g, uint8_t b)
158 {
159     return ((uint32_t)(a << ARGB_A_SHIFT) | (uint32_t)(r << ARGB_R_SHIFT)
160         | (uint32_t)(g << ARGB_G_SHIFT) | (uint32_t)(b << ARGB_B_SHIFT));
161 }
162 
163 static ImageInfo MakeImageInfo(int width, int height, PixelFormat pf, AlphaType at, ColorSpace cs = ColorSpace::SRGB)
164 {
165     ImageInfo info;
166     info.size.width = width;
167     info.size.height = height;
168     info.pixelFormat = pf;
169     info.alphaType = at;
170     info.colorSpace = cs;
171     return info;
172 }
173 
174 static bool CheckAshmemSize(const int &fd, const int32_t &bufferSize, bool isAstc = false)
175 {
176 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) &&!defined(ANDROID_PLATFORM)
177     if (fd < 0) {
178         return false;
179     }
180     int32_t ashmemSize = AshmemGetSize(fd);
181     return isAstc || bufferSize == ashmemSize;
182 #else
183     return false;
184 #endif
185 }
186 
ExpandRGBToRGBX(const uint8_t * srcPixels,int32_t srcBytes,std::unique_ptr<uint8_t[]> & dstPixels)187 static bool ExpandRGBToRGBX(const uint8_t* srcPixels, int32_t srcBytes, std::unique_ptr<uint8_t[]>& dstPixels)
188 {
189     if (srcPixels == nullptr) {
190         IMAGE_LOGE("[PixelMap] ExpandRGBToRGBX failed: srcPixels is null");
191         return false;
192     }
193     int64_t dstBytes = srcBytes / RGB_888_BYTES * ARGB_8888_BYTES;
194     if (srcBytes <= 0 || dstBytes > INT32_MAX) {
195         IMAGE_LOGE("[PixelMap] ExpandRGBToRGBX failed: byte count invalid or overflowed");
196         return false;
197     }
198 
199     dstPixels = std::make_unique<uint8_t[]>(dstBytes);
200     if (!PixelConvertAdapter::RGBToRGBx(srcPixels, dstPixels.get(), srcBytes)) {
201         IMAGE_LOGE("[PixelMap] ExpandRGBToRGBX failed: format conversion failed");
202         return false;
203     }
204     return true;
205 }
206 
ShrinkRGBXToRGB(const std::unique_ptr<AbsMemory> & srcMemory,std::unique_ptr<AbsMemory> & dstMemory)207 static bool ShrinkRGBXToRGB(const std::unique_ptr<AbsMemory>& srcMemory, std::unique_ptr<AbsMemory>& dstMemory)
208 {
209     size_t srcBytes = srcMemory->data.size;
210     if (srcBytes > INT32_MAX) {
211         IMAGE_LOGE("[PixelMap] ShrinkRGBXToRGB failed: byte count too large");
212         return false;
213     }
214     int32_t dstBytes = static_cast<int32_t>(srcBytes) / ARGB_8888_BYTES * RGB_888_BYTES;
215     MemoryData memoryData = {nullptr, dstBytes, "Shrink RGBX to RGB"};
216     memoryData.format = PixelFormat::RGB_888;
217     dstMemory = MemoryManager::CreateMemory(srcMemory->GetType(), memoryData);
218     if (dstMemory == nullptr) {
219         IMAGE_LOGE("[PixelMap] ShrinkRGBXToRGB failed: allocate memory failed");
220         return false;
221     }
222 
223     if (!PixelConvertAdapter::RGBxToRGB(static_cast<uint8_t*>(srcMemory->data.data),
224         static_cast<uint8_t*>(dstMemory->data.data), srcBytes)) {
225         IMAGE_LOGE("[PixelMap] ShrinkRGBXToRGB failed: format conversion failed");
226         dstMemory->Release();
227         return false;
228     }
229     return true;
230 }
231 
ConvertArgbAndRgba(PixelMap * pixelMap,PixelFormat dstPixelFormat)232 static uint32_t ConvertArgbAndRgba(PixelMap *pixelMap, PixelFormat dstPixelFormat)
233 {
234     bool cond = pixelMap == nullptr;
235     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_INVALID_PARAMETER, "%{public}s pixelMap is nullptr", __func__);
236     PixelFormat srcPixelFormat = pixelMap->GetPixelFormat();
237     cond = !((srcPixelFormat == PixelFormat::RGBA_8888 && dstPixelFormat == PixelFormat::ARGB_8888) ||
238         (srcPixelFormat == PixelFormat::ARGB_8888 && dstPixelFormat == PixelFormat::RGBA_8888));
239     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_MEDIA_INVALID_OPERATION,
240         "%{public}s unsupported convert: srcPixelFormat:%{public}d, dstPixelFormat:%{public}d",
241         __func__, srcPixelFormat, dstPixelFormat);
242 
243     ImageInfo srcImageInfo;
244     pixelMap->GetImageInfo(srcImageInfo);
245     uint32_t byteCount = pixelMap->GetAllocationByteCount();
246     MemoryData memoryData = {
247         .data = nullptr,
248         .size = byteCount,
249         .tag = "ARGBConvert Data",
250         .desiredSize = srcImageInfo.size,
251         .format = dstPixelFormat
252     };
253     AllocatorType allocatorType = pixelMap->GetAllocatorType();
254     std::unique_ptr<AbsMemory> dstMemory = MemoryManager::CreateMemory(allocatorType, memoryData);
255     cond = dstMemory == nullptr;
256     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_MALLOC_ABNORMAL, "%{public}s CreateMemory failed!", __func__);
257     ImageInfo dstImageInfo = MakeImageInfo(srcImageInfo.size.width, srcImageInfo.size.height, dstPixelFormat,
258         AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
259     BufferInfo srcInfo = {
260         .pixels = pixelMap->GetWritablePixels(),
261         .rowStride = pixelMap->GetRowStride(),
262         .imageInfo = srcImageInfo
263     };
264     BufferInfo dstInfo = {
265         .pixels = dstMemory->data.data,
266         .rowStride = 0,
267         .imageInfo = dstImageInfo
268     };
269     int32_t dstLength = PixelConvert::PixelsConvert(srcInfo, dstInfo, byteCount, pixelMap->IsStrideAlignment());
270     if (dstLength < 0) {
271         IMAGE_LOGE("%{public}s Convert to %{public}d format failed!", __func__, dstPixelFormat);
272         dstMemory->Release();
273         return ERR_IMAGE_READ_PIXELMAP_FAILED;
274     }
275 
276     pixelMap->SetPixelsAddr(static_cast<void *>(dstMemory->data.data), dstMemory->extend.data,
277         byteCount, allocatorType, nullptr);
278     dstMemory.release();
279     return pixelMap->SetImageInfo(dstImageInfo, true);
280 }
281 } // namespace Media
282 } // namespace OHOS
283 
284 #endif // FRAMEWORKS_INNERKITSIMPL_COMMON_INCLUDE_PIXEL_MAP_UTILS_H
285