14#include "scanlineconverter_p.h"
22#ifndef DDS_DISABLE_STRIDE_ALIGNMENT
41 FormatA2B10G10R10 = 31,
45 FormatA2R10G10B10 = 35,
46 FormatA16B16G16R16 = 36,
60 FormatA2W10V10U10 = 67,
62 FormatUYVY = 0x59565955,
63 FormatR8G8B8G8 = 0x47424752,
64 FormatYUY2 = 0x32595559,
65 FormatG8R8G8B8 = 0x42475247,
66 FormatDXT1 = 0x31545844,
67 FormatDXT2 = 0x32545844,
68 FormatDXT3 = 0x33545844,
69 FormatDXT4 = 0x34545844,
70 FormatDXT5 = 0x35545844,
71 FormatRXGB = 0x42475852,
72 FormatATI2 = 0x32495441,
74 FormatD16Lockable = 70,
82 FormatD32FLockable = 82,
85 FormatD32Lockable = 84,
86 FormatS8Lockable = 85,
90 FormatVertexData =100,
94 FormatQ16W16V16U16 = 110,
96 FormatMulti2ARGB8 = 0x3154454d,
100 FormatA16B16G16R16F = 113,
104 FormatA32B32G32R32F = 116,
109 FormatA2B10G10R10_XR_BIAS = 119,
110 FormatBinaryBuffer = 199,
115 FormatLast = 0x7fffffff
119 DXGIFormatUNKNOWN = 0,
120 DXGIFormatR32G32B32A32_TYPELESS = 1,
121 DXGIFormatR32G32B32A32_FLOAT = 2,
122 DXGIFormatR32G32B32A32_UINT = 3,
123 DXGIFormatR32G32B32A32_SINT = 4,
124 DXGIFormatR32G32B32_TYPELESS = 5,
125 DXGIFormatR32G32B32_FLOAT = 6,
126 DXGIFormatR32G32B32_UINT = 7,
127 DXGIFormatR32G32B32_SINT = 8,
128 DXGIFormatR16G16B16A16_TYPELESS = 9,
129 DXGIFormatR16G16B16A16_FLOAT = 10,
130 DXGIFormatR16G16B16A16_UNORM = 11,
131 DXGIFormatR16G16B16A16_UINT = 12,
132 DXGIFormatR16G16B16A16_SNORM = 13,
133 DXGIFormatR16G16B16A16_SINT = 14,
134 DXGIFormatR32G32_TYPELESS = 15,
135 DXGIFormatR32G32_FLOAT = 16,
136 DXGIFormatR32G32_UINT = 17,
137 DXGIFormatR32G32_SINT = 18,
138 DXGIFormatR32G8X24_TYPELESS = 19,
139 DXGIFormatD32_FLOAT_S8X24_UINT = 20,
140 DXGIFormatR32_FLOAT_X8X24_TYPELESS = 21,
141 DXGIFormatX32_TYPELESS_G8X24_UINT = 22,
142 DXGIFormatR10G10B10A2_TYPELESS = 23,
143 DXGIFormatR10G10B10A2_UNORM = 24,
144 DXGIFormatR10G10B10A2_UINT = 25,
145 DXGIFormatR11G11B10_FLOAT = 26,
146 DXGIFormatR8G8B8A8_TYPELESS = 27,
147 DXGIFormatR8G8B8A8_UNORM = 28,
148 DXGIFormatR8G8B8A8_UNORM_SRGB = 29,
149 DXGIFormatR8G8B8A8_UINT = 30,
150 DXGIFormatR8G8B8A8_SNORM = 31,
151 DXGIFormatR8G8B8A8_SINT = 32,
152 DXGIFormatR16G16_TYPELESS = 33,
153 DXGIFormatR16G16_FLOAT = 34,
154 DXGIFormatR16G16_UNORM = 35,
155 DXGIFormatR16G16_UINT = 36,
156 DXGIFormatR16G16_SNORM = 37,
157 DXGIFormatR16G16_SINT = 38,
158 DXGIFormatR32_TYPELESS = 39,
159 DXGIFormatD32_FLOAT = 40,
160 DXGIFormatR32_FLOAT = 41,
161 DXGIFormatR32_UINT = 42,
162 DXGIFormatR32_SINT = 43,
163 DXGIFormatR24G8_TYPELESS = 44,
164 DXGIFormatD24_UNORM_S8_UINT = 45,
165 DXGIFormatR24_UNORM_X8_TYPELESS = 46,
166 DXGIFormatX24_TYPELESS_G8_UINT = 47,
167 DXGIFormatR8G8_TYPELESS = 48,
168 DXGIFormatR8G8_UNORM = 49,
169 DXGIFormatR8G8_UINT = 50,
170 DXGIFormatR8G8_SNORM = 51,
171 DXGIFormatR8G8_SINT = 52,
172 DXGIFormatR16_TYPELESS = 53,
173 DXGIFormatR16_FLOAT = 54,
174 DXGIFormatD16_UNORM = 55,
175 DXGIFormatR16_UNORM = 56,
176 DXGIFormatR16_UINT = 57,
177 DXGIFormatR16_SNORM = 58,
178 DXGIFormatR16_SINT = 59,
179 DXGIFormatR8_TYPELESS = 60,
180 DXGIFormatR8_UNORM = 61,
181 DXGIFormatR8_UINT = 62,
182 DXGIFormatR8_SNORM = 63,
183 DXGIFormatR8_SINT = 64,
184 DXGIFormatA8_UNORM = 65,
185 DXGIFormatR1_UNORM = 66,
186 DXGIFormatR9G9B9E5_SHAREDEXP = 67,
187 DXGIFormatR8G8_B8G8_UNORM = 68,
188 DXGIFormatG8R8_G8B8_UNORM = 69,
189 DXGIFormatBC1_TYPELESS = 70,
190 DXGIFormatBC1_UNORM = 71,
191 DXGIFormatBC1_UNORM_SRGB = 72,
192 DXGIFormatBC2_TYPELESS = 73,
193 DXGIFormatBC2_UNORM = 74,
194 DXGIFormatBC2_UNORM_SRGB = 75,
195 DXGIFormatBC3_TYPELESS = 76,
196 DXGIFormatBC3_UNORM = 77,
197 DXGIFormatBC3_UNORM_SRGB = 78,
198 DXGIFormatBC4_TYPELESS = 79,
199 DXGIFormatBC4_UNORM = 80,
200 DXGIFormatBC4_SNORM = 81,
201 DXGIFormatBC5_TYPELESS = 82,
202 DXGIFormatBC5_UNORM = 83,
203 DXGIFormatBC5_SNORM = 84,
204 DXGIFormatB5G6R5_UNORM = 85,
205 DXGIFormatB5G5R5A1_UNORM = 86,
206 DXGIFormatB8G8R8A8_UNORM = 87,
207 DXGIFormatB8G8R8X8_UNORM = 88,
208 DXGIFormatR10G10B10_XR_BIAS_A2_UNORM = 89,
209 DXGIFormatB8G8R8A8_TYPELESS = 90,
210 DXGIFormatB8G8R8A8_UNORM_SRGB = 91,
211 DXGIFormatB8G8R8X8_TYPELESS = 92,
212 DXGIFormatB8G8R8X8_UNORM_SRGB = 93,
213 DXGIFormatBC6H_TYPELESS = 94,
214 DXGIFormatBC6H_UF16 = 95,
215 DXGIFormatBC6H_SF16 = 96,
216 DXGIFormatBC7_TYPELESS = 97,
217 DXGIFormatBC7_UNORM = 98,
218 DXGIFormatBC7_UNORM_SRGB = 99,
219 DXGIFormatAYUV = 100,
220 DXGIFormatY410 = 101,
221 DXGIFormatY416 = 102,
222 DXGIFormatNV12 = 103,
223 DXGIFormatP010 = 104,
224 DXGIFormatP016 = 105,
225 DXGIFormat420_OPAQUE = 106,
226 DXGIFormatYUY2 = 107,
227 DXGIFormatY210 = 108,
228 DXGIFormatY216 = 109,
229 DXGIFormatNV11 = 110,
230 DXGIFormatAI44 = 111,
231 DXGIFormatIA44 = 112,
233 DXGIFormatA8P8 = 114,
234 DXGIFormatB4G4R4A4_UNORM = 115,
235 DXGIFormatP208 = 130,
236 DXGIFormatV208 = 131,
237 DXGIFormatV408 = 132,
238 DXGIFormatSAMPLER_FEEDBACK_MIN_MIP_OPAQUE,
239 DXGIFormatSAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE,
240 DXGIFormatFORCE_UINT = 0xffffffff
246 DXGIAlphaModeUnknow = 0,
247 DXGIAlphaModeStraight = 1,
248 DXGIAlphaModePremultiplied = 2,
249 DXGIAlphaModeOpaque = 3,
250 DXGIAlphaModeCustom = 4
272static const quint32 ddsMagic = 0x20534444;
273static const quint32 dx10Magic = 0x30315844;
275static const qint64 headerSize = 128;
276static const quint32 ddsSize = 124;
277static const quint32 pixelFormatSize = 32;
284static const FaceOffset faceOffsets[6] = { {2, 1}, {0, 1}, {1, 0}, {1, 2}, {1, 1}, {3, 1} };
286static int faceFlags[6] = {
287 DDSHeader::Caps2CubeMapPositiveX,
288 DDSHeader::Caps2CubeMapNegativeX,
289 DDSHeader::Caps2CubeMapPositiveY,
290 DDSHeader::Caps2CubeMapNegativeY,
291 DDSHeader::Caps2CubeMapPositiveZ,
292 DDSHeader::Caps2CubeMapNegativeZ
306static const FormatInfo formatInfos[] = {
307 { FormatA8R8G8B8, DDSPixelFormat::FlagRGBA, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 },
308 { FormatX8R8G8B8, DDSPixelFormat::FlagRGB, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 },
309 { FormatA2B10G10R10, DDSPixelFormat::FlagRGBA, 32, 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000 },
310 { FormatA8B8G8R8, DDSPixelFormat::FlagRGBA, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 },
311 { FormatX8B8G8R8, DDSPixelFormat::FlagRGB, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 },
312 { FormatG16R16, DDSPixelFormat::FlagRGBA, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 },
313 { FormatG16R16, DDSPixelFormat::FlagRGB, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 },
314 { FormatA2R10G10B10, DDSPixelFormat::FlagRGBA, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 },
316 { FormatR8G8B8, DDSPixelFormat::FlagRGB, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 },
318 { FormatR5G6B5, DDSPixelFormat::FlagRGB, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 },
319 { FormatX1R5G5B5, DDSPixelFormat::FlagRGB, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00000000 },
320 { FormatA1R5G5B5, DDSPixelFormat::FlagRGBA, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 },
321 { FormatA4R4G4B4, DDSPixelFormat::FlagRGBA, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 },
322 { FormatA8R3G3B2, DDSPixelFormat::FlagRGBA, 16, 0x000000e0, 0x0000001c, 0x00000003, 0x0000ff00 },
323 { FormatX4R4G4B4, DDSPixelFormat::FlagRGB, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x00000000 },
324 { FormatA8L8, DDSPixelFormat::FlagLA, 16, 0x000000ff, 0x00000000, 0x00000000, 0x0000ff00 },
325 { FormatL16, DDSPixelFormat::FlagLuminance, 16, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000 },
327 { FormatR3G3B2, DDSPixelFormat::FlagRGB, 8, 0x000000e0, 0x0000001c, 0x00000003, 0x00000000 },
328 { FormatA8, DDSPixelFormat::FlagAlpha, 8, 0x00000000, 0x00000000, 0x00000000, 0x000000ff },
329 { FormatL8, DDSPixelFormat::FlagLuminance, 8, 0x000000ff, 0x00000000, 0x00000000, 0x00000000 },
330 { FormatA4L4, DDSPixelFormat::FlagLA, 8, 0x0000000f, 0x00000000, 0x00000000, 0x000000f0 },
332 { FormatV8U8, DDSPixelFormat::FlagNormal, 16, 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000 },
333 { FormatL6V5U5, 0, 16, 0x0000001f, 0x000003e0, 0x0000fc00, 0x00000000 },
334 { FormatX8L8V8U8, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 },
335 { FormatQ8W8V8U8, DDSPixelFormat::FlagNormal, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 },
336 { FormatV16U16, DDSPixelFormat::FlagNormal, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 },
337 { FormatA2W10V10U10, DDSPixelFormat::FlagNormal, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }
339static const size_t formatInfosSize =
sizeof(formatInfos)/
sizeof(FormatInfo);
341static const Format knownFourCCs[] = {
364static const size_t knownFourCCsSize =
sizeof(knownFourCCs)/
sizeof(Format);
366struct DXGIFormatToFormat
368 DXGIFormat dxgiFormat;
372static const DXGIFormatToFormat knownDXGIFormat[] = {
373 { DXGIFormatR16G16B16A16_FLOAT, FormatA16B16G16R16F },
374 { DXGIFormatR32G32B32A32_FLOAT, FormatA32B32G32R32F },
375 { DXGIFormatR16G16_FLOAT, FormatG16R16F },
376 { DXGIFormatR32G32_FLOAT, FormatG32R32F },
377 { DXGIFormatR16_FLOAT, FormatR16F },
378 { DXGIFormatR32_FLOAT, FormatR32F }
380static const size_t knownDXGIFormatSize =
sizeof(knownDXGIFormat)/
sizeof(DXGIFormatToFormat);
385 const char *
const name;
387static const FormatName formatNames[] = {
388 { FormatUnknown,
"unknown" },
390 { FormatR8G8B8,
"R8G8B8" },
391 { FormatA8R8G8B8,
"A8R8G8B8" },
392 { FormatX8R8G8B8,
"X8R8G8B8" },
393 { FormatR5G6B5,
"R5G6B5" },
394 { FormatX1R5G5B5,
"X1R5G5B5" },
395 { FormatA1R5G5B5,
"A1R5G5B5" },
396 { FormatA4R4G4B4,
"A4R4G4B4" },
397 { FormatR3G3B2,
"R3G3B2" },
399 { FormatA8R3G3B2,
"A8R3G3B2" },
400 { FormatX4R4G4B4,
"X4R4G4B4" },
401 { FormatA2B10G10R10,
"A2B10G10R10" },
402 { FormatA8B8G8R8,
"A8B8G8R8" },
403 { FormatX8B8G8R8,
"X8B8G8R8" },
404 { FormatG16R16,
"G16R16" },
405 { FormatA2R10G10B10,
"A2R10G10B10" },
406 { FormatA16B16G16R16,
"A16B16G16R16" },
408 { FormatA8P8,
"A8P8" },
412 { FormatA8L8,
"A8L8" },
413 { FormatA4L4,
"A4L4" },
415 { FormatV8U8,
"V8U8" },
416 { FormatL6V5U5,
"L6V5U5" },
417 { FormatX8L8V8U8,
"X8L8V8U8" },
418 { FormatQ8W8V8U8,
"Q8W8V8U8" },
419 { FormatV16U16,
"V16U16" },
420 { FormatA2W10V10U10,
"A2W10V10U10" },
422 { FormatUYVY,
"UYVY" },
423 { FormatR8G8B8G8,
"R8G8_B8G8" },
424 { FormatYUY2,
"YUY2" },
425 { FormatG8R8G8B8,
"G8R8_G8B8" },
426 { FormatDXT1,
"DXT1" },
427 { FormatDXT2,
"DXT2" },
428 { FormatDXT3,
"DXT3" },
429 { FormatDXT4,
"DXT4" },
430 { FormatDXT5,
"DXT5" },
431 { FormatRXGB,
"RXGB" },
432 { FormatATI2,
"ATI2" },
434 { FormatD16Lockable,
"D16Lockable" },
435 { FormatD32,
"D32" },
436 { FormatD15S1,
"D15S1" },
437 { FormatD24S8,
"D24S8" },
438 { FormatD24X8,
"D24X8" },
439 { FormatD24X4S4,
"D24X4S4" },
440 { FormatD16,
"D16" },
442 { FormatD32FLockable,
"D32FLockable" },
443 { FormatD24FS8,
"D24FS8" },
445 { FormatD32Lockable,
"D32Lockable" },
446 { FormatS8Lockable,
"S8Lockable" },
448 { FormatL16,
"L16" },
450 { FormatVertexData,
"VertexData" },
451 { FormatIndex32,
"Index32" },
452 { FormatIndex32,
"Index32" },
454 { FormatQ16W16V16U16,
"Q16W16V16U16" },
456 { FormatMulti2ARGB8,
"Multi2ARGB8" },
458 { FormatR16F,
"R16F" },
459 { FormatG16R16F,
"G16R16F" },
460 { FormatA16B16G16R16F,
"A16B16G16R16F" },
462 { FormatR32F,
"R32F" },
463 { FormatG32R32F,
"G32R32F" },
464 { FormatA32B32G32R32F,
"A32B32G32R32F" },
466 { FormatCxV8U8,
"CxV8U8" },
469 { FormatA2B10G10R10_XR_BIAS,
"A2B10G10R10_XR_BIAS" },
470 { FormatBinaryBuffer,
"BinaryBuffer" },
473 { FormatA4P4,
"A4P4" }
475static const size_t formatNamesSize =
sizeof(formatNames)/
sizeof(FormatName);
479 s >> pixelFormat.size;
480 s >> pixelFormat.flags;
481 s >> pixelFormat.fourCC;
482 s >> pixelFormat.rgbBitCount;
483 s >> pixelFormat.rBitMask;
484 s >> pixelFormat.gBitMask;
485 s >> pixelFormat.bBitMask;
486 s >> pixelFormat.aBitMask;
492 s << pixelFormat.size;
493 s << pixelFormat.flags;
494 s << pixelFormat.fourCC;
495 s << pixelFormat.rgbBitCount;
496 s << pixelFormat.rBitMask;
497 s << pixelFormat.gBitMask;
498 s << pixelFormat.bBitMask;
499 s << pixelFormat.aBitMask;
505 s >> header.dxgiFormat;
506 s >> header.resourceDimension;
507 s >> header.miscFlag;
508 s >> header.arraySize;
509 s >> header.miscFlags2;
515 s << header.dxgiFormat;
516 s << header.resourceDimension;
517 s << header.miscFlag;
518 s << header.arraySize;
519 s << header.miscFlags2;
530 s >> header.pitchOrLinearSize;
532 s >> header.mipMapCount;
533 for (
int i = 0; i < DDSHeader::ReservedCount; i++)
534 s >> header.reserved1[i];
535 s >> header.pixelFormat;
540 s >> header.reserved2;
541 if (header.pixelFormat.fourCC == dx10Magic)
542 s >> header.header10;
554 s << header.pitchOrLinearSize;
556 s << header.mipMapCount;
557 for (
int i = 0; i < DDSHeader::ReservedCount; i++)
558 s << header.reserved1[i];
559 s << header.pixelFormat;
564 s << header.reserved2;
565 if (header.pixelFormat.fourCC == dx10Magic)
566 s << header.header10;
571inline qsizetype ptrDiff(
const void *end,
const void *
start)
573 return qsizetype(
reinterpret_cast<const char*
>(end) -
reinterpret_cast<const char*
>(
start));
576static inline int maskToShift(quint32 mask)
582 while (!((mask >> result) & 1))
587static inline int maskLength(quint32 mask)
598static inline quint32 readValue(
QDataStream &s, quint32 size)
601 if (size != 8 && size != 16 && size != 24 && size != 32) {
607 for (
unsigned bit = 0; bit < size; bit += 8) {
609 value += (quint32(tmp) << bit);
614static inline bool hasAlpha(
const DDSHeader &dds)
616 return (dds.pixelFormat.flags & (DDSPixelFormat::FlagAlphaPixels | DDSPixelFormat::FlagAlpha)) != 0;
619static inline bool isCubeMap(
const DDSHeader &dds)
621 return (dds.caps2 & DDSHeader::Caps2CubeMap) != 0;
624static inline QRgb yuv2rgb(quint8 Y, quint8 U, quint8 V)
626 return qRgb(quint8(Y + 1.13983 * (V - 128)),
627 quint8(Y - 0.39465 * (U - 128) - 0.58060 * (V - 128)),
628 quint8(Y + 2.03211 * (U - 128)));
631static void strideAlignment(
QDataStream &s,
const DDSHeader &dds, quint32 width)
633#ifdef DDS_DISABLE_STRIDE_ALIGNMENT
638 if (dds.flags & DDSHeader::FlagPitch) {
639 if (
auto alignBytes = qint64(dds.pitchOrLinearSize) - (width * dds.pixelFormat.rgbBitCount + 7) / 8) {
641 for (; alignBytes > 0 && alignBytes < 4; --alignBytes) {
649static Format getFormat(
const DDSHeader &dds)
651 const DDSPixelFormat &format = dds.pixelFormat;
652 if (format.flags & DDSPixelFormat::FlagPaletteIndexed4) {
654 }
else if (format.flags & DDSPixelFormat::FlagPaletteIndexed8) {
656 }
else if (format.flags & DDSPixelFormat::FlagFourCC) {
657 if (dds.pixelFormat.fourCC == dx10Magic) {
658 for (
size_t i = 0; i < knownDXGIFormatSize; ++i) {
659 if (dds.header10.dxgiFormat == knownDXGIFormat[i].dxgiFormat)
660 return knownDXGIFormat[i].format;
663 for (
size_t i = 0; i < knownFourCCsSize; ++i) {
664 if (dds.pixelFormat.fourCC == knownFourCCs[i])
665 return knownFourCCs[i];
669 for (
size_t i = 0; i < formatInfosSize; ++i) {
670 const FormatInfo &info = formatInfos[i];
671 if ((format.flags & info.flags) == info.flags &&
672 format.rgbBitCount == info.bitCount &&
673 format.rBitMask == info.rBitMask &&
674 format.gBitMask == info.gBitMask &&
675 format.bBitMask == info.bBitMask &&
676 format.aBitMask == info.aBitMask) {
682 return FormatUnknown;
685static inline quint8 getNormalZ(quint8 nx, quint8 ny)
687 const double fx = nx / 127.5 - 1.0;
688 const double fy = ny / 127.5 - 1.0;
689 const double fxfy = 1.0 - fx * fx - fy * fy;
690 return fxfy > 0 ? 255 * std::sqrt(fxfy) : 0;
693static inline void decodeColor(quint16 color, quint8 &red, quint8 &green, quint8 &blue)
695 red = ((color >> 11) & 0x1f) << 3;
696 green = ((color >> 5) & 0x3f) << 2;
697 blue = (color & 0x1f) << 3;
700static inline quint8 calcC2(quint8 c0, quint8 c1)
702 return 2.0 * c0 / 3.0 + c1 / 3.0;
705static inline quint8 calcC2a(quint8 c0, quint8 c1)
707 return c0 / 2.0 + c1 / 2.0;
710static inline quint8 calcC3(quint8 c0, quint8 c1)
712 return c0 / 3.0 + 2.0 * c1 / 3.0;
715static void DXTFillColors(QRgb *result, quint16 c0, quint16 c1, quint32 table,
bool dxt1a =
false)
722 a[0] = a[1] = a[2] = a[3] = 255;
724 decodeColor(c0, r[0], g[0], b[0]);
725 decodeColor(c1, r[1], g[1], b[1]);
727 r[2] = calcC2(r[0], r[1]);
728 g[2] = calcC2(g[0], g[1]);
729 b[2] = calcC2(b[0], b[1]);
730 r[3] = calcC3(r[0], r[1]);
731 g[3] = calcC3(g[0], g[1]);
732 b[3] = calcC3(b[0], b[1]);
734 r[2] = calcC2a(r[0], r[1]);
735 g[2] = calcC2a(g[0], g[1]);
736 b[2] = calcC2a(b[0], b[1]);
737 r[3] = g[3] = b[3] = a[3] = 0;
740 for (
int k = 0; k < 4; k++)
741 for (
int l = 0; l < 4; l++) {
742 unsigned index = table & 0x0003;
745 result[k * 4 + l] = qRgba(r[index], g[index], b[index], a[index]);
749template <DXTVersions version>
750inline void setAlphaDXT32Helper(QRgb *rgbArr, quint64 alphas)
752 Q_STATIC_ASSERT(version == Two || version == Three);
753 for (
int i = 0; i < 16; i++) {
754 quint8 alpha = 16 * (alphas & 0x0f);
755 QRgb rgb = rgbArr[i];
757 rgbArr[i] = qRgba(qRed(rgb) * alpha / 0xff, qGreen(rgb) * alpha / 0xff, qBlue(rgb) * alpha / 0xff, alpha);
758 else if (version == Three)
759 rgbArr[i] = qRgba(qRed(rgb), qGreen(rgb), qBlue(rgb), alpha);
760 alphas = alphas >> 4;
764template <DXTVersions version>
765inline void setAlphaDXT45Helper(QRgb *rgbArr, quint64 alphas)
767 Q_STATIC_ASSERT(version == Four || version == Five);
769 a[0] = alphas & 0xff;
770 a[1] = (alphas >> 8) & 0xff;
772 a[2] = (6*a[0] + 1*a[1]) / 7;
773 a[3] = (5*a[0] + 2*a[1]) / 7;
774 a[4] = (4*a[0] + 3*a[1]) / 7;
775 a[5] = (3*a[0] + 4*a[1]) / 7;
776 a[6] = (2*a[0] + 5*a[1]) / 7;
777 a[7] = (1*a[0] + 6*a[1]) / 7;
779 a[2] = (4*a[0] + 1*a[1]) / 5;
780 a[3] = (3*a[0] + 2*a[1]) / 5;
781 a[4] = (2*a[0] + 3*a[1]) / 5;
782 a[5] = (1*a[0] + 4*a[1]) / 5;
787 for (
int i = 0; i < 16; i++) {
788 quint8 index = alphas & 0x07;
789 quint8 alpha = a[index];
790 QRgb rgb = rgbArr[i];
792 rgbArr[i] = qRgba(qRed(rgb) * alpha / 0xff, qGreen(rgb) * alpha / 0xff, qBlue(rgb) * alpha / 0xff, alpha);
793 else if (version == Five)
794 rgbArr[i] = qRgba(qRed(rgb), qGreen(rgb), qBlue(rgb), alpha);
795 alphas = alphas >> 3;
799template <DXTVersions version>
800inline void setAlphaDXT(QRgb *rgbArr, quint64 alphas)
807inline void setAlphaDXT<Two>(QRgb *rgbArr, quint64 alphas)
809 setAlphaDXT32Helper<Two>(rgbArr, alphas);
813inline void setAlphaDXT<Three>(QRgb *rgbArr, quint64 alphas)
815 setAlphaDXT32Helper<Three>(rgbArr, alphas);
819inline void setAlphaDXT<Four>(QRgb *rgbArr, quint64 alphas)
821 setAlphaDXT45Helper<Four>(rgbArr, alphas);
825inline void setAlphaDXT<Five>(QRgb *rgbArr, quint64 alphas)
827 setAlphaDXT45Helper<Five>(rgbArr, alphas);
831inline void setAlphaDXT<RXGB>(QRgb *rgbArr, quint64 alphas)
833 setAlphaDXT45Helper<Five>(rgbArr, alphas);
836static inline QRgb invertRXGBColors(QRgb pixel)
838 return qRgb(qAlpha(pixel), qGreen(pixel), qBlue(pixel));
841template <DXTVersions version>
847 QImage image = imageAlloc(width, height, format);
852 for (quint32 i = 0; i < height; i += 4) {
853 for (quint32 j = 0; j < width; j += 4) {
867 DXTFillColors(arr, c0, c1, table, version == One && c0 <= c1);
868 setAlphaDXT<version>(arr, alpha);
870 const quint32 kMax = qMin<quint32>(4, height - i);
871 const quint32 lMax = qMin<quint32>(4, width - j);
872 for (quint32 k = 0; k < kMax; k++) {
873 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(i + k));
874 for (quint32 l = 0; l < lMax; l++) {
875 QRgb pixel = arr[k * 4 + l];
877 pixel = invertRXGBColors(pixel);
889 return readDXT<One>(s, width, height);
894 return readDXT<Two>(s, width, height);
899 return readDXT<Three>(s, width, height);
904 return readDXT<Four>(s, width, height);
909 return readDXT<Five>(s, width, height);
914 return readDXT<RXGB>(s, width, height);
924 for (quint32 i = 0; i < height; i += 4) {
925 for (quint32 j = 0; j < width; j += 4) {
934 memset(arr, 0,
sizeof(QRgb) * 16);
935 setAlphaDXT<Five>(arr, alpha1);
936 for (
int k = 0; k < 16; ++k) {
937 quint8 a = qAlpha(arr[k]);
938 arr[k] = qRgba(0, 0, a, 0);
940 setAlphaDXT<Five>(arr, alpha2);
942 const quint32 kMax = qMin<quint32>(4, height - i);
943 const quint32 lMax = qMin<quint32>(4, width - j);
944 for (quint32 k = 0; k < kMax; k++) {
945 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(i + k));
946 for (quint32 l = 0; l < lMax; l++) {
947 QRgb pixel = arr[k * 4 + l];
948 const quint8 nx = qAlpha(pixel);
949 const quint8 ny = qBlue(pixel);
950 const quint8 nz = getNormalZ(nx, ny);
951 line[j + l] = qRgb(nx, ny, nz);
959static QImage readUnsignedImage(
QDataStream &s,
const DDSHeader &dds, quint32 width, quint32 height,
bool hasAlpha)
963 quint32 masks[ColorCount];
964 quint8 shifts[ColorCount];
965 quint8 bits[ColorCount];
966 masks[Red] = dds.pixelFormat.rBitMask;
967 masks[Green] = dds.pixelFormat.gBitMask;
968 masks[Blue] = dds.pixelFormat.bBitMask;
969 masks[Alpha] = hasAlpha ? dds.pixelFormat.aBitMask : 0;
970 for (
int i = 0; i < ColorCount; ++i) {
971 shifts[i] = maskToShift(masks[i]);
972 bits[i] = maskLength(masks[i]);
976 masks[i] = (masks[i] >> shifts[i]) << (8 - bits[i]);
980 if (!hasAlpha && (flags & DDSPixelFormat::FlagLuminance))
982 QImage image = imageAlloc(width, height, format);
987 for (quint32 y = 0; y < height; y++) {
988 for (quint32 x = 0; x < width; x++) {
989 quint8 *byteLine =
reinterpret_cast<quint8 *
>(image.
scanLine(y));
990 QRgb *line =
reinterpret_cast<QRgb *
>(byteLine);
992 quint32 value = readValue(s, dds.pixelFormat.rgbBitCount);
993 quint8 colors[ColorCount];
995 for (
int c = 0; c < ColorCount; ++c) {
998 colors[c] = (value & masks[c]) >> shifts[c] >> (bits[c] - 8);
1001 quint8 color = value >> shifts[c] << (8 - bits[c]) & masks[c];
1003 colors[c] = color * 0xff / masks[c];
1005 colors[c] = c == Alpha ? 0xff : 0;
1009 if (flags & DDSPixelFormat::FlagLuminance) {
1011 line[x] = qRgba(colors[Red], colors[Red], colors[Red], colors[Alpha]);
1013 byteLine[x] = colors[Red];
1015 else if (flags & DDSPixelFormat::FlagYUV) {
1016 line[x] = yuv2rgb(colors[Red], colors[Green], colors[Blue]);
1019 line[x] = qRgba(colors[Red], colors[Green], colors[Blue], colors[Alpha]);
1025 strideAlignment(s, dds, width);
1040 Q_ASSERT(
sizeof(
float) == 4);
1050static QImage readR16F(
QDataStream &s,
const quint32 width,
const quint32 height)
1057 for (quint32 y = 0; y < height; y++) {
1059 for (quint32 x = 0; x < width; x++) {
1060 line[x * 4] = readFloat16(s);
1061 line[x * 4 + 1] = 0;
1062 line[x * 4 + 2] = 0;
1063 line[x * 4 + 3] = 1;
1073static QImage readRG16F(
QDataStream &s,
const quint32 width,
const quint32 height)
1080 for (quint32 y = 0; y < height; y++) {
1082 for (quint32 x = 0; x < width; x++) {
1083 line[x * 4] = readFloat16(s);
1084 line[x * 4 + 1] = readFloat16(s);
1085 line[x * 4 + 2] = 0;
1086 line[x * 4 + 3] = 1;
1096static QImage readARGB16F(
QDataStream &s,
const quint32 width,
const quint32 height,
bool alphaPremul)
1103 for (quint32 y = 0; y < height; y++) {
1105 for (quint32 x = 0; x < width; x++) {
1106 line[x * 4] = readFloat16(s);
1107 line[x * 4 + 1] = readFloat16(s);
1108 line[x * 4 + 2] = readFloat16(s);
1109 line[x * 4 + 3] = readFloat16(s);
1119static QImage readR32F(
QDataStream &s,
const quint32 width,
const quint32 height)
1126 for (quint32 y = 0; y < height; y++) {
1127 float *line =
reinterpret_cast<float *
>(image.
scanLine(y));
1128 for (quint32 x = 0; x < width; x++) {
1129 line[x * 4] = readFloat32(s);
1130 line[x * 4 + 1] = 0;
1131 line[x * 4 + 2] = 0;
1132 line[x * 4 + 3] = 1;
1142static QImage readRG32F(
QDataStream &s,
const quint32 width,
const quint32 height)
1149 for (quint32 y = 0; y < height; y++) {
1150 float *line =
reinterpret_cast<float *
>(image.
scanLine(y));
1151 for (quint32 x = 0; x < width; x++) {
1152 line[x * 4] = readFloat32(s);
1153 line[x * 4 + 1] = readFloat32(s);
1154 line[x * 4 + 2] = 0;
1155 line[x * 4 + 3] = 1;
1165static QImage readARGB32F(
QDataStream &s,
const quint32 width,
const quint32 height,
bool alphaPremul)
1172 for (quint32 y = 0; y < height; y++) {
1173 float *line =
reinterpret_cast<float *
>(image.
scanLine(y));
1174 for (quint32 x = 0; x < width; x++) {
1175 line[x * 4] = readFloat32(s);
1176 line[x * 4 + 1] = readFloat32(s);
1177 line[x * 4 + 2] = readFloat32(s);
1178 line[x * 4 + 3] = readFloat32(s);
1188static QImage readQ16W16V16U16(
QDataStream &s,
const quint32 width,
const quint32 height)
1195 quint8 colors[ColorCount];
1197 for (quint32 y = 0; y < height; y++) {
1198 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1199 for (quint32 x = 0; x < width; x++) {
1200 for (
int i = 0; i < ColorCount; i++) {
1202 colors[i] = (tmp + 0x7FFF) >> 8;
1204 line[x] = qRgba(colors[Red], colors[Green], colors[Blue], colors[Alpha]);
1213static QImage readCxV8U8(
QDataStream &s,
const quint32 width,
const quint32 height)
1220 for (quint32 y = 0; y < height; y++) {
1221 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1222 for (quint32 x = 0; x < width; x++) {
1226 const quint8 vn = v + 128;
1227 const quint8 un = u + 128;
1228 const quint8 c = getNormalZ(vn, un);
1230 line[x] = qRgb(vn, un, c);
1240static QImage readPalette8Image(
QDataStream &s,
const DDSHeader &dds, quint32 width, quint32 height)
1247 for (
int i = 0; i < 256; ++i) {
1249 s >> r >> g >> b >> a;
1250 image.
setColor(i, qRgba(r, g, b, a));
1253 for (quint32 y = 0; y < height; y++) {
1254 quint8 *scanLine =
reinterpret_cast<quint8 *
>(image.
scanLine(y));
1255 for (quint32 x = 0; x < width; x++) {
1256 quint32 value = readValue(s, dds.pixelFormat.rgbBitCount);
1259 scanLine[x] = (value & 0xff);
1273 for (
int i = 0; i < 16; ++i) {
1275 s >> r >> g >> b >> a;
1276 image.
setColor(i, qRgba(r, g, b, a));
1279 for (quint32 y = 0; y < height; y++) {
1281 for (quint32 x = 0; x < width - 1; ) {
1283 image.
setPixel(x++, y, (index & 0x0f) >> 0);
1284 image.
setPixel(x++, y, (index & 0xf0) >> 4);
1288 if (width % 2 == 1) {
1290 image.
setPixel(width - 1, y, (index & 0x0f) >> 0);
1306 for (quint32 y = 0; y < height; y++) {
1307 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1308 for (quint32 x = 0; x < width; x++) {
1309 quint8 colors[ColorCount];
1310 for (
int i = 0; i < ColorCount; ++i) {
1313 colors[i] = quint8(color >> 8);
1315 line[x] = qRgba(colors[Red], colors[Green], colors[Blue], colors[Alpha]);
1331 for (quint32 y = 0; y < height; y++) {
1332 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1333 for (quint32 x = 0; x < width; x++) {
1336 line[x] = qRgb(v + 128, u + 128, 255);
1353 for (quint32 y = 0; y < height; y++) {
1354 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1355 for (quint32 x = 0; x < width; x++) {
1357 quint8 r = qint8((tmp & 0x001f) >> 0) * 0xff/0x1f + 128;
1358 quint8 g = qint8((tmp & 0x03e0) >> 5) * 0xff/0x1f + 128;
1359 quint8 b = quint8((tmp & 0xfc00) >> 10) * 0xff/0x3f;
1360 line[x] = qRgba(r, g, 0xff, b);
1377 for (quint32 y = 0; y < height; y++) {
1378 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1379 for (quint32 x = 0; x < width; x++) {
1380 s >> v >> u >> a >> l;
1381 line[x] = qRgba(v + 128, u + 128, 255, a);
1397 quint8 colors[ColorCount];
1399 for (quint32 y = 0; y < height; y++) {
1400 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1401 for (quint32 x = 0; x < width; x++) {
1402 for (
int i = 0; i < ColorCount; i++) {
1404 colors[i] = tmp + 128;
1406 line[x] = qRgba(colors[Red], colors[Green], colors[Blue], colors[Alpha]);
1422 for (quint32 y = 0; y < height; y++) {
1423 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1424 for (quint32 x = 0; x < width; x++) {
1427 v = (v + 0x8000) >> 8;
1428 u = (u + 0x8000) >> 8;
1429 line[x] = qRgb(v, u, 255);
1446 for (quint32 y = 0; y < height; y++) {
1447 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1448 for (quint32 x = 0; x < width; x++) {
1450 quint8 r = qint8((tmp & 0x3ff00000) >> 20 >> 2) + 128;
1451 quint8 g = qint8((tmp & 0x000ffc00) >> 10 >> 2) + 128;
1452 quint8 b = qint8((tmp & 0x000003ff) >> 0 >> 2) + 128;
1453 quint8 a = 0xff * ((tmp & 0xc0000000) >> 30) / 3;
1456 line[x] = qRgba(r, g, b, a);
1473 for (quint32 y = 0; y < height; y++) {
1474 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1475 for (quint32 x = 0; x < width - 1; ) {
1476 s >> uyvy[0] >> uyvy[1] >> uyvy[2] >> uyvy[3];
1477 line[x++] = yuv2rgb(uyvy[1], uyvy[0], uyvy[2]);
1478 line[x++] = yuv2rgb(uyvy[3], uyvy[0], uyvy[2]);
1482 if (width % 2 == 1) {
1483 s >> uyvy[0] >> uyvy[1] >> uyvy[2] >> uyvy[3];
1484 line[width - 1] = yuv2rgb(uyvy[1], uyvy[0], uyvy[2]);
1501 for (quint32 y = 0; y < height; y++) {
1502 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1503 for (quint32 x = 0; x < width - 1; ) {
1504 s >> rgbg[1] >> rgbg[0] >> rgbg[3] >> rgbg[2];
1505 line[x++] = qRgb(rgbg[0], rgbg[1], rgbg[2]);
1506 line[x++] = qRgb(rgbg[0], rgbg[3], rgbg[2]);
1510 if (width % 2 == 1) {
1511 s >> rgbg[1] >> rgbg[0] >> rgbg[3] >> rgbg[2];
1512 line[width - 1] = qRgb(rgbg[0], rgbg[1], rgbg[2]);
1529 for (quint32 y = 0; y < height; y++) {
1530 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1531 for (quint32 x = 0; x < width - 1; ) {
1532 s >> yuyv[0] >> yuyv[1] >> yuyv[2] >> yuyv[3];
1533 line[x++] = yuv2rgb(yuyv[0], yuyv[1], yuyv[3]);
1534 line[x++] = yuv2rgb(yuyv[2], yuyv[1], yuyv[3]);
1538 if (width % 2 == 1) {
1539 s >> yuyv[0] >> yuyv[1] >> yuyv[2] >> yuyv[3];
1540 line[width - 1] = yuv2rgb(yuyv[2], yuyv[1], yuyv[3]);
1557 for (quint32 y = 0; y < height; y++) {
1558 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1559 for (quint32 x = 0; x < width - 1; ) {
1560 s >> grgb[1] >> grgb[0] >> grgb[3] >> grgb[2];
1561 line[x++] = qRgb(grgb[1], grgb[0], grgb[3]);
1562 line[x++] = qRgb(grgb[1], grgb[2], grgb[3]);
1566 if (width % 2 == 1) {
1567 s >> grgb[1] >> grgb[0] >> grgb[3] >> grgb[2];
1568 line[width - 1] = qRgb(grgb[1], grgb[0], grgb[3]);
1577static QImage readA2R10G10B10(
QDataStream &s,
const DDSHeader &dds, quint32 width, quint32 height)
1579 QImage image = readUnsignedImage(s, dds, width, height,
true);
1584 for (quint32 y = 0; y < height; y++) {
1585 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1586 for (quint32 x = 0; x < width; x++) {
1587 QRgb pixel = image.
pixel(x, y);
1588 line[x] = qRgba(qBlue(pixel), qGreen(pixel), qRed(pixel), qAlpha(pixel));
1596static QImage readLayer(
QDataStream &s,
const DDSHeader &dds,
const int format, quint32 width, quint32 height)
1598 if (width * height == 0)
1601 bool alphaPremul = dds.header10.miscFlags2 == DXGIAlphaModePremultiplied;
1605 case FormatX8R8G8B8:
1608 case FormatX1R5G5B5:
1609 case FormatX4R4G4B4:
1610 case FormatX8B8G8R8:
1614 return readUnsignedImage(s, dds, width, height,
false);
1615 case FormatA8R8G8B8:
1616 case FormatA1R5G5B5:
1617 case FormatA4R4G4B4:
1619 case FormatA8R3G3B2:
1620 case FormatA8B8G8R8:
1623 return readUnsignedImage(s, dds, width, height,
true);
1624 case FormatA2R10G10B10:
1625 case FormatA2B10G10R10:
1626 return readA2R10G10B10(s, dds, width, height);
1629 return readPalette8Image(s, dds, width, height);
1632 return readPalette4Image(s, width, height);
1633 case FormatA16B16G16R16:
1634 return readARGB16(s, width, height);
1636 return readV8U8(s, width, height);
1638 return readL6V5U5(s, width, height);
1639 case FormatX8L8V8U8:
1640 return readX8L8V8U8(s, width, height);
1641 case FormatQ8W8V8U8:
1642 return readQ8W8V8U8(s, width, height);
1644 return readV16U16(s, width, height);
1645 case FormatA2W10V10U10:
1646 return readA2W10V10U10(s, width, height);
1648 return readUYVY(s, width, height);
1649 case FormatR8G8B8G8:
1650 return readR8G8B8G8(s, width, height);
1652 return readYUY2(s, width, height);
1653 case FormatG8R8G8B8:
1654 return readG8R8G8B8(s, width, height);
1656 return readDXT1(s, width, height);
1658 return readDXT2(s, width, height);
1660 return readDXT3(s, width, height);
1662 return readDXT4(s, width, height);
1664 return readDXT5(s, width, height);
1666 return readRXGB(s, width, height);
1668 return readATI2(s, width, height);
1670 return readR16F(s, width, height);
1672 return readRG16F(s, width, height);
1673 case FormatA16B16G16R16F:
1674 return readARGB16F(s, width, height, alphaPremul);
1676 return readR32F(s, width, height);
1678 return readRG32F(s, width, height);
1679 case FormatA32B32G32R32F:
1680 return readARGB32F(s, width, height, alphaPremul);
1681 case FormatD16Lockable:
1688 case FormatD32FLockable:
1690 case FormatD32Lockable:
1691 case FormatS8Lockable:
1692 case FormatVertexData:
1696 case FormatQ16W16V16U16:
1697 return readQ16W16V16U16(s, width, height);
1698 case FormatMulti2ARGB8:
1701 return readCxV8U8(s, width, height);
1703 case FormatA2B10G10R10_XR_BIAS:
1704 case FormatBinaryBuffer:
1712static inline QImage readTexture(
QDataStream &s,
const DDSHeader &dds,
const int format,
const int mipmapLevel)
1714 quint32 width = dds.width / (1 << mipmapLevel);
1715 quint32 height = dds.height / (1 << mipmapLevel);
1716 return readLayer(s, dds, format, width, height);
1719static qint64 mipmapSize(
const DDSHeader &dds,
const int format,
const int level)
1721 quint32 w = dds.width/(1 <<
level);
1722 quint32 h = dds.height/(1 <<
level);
1726 case FormatX8R8G8B8:
1728 case FormatX1R5G5B5:
1729 case FormatX4R4G4B4:
1730 case FormatX8B8G8R8:
1734 return w * h * dds.pixelFormat.rgbBitCount / 8;
1735 case FormatA8R8G8B8:
1736 case FormatA1R5G5B5:
1737 case FormatA4R4G4B4:
1739 case FormatA8R3G3B2:
1740 case FormatA2B10G10R10:
1741 case FormatA8B8G8R8:
1742 case FormatA2R10G10B10:
1745 return w * h * dds.pixelFormat.rgbBitCount / 8;
1747 return 256 + w * h * 8;
1748 case FormatA16B16G16R16:
1749 return w * h * 4 * 2;
1755 case FormatX8L8V8U8:
1756 case FormatQ8W8V8U8:
1758 case FormatA2W10V10U10:
1761 case FormatR8G8B8G8:
1763 case FormatG8R8G8B8:
1766 return ((w + 3)/4) * ((h + 3)/4) * 8;
1771 return ((w + 3)/4) * ((h + 3)/4) * 16;
1772 case FormatD16Lockable:
1779 case FormatD32FLockable:
1781 case FormatD32Lockable:
1782 case FormatS8Lockable:
1783 case FormatVertexData:
1787 case FormatQ16W16V16U16:
1788 return w * h * 4 * 2;
1789 case FormatMulti2ARGB8:
1792 return w * h * 1 * 2;
1794 return w * h * 2 * 2;
1795 case FormatA16B16G16R16F:
1796 return w * h * 4 * 2;
1798 return w * h * 1 * 4;
1800 return w * h * 2 * 4;
1801 case FormatA32B32G32R32F:
1802 return w * h * 4 * 4;
1806 case FormatA2B10G10R10_XR_BIAS:
1807 case FormatBinaryBuffer:
1815static qint64 mipmapOffset(
const DDSHeader &dds,
const int format,
const int level)
1818 for (
int i = 0; i <
level; ++i)
1819 result += mipmapSize(dds, format, i);
1826 QImage image = imageAlloc(4 * dds.width, 3 * dds.height, format);
1833 for (
int i = 0; i < 6; i++) {
1834 if (!(dds.caps2 & faceFlags[i]))
1837 QImage face = readLayer(s, dds, fmt, dds.width, dds.height);
1850 int offset_x = faceOffsets[i].x * dds.width;
1851 int offset_y = faceOffsets[i].y * dds.height;
1854 for (quint32 y = 0; y < dds.height; y++) {
1855 if (y + offset_y >= quint32(image.
height())) {
1858 const QRgb *src =
reinterpret_cast<const QRgb *
>(face.
constScanLine(y));
1859 QRgb *dst =
reinterpret_cast<QRgb *
>(image.
scanLine(y + offset_y)) + offset_x;
1860 qsizetype sz =
sizeof(QRgb) * dds.width;
1864 memcpy(dst, src, sz);
1873 for (
size_t i = 0; i < formatNamesSize; ++i) {
1874 if (formatNames[i].format == format)
1875 return formatNames[i].name;
1878 return formatNames[0].name;
1881static int formatByName(
const QByteArray &name)
1884 for (
size_t i = 0; i < formatNamesSize; ++i) {
1885 if (
QByteArray(formatNames[i].name).toLower() == loweredName)
1886 return formatNames[i].format;
1889 return FormatUnknown;
1892QDDSHandler::QDDSHandler() :
1894 m_format(FormatUnknown),
1896 m_scanState(ScanNotScanned)
1900bool QDDSHandler::canRead()
const
1902 if (m_scanState == ScanNotScanned && !canRead(device()))
1905 if (m_scanState != ScanError) {
1906 setFormat(QByteArrayLiteral(
"dds"));
1913bool QDDSHandler::read(
QImage *outImage)
1915 if (!ensureScanned() || device()->isSequential())
1918 qint64 pos = headerSize;
1919 if (m_header.pixelFormat.fourCC == dx10Magic)
1921 pos += mipmapOffset(m_header, m_format, m_currentImage);
1922 if (!device()->seek(pos))
1927 QImage image = isCubeMap(m_header) ?
1928 readCubeMap(s, m_header, m_format) :
1929 readTexture(s, m_header, m_format, m_currentImage);
1944 dds.magic = ddsMagic;
1946 dds.flags = DDSHeader::FlagCaps | DDSHeader::FlagHeight |
1947 DDSHeader::FlagWidth | DDSHeader::FlagPixelFormat |
1948 DDSHeader::FlagPitch;
1949 dds.height = outImage.
height();
1950 dds.width = outImage.
width();
1951 dds.pitchOrLinearSize = dds.width * 32 / 8;
1953 dds.mipMapCount = 0;
1954 for (
int i = 0; i < DDSHeader::ReservedCount; i++)
1955 dds.reserved1[i] = 0;
1956 dds.caps = DDSHeader::CapsTexture;
1963 dds.pixelFormat.size = 32;
1964 dds.pixelFormat.flags = DDSPixelFormat::FlagAlphaPixels | DDSPixelFormat::FlagRGB;
1965 dds.pixelFormat.fourCC = 0;
1966 dds.pixelFormat.rgbBitCount = 32;
1967 dds.pixelFormat.aBitMask = 0xff000000;
1968 dds.pixelFormat.rBitMask = 0x00ff0000;
1969 dds.pixelFormat.gBitMask = 0x0000ff00;
1970 dds.pixelFormat.bBitMask = 0x000000ff;
1981 for (
int y = 0, h = outImage.
height(); y < h; ++y) {
1982 const QRgb *scanLine =
reinterpret_cast<const QRgb*
>(slc.convertedScanLine(outImage, y));
1983 if (scanLine ==
nullptr) {
1986 for (
int x = 0, w = outImage.
width(); x < w; ++x) {
1987 s << quint32(scanLine[x]);
2001 dds.magic = ddsMagic;
2003 dds.flags = DDSHeader::FlagCaps | DDSHeader::FlagHeight |
2004 DDSHeader::FlagWidth | DDSHeader::FlagPixelFormat |
2005 DDSHeader::FlagPitch;
2006 dds.height = outImage.
height();
2007 dds.width = outImage.
width();
2008 dds.pitchOrLinearSize = dds.width * 24 / 8;
2010 dds.mipMapCount = 0;
2011 for (
int i = 0; i < DDSHeader::ReservedCount; i++)
2012 dds.reserved1[i] = 0;
2013 dds.caps = DDSHeader::CapsTexture;
2020 dds.pixelFormat.size = 32;
2021 dds.pixelFormat.flags = DDSPixelFormat::FlagRGB;
2022 dds.pixelFormat.fourCC = 0;
2023 dds.pixelFormat.rgbBitCount = 24;
2024 dds.pixelFormat.aBitMask = 0x00000000;
2025 dds.pixelFormat.rBitMask = 0x00ff0000;
2026 dds.pixelFormat.gBitMask = 0x0000ff00;
2027 dds.pixelFormat.bBitMask = 0x000000ff;
2038 for (
int y = 0, h = outImage.
height(); y < h; ++y) {
2039 const quint8 *scanLine =
reinterpret_cast<const quint8*
>(slc.convertedScanLine(outImage, y));
2040 if (scanLine ==
nullptr) {
2043 for (
int x = 0, w = outImage.
width(); x < w; ++x) {
2044 size_t x3 = size_t(x) * 3;
2045 s << scanLine[x3 + 2];
2046 s << scanLine[x3 + 1];
2061 dds.magic = ddsMagic;
2063 dds.flags = DDSHeader::FlagCaps | DDSHeader::FlagHeight |
2064 DDSHeader::FlagWidth | DDSHeader::FlagPixelFormat |
2065 DDSHeader::FlagPitch;
2066 dds.height = outImage.
height();
2067 dds.width = outImage.
width();
2068 dds.pitchOrLinearSize = dds.width;
2070 dds.mipMapCount = 0;
2071 for (
int i = 0; i < DDSHeader::ReservedCount; i++)
2072 dds.reserved1[i] = 0;
2073 dds.caps = DDSHeader::CapsTexture;
2080 dds.pixelFormat.size = 32;
2081 dds.pixelFormat.flags = DDSPixelFormat::FlagLuminance | DDSPixelFormat::FlagRGB;
2082 dds.pixelFormat.fourCC = 0;
2083 dds.pixelFormat.rgbBitCount = 8;
2084 dds.pixelFormat.aBitMask = 0x00000000;
2085 dds.pixelFormat.rBitMask = 0x000000ff;
2086 dds.pixelFormat.gBitMask = 0x00000000;
2087 dds.pixelFormat.bBitMask = 0x00000000;
2095#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
2097 slc.setTargetColorSpace(
QColorSpace(
QPointF(0.3127, 0.3291), QColorSpace::TransferFunction::SRgb));
2100 for (
int y = 0, h = outImage.
height(); y < h; ++y) {
2101 const quint8 *scanLine =
reinterpret_cast<const quint8*
>(slc.convertedScanLine(outImage, y));
2102 if (scanLine ==
nullptr) {
2105 for (
int x = 0, w = outImage.
width(); x < w; ++x) {
2128 dds.magic = ddsMagic;
2130 dds.flags = DDSHeader::FlagCaps | DDSHeader::FlagHeight |
2131 DDSHeader::FlagWidth | DDSHeader::FlagPixelFormat |
2132 DDSHeader::FlagPitch;
2134 dds.width = outImage.
width();
2135 dds.pitchOrLinearSize = dds.width;
2137 dds.mipMapCount = 0;
2138 for (
int i = 0; i < DDSHeader::ReservedCount; i++)
2139 dds.reserved1[i] = 0;
2140 dds.caps = DDSHeader::CapsTexture;
2147 dds.pixelFormat.size = 32;
2148 dds.pixelFormat.flags = DDSPixelFormat::FlagPaletteIndexed8;
2149 dds.pixelFormat.fourCC = 0;
2150 dds.pixelFormat.rgbBitCount = 8;
2151 dds.pixelFormat.aBitMask = 0x00000000;
2152 dds.pixelFormat.rBitMask = 0x00000000;
2153 dds.pixelFormat.gBitMask = 0x00000000;
2154 dds.pixelFormat.bBitMask = 0x00000000;
2159 for (
int i = 0; i < 256; ++i) {
2160 quint8 r = 0, g = 0, b = 0, a = 0xff;
2161 if (i < palette.
size()) {
2162 auto&& rgba = palette.
at(i);
2178 for (
int y = 0, h = outImage.
height(); y < h; ++y) {
2179 const quint8 *scanLine =
reinterpret_cast<const quint8*
>(outImage.
constScanLine(y));
2180 if (scanLine ==
nullptr) {
2183 for (
int x = 0, w = outImage.
width(); x < w; ++x) {
2198 dds.magic = ddsMagic;
2200 dds.flags = DDSHeader::FlagCaps | DDSHeader::FlagHeight |
2201 DDSHeader::FlagWidth | DDSHeader::FlagPitch |
2202 DDSHeader::FlagPixelFormat;
2203 dds.height = outImage.
height();
2204 dds.width = outImage.
width();
2205 dds.pitchOrLinearSize = dds.width * 64 / 8;
2207 dds.mipMapCount = 0;
2208 for (
int i = 0; i < DDSHeader::ReservedCount; i++)
2209 dds.reserved1[i] = 0;
2210 dds.caps = DDSHeader::CapsTexture;
2217 dds.pixelFormat.size = 32;
2218 dds.pixelFormat.flags = DDSPixelFormat::FlagFourCC;
2219 dds.pixelFormat.fourCC = 113;
2220 dds.pixelFormat.rgbBitCount = 0;
2221 dds.pixelFormat.aBitMask = 0;
2222 dds.pixelFormat.rBitMask = 0;
2223 dds.pixelFormat.gBitMask = 0;
2224 dds.pixelFormat.bBitMask = 0;
2235 for (
int y = 0, h = outImage.
height(); y < h; ++y) {
2236 const quint16 *scanLine =
reinterpret_cast<const quint16*
>(slc.convertedScanLine(outImage, y));
2237 if (scanLine ==
nullptr) {
2240 for (
int x = 0, w = outImage.
width(); x < w; ++x) {
2241 size_t x4 = size_t(x) * 4;
2243 s << scanLine[x4 + 1];
2244 s << scanLine[x4 + 2];
2245 s << scanLine[x4 + 3];
2259 dds.magic = ddsMagic;
2261 dds.flags = DDSHeader::FlagCaps | DDSHeader::FlagHeight |
2262 DDSHeader::FlagWidth | DDSHeader::FlagPitch |
2263 DDSHeader::FlagPixelFormat;
2264 dds.height = outImage.
height();
2265 dds.width = outImage.
width();
2266 dds.pitchOrLinearSize = dds.width * 128 / 8;
2268 dds.mipMapCount = 0;
2269 for (
int i = 0; i < DDSHeader::ReservedCount; i++)
2270 dds.reserved1[i] = 0;
2271 dds.caps = DDSHeader::CapsTexture;
2278 dds.pixelFormat.size = 32;
2279 dds.pixelFormat.flags = DDSPixelFormat::FlagFourCC;
2280 dds.pixelFormat.fourCC = 116;
2281 dds.pixelFormat.rgbBitCount = 0;
2282 dds.pixelFormat.aBitMask = 0;
2283 dds.pixelFormat.rBitMask = 0;
2284 dds.pixelFormat.gBitMask = 0;
2285 dds.pixelFormat.bBitMask = 0;
2296 for (
int y = 0, h = outImage.
height(); y < h; ++y) {
2297 const quint32 *scanLine =
reinterpret_cast<const quint32*
>(slc.convertedScanLine(outImage, y));
2298 if (scanLine ==
nullptr) {
2301 for (
int x = 0, w = outImage.
width(); x < w; ++x) {
2302 size_t x4 = size_t(x) * 4;
2304 s << scanLine[x4 + 1];
2305 s << scanLine[x4 + 2];
2306 s << scanLine[x4 + 3];
2316bool QDDSHandler::write(
const QImage &outImage)
2318 if (outImage.
isNull() || device() ==
nullptr) {
2325 int format = m_format;
2326 if (format == FormatUnknown) {
2327 switch (outImage.
format()) {
2331 format = FormatA16B16G16R16F;
2337 format = FormatA32B32G32R32F;
2356 if (format == FormatA8R8G8B8) {
2357 return writeA8R8G8B8(outImage, s);
2360 if (format == FormatR8G8B8) {
2361 return writeR8G8B8(outImage, s);
2364 if (format == FormatL8) {
2365 return writeL8(outImage, s);
2368 if (format == FormatP8) {
2369 return writeP8(outImage, s);
2372 if (format == FormatA16B16G16R16F) {
2373 return writeA16B16G16R16F(outImage, s);
2376 if (format == FormatA32B32G32R32F) {
2377 return writeA32B32G32R32F(outImage, s);
2380 qWarning() <<
"Format" << formatName(format) <<
"is not supported";
2386 if (!supportsOption(option)) {
2393 << QByteArrayLiteral(
"Automatic")
2394 << formatName(FormatA8R8G8B8)
2395 << formatName(FormatR8G8B8)
2396 << formatName(FormatL8)
2397 << formatName(FormatP8)
2398 << formatName(FormatA16B16G16R16F)
2399 << formatName(FormatA32B32G32R32F));
2403 if (!ensureScanned()) {
2408 return isCubeMap(m_header) ?
QSize(m_header.width * 4, m_header.height * 3) :
QSize(m_header.width, m_header.height);
2412 return m_format == FormatUnknown ? QByteArrayLiteral(
"Automatic") : formatName(m_format);
2422 m_format = formatByName(subType.
toUpper());
2433int QDDSHandler::imageCount()
const
2435 if (!ensureScanned())
2438 return qMax<quint32>(1, m_header.mipMapCount);
2441bool QDDSHandler::jumpToImage(
int imageNumber)
2443 if (imageNumber >= imageCount())
2446 m_currentImage = imageNumber;
2450bool QDDSHandler::canRead(
QIODevice *device)
2453 qWarning() <<
"DDSHandler::canRead() called with no device";
2460 return device->
peek(4) == QByteArrayLiteral(
"DDS ");
2463bool QDDSHandler::ensureScanned()
const
2465 if (device() ==
nullptr) {
2469 if (m_scanState != ScanNotScanned)
2470 return m_scanState == ScanSuccess;
2472 m_scanState = ScanError;
2474 QDDSHandler *that =
const_cast<QDDSHandler *
>(
this);
2475 that->m_format = FormatUnknown;
2477 if (device()->isSequential()) {
2478 qWarning() <<
"Sequential devices are not supported";
2482 qint64 oldPos = device()->
pos();
2487 s >> that->m_header;
2489 device()->
seek(oldPos);
2494 if (!verifyHeader(m_header))
2497 that->m_format = getFormat(m_header);
2498 if (that->m_format == FormatUnknown)
2501 m_scanState = ScanSuccess;
2505bool QDDSHandler::verifyHeader(
const DDSHeader &dds)
const
2507 quint32 flags = dds.flags;
2508 quint32 requiredFlags = DDSHeader::FlagCaps | DDSHeader::FlagHeight
2509 | DDSHeader::FlagWidth | DDSHeader::FlagPixelFormat;
2510 if ((flags & requiredFlags) != requiredFlags) {
2511 qWarning() <<
"Wrong dds.flags - not all required flags present. "
2512 "Actual flags :" << flags;
2516 if (dds.size != ddsSize) {
2517 qWarning() <<
"Wrong dds.size: actual =" << dds.size
2518 <<
"expected =" << ddsSize;
2522 if (dds.pixelFormat.size != pixelFormatSize) {
2523 qWarning() <<
"Wrong dds.pixelFormat.size: actual =" << dds.pixelFormat.size
2524 <<
"expected =" << pixelFormatSize;
2528 if (dds.width > INT_MAX || dds.height > INT_MAX) {
2529 qWarning() <<
"Can't read image with w/h bigger than INT_MAX";
2538 if (format == QByteArrayLiteral(
"dds"))
2542 if (!device || !device->
isOpen())
2546 if (device->
isReadable() && QDDSHandler::canRead(device))
Q_SCRIPTABLE QString start(QString train="")
QFlags< Capability > Capabilities
QStringView level(QStringView ifopt)
QString name(StandardAction id)
NETWORKMANAGERQT_EXPORT QString version()
bool isEmpty() const const
QByteArray toUpper() const const
bool isValid() const const
FloatingPointPrecision floatingPointPrecision() const const
void setByteOrder(ByteOrder bo)
void setFloatingPointPrecision(FloatingPointPrecision precision)
void setStatus(Status status)
Status status() const const
QColorSpace colorSpace() const const
QList< QRgb > colorTable() const const
const uchar * constScanLine(int i) const const
void convertTo(Format format, Qt::ImageConversionFlags flags)
void convertToColorSpace(const QColorSpace &colorSpace)
void fill(Qt::GlobalColor color)
bool hasAlphaChannel() const const
bool isNull() const const
QRgb pixel(const QPoint &position) const const
void setColor(int index, QRgb colorValue)
void setColorSpace(const QColorSpace &colorSpace)
void setPixel(const QPoint &position, uint index_or_rgb)
qsizetype sizeInBytes() const const
void setDevice(QIODevice *device)
bool isOpen() const const
bool isReadable() const const
virtual bool isSequential() const const
bool isWritable() const const
QByteArray peek(qint64 maxSize)
virtual qint64 pos() const const
virtual bool seek(qint64 pos)
const_reference at(qsizetype i) const const
qsizetype size() const const
QString toLower() const const
QVariant fromValue(T &&value)
QByteArray toByteArray() const const