1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QPIXELFORMAT_H |
5 | #define QPIXELFORMAT_H |
6 | |
7 | #include <QtGui/qtguiglobal.h> |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | class QPixelFormat |
12 | { |
13 | // QPixelFormat basically is a glorified quint64, split into several fields. |
14 | // We could use bit-fields, but GCC at least generates horrible, horrible code for them, |
15 | // so we do the bit-twiddling ourselves. |
16 | enum FieldWidth { |
17 | ModelFieldWidth = 4, |
18 | FirstFieldWidth = 6, |
19 | SecondFieldWidth = FirstFieldWidth, |
20 | ThirdFieldWidth = FirstFieldWidth, |
21 | FourthFieldWidth = FirstFieldWidth, |
22 | FifthFieldWidth = FirstFieldWidth, |
23 | AlphaFieldWidth = FirstFieldWidth, |
24 | AlphaUsageFieldWidth = 1, |
25 | AlphaPositionFieldWidth = 1, |
26 | PremulFieldWidth = 1, |
27 | TypeInterpretationFieldWidth = 4, |
28 | ByteOrderFieldWidth = 2, |
29 | SubEnumFieldWidth = 6, |
30 | UnusedFieldWidth = 9, |
31 | |
32 | TotalFieldWidthByWidths = ModelFieldWidth + FirstFieldWidth + SecondFieldWidth + ThirdFieldWidth + |
33 | FourthFieldWidth + FifthFieldWidth + AlphaFieldWidth + AlphaUsageFieldWidth + |
34 | AlphaPositionFieldWidth + PremulFieldWidth + TypeInterpretationFieldWidth + |
35 | ByteOrderFieldWidth + SubEnumFieldWidth + UnusedFieldWidth |
36 | }; |
37 | |
38 | enum Field { |
39 | ModelField = 0, |
40 | // work around bug in old clang versions: when building webkit |
41 | // with XCode 4.6 and older this fails compilation, thus cast to int |
42 | FirstField = ModelField + int(ModelFieldWidth), |
43 | SecondField = FirstField + int(FirstFieldWidth), |
44 | ThirdField = SecondField + int(SecondFieldWidth), |
45 | FourthField = ThirdField + int(ThirdFieldWidth), |
46 | FifthField = FourthField + int(FourthFieldWidth), |
47 | AlphaField = FifthField + int(FifthFieldWidth), |
48 | AlphaUsageField = AlphaField + int(AlphaFieldWidth), |
49 | AlphaPositionField = AlphaUsageField + int(AlphaUsageFieldWidth), |
50 | PremulField = AlphaPositionField + int(AlphaPositionFieldWidth), |
51 | TypeInterpretationField = PremulField + int(PremulFieldWidth), |
52 | ByteOrderField = TypeInterpretationField + int(TypeInterpretationFieldWidth), |
53 | SubEnumField = ByteOrderField + int(ByteOrderFieldWidth), |
54 | UnusedField = SubEnumField + int(SubEnumFieldWidth), |
55 | |
56 | TotalFieldWidthByOffsets = UnusedField + int(UnusedFieldWidth) |
57 | }; |
58 | |
59 | static_assert(uint(TotalFieldWidthByWidths) == uint(TotalFieldWidthByOffsets)); |
60 | static_assert(uint(TotalFieldWidthByWidths) == 8 * sizeof(quint64)); |
61 | |
62 | constexpr inline uchar get(Field offset, FieldWidth width) const noexcept |
63 | { return uchar((data >> uint(offset)) & ((Q_UINT64_C(1) << uint(width)) - Q_UINT64_C(1))); } |
64 | constexpr static inline quint64 set(Field offset, FieldWidth width, uchar value) |
65 | { return (quint64(value) & ((Q_UINT64_C(1) << uint(width)) - Q_UINT64_C(1))) << uint(offset); } |
66 | |
67 | public: |
68 | enum ColorModel { |
69 | RGB, |
70 | BGR, |
71 | Indexed, |
72 | Grayscale, |
73 | CMYK, |
74 | HSL, |
75 | HSV, |
76 | YUV, |
77 | Alpha |
78 | }; |
79 | |
80 | enum AlphaUsage { |
81 | UsesAlpha, |
82 | IgnoresAlpha |
83 | }; |
84 | |
85 | enum AlphaPosition { |
86 | AtBeginning, |
87 | AtEnd |
88 | }; |
89 | |
90 | enum AlphaPremultiplied { |
91 | NotPremultiplied, |
92 | Premultiplied |
93 | }; |
94 | |
95 | enum TypeInterpretation { |
96 | UnsignedInteger, |
97 | UnsignedShort, |
98 | UnsignedByte, |
99 | FloatingPoint |
100 | }; |
101 | |
102 | enum YUVLayout { |
103 | YUV444, |
104 | YUV422, |
105 | YUV411, |
106 | YUV420P, |
107 | YUV420SP, |
108 | YV12, |
109 | UYVY, |
110 | YUYV, |
111 | NV12, |
112 | NV21, |
113 | IMC1, |
114 | IMC2, |
115 | IMC3, |
116 | IMC4, |
117 | Y8, |
118 | Y16 |
119 | }; |
120 | |
121 | enum ByteOrder { |
122 | LittleEndian, |
123 | BigEndian, |
124 | CurrentSystemEndian |
125 | }; |
126 | |
127 | constexpr inline QPixelFormat() noexcept : data(0) {} |
128 | constexpr inline QPixelFormat(ColorModel colorModel, |
129 | uchar firstSize, |
130 | uchar secondSize, |
131 | uchar thirdSize, |
132 | uchar fourthSize, |
133 | uchar fifthSize, |
134 | uchar alphaSize, |
135 | AlphaUsage alphaUsage, |
136 | AlphaPosition alphaPosition, |
137 | AlphaPremultiplied premultiplied, |
138 | TypeInterpretation typeInterpretation, |
139 | ByteOrder byteOrder = CurrentSystemEndian, |
140 | uchar subEnum = 0) noexcept; |
141 | |
142 | constexpr inline ColorModel colorModel() const noexcept { return ColorModel(get(offset: ModelField, width: ModelFieldWidth)); } |
143 | constexpr inline uchar channelCount() const noexcept { return (get(offset: FirstField, width: FirstFieldWidth) > 0) + |
144 | (get(offset: SecondField, width: SecondFieldWidth) > 0) + |
145 | (get(offset: ThirdField, width: ThirdFieldWidth) > 0) + |
146 | (get(offset: FourthField, width: FourthFieldWidth) > 0) + |
147 | (get(offset: FifthField, width: FifthFieldWidth) > 0) + |
148 | (get(offset: AlphaField, width: AlphaFieldWidth) > 0); } |
149 | |
150 | constexpr inline uchar redSize() const noexcept { return get(offset: FirstField, width: FirstFieldWidth); } |
151 | constexpr inline uchar greenSize() const noexcept { return get(offset: SecondField, width: SecondFieldWidth); } |
152 | constexpr inline uchar blueSize() const noexcept { return get(offset: ThirdField, width: ThirdFieldWidth); } |
153 | |
154 | constexpr inline uchar cyanSize() const noexcept { return get(offset: FirstField, width: FirstFieldWidth); } |
155 | constexpr inline uchar magentaSize() const noexcept { return get(offset: SecondField, width: SecondFieldWidth); } |
156 | constexpr inline uchar yellowSize() const noexcept { return get(offset: ThirdField, width: ThirdFieldWidth); } |
157 | constexpr inline uchar blackSize() const noexcept { return get(offset: FourthField, width: FourthFieldWidth); } |
158 | |
159 | constexpr inline uchar hueSize() const noexcept { return get(offset: FirstField, width: FirstFieldWidth); } |
160 | constexpr inline uchar saturationSize() const noexcept { return get(offset: SecondField, width: SecondFieldWidth); } |
161 | constexpr inline uchar lightnessSize() const noexcept { return get(offset: ThirdField, width: ThirdFieldWidth); } |
162 | constexpr inline uchar brightnessSize() const noexcept { return get(offset: ThirdField, width: ThirdFieldWidth); } |
163 | |
164 | constexpr inline uchar alphaSize() const noexcept { return get(offset: AlphaField, width: AlphaFieldWidth); } |
165 | |
166 | constexpr inline uchar bitsPerPixel() const noexcept { return get(offset: FirstField, width: FirstFieldWidth) + |
167 | get(offset: SecondField, width: SecondFieldWidth) + |
168 | get(offset: ThirdField, width: ThirdFieldWidth) + |
169 | get(offset: FourthField, width: FourthFieldWidth) + |
170 | get(offset: FifthField, width: FifthFieldWidth) + |
171 | get(offset: AlphaField, width: AlphaFieldWidth); } |
172 | |
173 | constexpr inline AlphaUsage alphaUsage() const noexcept { return AlphaUsage(get(offset: AlphaUsageField, width: AlphaUsageFieldWidth)); } |
174 | constexpr inline AlphaPosition alphaPosition() const noexcept { return AlphaPosition(get(offset: AlphaPositionField, width: AlphaPositionFieldWidth)); } |
175 | constexpr inline AlphaPremultiplied premultiplied() const noexcept { return AlphaPremultiplied(get(offset: PremulField, width: PremulFieldWidth)); } |
176 | constexpr inline TypeInterpretation typeInterpretation() const noexcept { return TypeInterpretation(get(offset: TypeInterpretationField, width: TypeInterpretationFieldWidth)); } |
177 | constexpr inline ByteOrder byteOrder() const noexcept { return ByteOrder(get(offset: ByteOrderField, width: ByteOrderFieldWidth)); } |
178 | |
179 | constexpr inline YUVLayout yuvLayout() const noexcept { return YUVLayout(get(offset: SubEnumField, width: SubEnumFieldWidth)); } |
180 | constexpr inline uchar subEnum() const noexcept { return get(offset: SubEnumField, width: SubEnumFieldWidth); } |
181 | |
182 | private: |
183 | constexpr static inline ByteOrder resolveByteOrder(ByteOrder bo) |
184 | { return bo == CurrentSystemEndian ? Q_BYTE_ORDER == Q_LITTLE_ENDIAN ? LittleEndian : BigEndian : bo ; } |
185 | |
186 | private: |
187 | quint64 data; |
188 | |
189 | friend Q_DECL_CONST_FUNCTION constexpr inline bool operator==(QPixelFormat fmt1, QPixelFormat fmt2) |
190 | { return fmt1.data == fmt2.data; } |
191 | |
192 | friend Q_DECL_CONST_FUNCTION constexpr inline bool operator!=(QPixelFormat fmt1, QPixelFormat fmt2) |
193 | { return !(fmt1 == fmt2); } |
194 | }; |
195 | static_assert(sizeof(QPixelFormat) == sizeof(quint64)); |
196 | Q_DECLARE_TYPEINFO(QPixelFormat, Q_PRIMITIVE_TYPE); |
197 | |
198 | |
199 | namespace QtPrivate { |
200 | QPixelFormat Q_GUI_EXPORT QPixelFormat_createYUV(QPixelFormat::YUVLayout yuvLayout, |
201 | uchar alphaSize, |
202 | QPixelFormat::AlphaUsage alphaUsage, |
203 | QPixelFormat::AlphaPosition alphaPosition, |
204 | QPixelFormat::AlphaPremultiplied premultiplied, |
205 | QPixelFormat::TypeInterpretation typeInterpretation, |
206 | QPixelFormat::ByteOrder byteOrder); |
207 | } |
208 | |
209 | constexpr QPixelFormat::QPixelFormat(ColorModel mdl, |
210 | uchar firstSize, |
211 | uchar secondSize, |
212 | uchar thirdSize, |
213 | uchar fourthSize, |
214 | uchar fifthSize, |
215 | uchar alfa, |
216 | AlphaUsage usage, |
217 | AlphaPosition position, |
218 | AlphaPremultiplied premult, |
219 | TypeInterpretation typeInterp, |
220 | ByteOrder b_order, |
221 | uchar s_enum) noexcept |
222 | : data(set(offset: ModelField, width: ModelFieldWidth, value: uchar(mdl)) | |
223 | set(offset: FirstField, width: FirstFieldWidth, value: firstSize) | |
224 | set(offset: SecondField, width: SecondFieldWidth, value: secondSize) | |
225 | set(offset: ThirdField, width: ThirdFieldWidth, value: thirdSize) | |
226 | set(offset: FourthField, width: FourthFieldWidth, value: fourthSize) | |
227 | set(offset: FifthField, width: FifthFieldWidth, value: fifthSize) | |
228 | set(offset: AlphaField, width: AlphaFieldWidth, value: alfa) | |
229 | set(offset: AlphaUsageField, width: AlphaUsageFieldWidth, value: uchar(usage)) | |
230 | set(offset: AlphaPositionField, width: AlphaPositionFieldWidth, value: uchar(position)) | |
231 | set(offset: PremulField, width: PremulFieldWidth, value: uchar(premult)) | |
232 | set(offset: TypeInterpretationField, width: TypeInterpretationFieldWidth, value: uchar(typeInterp)) | |
233 | set(offset: ByteOrderField, width: ByteOrderFieldWidth, value: uchar(resolveByteOrder(bo: b_order))) | |
234 | set(offset: SubEnumField, width: SubEnumFieldWidth, value: s_enum) | |
235 | set(offset: UnusedField, width: UnusedFieldWidth, value: 0)) |
236 | { |
237 | } |
238 | |
239 | constexpr inline QPixelFormat qPixelFormatRgba(uchar red, |
240 | uchar green, |
241 | uchar blue, |
242 | uchar alfa, |
243 | QPixelFormat::AlphaUsage usage, |
244 | QPixelFormat::AlphaPosition position, |
245 | QPixelFormat::AlphaPremultiplied pmul=QPixelFormat::NotPremultiplied, |
246 | QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) noexcept |
247 | { |
248 | return QPixelFormat(QPixelFormat::RGB, |
249 | red, |
250 | green, |
251 | blue, |
252 | 0, |
253 | 0, |
254 | alfa, |
255 | usage, |
256 | position, |
257 | pmul, |
258 | typeInt); |
259 | } |
260 | |
261 | constexpr inline QPixelFormat qPixelFormatGrayscale(uchar channelSize, |
262 | QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) noexcept |
263 | { |
264 | return QPixelFormat(QPixelFormat::Grayscale, |
265 | channelSize, |
266 | 0, |
267 | 0, |
268 | 0, |
269 | 0, |
270 | 0, |
271 | QPixelFormat::IgnoresAlpha, |
272 | QPixelFormat::AtBeginning, |
273 | QPixelFormat::NotPremultiplied, |
274 | typeInt); |
275 | } |
276 | |
277 | constexpr inline QPixelFormat qPixelFormatAlpha(uchar channelSize, |
278 | QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) noexcept |
279 | { |
280 | return QPixelFormat(QPixelFormat::Alpha, |
281 | 0, |
282 | 0, |
283 | 0, |
284 | 0, |
285 | 0, |
286 | channelSize, |
287 | QPixelFormat::UsesAlpha, |
288 | QPixelFormat::AtBeginning, |
289 | QPixelFormat::NotPremultiplied, |
290 | typeInt); |
291 | } |
292 | |
293 | constexpr inline QPixelFormat qPixelFormatCmyk(uchar channelSize, |
294 | uchar alfa=0, |
295 | QPixelFormat::AlphaUsage usage=QPixelFormat::IgnoresAlpha, |
296 | QPixelFormat::AlphaPosition position=QPixelFormat::AtBeginning, |
297 | QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) noexcept |
298 | { |
299 | return QPixelFormat(QPixelFormat::CMYK, |
300 | channelSize, |
301 | channelSize, |
302 | channelSize, |
303 | channelSize, |
304 | 0, |
305 | alfa, |
306 | usage, |
307 | position, |
308 | QPixelFormat::NotPremultiplied, |
309 | typeInt); |
310 | } |
311 | |
312 | constexpr inline QPixelFormat qPixelFormatHsl(uchar channelSize, |
313 | uchar alfa=0, |
314 | QPixelFormat::AlphaUsage usage=QPixelFormat::IgnoresAlpha, |
315 | QPixelFormat::AlphaPosition position=QPixelFormat::AtBeginning, |
316 | QPixelFormat::TypeInterpretation typeInt=QPixelFormat::FloatingPoint) noexcept |
317 | { |
318 | return QPixelFormat(QPixelFormat::HSL, |
319 | channelSize, |
320 | channelSize, |
321 | channelSize, |
322 | 0, |
323 | 0, |
324 | alfa, |
325 | usage, |
326 | position, |
327 | QPixelFormat::NotPremultiplied, |
328 | typeInt); |
329 | } |
330 | |
331 | constexpr inline QPixelFormat qPixelFormatHsv(uchar channelSize, |
332 | uchar alfa=0, |
333 | QPixelFormat::AlphaUsage usage=QPixelFormat::IgnoresAlpha, |
334 | QPixelFormat::AlphaPosition position=QPixelFormat::AtBeginning, |
335 | QPixelFormat::TypeInterpretation typeInt=QPixelFormat::FloatingPoint) noexcept |
336 | { |
337 | return QPixelFormat(QPixelFormat::HSV, |
338 | channelSize, |
339 | channelSize, |
340 | channelSize, |
341 | 0, |
342 | 0, |
343 | alfa, |
344 | usage, |
345 | position, |
346 | QPixelFormat::NotPremultiplied, |
347 | typeInt); |
348 | } |
349 | |
350 | inline QPixelFormat qPixelFormatYuv(QPixelFormat::YUVLayout layout, |
351 | uchar alfa=0, |
352 | QPixelFormat::AlphaUsage usage=QPixelFormat::IgnoresAlpha, |
353 | QPixelFormat::AlphaPosition position=QPixelFormat::AtBeginning, |
354 | QPixelFormat::AlphaPremultiplied p_mul=QPixelFormat::NotPremultiplied, |
355 | QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedByte, |
356 | QPixelFormat::ByteOrder b_order=QPixelFormat::LittleEndian) |
357 | { |
358 | return QtPrivate::QPixelFormat_createYUV(yuvLayout: layout, |
359 | alphaSize: alfa, |
360 | alphaUsage: usage, |
361 | alphaPosition: position, |
362 | premultiplied: p_mul, |
363 | typeInterpretation: typeInt, |
364 | byteOrder: b_order); |
365 | } |
366 | |
367 | QT_END_NAMESPACE |
368 | |
369 | #endif //QPIXELFORMAT_H |
370 | |