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);
1037 memcpy(&f16, &rawData,
sizeof(rawData));
1044 Q_ASSERT(
sizeof(
float) == 4);
1054static QImage readR16F(
QDataStream &s,
const quint32 width,
const quint32 height)
1061 for (quint32 y = 0; y < height; y++) {
1063 for (quint32 x = 0; x < width; x++) {
1064 line[x * 4] = readFloat16(s);
1065 line[x * 4 + 1] = 0;
1066 line[x * 4 + 2] = 0;
1067 line[x * 4 + 3] = 1;
1077static QImage readRG16F(
QDataStream &s,
const quint32 width,
const quint32 height)
1084 for (quint32 y = 0; y < height; y++) {
1086 for (quint32 x = 0; x < width; x++) {
1087 line[x * 4] = readFloat16(s);
1088 line[x * 4 + 1] = readFloat16(s);
1089 line[x * 4 + 2] = 0;
1090 line[x * 4 + 3] = 1;
1100static QImage readARGB16F(
QDataStream &s,
const quint32 width,
const quint32 height,
bool alphaPremul)
1107 for (quint32 y = 0; y < height; y++) {
1109 for (quint32 x = 0; x < width; x++) {
1110 line[x * 4] = readFloat16(s);
1111 line[x * 4 + 1] = readFloat16(s);
1112 line[x * 4 + 2] = readFloat16(s);
1113 line[x * 4 + 3] = readFloat16(s);
1123static QImage readR32F(
QDataStream &s,
const quint32 width,
const quint32 height)
1130 for (quint32 y = 0; y < height; y++) {
1131 float *line =
reinterpret_cast<float *
>(image.
scanLine(y));
1132 for (quint32 x = 0; x < width; x++) {
1133 line[x * 4] = readFloat32(s);
1134 line[x * 4 + 1] = 0;
1135 line[x * 4 + 2] = 0;
1136 line[x * 4 + 3] = 1;
1146static QImage readRG32F(
QDataStream &s,
const quint32 width,
const quint32 height)
1153 for (quint32 y = 0; y < height; y++) {
1154 float *line =
reinterpret_cast<float *
>(image.
scanLine(y));
1155 for (quint32 x = 0; x < width; x++) {
1156 line[x * 4] = readFloat32(s);
1157 line[x * 4 + 1] = readFloat32(s);
1158 line[x * 4 + 2] = 0;
1159 line[x * 4 + 3] = 1;
1169static QImage readARGB32F(
QDataStream &s,
const quint32 width,
const quint32 height,
bool alphaPremul)
1176 for (quint32 y = 0; y < height; y++) {
1177 float *line =
reinterpret_cast<float *
>(image.
scanLine(y));
1178 for (quint32 x = 0; x < width; x++) {
1179 line[x * 4] = readFloat32(s);
1180 line[x * 4 + 1] = readFloat32(s);
1181 line[x * 4 + 2] = readFloat32(s);
1182 line[x * 4 + 3] = readFloat32(s);
1192static QImage readQ16W16V16U16(
QDataStream &s,
const quint32 width,
const quint32 height)
1199 quint8 colors[ColorCount];
1201 for (quint32 y = 0; y < height; y++) {
1202 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1203 for (quint32 x = 0; x < width; x++) {
1204 for (
int i = 0; i < ColorCount; i++) {
1206 colors[i] = (tmp + 0x7FFF) >> 8;
1208 line[x] = qRgba(colors[Red], colors[Green], colors[Blue], colors[Alpha]);
1217static QImage readCxV8U8(
QDataStream &s,
const quint32 width,
const quint32 height)
1224 for (quint32 y = 0; y < height; y++) {
1225 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1226 for (quint32 x = 0; x < width; x++) {
1230 const quint8 vn = v + 128;
1231 const quint8 un = u + 128;
1232 const quint8 c = getNormalZ(vn, un);
1234 line[x] = qRgb(vn, un, c);
1244static QImage readPalette8Image(
QDataStream &s,
const DDSHeader &dds, quint32 width, quint32 height)
1251 for (
int i = 0; i < 256; ++i) {
1253 s >> r >> g >> b >> a;
1254 image.
setColor(i, qRgba(r, g, b, a));
1257 for (quint32 y = 0; y < height; y++) {
1258 quint8 *scanLine =
reinterpret_cast<quint8 *
>(image.
scanLine(y));
1259 for (quint32 x = 0; x < width; x++) {
1260 quint32 value = readValue(s, dds.pixelFormat.rgbBitCount);
1263 scanLine[x] = (value & 0xff);
1277 for (
int i = 0; i < 16; ++i) {
1279 s >> r >> g >> b >> a;
1280 image.
setColor(i, qRgba(r, g, b, a));
1283 for (quint32 y = 0; y < height; y++) {
1285 for (quint32 x = 0; x < width - 1; ) {
1287 image.
setPixel(x++, y, (index & 0x0f) >> 0);
1288 image.
setPixel(x++, y, (index & 0xf0) >> 4);
1292 if (width % 2 == 1) {
1294 image.
setPixel(width - 1, y, (index & 0x0f) >> 0);
1310 for (quint32 y = 0; y < height; y++) {
1311 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1312 for (quint32 x = 0; x < width; x++) {
1313 quint8 colors[ColorCount];
1314 for (
int i = 0; i < ColorCount; ++i) {
1317 colors[i] = quint8(color >> 8);
1319 line[x] = qRgba(colors[Red], colors[Green], colors[Blue], colors[Alpha]);
1335 for (quint32 y = 0; y < height; y++) {
1336 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1337 for (quint32 x = 0; x < width; x++) {
1340 line[x] = qRgb(v + 128, u + 128, 255);
1357 for (quint32 y = 0; y < height; y++) {
1358 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1359 for (quint32 x = 0; x < width; x++) {
1361 quint8 r = qint8((tmp & 0x001f) >> 0) * 0xff/0x1f + 128;
1362 quint8 g = qint8((tmp & 0x03e0) >> 5) * 0xff/0x1f + 128;
1363 quint8 b = quint8((tmp & 0xfc00) >> 10) * 0xff/0x3f;
1364 line[x] = qRgba(r, g, 0xff, b);
1381 for (quint32 y = 0; y < height; y++) {
1382 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1383 for (quint32 x = 0; x < width; x++) {
1384 s >> v >> u >> a >> l;
1385 line[x] = qRgba(v + 128, u + 128, 255, a);
1401 quint8 colors[ColorCount];
1403 for (quint32 y = 0; y < height; y++) {
1404 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1405 for (quint32 x = 0; x < width; x++) {
1406 for (
int i = 0; i < ColorCount; i++) {
1408 colors[i] = tmp + 128;
1410 line[x] = qRgba(colors[Red], colors[Green], colors[Blue], colors[Alpha]);
1426 for (quint32 y = 0; y < height; y++) {
1427 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1428 for (quint32 x = 0; x < width; x++) {
1431 v = (v + 0x8000) >> 8;
1432 u = (u + 0x8000) >> 8;
1433 line[x] = qRgb(v, u, 255);
1450 for (quint32 y = 0; y < height; y++) {
1451 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1452 for (quint32 x = 0; x < width; x++) {
1454 quint8 r = qint8((tmp & 0x3ff00000) >> 20 >> 2) + 128;
1455 quint8 g = qint8((tmp & 0x000ffc00) >> 10 >> 2) + 128;
1456 quint8 b = qint8((tmp & 0x000003ff) >> 0 >> 2) + 128;
1457 quint8 a = 0xff * ((tmp & 0xc0000000) >> 30) / 3;
1460 line[x] = qRgba(r, g, b, a);
1477 for (quint32 y = 0; y < height; y++) {
1478 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1479 for (quint32 x = 0; x < width - 1; ) {
1480 s >> uyvy[0] >> uyvy[1] >> uyvy[2] >> uyvy[3];
1481 line[x++] = yuv2rgb(uyvy[1], uyvy[0], uyvy[2]);
1482 line[x++] = yuv2rgb(uyvy[3], uyvy[0], uyvy[2]);
1486 if (width % 2 == 1) {
1487 s >> uyvy[0] >> uyvy[1] >> uyvy[2] >> uyvy[3];
1488 line[width - 1] = yuv2rgb(uyvy[1], uyvy[0], uyvy[2]);
1505 for (quint32 y = 0; y < height; y++) {
1506 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1507 for (quint32 x = 0; x < width - 1; ) {
1508 s >> rgbg[1] >> rgbg[0] >> rgbg[3] >> rgbg[2];
1509 line[x++] = qRgb(rgbg[0], rgbg[1], rgbg[2]);
1510 line[x++] = qRgb(rgbg[0], rgbg[3], rgbg[2]);
1514 if (width % 2 == 1) {
1515 s >> rgbg[1] >> rgbg[0] >> rgbg[3] >> rgbg[2];
1516 line[width - 1] = qRgb(rgbg[0], rgbg[1], rgbg[2]);
1533 for (quint32 y = 0; y < height; y++) {
1534 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1535 for (quint32 x = 0; x < width - 1; ) {
1536 s >> yuyv[0] >> yuyv[1] >> yuyv[2] >> yuyv[3];
1537 line[x++] = yuv2rgb(yuyv[0], yuyv[1], yuyv[3]);
1538 line[x++] = yuv2rgb(yuyv[2], yuyv[1], yuyv[3]);
1542 if (width % 2 == 1) {
1543 s >> yuyv[0] >> yuyv[1] >> yuyv[2] >> yuyv[3];
1544 line[width - 1] = yuv2rgb(yuyv[2], yuyv[1], yuyv[3]);
1561 for (quint32 y = 0; y < height; y++) {
1562 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1563 for (quint32 x = 0; x < width - 1; ) {
1564 s >> grgb[1] >> grgb[0] >> grgb[3] >> grgb[2];
1565 line[x++] = qRgb(grgb[1], grgb[0], grgb[3]);
1566 line[x++] = qRgb(grgb[1], grgb[2], grgb[3]);
1570 if (width % 2 == 1) {
1571 s >> grgb[1] >> grgb[0] >> grgb[3] >> grgb[2];
1572 line[width - 1] = qRgb(grgb[1], grgb[0], grgb[3]);
1581static QImage readA2R10G10B10(
QDataStream &s,
const DDSHeader &dds, quint32 width, quint32 height)
1583 QImage image = readUnsignedImage(s, dds, width, height,
true);
1588 for (quint32 y = 0; y < height; y++) {
1589 QRgb *line =
reinterpret_cast<QRgb *
>(image.
scanLine(y));
1590 for (quint32 x = 0; x < width; x++) {
1591 QRgb pixel = image.
pixel(x, y);
1592 line[x] = qRgba(qBlue(pixel), qGreen(pixel), qRed(pixel), qAlpha(pixel));
1600static QImage readLayer(
QDataStream &s,
const DDSHeader &dds,
const int format, quint32 width, quint32 height)
1602 if (width * height == 0)
1605 bool alphaPremul = dds.header10.miscFlags2 == DXGIAlphaModePremultiplied;
1609 case FormatX8R8G8B8:
1612 case FormatX1R5G5B5:
1613 case FormatX4R4G4B4:
1614 case FormatX8B8G8R8:
1618 return readUnsignedImage(s, dds, width, height,
false);
1619 case FormatA8R8G8B8:
1620 case FormatA1R5G5B5:
1621 case FormatA4R4G4B4:
1623 case FormatA8R3G3B2:
1624 case FormatA8B8G8R8:
1627 return readUnsignedImage(s, dds, width, height,
true);
1628 case FormatA2R10G10B10:
1629 case FormatA2B10G10R10:
1630 return readA2R10G10B10(s, dds, width, height);
1633 return readPalette8Image(s, dds, width, height);
1636 return readPalette4Image(s, width, height);
1637 case FormatA16B16G16R16:
1638 return readARGB16(s, width, height);
1640 return readV8U8(s, width, height);
1642 return readL6V5U5(s, width, height);
1643 case FormatX8L8V8U8:
1644 return readX8L8V8U8(s, width, height);
1645 case FormatQ8W8V8U8:
1646 return readQ8W8V8U8(s, width, height);
1648 return readV16U16(s, width, height);
1649 case FormatA2W10V10U10:
1650 return readA2W10V10U10(s, width, height);
1652 return readUYVY(s, width, height);
1653 case FormatR8G8B8G8:
1654 return readR8G8B8G8(s, width, height);
1656 return readYUY2(s, width, height);
1657 case FormatG8R8G8B8:
1658 return readG8R8G8B8(s, width, height);
1660 return readDXT1(s, width, height);
1662 return readDXT2(s, width, height);
1664 return readDXT3(s, width, height);
1666 return readDXT4(s, width, height);
1668 return readDXT5(s, width, height);
1670 return readRXGB(s, width, height);
1672 return readATI2(s, width, height);
1674 return readR16F(s, width, height);
1676 return readRG16F(s, width, height);
1677 case FormatA16B16G16R16F:
1678 return readARGB16F(s, width, height, alphaPremul);
1680 return readR32F(s, width, height);
1682 return readRG32F(s, width, height);
1683 case FormatA32B32G32R32F:
1684 return readARGB32F(s, width, height, alphaPremul);
1685 case FormatD16Lockable:
1692 case FormatD32FLockable:
1694 case FormatD32Lockable:
1695 case FormatS8Lockable:
1696 case FormatVertexData:
1700 case FormatQ16W16V16U16:
1701 return readQ16W16V16U16(s, width, height);
1702 case FormatMulti2ARGB8:
1705 return readCxV8U8(s, width, height);
1707 case FormatA2B10G10R10_XR_BIAS:
1708 case FormatBinaryBuffer:
1716static inline QImage readTexture(
QDataStream &s,
const DDSHeader &dds,
const int format,
const int mipmapLevel)
1718 quint32 width = dds.width / (1 << mipmapLevel);
1719 quint32 height = dds.height / (1 << mipmapLevel);
1720 return readLayer(s, dds, format, width, height);
1723static qint64 mipmapSize(
const DDSHeader &dds,
const int format,
const int level)
1725 quint32 w = dds.width/(1 <<
level);
1726 quint32 h = dds.height/(1 <<
level);
1730 case FormatX8R8G8B8:
1732 case FormatX1R5G5B5:
1733 case FormatX4R4G4B4:
1734 case FormatX8B8G8R8:
1738 return w * h * dds.pixelFormat.rgbBitCount / 8;
1739 case FormatA8R8G8B8:
1740 case FormatA1R5G5B5:
1741 case FormatA4R4G4B4:
1743 case FormatA8R3G3B2:
1744 case FormatA2B10G10R10:
1745 case FormatA8B8G8R8:
1746 case FormatA2R10G10B10:
1749 return w * h * dds.pixelFormat.rgbBitCount / 8;
1751 return 256 + w * h * 8;
1752 case FormatA16B16G16R16:
1753 return w * h * 4 * 2;
1759 case FormatX8L8V8U8:
1760 case FormatQ8W8V8U8:
1762 case FormatA2W10V10U10:
1765 case FormatR8G8B8G8:
1767 case FormatG8R8G8B8:
1770 return ((w + 3)/4) * ((h + 3)/4) * 8;
1775 return ((w + 3)/4) * ((h + 3)/4) * 16;
1776 case FormatD16Lockable:
1783 case FormatD32FLockable:
1785 case FormatD32Lockable:
1786 case FormatS8Lockable:
1787 case FormatVertexData:
1791 case FormatQ16W16V16U16:
1792 return w * h * 4 * 2;
1793 case FormatMulti2ARGB8:
1796 return w * h * 1 * 2;
1798 return w * h * 2 * 2;
1799 case FormatA16B16G16R16F:
1800 return w * h * 4 * 2;
1802 return w * h * 1 * 4;
1804 return w * h * 2 * 4;
1805 case FormatA32B32G32R32F:
1806 return w * h * 4 * 4;
1810 case FormatA2B10G10R10_XR_BIAS:
1811 case FormatBinaryBuffer:
1819static qint64 mipmapOffset(
const DDSHeader &dds,
const int format,
const int level)
1822 for (
int i = 0; i <
level; ++i)
1823 result += mipmapSize(dds, format, i);
1830 QImage image = imageAlloc(4 * dds.width, 3 * dds.height, format);
1837 for (
int i = 0; i < 6; i++) {
1838 if (!(dds.caps2 & faceFlags[i]))
1841 QImage face = readLayer(s, dds, fmt, dds.width, dds.height);
1854 int offset_x = faceOffsets[i].x * dds.width;
1855 int offset_y = faceOffsets[i].y * dds.height;
1858 for (quint32 y = 0; y < dds.height; y++) {
1859 if (y + offset_y >= quint32(image.
height())) {
1862 const QRgb *src =
reinterpret_cast<const QRgb *
>(face.
constScanLine(y));
1863 QRgb *dst =
reinterpret_cast<QRgb *
>(image.
scanLine(y + offset_y)) + offset_x;
1864 qsizetype sz =
sizeof(QRgb) * dds.width;
1868 memcpy(dst, src, sz);
1877 for (
size_t i = 0; i < formatNamesSize; ++i) {
1878 if (formatNames[i].format == format)
1879 return formatNames[i].name;
1882 return formatNames[0].name;
1885static int formatByName(
const QByteArray &name)
1888 for (
size_t i = 0; i < formatNamesSize; ++i) {
1889 if (
QByteArray(formatNames[i].name).toLower() == loweredName)
1890 return formatNames[i].format;
1893 return FormatUnknown;
1896QDDSHandler::QDDSHandler() :
1898 m_format(FormatUnknown),
1900 m_scanState(ScanNotScanned)
1904bool QDDSHandler::canRead()
const
1906 if (m_scanState == ScanNotScanned && !canRead(device()))
1909 if (m_scanState != ScanError) {
1910 setFormat(QByteArrayLiteral(
"dds"));
1917bool QDDSHandler::read(
QImage *outImage)
1919 if (!ensureScanned() || device()->isSequential())
1922 qint64 pos = headerSize;
1923 if (m_header.pixelFormat.fourCC == dx10Magic)
1925 pos += mipmapOffset(m_header, m_format, m_currentImage);
1926 if (!device()->seek(pos))
1931 QImage image = isCubeMap(m_header) ?
1932 readCubeMap(s, m_header, m_format) :
1933 readTexture(s, m_header, m_format, m_currentImage);
1948 dds.magic = ddsMagic;
1950 dds.flags = DDSHeader::FlagCaps | DDSHeader::FlagHeight |
1951 DDSHeader::FlagWidth | DDSHeader::FlagPixelFormat |
1952 DDSHeader::FlagPitch;
1953 dds.height = outImage.
height();
1954 dds.width = outImage.
width();
1955 dds.pitchOrLinearSize = dds.width * 32 / 8;
1957 dds.mipMapCount = 0;
1958 for (
int i = 0; i < DDSHeader::ReservedCount; i++)
1959 dds.reserved1[i] = 0;
1960 dds.caps = DDSHeader::CapsTexture;
1967 dds.pixelFormat.size = 32;
1968 dds.pixelFormat.flags = DDSPixelFormat::FlagAlphaPixels | DDSPixelFormat::FlagRGB;
1969 dds.pixelFormat.fourCC = 0;
1970 dds.pixelFormat.rgbBitCount = 32;
1971 dds.pixelFormat.aBitMask = 0xff000000;
1972 dds.pixelFormat.rBitMask = 0x00ff0000;
1973 dds.pixelFormat.gBitMask = 0x0000ff00;
1974 dds.pixelFormat.bBitMask = 0x000000ff;
1985 for (
int y = 0, h = outImage.
height(); y < h; ++y) {
1986 const QRgb *scanLine =
reinterpret_cast<const QRgb*
>(slc.convertedScanLine(outImage, y));
1987 if (scanLine ==
nullptr) {
1990 for (
int x = 0, w = outImage.
width(); x < w; ++x) {
1991 s << quint32(scanLine[x]);
2005 dds.magic = ddsMagic;
2007 dds.flags = DDSHeader::FlagCaps | DDSHeader::FlagHeight |
2008 DDSHeader::FlagWidth | DDSHeader::FlagPixelFormat |
2009 DDSHeader::FlagPitch;
2010 dds.height = outImage.
height();
2011 dds.width = outImage.
width();
2012 dds.pitchOrLinearSize = dds.width * 24 / 8;
2014 dds.mipMapCount = 0;
2015 for (
int i = 0; i < DDSHeader::ReservedCount; i++)
2016 dds.reserved1[i] = 0;
2017 dds.caps = DDSHeader::CapsTexture;
2024 dds.pixelFormat.size = 32;
2025 dds.pixelFormat.flags = DDSPixelFormat::FlagRGB;
2026 dds.pixelFormat.fourCC = 0;
2027 dds.pixelFormat.rgbBitCount = 24;
2028 dds.pixelFormat.aBitMask = 0x00000000;
2029 dds.pixelFormat.rBitMask = 0x00ff0000;
2030 dds.pixelFormat.gBitMask = 0x0000ff00;
2031 dds.pixelFormat.bBitMask = 0x000000ff;
2042 for (
int y = 0, h = outImage.
height(); y < h; ++y) {
2043 const quint8 *scanLine =
reinterpret_cast<const quint8*
>(slc.convertedScanLine(outImage, y));
2044 if (scanLine ==
nullptr) {
2047 for (
int x = 0, w = outImage.
width(); x < w; ++x) {
2048 size_t x3 = size_t(x) * 3;
2049 s << scanLine[x3 + 2];
2050 s << scanLine[x3 + 1];
2065 dds.magic = ddsMagic;
2067 dds.flags = DDSHeader::FlagCaps | DDSHeader::FlagHeight |
2068 DDSHeader::FlagWidth | DDSHeader::FlagPixelFormat |
2069 DDSHeader::FlagPitch;
2070 dds.height = outImage.
height();
2071 dds.width = outImage.
width();
2072 dds.pitchOrLinearSize = dds.width;
2074 dds.mipMapCount = 0;
2075 for (
int i = 0; i < DDSHeader::ReservedCount; i++)
2076 dds.reserved1[i] = 0;
2077 dds.caps = DDSHeader::CapsTexture;
2084 dds.pixelFormat.size = 32;
2085 dds.pixelFormat.flags = DDSPixelFormat::FlagLuminance | DDSPixelFormat::FlagRGB;
2086 dds.pixelFormat.fourCC = 0;
2087 dds.pixelFormat.rgbBitCount = 8;
2088 dds.pixelFormat.aBitMask = 0x00000000;
2089 dds.pixelFormat.rBitMask = 0x000000ff;
2090 dds.pixelFormat.gBitMask = 0x00000000;
2091 dds.pixelFormat.bBitMask = 0x00000000;
2099#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
2101 slc.setTargetColorSpace(
QColorSpace(
QPointF(0.3127, 0.3291), QColorSpace::TransferFunction::SRgb));
2104 for (
int y = 0, h = outImage.
height(); y < h; ++y) {
2105 const quint8 *scanLine =
reinterpret_cast<const quint8*
>(slc.convertedScanLine(outImage, y));
2106 if (scanLine ==
nullptr) {
2109 for (
int x = 0, w = outImage.
width(); x < w; ++x) {
2132 dds.magic = ddsMagic;
2134 dds.flags = DDSHeader::FlagCaps | DDSHeader::FlagHeight |
2135 DDSHeader::FlagWidth | DDSHeader::FlagPixelFormat |
2136 DDSHeader::FlagPitch;
2137 dds.height = outImage.
height();
2138 dds.width = outImage.
width();
2139 dds.pitchOrLinearSize = dds.width;
2141 dds.mipMapCount = 0;
2142 for (
int i = 0; i < DDSHeader::ReservedCount; i++)
2143 dds.reserved1[i] = 0;
2144 dds.caps = DDSHeader::CapsTexture;
2151 dds.pixelFormat.size = 32;
2152 dds.pixelFormat.flags = DDSPixelFormat::FlagPaletteIndexed8;
2153 dds.pixelFormat.fourCC = 0;
2154 dds.pixelFormat.rgbBitCount = 8;
2155 dds.pixelFormat.aBitMask = 0x00000000;
2156 dds.pixelFormat.rBitMask = 0x00000000;
2157 dds.pixelFormat.gBitMask = 0x00000000;
2158 dds.pixelFormat.bBitMask = 0x00000000;
2163 for (
int i = 0; i < 256; ++i) {
2164 quint8 r = 0, g = 0, b = 0, a = 0xff;
2165 if (i < palette.
size()) {
2166 auto&& rgba = palette.
at(i);
2182 for (
int y = 0, h = outImage.
height(); y < h; ++y) {
2183 const quint8 *scanLine =
reinterpret_cast<const quint8*
>(outImage.
constScanLine(y));
2184 if (scanLine ==
nullptr) {
2187 for (
int x = 0, w = outImage.
width(); x < w; ++x) {
2202 dds.magic = ddsMagic;
2204 dds.flags = DDSHeader::FlagCaps | DDSHeader::FlagHeight |
2205 DDSHeader::FlagWidth | DDSHeader::FlagPitch |
2206 DDSHeader::FlagPixelFormat;
2207 dds.height = outImage.
height();
2208 dds.width = outImage.
width();
2209 dds.pitchOrLinearSize = dds.width * 64 / 8;
2211 dds.mipMapCount = 0;
2212 for (
int i = 0; i < DDSHeader::ReservedCount; i++)
2213 dds.reserved1[i] = 0;
2214 dds.caps = DDSHeader::CapsTexture;
2221 dds.pixelFormat.size = 32;
2222 dds.pixelFormat.flags = DDSPixelFormat::FlagFourCC;
2223 dds.pixelFormat.fourCC = 113;
2224 dds.pixelFormat.rgbBitCount = 0;
2225 dds.pixelFormat.aBitMask = 0;
2226 dds.pixelFormat.rBitMask = 0;
2227 dds.pixelFormat.gBitMask = 0;
2228 dds.pixelFormat.bBitMask = 0;
2239 for (
int y = 0, h = outImage.
height(); y < h; ++y) {
2240 const quint16 *scanLine =
reinterpret_cast<const quint16*
>(slc.convertedScanLine(outImage, y));
2241 if (scanLine ==
nullptr) {
2244 for (
int x = 0, w = outImage.
width(); x < w; ++x) {
2245 size_t x4 = size_t(x) * 4;
2247 s << scanLine[x4 + 1];
2248 s << scanLine[x4 + 2];
2249 s << scanLine[x4 + 3];
2263 dds.magic = ddsMagic;
2265 dds.flags = DDSHeader::FlagCaps | DDSHeader::FlagHeight |
2266 DDSHeader::FlagWidth | DDSHeader::FlagPitch |
2267 DDSHeader::FlagPixelFormat;
2268 dds.height = outImage.
height();
2269 dds.width = outImage.
width();
2270 dds.pitchOrLinearSize = dds.width * 128 / 8;
2272 dds.mipMapCount = 0;
2273 for (
int i = 0; i < DDSHeader::ReservedCount; i++)
2274 dds.reserved1[i] = 0;
2275 dds.caps = DDSHeader::CapsTexture;
2282 dds.pixelFormat.size = 32;
2283 dds.pixelFormat.flags = DDSPixelFormat::FlagFourCC;
2284 dds.pixelFormat.fourCC = 116;
2285 dds.pixelFormat.rgbBitCount = 0;
2286 dds.pixelFormat.aBitMask = 0;
2287 dds.pixelFormat.rBitMask = 0;
2288 dds.pixelFormat.gBitMask = 0;
2289 dds.pixelFormat.bBitMask = 0;
2300 for (
int y = 0, h = outImage.
height(); y < h; ++y) {
2301 const quint32 *scanLine =
reinterpret_cast<const quint32*
>(slc.convertedScanLine(outImage, y));
2302 if (scanLine ==
nullptr) {
2305 for (
int x = 0, w = outImage.
width(); x < w; ++x) {
2306 size_t x4 = size_t(x) * 4;
2308 s << scanLine[x4 + 1];
2309 s << scanLine[x4 + 2];
2310 s << scanLine[x4 + 3];
2320bool QDDSHandler::write(
const QImage &outImage)
2322 if (outImage.
isNull() || device() ==
nullptr) {
2329 int format = m_format;
2330 if (format == FormatUnknown) {
2331 switch (outImage.
format()) {
2335 format = FormatA16B16G16R16F;
2341 format = FormatA32B32G32R32F;
2360 if (format == FormatA8R8G8B8) {
2361 return writeA8R8G8B8(outImage, s);
2364 if (format == FormatR8G8B8) {
2365 return writeR8G8B8(outImage, s);
2368 if (format == FormatL8) {
2369 return writeL8(outImage, s);
2372 if (format == FormatP8) {
2373 return writeP8(outImage, s);
2376 if (format == FormatA16B16G16R16F) {
2377 return writeA16B16G16R16F(outImage, s);
2380 if (format == FormatA32B32G32R32F) {
2381 return writeA32B32G32R32F(outImage, s);
2384 qWarning() <<
"Format" << formatName(format) <<
"is not supported";
2390 if (!supportsOption(option)) {
2397 << QByteArrayLiteral(
"Automatic")
2398 << formatName(FormatA8R8G8B8)
2399 << formatName(FormatR8G8B8)
2400 << formatName(FormatL8)
2401 << formatName(FormatP8)
2402 << formatName(FormatA16B16G16R16F)
2403 << formatName(FormatA32B32G32R32F));
2407 if (!ensureScanned()) {
2412 return isCubeMap(m_header) ?
QSize(m_header.width * 4, m_header.height * 3) :
QSize(m_header.width, m_header.height);
2416 return m_format == FormatUnknown ? QByteArrayLiteral(
"Automatic") : formatName(m_format);
2426 m_format = formatByName(subType.
toUpper());
2437int QDDSHandler::imageCount()
const
2439 if (!ensureScanned())
2442 return qMax<quint32>(1, m_header.mipMapCount);
2445bool QDDSHandler::jumpToImage(
int imageNumber)
2447 if (imageNumber >= imageCount())
2450 m_currentImage = imageNumber;
2454bool QDDSHandler::canRead(
QIODevice *device)
2457 qWarning() <<
"DDSHandler::canRead() called with no device";
2464 return device->
peek(4) == QByteArrayLiteral(
"DDS ");
2467bool QDDSHandler::ensureScanned()
const
2469 if (device() ==
nullptr) {
2473 if (m_scanState != ScanNotScanned)
2474 return m_scanState == ScanSuccess;
2476 m_scanState = ScanError;
2478 QDDSHandler *that =
const_cast<QDDSHandler *
>(
this);
2479 that->m_format = FormatUnknown;
2481 if (device()->isSequential()) {
2482 qWarning() <<
"Sequential devices are not supported";
2486 qint64 oldPos = device()->
pos();
2491 s >> that->m_header;
2493 device()->
seek(oldPos);
2498 if (!verifyHeader(m_header))
2501 that->m_format = getFormat(m_header);
2502 if (that->m_format == FormatUnknown)
2505 m_scanState = ScanSuccess;
2509bool QDDSHandler::verifyHeader(
const DDSHeader &dds)
const
2511 quint32 flags = dds.flags;
2512 quint32 requiredFlags = DDSHeader::FlagCaps | DDSHeader::FlagHeight
2513 | DDSHeader::FlagWidth | DDSHeader::FlagPixelFormat;
2514 if ((flags & requiredFlags) != requiredFlags) {
2515 qWarning() <<
"Wrong dds.flags - not all required flags present. "
2516 "Actual flags :" << flags;
2520 if (dds.size != ddsSize) {
2521 qWarning() <<
"Wrong dds.size: actual =" << dds.size
2522 <<
"expected =" << ddsSize;
2526 if (dds.pixelFormat.size != pixelFormatSize) {
2527 qWarning() <<
"Wrong dds.pixelFormat.size: actual =" << dds.pixelFormat.size
2528 <<
"expected =" << pixelFormatSize;
2532 if (dds.width > INT_MAX || dds.height > INT_MAX) {
2533 qWarning() <<
"Can't read image with w/h bigger than INT_MAX";
2542 if (format == QByteArrayLiteral(
"dds"))
2546 if (!device || !device->
isOpen())
2550 if (device->
isReadable() && QDDSHandler::canRead(device))
Q_SCRIPTABLE Q_NOREPLY void start()
KCALENDARCORE_EXPORT QDataStream & operator>>(QDataStream &in, const KCalendarCore::Alarm::Ptr &)
KCOREADDONS_EXPORT unsigned int version()
QDebug operator<<(QDebug dbg, const DcrawInfoContainer &c)
QFlags< Capability > Capabilities
QStringView level(QStringView ifopt)
QString name(StandardAction id)
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