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_CONVERTER_INCLUDE_PIXEL_CONVERT_H
17 #define FRAMEWORKS_INNERKITSIMPL_CONVERTER_INCLUDE_PIXEL_CONVERT_H
18
19 #include <cstdint>
20 #include <cmath>
21 #include <memory>
22 #include "image_type.h"
23
24 namespace OHOS {
25 namespace Media {
26 enum class AlphaConvertType : uint32_t {
27 NO_CONVERT = 0,
28 PREMUL_CONVERT_UNPREMUL = 1,
29 PREMUL_CONVERT_OPAQUE = 2,
30 UNPREMUL_CONVERT_PREMUL = 3,
31 UNPREMUL_CONVERT_OPAQUE = 4,
32 };
33
34 // now support AlphaConvertType
35 struct ProcFuncExtension {
36 AlphaConvertType alphaConvertType;
37 };
38
39 // These values SHOULD be sync with image_type.h PixelFormat
40 constexpr uint32_t GRAY_BIT = 0x80000001; /* Tow value image, just white or black. */
41 constexpr uint32_t GRAY_ALPHA = 0x80000002;
42 constexpr uint32_t ARGB_8888 = 0x00000001;
43 constexpr uint32_t RGB_565 = 0x00000002;
44 constexpr uint32_t RGBA_8888 = 0x00000003;
45 constexpr uint32_t BGRA_8888 = 0x00000004;
46 constexpr uint32_t RGB_888 = 0x00000005;
47 constexpr uint32_t ALPHA_8 = 0x00000006; /* Gray image, 8 bit = 255 color. */
48 constexpr uint32_t RGBA_F16 = 0x00000007;
49 constexpr uint32_t ABGR_8888 = 0x00000008;
50 constexpr uint32_t BGR_888 = 0x40000002;
51 constexpr uint32_t RGB_161616 = 0x40000007;
52 constexpr uint32_t RGBA_16161616 = 0x40000008;
53
54 constexpr uint32_t CMKY = 0x0000000A;
55
56 constexpr uint32_t SIZE_1_BYTE = 0x00000001; /* a pixel has 8 bit = 1 byte */
57 constexpr uint32_t SIZE_2_BYTE = 0x00000002; /* a pixel has 16 bit = 2 byte */
58 constexpr uint32_t SIZE_3_BYTE = 0x00000003;
59 constexpr uint32_t SIZE_4_BYTE = 0x00000004;
60 constexpr uint32_t SIZE_6_BYTE = 0x00000006;
61 constexpr uint32_t SIZE_8_BYTE = 0x00000008;
62
63 constexpr uint8_t GRAYSCALE_WHITE = 0xFF;
64 constexpr uint8_t GRAYSCALE_BLACK = 0x00;
65 constexpr uint32_t ARGB_WHITE = 0xFFFFFFFF;
66 constexpr uint32_t ARGB_BLACK = 0xFF000000;
67 constexpr uint16_t RGB_WHITE = 0xFFFF;
68 constexpr uint16_t RGB_BLACK = 0x0000;
69
70 constexpr uint8_t ALPHA_OPAQUE = 0xFF;
71 constexpr uint8_t ALPHA_TRANSPARENT = 0x00;
72
73 constexpr uint32_t GET_8_BIT = 0x80;
74 constexpr uint32_t GET_1_BIT = 0x01;
75
76 constexpr uint32_t SHIFT_48_BIT = 0x30;
77 constexpr uint32_t SHIFT_32_BIT = 0x20;
78 constexpr uint32_t SHIFT_24_BIT = 0x18;
79 constexpr uint32_t SHIFT_16_BIT = 0x10;
80 constexpr uint32_t SHIFT_8_BIT = 0x08;
81 constexpr uint32_t SHIFT_11_BIT = 0x0B;
82 constexpr uint32_t SHIFT_5_BIT = 0x05;
83 constexpr uint32_t SHIFT_3_BIT = 0x03;
84 constexpr uint32_t SHIFT_2_BIT = 0x02;
85
86 constexpr uint32_t SHIFT_32_MASK = 0x80000000;
87 constexpr uint32_t SHIFT_16_MASK = 0x8000;
88 constexpr uint32_t SHIFT_7_MASK = 0x1C000;
89 constexpr uint8_t SHIFT_5_MASK = 0x1F;
90 constexpr uint8_t SHIFT_3_MASK = 0x07;
91
92 constexpr uint8_t SHIFT_HALF_BIT = 0x0D;
93 constexpr uint32_t SHIFT_HALF_MASK = 0x38000000;
94
95 constexpr uint16_t MAX_15_BIT_VALUE = 0x7FFF;
96 constexpr uint16_t MAX_16_BIT_VALUE = 0xFFFF;
97 constexpr uint32_t MAX_31_BIT_VALUE = 0x7FFFFFFF;
98 constexpr float HALF_ONE = 0.5F;
99 constexpr float MAX_HALF = 65504;
100 constexpr float MIN_EPSILON = 1e-6;
101
FloatCompareTo(float val,float compare)102 static inline bool FloatCompareTo(float val, float compare)
103 {
104 return fabs(val - compare) < MIN_EPSILON;
105 }
106
Premul255(uint32_t colorComponent,uint32_t alpha)107 static inline uint32_t Premul255(uint32_t colorComponent, uint32_t alpha)
108 {
109 if (colorComponent == 0 || colorComponent > MAX_15_BIT_VALUE || alpha > MAX_15_BIT_VALUE) {
110 return 0;
111 }
112 uint32_t product = colorComponent * alpha + GET_8_BIT;
113 if (colorComponent * alpha / colorComponent != alpha) {
114 return 0;
115 }
116 return ((product + (product >> SHIFT_8_BIT)) >> SHIFT_8_BIT);
117 }
118
Unpremul255(uint32_t colorComponent,uint32_t alpha)119 static inline uint32_t Unpremul255(uint32_t colorComponent, uint32_t alpha)
120 {
121 if (colorComponent > ALPHA_OPAQUE || alpha > ALPHA_OPAQUE) {
122 return 0;
123 }
124 if (alpha == ALPHA_TRANSPARENT) {
125 return ALPHA_TRANSPARENT;
126 }
127 if (alpha == ALPHA_OPAQUE) {
128 return colorComponent;
129 }
130 uint32_t result = static_cast<float>(colorComponent) * ALPHA_OPAQUE / alpha + HALF_ONE;
131 return (result > ALPHA_OPAQUE) ? ALPHA_OPAQUE : result;
132 }
133
FloatToUint(float f)134 static inline uint32_t FloatToUint(float f)
135 {
136 uint32_t *p = reinterpret_cast<uint32_t*>(&f);
137 return *p;
138 }
139
UintToFloat(uint32_t ui)140 static inline float UintToFloat(uint32_t ui)
141 {
142 float *pf = reinterpret_cast<float*>(&ui);
143 return *pf;
144 }
145
FloatToHalf(float f)146 static inline uint16_t FloatToHalf(float f)
147 {
148 uint32_t u32 = FloatToUint(f);
149 uint16_t u16 = static_cast<uint16_t>(
150 (((u32 & MAX_31_BIT_VALUE) >> SHIFT_HALF_BIT) - SHIFT_7_MASK) & MAX_16_BIT_VALUE);
151 u16 |= static_cast<uint16_t>(
152 ((u32 & SHIFT_32_MASK) >> SHIFT_16_BIT) & MAX_16_BIT_VALUE);
153 return u16;
154 }
155
HalfToFloat(uint16_t ui)156 static inline float HalfToFloat(uint16_t ui)
157 {
158 uint32_t u32 = ((ui & MAX_15_BIT_VALUE) << SHIFT_HALF_BIT) + SHIFT_HALF_MASK;
159 u32 |= ((ui & SHIFT_16_MASK) << SHIFT_16_BIT);
160 return UintToFloat(u32);
161 }
162
U8ToU16(uint8_t val1,uint8_t val2)163 static inline uint16_t U8ToU16(uint8_t val1, uint8_t val2)
164 {
165 uint16_t ret = val1;
166 return ((ret << SHIFT_8_BIT) | val2);
167 }
168
HalfToUint32(const uint8_t * ui,bool isLittleEndian)169 static inline uint32_t HalfToUint32(const uint8_t* ui, bool isLittleEndian)
170 {
171 uint16_t val = isLittleEndian ? U8ToU16(*ui, *(ui + 1)) : U8ToU16(*(ui + 1), *ui);
172 float fRet = HalfToFloat(val);
173 return static_cast<uint32_t>(fRet);
174 }
175
176 using ProcFuncType = void (*)(void *destinationRow, const uint8_t *sourceRow, uint32_t sourceWidth,
177 const ProcFuncExtension &extension);
178 class PixelConvert {
179 public:
180 ~PixelConvert() = default;
181 static std::unique_ptr<PixelConvert> Create(const ImageInfo &srcInfo, const ImageInfo &dstInfo);
182 void Convert(void *destinationPixels, const uint8_t *sourcePixels, uint32_t sourcePixelsNum);
183
184 private:
185 PixelConvert(ProcFuncType funcPtr, ProcFuncExtension extension, bool isNeedConvert);
186 static AlphaConvertType GetAlphaConvertType(const AlphaType &srcType, const AlphaType &dstType);
187
188 ProcFuncType procFunc_;
189 ProcFuncExtension procFuncExtension_;
190 bool isNeedConvert_ = true;
191 };
192 } // namespace Media
193 } // namespace OHOS
194
195 #endif // FRAMEWORKS_INNERKITSIMPL_CONVERTER_INCLUDE_PIXEL_CONVERT_H
196