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_adapter.h"
27 #include "pixel_map.h"
28
29 namespace OHOS {
30 namespace Media {
31 // Define bytes per pixel
32 constexpr int8_t ALPHA_8_BYTES = 1;
33 constexpr int8_t RGB_565_BYTES = 2;
34 constexpr int8_t RGB_888_BYTES = 3;
35 constexpr int8_t ARGB_8888_BYTES = 4;
36 constexpr int8_t BGRA_F16_BYTES = 8;
37 constexpr int8_t YUV420_BYTES = 2; // in fact NV21 one pixel used 1.5 bytes.
38 constexpr int8_t YUV420_P010_BYTES = 3;
39 constexpr int8_t ASTC_4x4_BYTES = 1;
40
41 // Define shift bits of bytes per pixel
42 constexpr int8_t ALPHA_8_SHIFT = 0;
43 constexpr int8_t RGB_565_SHIFT = 1;
44 constexpr int8_t ARGB_8888_SHIFT = 2;
45
46 // Convert RGB565 16bit pixel to 32bit pixel
47 constexpr uint8_t RGB565_R_BITS = 5;
48 constexpr uint8_t RGB565_G_BITS = 6;
49 constexpr uint8_t RGB565_B_BITS = 5;
50
51 #if __BYTE_ORDER == __LITTLE_ENDIAN
52 constexpr uint8_t RGB565_R_SHIFT = 0;
53 constexpr uint8_t RGB565_G_SHIFT = RGB565_R_BITS;
54 constexpr uint8_t RGB565_B_SHIFT = RGB565_R_BITS + RGB565_G_BITS;
55 constexpr uint16_t RGB565_R_MASK = 0x001F;
56 constexpr uint16_t RGB565_G_MASK = 0x07E0;
57 constexpr uint16_t RGB565_B_MASK = 0xF800;
58 #else
59 constexpr uint8_t RGB565_R_SHIFT = RGB565_B_BITS + RGB565_G_BITS;
60 constexpr uint8_t RGB565_G_SHIFT = RGB565_B_BITS;
61 constexpr uint8_t RGB565_B_SHIFT = 0;
62 constexpr uint16_t RGB565_R_MASK = 0xF800;
63 constexpr uint16_t RGB565_G_MASK = 0x07E0;
64 constexpr uint16_t RGB565_B_MASK = 0x001F;
65 #endif
66 constexpr uint8_t BYTE_BITS = 8;
67 constexpr uint8_t RGB565_CONVERT_BIT = 2;
68 constexpr uint8_t ARGB8888_CONVERT_BIT = 24;
69
70 // Convert for ARGB_8888 32bit pixel
71 #if __BYTE_ORDER == __LITTLE_ENDIAN
72 constexpr uint8_t ARGB32_A_SHIFT = 0;
73 constexpr uint8_t ARGB32_R_SHIFT = 8;
74 constexpr uint8_t ARGB32_G_SHIFT = 16;
75 constexpr uint8_t ARGB32_B_SHIFT = 24;
76 #else
77 constexpr uint8_t ARGB32_A_SHIFT = 24;
78 constexpr uint8_t ARGB32_R_SHIFT = 16;
79 constexpr uint8_t ARGB32_G_SHIFT = 8;
80 constexpr uint8_t ARGB32_B_SHIFT = 0;
81 #endif
82
83 // Convert for RGBA_8888 32bit pixel
84 #if __BYTE_ORDER == __LITTLE_ENDIAN
85 constexpr uint8_t RGBA32_R_SHIFT = 0;
86 constexpr uint8_t RGBA32_G_SHIFT = 8;
87 constexpr uint8_t RGBA32_B_SHIFT = 16;
88 constexpr uint8_t RGBA32_A_SHIFT = 24;
89 #else
90 constexpr uint8_t RGBA32_R_SHIFT = 24;
91 constexpr uint8_t RGBA32_G_SHIFT = 16;
92 constexpr uint8_t RGBA32_B_SHIFT = 8;
93 constexpr uint8_t RGBA32_A_SHIFT = 0;
94 #endif
95
96 // Convert for BGRA_8888 32bit pixel
97 #if __BYTE_ORDER == __LITTLE_ENDIAN
98 constexpr uint8_t BGRA32_B_SHIFT = 0;
99 constexpr uint8_t BGRA32_G_SHIFT = 8;
100 constexpr uint8_t BGRA32_R_SHIFT = 16;
101 constexpr uint8_t BGRA32_A_SHIFT = 24;
102 #else
103 constexpr uint8_t BGRA32_B_SHIFT = 24;
104 constexpr uint8_t BGRA32_G_SHIFT = 16;
105 constexpr uint8_t BGRA32_R_SHIFT = 8;
106 constexpr uint8_t BGRA32_A_SHIFT = 0;
107 #endif
108
109 constexpr uint8_t BYTE_FULL = 0xFF;
110 constexpr uint8_t BYTE_ZERO = 0;
111 constexpr uint8_t ONE_PIXEL_SIZE = 1;
112
113 /*
114 * For RGB_565
115 * 1. get R(5-bits)/G(6-bits)/B(5-bits) channel value form color value(uint16_t)
116 * 2. convert R(5-bits)/G(6-bits)/B(5-bits) value to R(8-bits)/G(8-bits)/B(8-bits)
117 * 3. construct normalized color value with A(255)/R(8-bits)/G(8-bits)/B(8-bits)
118 * 4. the normalized color format: (A << 24 | R << 16 | G << 8 | B << 0)
119 */
GetRGB565Channel(uint16_t color,uint16_t mask,uint8_t shift)120 static uint8_t GetRGB565Channel(uint16_t color, uint16_t mask, uint8_t shift)
121 {
122 return (color & mask) >> shift;
123 }
124
RGB565To32(uint8_t channel,uint8_t bits)125 static uint8_t RGB565To32(uint8_t channel, uint8_t bits)
126 {
127 return (channel << (BYTE_BITS - bits)) | (channel >> (RGB565_CONVERT_BIT * bits - BYTE_BITS));
128 }
129
RGB565ToR32(uint16_t color)130 static uint8_t RGB565ToR32(uint16_t color)
131 {
132 return RGB565To32(GetRGB565Channel(color, RGB565_R_MASK, RGB565_R_SHIFT), RGB565_R_BITS);
133 }
134
RGB565ToG32(uint16_t color)135 static uint8_t RGB565ToG32(uint16_t color)
136 {
137 return RGB565To32(GetRGB565Channel(color, RGB565_G_MASK, RGB565_G_SHIFT), RGB565_G_BITS);
138 }
139
RGB565ToB32(uint16_t color)140 static uint8_t RGB565ToB32(uint16_t color)
141 {
142 return RGB565To32(GetRGB565Channel(color, RGB565_B_MASK, RGB565_B_SHIFT), RGB565_B_BITS);
143 }
144
145 /*
146 * For ARGB_8888
147 * 1. get A(8-bits)/R(8-bits)/G(8-bits)/B(8-bits) channel value form color value(uint32_t)
148 * 2. construct normalized color value with A(8-bits)/R(8-bits)/G(8-bits)/B(8-bits)
149 * 3. the normalized color format: (A << 24 | R << 16 | G << 8 | B << 0)
150 */
GetColorComp(uint32_t color,uint8_t shift)151 static uint8_t GetColorComp(uint32_t color, uint8_t shift)
152 {
153 return ((color) << (ARGB8888_CONVERT_BIT - shift)) >> ARGB8888_CONVERT_BIT;
154 }
155
GetColorARGB(uint8_t a,uint8_t r,uint8_t g,uint8_t b)156 static uint32_t GetColorARGB(uint8_t a, uint8_t r, uint8_t g, uint8_t b)
157 {
158 return ((uint32_t)(a << ARGB_A_SHIFT) | (uint32_t)(r << ARGB_R_SHIFT)
159 | (uint32_t)(g << ARGB_G_SHIFT) | (uint32_t)(b << ARGB_B_SHIFT));
160 }
161
162 static ImageInfo MakeImageInfo(int width, int height, PixelFormat pf, AlphaType at, ColorSpace cs = ColorSpace::SRGB)
163 {
164 ImageInfo info;
165 info.size.width = width;
166 info.size.height = height;
167 info.pixelFormat = pf;
168 info.alphaType = at;
169 info.colorSpace = cs;
170 return info;
171 }
172
173 static bool CheckAshmemSize(const int &fd, const int32_t &bufferSize, bool isAstc = false)
174 {
175 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) &&!defined(ANDROID_PLATFORM)
176 if (fd < 0) {
177 return false;
178 }
179 int32_t ashmemSize = AshmemGetSize(fd);
180 return isAstc || bufferSize == ashmemSize;
181 #else
182 return false;
183 #endif
184 }
185
ExpandRGBToRGBX(const uint8_t * srcPixels,int32_t srcBytes,std::unique_ptr<uint8_t[]> & dstPixels)186 static bool ExpandRGBToRGBX(const uint8_t* srcPixels, int32_t srcBytes, std::unique_ptr<uint8_t[]>& dstPixels)
187 {
188 if (srcPixels == nullptr) {
189 IMAGE_LOGE("[PixelMap] ExpandRGBToRGBX failed: srcPixels is null");
190 return false;
191 }
192 int64_t dstBytes = srcBytes / RGB_888_BYTES * ARGB_8888_BYTES;
193 if (srcBytes <= 0 || dstBytes > INT32_MAX) {
194 IMAGE_LOGE("[PixelMap] ExpandRGBToRGBX failed: byte count invalid or overflowed");
195 return false;
196 }
197
198 dstPixels = std::make_unique<uint8_t[]>(dstBytes);
199 if (!PixelConvertAdapter::RGBToRGBx(srcPixels, dstPixels.get(), srcBytes)) {
200 IMAGE_LOGE("[PixelMap] ExpandRGBToRGBX failed: format conversion failed");
201 return false;
202 }
203 return true;
204 }
205
ShrinkRGBXToRGB(const std::unique_ptr<AbsMemory> & srcMemory,std::unique_ptr<AbsMemory> & dstMemory)206 static bool ShrinkRGBXToRGB(const std::unique_ptr<AbsMemory>& srcMemory, std::unique_ptr<AbsMemory>& dstMemory)
207 {
208 size_t srcBytes = srcMemory->data.size;
209 if (srcBytes > INT32_MAX) {
210 IMAGE_LOGE("[PixelMap] ShrinkRGBXToRGB failed: byte count too large");
211 return false;
212 }
213 int32_t dstBytes = static_cast<int32_t>(srcBytes) / ARGB_8888_BYTES * RGB_888_BYTES;
214 MemoryData memoryData = {nullptr, dstBytes, "Shrink RGBX to RGB"};
215 memoryData.format = PixelFormat::RGB_888;
216 memoryData.usage = srcMemory->data.usage;
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 } // namespace Media
232 } // namespace OHOS
233
234 #endif // FRAMEWORKS_INNERKITSIMPL_COMMON_INCLUDE_PIXEL_MAP_UTILS_H
235