tinyddsloader.h 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514
  1. //
  2. // Copyright(c) 2019 benikabocha.
  3. // Distributed under the MIT License (http://opensource.org/licenses/MIT)
  4. //
  5. #ifndef TINYDDSLOADER_H_
  6. #define TINYDDSLOADER_H_
  7. #include <iostream>
  8. #include <vector>
  9. namespace tinyddsloader {
  10. enum Result {
  11. Success,
  12. ErrorFileOpen,
  13. ErrorRead,
  14. ErrorMagicWord,
  15. ErrorSize,
  16. ErrorVerify,
  17. ErrorNotSupported,
  18. ErrorInvalidData,
  19. };
  20. class DDSFile {
  21. public:
  22. static const char Magic[4];
  23. enum class PixelFormatFlagBits : uint32_t {
  24. FourCC = 0x00000004,
  25. RGB = 0x00000040,
  26. RGBA = 0x00000041,
  27. Luminance = 0x00020000,
  28. LuminanceA = 0x00020001,
  29. AlphaPixels = 0x00000001,
  30. Alpha = 0x00000002,
  31. Palette8 = 0x00000020,
  32. Palette8A = 0x00000021,
  33. BumpDUDV = 0x00080000
  34. };
  35. enum class DXGIFormat : uint32_t {
  36. Unknown = 0,
  37. R32G32B32A32_Typeless = 1,
  38. R32G32B32A32_Float = 2,
  39. R32G32B32A32_UInt = 3,
  40. R32G32B32A32_SInt = 4,
  41. R32G32B32_Typeless = 5,
  42. R32G32B32_Float = 6,
  43. R32G32B32_UInt = 7,
  44. R32G32B32_SInt = 8,
  45. R16G16B16A16_Typeless = 9,
  46. R16G16B16A16_Float = 10,
  47. R16G16B16A16_UNorm = 11,
  48. R16G16B16A16_UInt = 12,
  49. R16G16B16A16_SNorm = 13,
  50. R16G16B16A16_SInt = 14,
  51. R32G32_Typeless = 15,
  52. R32G32_Float = 16,
  53. R32G32_UInt = 17,
  54. R32G32_SInt = 18,
  55. R32G8X24_Typeless = 19,
  56. D32_Float_S8X24_UInt = 20,
  57. R32_Float_X8X24_Typeless = 21,
  58. X32_Typeless_G8X24_UInt = 22,
  59. R10G10B10A2_Typeless = 23,
  60. R10G10B10A2_UNorm = 24,
  61. R10G10B10A2_UInt = 25,
  62. R11G11B10_Float = 26,
  63. R8G8B8A8_Typeless = 27,
  64. R8G8B8A8_UNorm = 28,
  65. R8G8B8A8_UNorm_SRGB = 29,
  66. R8G8B8A8_UInt = 30,
  67. R8G8B8A8_SNorm = 31,
  68. R8G8B8A8_SInt = 32,
  69. R16G16_Typeless = 33,
  70. R16G16_Float = 34,
  71. R16G16_UNorm = 35,
  72. R16G16_UInt = 36,
  73. R16G16_SNorm = 37,
  74. R16G16_SInt = 38,
  75. R32_Typeless = 39,
  76. D32_Float = 40,
  77. R32_Float = 41,
  78. R32_UInt = 42,
  79. R32_SInt = 43,
  80. R24G8_Typeless = 44,
  81. D24_UNorm_S8_UInt = 45,
  82. R24_UNorm_X8_Typeless = 46,
  83. X24_Typeless_G8_UInt = 47,
  84. R8G8_Typeless = 48,
  85. R8G8_UNorm = 49,
  86. R8G8_UInt = 50,
  87. R8G8_SNorm = 51,
  88. R8G8_SInt = 52,
  89. R16_Typeless = 53,
  90. R16_Float = 54,
  91. D16_UNorm = 55,
  92. R16_UNorm = 56,
  93. R16_UInt = 57,
  94. R16_SNorm = 58,
  95. R16_SInt = 59,
  96. R8_Typeless = 60,
  97. R8_UNorm = 61,
  98. R8_UInt = 62,
  99. R8_SNorm = 63,
  100. R8_SInt = 64,
  101. A8_UNorm = 65,
  102. R1_UNorm = 66,
  103. R9G9B9E5_SHAREDEXP = 67,
  104. R8G8_B8G8_UNorm = 68,
  105. G8R8_G8B8_UNorm = 69,
  106. BC1_Typeless = 70,
  107. BC1_UNorm = 71,
  108. BC1_UNorm_SRGB = 72,
  109. BC2_Typeless = 73,
  110. BC2_UNorm = 74,
  111. BC2_UNorm_SRGB = 75,
  112. BC3_Typeless = 76,
  113. BC3_UNorm = 77,
  114. BC3_UNorm_SRGB = 78,
  115. BC4_Typeless = 79,
  116. BC4_UNorm = 80,
  117. BC4_SNorm = 81,
  118. BC5_Typeless = 82,
  119. BC5_UNorm = 83,
  120. BC5_SNorm = 84,
  121. B5G6R5_UNorm = 85,
  122. B5G5R5A1_UNorm = 86,
  123. B8G8R8A8_UNorm = 87,
  124. B8G8R8X8_UNorm = 88,
  125. R10G10B10_XR_BIAS_A2_UNorm = 89,
  126. B8G8R8A8_Typeless = 90,
  127. B8G8R8A8_UNorm_SRGB = 91,
  128. B8G8R8X8_Typeless = 92,
  129. B8G8R8X8_UNorm_SRGB = 93,
  130. BC6H_Typeless = 94,
  131. BC6H_UF16 = 95,
  132. BC6H_SF16 = 96,
  133. BC7_Typeless = 97,
  134. BC7_UNorm = 98,
  135. BC7_UNorm_SRGB = 99,
  136. AYUV = 100,
  137. Y410 = 101,
  138. Y416 = 102,
  139. NV12 = 103,
  140. P010 = 104,
  141. P016 = 105,
  142. YUV420_OPAQUE = 106,
  143. YUY2 = 107,
  144. Y210 = 108,
  145. Y216 = 109,
  146. NV11 = 110,
  147. AI44 = 111,
  148. IA44 = 112,
  149. P8 = 113,
  150. A8P8 = 114,
  151. B4G4R4A4_UNorm = 115,
  152. P208 = 130,
  153. V208 = 131,
  154. V408 = 132,
  155. };
  156. enum class HeaderFlagBits : uint32_t {
  157. Height = 0x00000002,
  158. Width = 0x00000004,
  159. Texture = 0x00001007,
  160. Mipmap = 0x00020000,
  161. Volume = 0x00800000,
  162. Pitch = 0x00000008,
  163. LinearSize = 0x00080000,
  164. };
  165. enum class HeaderCaps2FlagBits : uint32_t {
  166. CubemapPositiveX = 0x00000600,
  167. CubemapNegativeX = 0x00000a00,
  168. CubemapPositiveY = 0x00001200,
  169. CubemapNegativeY = 0x00002200,
  170. CubemapPositiveZ = 0x00004200,
  171. CubemapNegativeZ = 0x00008200,
  172. CubemapAllFaces = CubemapPositiveX | CubemapNegativeX |
  173. CubemapPositiveY | CubemapNegativeY |
  174. CubemapPositiveZ | CubemapNegativeZ,
  175. Volume = 0x00200000,
  176. };
  177. struct PixelFormat {
  178. uint32_t m_size;
  179. uint32_t m_flags;
  180. uint32_t m_fourCC;
  181. uint32_t m_bitCount;
  182. uint32_t m_RBitMask;
  183. uint32_t m_GBitMask;
  184. uint32_t m_BBitMask;
  185. uint32_t m_ABitMask;
  186. };
  187. struct Header {
  188. uint32_t m_size;
  189. uint32_t m_flags;
  190. uint32_t m_height;
  191. uint32_t m_width;
  192. uint32_t m_pitchOrLinerSize;
  193. uint32_t m_depth;
  194. uint32_t m_mipMapCount;
  195. uint32_t m_reserved1[11];
  196. PixelFormat m_pixelFormat;
  197. uint32_t m_caps;
  198. uint32_t m_caps2;
  199. uint32_t m_caps3;
  200. uint32_t m_caps4;
  201. uint32_t m_reserved2;
  202. };
  203. enum class TextureDimension : uint32_t {
  204. Unknown = 0,
  205. Texture1D = 2,
  206. Texture2D = 3,
  207. Texture3D = 4
  208. };
  209. enum class DXT10MiscFlagBits : uint32_t { TextureCube = 0x4 };
  210. struct HeaderDXT10 {
  211. DXGIFormat m_format;
  212. TextureDimension m_resourceDimension;
  213. uint32_t m_miscFlag;
  214. uint32_t m_arraySize;
  215. uint32_t m_miscFlag2;
  216. };
  217. struct ImageData {
  218. uint32_t m_width;
  219. uint32_t m_height;
  220. uint32_t m_depth;
  221. void* m_mem;
  222. uint32_t m_memPitch;
  223. uint32_t m_memSlicePitch;
  224. };
  225. struct BC1Block {
  226. uint16_t m_color0;
  227. uint16_t m_color1;
  228. uint8_t m_row0;
  229. uint8_t m_row1;
  230. uint8_t m_row2;
  231. uint8_t m_row3;
  232. };
  233. struct BC2Block {
  234. uint16_t m_alphaRow0;
  235. uint16_t m_alphaRow1;
  236. uint16_t m_alphaRow2;
  237. uint16_t m_alphaRow3;
  238. uint16_t m_color0;
  239. uint16_t m_color1;
  240. uint8_t m_row0;
  241. uint8_t m_row1;
  242. uint8_t m_row2;
  243. uint8_t m_row3;
  244. };
  245. struct BC3Block {
  246. uint8_t m_alpha0;
  247. uint8_t m_alpha1;
  248. uint8_t m_alphaR0;
  249. uint8_t m_alphaR1;
  250. uint8_t m_alphaR2;
  251. uint8_t m_alphaR3;
  252. uint8_t m_alphaR4;
  253. uint8_t m_alphaR5;
  254. uint16_t m_color0;
  255. uint16_t m_color1;
  256. uint8_t m_row0;
  257. uint8_t m_row1;
  258. uint8_t m_row2;
  259. uint8_t m_row3;
  260. };
  261. struct BC4Block {
  262. uint8_t m_red0;
  263. uint8_t m_red1;
  264. uint8_t m_redR0;
  265. uint8_t m_redR1;
  266. uint8_t m_redR2;
  267. uint8_t m_redR3;
  268. uint8_t m_redR4;
  269. uint8_t m_redR5;
  270. };
  271. struct BC5Block {
  272. uint8_t m_red0;
  273. uint8_t m_red1;
  274. uint8_t m_redR0;
  275. uint8_t m_redR1;
  276. uint8_t m_redR2;
  277. uint8_t m_redR3;
  278. uint8_t m_redR4;
  279. uint8_t m_redR5;
  280. uint8_t m_green0;
  281. uint8_t m_green1;
  282. uint8_t m_greenR0;
  283. uint8_t m_greenR1;
  284. uint8_t m_greenR2;
  285. uint8_t m_greenR3;
  286. uint8_t m_greenR4;
  287. uint8_t m_greenR5;
  288. };
  289. public:
  290. static bool IsCompressed(DXGIFormat fmt);
  291. static uint32_t MakeFourCC(char ch0, char ch1, char ch2, char ch3);
  292. static DXGIFormat GetDXGIFormat(const PixelFormat& pf);
  293. static uint32_t GetBitsPerPixel(DXGIFormat fmt);
  294. Result Load(const char* filepath);
  295. Result Load(std::istream& input);
  296. Result Load(const uint8_t* data, size_t size);
  297. Result Load(std::vector<uint8_t>&& dds);
  298. const ImageData* GetImageData(uint32_t mipIdx = 0,
  299. uint32_t arrayIdx = 0) const {
  300. if (mipIdx < m_mipCount && arrayIdx < m_arraySize) {
  301. return &m_imageDatas[m_mipCount * arrayIdx + mipIdx];
  302. }
  303. return nullptr;
  304. }
  305. bool Flip();
  306. uint32_t GetWidth() const { return m_width; }
  307. uint32_t GetHeight() const { return m_height; }
  308. uint32_t GetDepth() const { return m_depth; }
  309. uint32_t GetMipCount() const { return m_mipCount; }
  310. uint32_t GetArraySize() const { return m_arraySize; }
  311. DXGIFormat GetFormat() const { return m_format; }
  312. bool IsCubemap() const { return m_isCubemap; }
  313. TextureDimension GetTextureDimension() const { return m_texDim; }
  314. private:
  315. void GetImageInfo(uint32_t w, uint32_t h, DXGIFormat fmt,
  316. uint32_t* outNumBytes, uint32_t* outRowBytes,
  317. uint32_t* outNumRows);
  318. bool FlipImage(ImageData& imageData);
  319. bool FlipCompressedImage(ImageData& imageData);
  320. void FlipCompressedImageBC1(ImageData& imageData);
  321. void FlipCompressedImageBC2(ImageData& imageData);
  322. void FlipCompressedImageBC3(ImageData& imageData);
  323. void FlipCompressedImageBC4(ImageData& imageData);
  324. void FlipCompressedImageBC5(ImageData& imageData);
  325. private:
  326. std::vector<uint8_t> m_dds;
  327. std::vector<ImageData> m_imageDatas;
  328. uint32_t m_height;
  329. uint32_t m_width;
  330. uint32_t m_depth;
  331. uint32_t m_mipCount;
  332. uint32_t m_arraySize;
  333. DXGIFormat m_format;
  334. bool m_isCubemap;
  335. TextureDimension m_texDim;
  336. };
  337. } // namespace tinyddsloader
  338. #ifdef TINYDDSLOADER_IMPLEMENTATION
  339. #if _WIN32
  340. #undef min
  341. #undef max
  342. #endif // _Win32
  343. #include <algorithm>
  344. #include <fstream>
  345. namespace tinyddsloader {
  346. const char DDSFile::Magic[4] = {'D', 'D', 'S', ' '};
  347. bool DDSFile::IsCompressed(DXGIFormat fmt) {
  348. switch (fmt) {
  349. case DXGIFormat::BC1_Typeless:
  350. case DXGIFormat::BC1_UNorm:
  351. case DXGIFormat::BC1_UNorm_SRGB:
  352. case DXGIFormat::BC2_Typeless:
  353. case DXGIFormat::BC2_UNorm:
  354. case DXGIFormat::BC2_UNorm_SRGB:
  355. case DXGIFormat::BC3_Typeless:
  356. case DXGIFormat::BC3_UNorm:
  357. case DXGIFormat::BC3_UNorm_SRGB:
  358. case DXGIFormat::BC4_Typeless:
  359. case DXGIFormat::BC4_UNorm:
  360. case DXGIFormat::BC4_SNorm:
  361. case DXGIFormat::BC5_Typeless:
  362. case DXGIFormat::BC5_UNorm:
  363. case DXGIFormat::BC5_SNorm:
  364. case DXGIFormat::BC6H_Typeless:
  365. case DXGIFormat::BC6H_UF16:
  366. case DXGIFormat::BC6H_SF16:
  367. case DXGIFormat::BC7_Typeless:
  368. case DXGIFormat::BC7_UNorm:
  369. case DXGIFormat::BC7_UNorm_SRGB:
  370. return true;
  371. }
  372. return false;
  373. }
  374. uint32_t DDSFile::MakeFourCC(char ch0, char ch1, char ch2, char ch3) {
  375. return (uint32_t(uint8_t(ch0)) | (uint32_t(uint8_t(ch1)) << 8) |
  376. (uint32_t(uint8_t(ch2)) << 16) | (uint32_t(uint8_t(ch3)) << 24));
  377. }
  378. DDSFile::DXGIFormat DDSFile::GetDXGIFormat(const PixelFormat& pf) {
  379. if (pf.m_flags & uint32_t(PixelFormatFlagBits::RGB)) {
  380. switch (pf.m_bitCount) {
  381. case 32:
  382. if (pf.m_RBitMask == 0x000000ff &&
  383. pf.m_GBitMask == 0x0000ff00 &&
  384. pf.m_BBitMask == 0x00ff0000 &&
  385. pf.m_ABitMask == 0xff000000) {
  386. return DXGIFormat::R8G8B8A8_UNorm;
  387. }
  388. if (pf.m_RBitMask == 0x00ff0000 &&
  389. pf.m_GBitMask == 0x0000ff00 &&
  390. pf.m_BBitMask == 0x000000ff &&
  391. pf.m_ABitMask == 0xff000000) {
  392. return DXGIFormat::B8G8R8A8_UNorm;
  393. }
  394. if (pf.m_RBitMask == 0x00ff0000 &&
  395. pf.m_GBitMask == 0x0000ff00 &&
  396. pf.m_BBitMask == 0x000000ff &&
  397. pf.m_ABitMask == 0x00000000) {
  398. return DXGIFormat::B8G8R8X8_UNorm;
  399. }
  400. if (pf.m_RBitMask == 0x0000ffff &&
  401. pf.m_GBitMask == 0xffff0000 &&
  402. pf.m_BBitMask == 0x00000000 &&
  403. pf.m_ABitMask == 0x00000000) {
  404. return DXGIFormat::R16G16_UNorm;
  405. }
  406. if (pf.m_RBitMask == 0xffffffff &&
  407. pf.m_GBitMask == 0x00000000 &&
  408. pf.m_BBitMask == 0x00000000 &&
  409. pf.m_ABitMask == 0x00000000) {
  410. return DXGIFormat::R32_Float;
  411. }
  412. break;
  413. case 24:
  414. break;
  415. case 16:
  416. if (pf.m_RBitMask == 0x7c00 && pf.m_GBitMask == 0x03e0 &&
  417. pf.m_BBitMask == 0x001f && pf.m_ABitMask == 0x8000) {
  418. return DXGIFormat::B5G5R5A1_UNorm;
  419. }
  420. if (pf.m_RBitMask == 0xf800 && pf.m_GBitMask == 0x07e0 &&
  421. pf.m_BBitMask == 0x001f && pf.m_ABitMask == 0x0000) {
  422. return DXGIFormat::B5G6R5_UNorm;
  423. }
  424. if (pf.m_RBitMask == 0x0f00 && pf.m_GBitMask == 0x00f0 &&
  425. pf.m_BBitMask == 0x000f && pf.m_ABitMask == 0xf000) {
  426. return DXGIFormat::B4G4R4A4_UNorm;
  427. }
  428. break;
  429. default:
  430. break;
  431. }
  432. } else if (pf.m_flags & uint32_t(PixelFormatFlagBits::Luminance)) {
  433. if (8 == pf.m_bitCount) {
  434. if (pf.m_RBitMask == 0x000000ff && pf.m_GBitMask == 0x00000000 &&
  435. pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) {
  436. return DXGIFormat::R8_UNorm;
  437. }
  438. if (pf.m_RBitMask == 0x000000ff && pf.m_GBitMask == 0x0000ff00 &&
  439. pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) {
  440. return DXGIFormat::R8G8_UNorm;
  441. }
  442. }
  443. if (16 == pf.m_bitCount) {
  444. if (pf.m_RBitMask == 0x0000ffff && pf.m_GBitMask == 0x00000000 &&
  445. pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) {
  446. return DXGIFormat::R16_UNorm;
  447. }
  448. if (pf.m_RBitMask == 0x000000ff && pf.m_GBitMask == 0x0000ff00 &&
  449. pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) {
  450. return DXGIFormat::R8G8_UNorm;
  451. }
  452. }
  453. } else if (pf.m_flags & uint32_t(PixelFormatFlagBits::Alpha)) {
  454. if (8 == pf.m_bitCount) {
  455. return DXGIFormat::A8_UNorm;
  456. }
  457. } else if (pf.m_flags & uint32_t(PixelFormatFlagBits::BumpDUDV)) {
  458. if (16 == pf.m_bitCount) {
  459. if (pf.m_RBitMask == 0x00ff && pf.m_GBitMask == 0xff00 &&
  460. pf.m_BBitMask == 0x0000 && pf.m_ABitMask == 0x0000) {
  461. return DXGIFormat::R8G8_SNorm;
  462. }
  463. }
  464. if (32 == pf.m_bitCount) {
  465. if (pf.m_RBitMask == 0x000000ff && pf.m_GBitMask == 0x0000ff00 &&
  466. pf.m_BBitMask == 0x00ff0000 && pf.m_ABitMask == 0xff000000) {
  467. return DXGIFormat::R8G8B8A8_SNorm;
  468. }
  469. if (pf.m_RBitMask == 0x0000ffff && pf.m_GBitMask == 0xffff0000 &&
  470. pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) {
  471. return DXGIFormat::R16G16_SNorm;
  472. }
  473. }
  474. } else if (pf.m_flags & uint32_t(PixelFormatFlagBits::FourCC)) {
  475. if (MakeFourCC('D', 'X', 'T', '1') == pf.m_fourCC) {
  476. return DXGIFormat::BC1_UNorm;
  477. }
  478. if (MakeFourCC('D', 'X', 'T', '3') == pf.m_fourCC) {
  479. return DXGIFormat::BC2_UNorm;
  480. }
  481. if (MakeFourCC('D', 'X', 'T', '5') == pf.m_fourCC) {
  482. return DXGIFormat::BC3_UNorm;
  483. }
  484. if (MakeFourCC('D', 'X', 'T', '4') == pf.m_fourCC) {
  485. return DXGIFormat::BC2_UNorm;
  486. }
  487. if (MakeFourCC('D', 'X', 'T', '5') == pf.m_fourCC) {
  488. return DXGIFormat::BC3_UNorm;
  489. }
  490. if (MakeFourCC('A', 'T', 'I', '1') == pf.m_fourCC) {
  491. return DXGIFormat::BC4_UNorm;
  492. }
  493. if (MakeFourCC('B', 'C', '4', 'U') == pf.m_fourCC) {
  494. return DXGIFormat::BC4_UNorm;
  495. }
  496. if (MakeFourCC('B', 'C', '4', 'S') == pf.m_fourCC) {
  497. return DXGIFormat::BC4_SNorm;
  498. }
  499. if (MakeFourCC('A', 'T', 'I', '2') == pf.m_fourCC) {
  500. return DXGIFormat::BC5_UNorm;
  501. }
  502. if (MakeFourCC('B', 'C', '5', 'U') == pf.m_fourCC) {
  503. return DXGIFormat::BC5_UNorm;
  504. }
  505. if (MakeFourCC('B', 'C', '5', 'S') == pf.m_fourCC) {
  506. return DXGIFormat::BC5_SNorm;
  507. }
  508. if (MakeFourCC('R', 'G', 'B', 'G') == pf.m_fourCC) {
  509. return DXGIFormat::R8G8_B8G8_UNorm;
  510. }
  511. if (MakeFourCC('G', 'R', 'G', 'B') == pf.m_fourCC) {
  512. return DXGIFormat::G8R8_G8B8_UNorm;
  513. }
  514. if (MakeFourCC('Y', 'U', 'Y', '2') == pf.m_fourCC) {
  515. return DXGIFormat::YUY2;
  516. }
  517. switch (pf.m_fourCC) {
  518. case 36:
  519. return DXGIFormat::R16G16B16A16_UNorm;
  520. case 110:
  521. return DXGIFormat::R16G16B16A16_SNorm;
  522. case 111:
  523. return DXGIFormat::R16_Float;
  524. case 112:
  525. return DXGIFormat::R16G16_Float;
  526. case 113:
  527. return DXGIFormat::R16G16B16A16_Float;
  528. case 114:
  529. return DXGIFormat::R32_Float;
  530. case 115:
  531. return DXGIFormat::R32G32_Float;
  532. case 116:
  533. return DXGIFormat::R32G32B32A32_Float;
  534. }
  535. }
  536. return DXGIFormat::Unknown;
  537. }
  538. uint32_t DDSFile::GetBitsPerPixel(DXGIFormat fmt) {
  539. switch (fmt) {
  540. case DXGIFormat::R32G32B32A32_Typeless:
  541. case DXGIFormat::R32G32B32A32_Float:
  542. case DXGIFormat::R32G32B32A32_UInt:
  543. case DXGIFormat::R32G32B32A32_SInt:
  544. return 128;
  545. case DXGIFormat::R32G32B32_Typeless:
  546. case DXGIFormat::R32G32B32_Float:
  547. case DXGIFormat::R32G32B32_UInt:
  548. case DXGIFormat::R32G32B32_SInt:
  549. return 96;
  550. case DXGIFormat::R16G16B16A16_Typeless:
  551. case DXGIFormat::R16G16B16A16_Float:
  552. case DXGIFormat::R16G16B16A16_UNorm:
  553. case DXGIFormat::R16G16B16A16_UInt:
  554. case DXGIFormat::R16G16B16A16_SNorm:
  555. case DXGIFormat::R16G16B16A16_SInt:
  556. case DXGIFormat::R32G32_Typeless:
  557. case DXGIFormat::R32G32_Float:
  558. case DXGIFormat::R32G32_UInt:
  559. case DXGIFormat::R32G32_SInt:
  560. case DXGIFormat::R32G8X24_Typeless:
  561. case DXGIFormat::D32_Float_S8X24_UInt:
  562. case DXGIFormat::R32_Float_X8X24_Typeless:
  563. case DXGIFormat::X32_Typeless_G8X24_UInt:
  564. case DXGIFormat::Y416:
  565. case DXGIFormat::Y210:
  566. case DXGIFormat::Y216:
  567. return 64;
  568. case DXGIFormat::R10G10B10A2_Typeless:
  569. case DXGIFormat::R10G10B10A2_UNorm:
  570. case DXGIFormat::R10G10B10A2_UInt:
  571. case DXGIFormat::R11G11B10_Float:
  572. case DXGIFormat::R8G8B8A8_Typeless:
  573. case DXGIFormat::R8G8B8A8_UNorm:
  574. case DXGIFormat::R8G8B8A8_UNorm_SRGB:
  575. case DXGIFormat::R8G8B8A8_UInt:
  576. case DXGIFormat::R8G8B8A8_SNorm:
  577. case DXGIFormat::R8G8B8A8_SInt:
  578. case DXGIFormat::R16G16_Typeless:
  579. case DXGIFormat::R16G16_Float:
  580. case DXGIFormat::R16G16_UNorm:
  581. case DXGIFormat::R16G16_UInt:
  582. case DXGIFormat::R16G16_SNorm:
  583. case DXGIFormat::R16G16_SInt:
  584. case DXGIFormat::R32_Typeless:
  585. case DXGIFormat::D32_Float:
  586. case DXGIFormat::R32_Float:
  587. case DXGIFormat::R32_UInt:
  588. case DXGIFormat::R32_SInt:
  589. case DXGIFormat::R24G8_Typeless:
  590. case DXGIFormat::D24_UNorm_S8_UInt:
  591. case DXGIFormat::R24_UNorm_X8_Typeless:
  592. case DXGIFormat::X24_Typeless_G8_UInt:
  593. case DXGIFormat::R9G9B9E5_SHAREDEXP:
  594. case DXGIFormat::R8G8_B8G8_UNorm:
  595. case DXGIFormat::G8R8_G8B8_UNorm:
  596. case DXGIFormat::B8G8R8A8_UNorm:
  597. case DXGIFormat::B8G8R8X8_UNorm:
  598. case DXGIFormat::R10G10B10_XR_BIAS_A2_UNorm:
  599. case DXGIFormat::B8G8R8A8_Typeless:
  600. case DXGIFormat::B8G8R8A8_UNorm_SRGB:
  601. case DXGIFormat::B8G8R8X8_Typeless:
  602. case DXGIFormat::B8G8R8X8_UNorm_SRGB:
  603. case DXGIFormat::AYUV:
  604. case DXGIFormat::Y410:
  605. case DXGIFormat::YUY2:
  606. return 32;
  607. case DXGIFormat::P010:
  608. case DXGIFormat::P016:
  609. return 24;
  610. case DXGIFormat::R8G8_Typeless:
  611. case DXGIFormat::R8G8_UNorm:
  612. case DXGIFormat::R8G8_UInt:
  613. case DXGIFormat::R8G8_SNorm:
  614. case DXGIFormat::R8G8_SInt:
  615. case DXGIFormat::R16_Typeless:
  616. case DXGIFormat::R16_Float:
  617. case DXGIFormat::D16_UNorm:
  618. case DXGIFormat::R16_UNorm:
  619. case DXGIFormat::R16_UInt:
  620. case DXGIFormat::R16_SNorm:
  621. case DXGIFormat::R16_SInt:
  622. case DXGIFormat::B5G6R5_UNorm:
  623. case DXGIFormat::B5G5R5A1_UNorm:
  624. case DXGIFormat::A8P8:
  625. case DXGIFormat::B4G4R4A4_UNorm:
  626. return 16;
  627. case DXGIFormat::NV12:
  628. case DXGIFormat::YUV420_OPAQUE:
  629. case DXGIFormat::NV11:
  630. return 12;
  631. case DXGIFormat::R8_Typeless:
  632. case DXGIFormat::R8_UNorm:
  633. case DXGIFormat::R8_UInt:
  634. case DXGIFormat::R8_SNorm:
  635. case DXGIFormat::R8_SInt:
  636. case DXGIFormat::A8_UNorm:
  637. case DXGIFormat::AI44:
  638. case DXGIFormat::IA44:
  639. case DXGIFormat::P8:
  640. return 8;
  641. case DXGIFormat::R1_UNorm:
  642. return 1;
  643. case DXGIFormat::BC1_Typeless:
  644. case DXGIFormat::BC1_UNorm:
  645. case DXGIFormat::BC1_UNorm_SRGB:
  646. case DXGIFormat::BC4_Typeless:
  647. case DXGIFormat::BC4_UNorm:
  648. case DXGIFormat::BC4_SNorm:
  649. return 4;
  650. case DXGIFormat::BC2_Typeless:
  651. case DXGIFormat::BC2_UNorm:
  652. case DXGIFormat::BC2_UNorm_SRGB:
  653. case DXGIFormat::BC3_Typeless:
  654. case DXGIFormat::BC3_UNorm:
  655. case DXGIFormat::BC3_UNorm_SRGB:
  656. case DXGIFormat::BC5_Typeless:
  657. case DXGIFormat::BC5_UNorm:
  658. case DXGIFormat::BC5_SNorm:
  659. case DXGIFormat::BC6H_Typeless:
  660. case DXGIFormat::BC6H_UF16:
  661. case DXGIFormat::BC6H_SF16:
  662. case DXGIFormat::BC7_Typeless:
  663. case DXGIFormat::BC7_UNorm:
  664. case DXGIFormat::BC7_UNorm_SRGB:
  665. return 8;
  666. default:
  667. return 0;
  668. }
  669. }
  670. Result DDSFile::Load(const char* filepath) {
  671. std::ifstream ifs(filepath, std::ios_base::binary);
  672. if (!ifs.is_open()) {
  673. return Result::ErrorFileOpen;
  674. }
  675. return Load(ifs);
  676. }
  677. Result DDSFile::Load(std::istream& input) {
  678. m_dds.clear();
  679. input.seekg(0, std::ios_base::beg);
  680. auto begPos = input.tellg();
  681. input.seekg(0, std::ios_base::end);
  682. auto endPos = input.tellg();
  683. input.seekg(0, std::ios_base::beg);
  684. auto fileSize = endPos - begPos;
  685. if (fileSize == 0) {
  686. return Result::ErrorRead;
  687. }
  688. std::vector<uint8_t> dds(fileSize);
  689. input.read(reinterpret_cast<char*>(dds.data()), fileSize);
  690. if (input.bad()) {
  691. return Result::ErrorRead;
  692. }
  693. return Load(std::move(dds));
  694. }
  695. Result DDSFile::Load(const uint8_t* data, size_t size) {
  696. std::vector<uint8_t> dds(data, data + size);
  697. return Load(std::move(dds));
  698. }
  699. Result DDSFile::Load(std::vector<uint8_t>&& dds) {
  700. m_dds.clear();
  701. if (dds.size() < 4) {
  702. return Result::ErrorSize;
  703. }
  704. for (int i = 0; i < 4; i++) {
  705. if (dds[i] != Magic[i]) {
  706. return Result::ErrorMagicWord;
  707. }
  708. }
  709. if ((sizeof(uint32_t) + sizeof(Header)) >= dds.size()) {
  710. return Result::ErrorSize;
  711. }
  712. auto header =
  713. reinterpret_cast<const Header*>(dds.data() + sizeof(uint32_t));
  714. if (header->m_size != sizeof(Header) ||
  715. header->m_pixelFormat.m_size != sizeof(PixelFormat)) {
  716. return Result::ErrorVerify;
  717. }
  718. bool dxt10Header = false;
  719. if ((header->m_pixelFormat.m_flags &
  720. uint32_t(PixelFormatFlagBits::FourCC)) &&
  721. (MakeFourCC('D', 'X', '1', '0') == header->m_pixelFormat.m_fourCC)) {
  722. if ((sizeof(uint32_t) + sizeof(Header) + sizeof(HeaderDXT10)) >=
  723. dds.size()) {
  724. return Result::ErrorSize;
  725. }
  726. dxt10Header = true;
  727. }
  728. ptrdiff_t offset = sizeof(uint32_t) + sizeof(Header) +
  729. (dxt10Header ? sizeof(HeaderDXT10) : 0);
  730. m_height = header->m_height;
  731. m_width = header->m_width;
  732. m_texDim = TextureDimension::Unknown;
  733. m_arraySize = 1;
  734. m_format = DXGIFormat::Unknown;
  735. m_isCubemap = false;
  736. m_mipCount = header->m_mipMapCount;
  737. if (0 == m_mipCount) {
  738. m_mipCount = 1;
  739. }
  740. if (dxt10Header) {
  741. auto dxt10Header = reinterpret_cast<const HeaderDXT10*>(
  742. reinterpret_cast<const char*>(header) + sizeof(Header));
  743. m_arraySize = dxt10Header->m_arraySize;
  744. if (m_arraySize == 0) {
  745. return Result::ErrorInvalidData;
  746. }
  747. switch (dxt10Header->m_format) {
  748. case DXGIFormat::AI44:
  749. case DXGIFormat::IA44:
  750. case DXGIFormat::P8:
  751. case DXGIFormat::A8P8:
  752. return Result::ErrorNotSupported;
  753. default:
  754. if (GetBitsPerPixel(dxt10Header->m_format) == 0) {
  755. return Result::ErrorNotSupported;
  756. }
  757. }
  758. m_format = dxt10Header->m_format;
  759. switch (dxt10Header->m_resourceDimension) {
  760. case TextureDimension::Texture1D:
  761. if ((header->m_flags & uint32_t(HeaderFlagBits::Height) &&
  762. (m_height != 1))) {
  763. return Result::ErrorInvalidData;
  764. }
  765. m_height = m_depth = 1;
  766. break;
  767. case TextureDimension::Texture2D:
  768. if (dxt10Header->m_miscFlag &
  769. uint32_t(DXT10MiscFlagBits::TextureCube)) {
  770. m_arraySize *= 6;
  771. m_isCubemap = true;
  772. }
  773. m_depth = 1;
  774. break;
  775. case TextureDimension::Texture3D:
  776. if (!(header->m_flags & uint32_t(HeaderFlagBits::Volume))) {
  777. return Result::ErrorInvalidData;
  778. }
  779. if (m_arraySize > 1) {
  780. return Result::ErrorNotSupported;
  781. }
  782. break;
  783. default:
  784. return Result::ErrorNotSupported;
  785. }
  786. m_texDim = dxt10Header->m_resourceDimension;
  787. } else {
  788. m_format = GetDXGIFormat(header->m_pixelFormat);
  789. if (m_format == DXGIFormat::Unknown) {
  790. return Result::ErrorNotSupported;
  791. }
  792. if (header->m_flags & uint32_t(HeaderFlagBits::Volume)) {
  793. m_texDim = TextureDimension::Texture3D;
  794. } else {
  795. auto caps2 = header->m_caps2 &
  796. uint32_t(HeaderCaps2FlagBits::CubemapAllFaces);
  797. if (caps2) {
  798. if (caps2 != uint32_t(HeaderCaps2FlagBits::CubemapAllFaces)) {
  799. return Result::ErrorNotSupported;
  800. }
  801. m_arraySize = 6;
  802. m_isCubemap = true;
  803. }
  804. m_depth = 1;
  805. m_texDim = TextureDimension::Texture2D;
  806. }
  807. }
  808. std::vector<ImageData> imageDatas(m_mipCount * m_arraySize);
  809. uint8_t* srcBits = dds.data() + offset;
  810. uint8_t* endBits = dds.data() + dds.size();
  811. uint32_t idx = 0;
  812. for (uint32_t j = 0; j < m_arraySize; j++) {
  813. uint32_t w = m_width;
  814. uint32_t h = m_height;
  815. uint32_t d = m_depth;
  816. for (uint32_t i = 0; i < m_mipCount; i++) {
  817. uint32_t numBytes;
  818. uint32_t rowBytes;
  819. GetImageInfo(w, h, m_format, &numBytes, &rowBytes, nullptr);
  820. imageDatas[idx].m_width = w;
  821. imageDatas[idx].m_height = h;
  822. imageDatas[idx].m_depth = d;
  823. imageDatas[idx].m_mem = srcBits;
  824. imageDatas[idx].m_memPitch = rowBytes;
  825. imageDatas[idx].m_memSlicePitch = numBytes;
  826. idx++;
  827. if (srcBits + (numBytes * d) > endBits) {
  828. return Result::ErrorInvalidData;
  829. }
  830. srcBits += numBytes * d;
  831. w = std::max<uint32_t>(1, w / 2);
  832. h = std::max<uint32_t>(1, h / 2);
  833. d = std::max<uint32_t>(1, d / 2);
  834. }
  835. }
  836. m_dds = std::move(dds);
  837. m_imageDatas = std::move(imageDatas);
  838. return Result::Success;
  839. }
  840. void DDSFile::GetImageInfo(uint32_t w, uint32_t h, DXGIFormat fmt,
  841. uint32_t* outNumBytes, uint32_t* outRowBytes,
  842. uint32_t* outNumRows) {
  843. uint32_t numBytes = 0;
  844. uint32_t rowBytes = 0;
  845. uint32_t numRows = 0;
  846. bool bc = false;
  847. bool packed = false;
  848. bool planar = false;
  849. uint32_t bpe = 0;
  850. switch (fmt) {
  851. case DXGIFormat::BC1_Typeless:
  852. case DXGIFormat::BC1_UNorm:
  853. case DXGIFormat::BC1_UNorm_SRGB:
  854. case DXGIFormat::BC4_Typeless:
  855. case DXGIFormat::BC4_UNorm:
  856. case DXGIFormat::BC4_SNorm:
  857. bc = true;
  858. bpe = 8;
  859. break;
  860. case DXGIFormat::BC2_Typeless:
  861. case DXGIFormat::BC2_UNorm:
  862. case DXGIFormat::BC2_UNorm_SRGB:
  863. case DXGIFormat::BC3_Typeless:
  864. case DXGIFormat::BC3_UNorm:
  865. case DXGIFormat::BC3_UNorm_SRGB:
  866. case DXGIFormat::BC5_Typeless:
  867. case DXGIFormat::BC5_UNorm:
  868. case DXGIFormat::BC5_SNorm:
  869. case DXGIFormat::BC6H_Typeless:
  870. case DXGIFormat::BC6H_UF16:
  871. case DXGIFormat::BC6H_SF16:
  872. case DXGIFormat::BC7_Typeless:
  873. case DXGIFormat::BC7_UNorm:
  874. case DXGIFormat::BC7_UNorm_SRGB:
  875. bc = true;
  876. bpe = 16;
  877. break;
  878. case DXGIFormat::R8G8_B8G8_UNorm:
  879. case DXGIFormat::G8R8_G8B8_UNorm:
  880. case DXGIFormat::YUY2:
  881. packed = true;
  882. bpe = 4;
  883. break;
  884. case DXGIFormat::Y210:
  885. case DXGIFormat::Y216:
  886. packed = true;
  887. bpe = 8;
  888. break;
  889. case DXGIFormat::NV12:
  890. case DXGIFormat::YUV420_OPAQUE:
  891. planar = true;
  892. bpe = 2;
  893. break;
  894. case DXGIFormat::P010:
  895. case DXGIFormat::P016:
  896. planar = true;
  897. bpe = 4;
  898. break;
  899. default:
  900. break;
  901. }
  902. if (bc) {
  903. uint32_t numBlocksWide = 0;
  904. if (w > 0) {
  905. numBlocksWide = std::max<uint32_t>(1, (w + 3) / 4);
  906. }
  907. uint32_t numBlocksHigh = 0;
  908. if (h > 0) {
  909. numBlocksHigh = std::max<uint32_t>(1, (h + 3) / 4);
  910. }
  911. rowBytes = numBlocksWide * bpe;
  912. numRows = numBlocksHigh;
  913. numBytes = rowBytes * numBlocksHigh;
  914. } else if (packed) {
  915. rowBytes = ((w + 1) >> 1) * bpe;
  916. numRows = h;
  917. numBytes = rowBytes * h;
  918. } else if (fmt == DXGIFormat::NV11) {
  919. rowBytes = ((w + 3) >> 2) * 4;
  920. numRows = h * 2;
  921. numBytes = rowBytes + numRows;
  922. } else if (planar) {
  923. rowBytes = ((w + 1) >> 1) * bpe;
  924. numBytes = (rowBytes * h) + ((rowBytes * h + 1) >> 1);
  925. numRows = h + ((h + 1) >> 1);
  926. } else {
  927. uint32_t bpp = GetBitsPerPixel(fmt);
  928. rowBytes = (w * bpp + 7) / 8;
  929. numRows = h;
  930. numBytes = rowBytes * h;
  931. }
  932. if (outNumBytes) {
  933. *outNumBytes = numBytes;
  934. }
  935. if (outRowBytes) {
  936. *outRowBytes = rowBytes;
  937. }
  938. if (outNumRows) {
  939. *outNumRows = numRows;
  940. }
  941. }
  942. bool DDSFile::Flip() {
  943. if (IsCompressed(m_format)) {
  944. for (auto& imageData : m_imageDatas) {
  945. if (!FlipCompressedImage(imageData)) {
  946. return false;
  947. }
  948. }
  949. } else {
  950. for (auto& imageData : m_imageDatas) {
  951. if (!FlipImage(imageData)) {
  952. return false;
  953. }
  954. }
  955. }
  956. return true;
  957. }
  958. bool DDSFile::FlipImage(ImageData& imageData) {
  959. for (uint32_t y = 0; y < imageData.m_height / 2; y++) {
  960. auto line0 = (uint8_t*)imageData.m_mem + y * imageData.m_memPitch;
  961. auto line1 = (uint8_t*)imageData.m_mem +
  962. (imageData.m_height - y - 1) * imageData.m_memPitch;
  963. for (uint32_t i = 0; i < imageData.m_memPitch; i++) {
  964. std::swap(*line0, *line1);
  965. line0++;
  966. line1++;
  967. }
  968. }
  969. return true;
  970. }
  971. bool DDSFile::FlipCompressedImage(ImageData& imageData) {
  972. if (DXGIFormat::BC1_Typeless == m_format ||
  973. DXGIFormat::BC1_UNorm == m_format ||
  974. DXGIFormat::BC1_UNorm_SRGB == m_format) {
  975. FlipCompressedImageBC1(imageData);
  976. return true;
  977. } else if (DXGIFormat::BC2_Typeless == m_format ||
  978. DXGIFormat::BC2_UNorm == m_format ||
  979. DXGIFormat::BC2_UNorm_SRGB == m_format) {
  980. FlipCompressedImageBC2(imageData);
  981. return true;
  982. } else if (DXGIFormat::BC3_Typeless == m_format ||
  983. DXGIFormat::BC3_UNorm == m_format ||
  984. DXGIFormat::BC3_UNorm_SRGB == m_format) {
  985. FlipCompressedImageBC3(imageData);
  986. return true;
  987. } else if (DXGIFormat::BC4_Typeless == m_format ||
  988. DXGIFormat::BC4_UNorm == m_format ||
  989. DXGIFormat::BC4_SNorm == m_format) {
  990. FlipCompressedImageBC4(imageData);
  991. return true;
  992. } else if (DXGIFormat::BC5_Typeless == m_format ||
  993. DXGIFormat::BC5_UNorm == m_format ||
  994. DXGIFormat::BC5_SNorm == m_format) {
  995. FlipCompressedImageBC5(imageData);
  996. return true;
  997. }
  998. return false;
  999. }
  1000. void DDSFile::FlipCompressedImageBC1(ImageData& imageData) {
  1001. uint32_t numXBlocks = (imageData.m_width + 3) / 4;
  1002. uint32_t numYBlocks = (imageData.m_height + 3) / 4;
  1003. if (imageData.m_height == 1) {
  1004. } else if (imageData.m_height == 2) {
  1005. auto blocks = (BC1Block*)imageData.m_mem;
  1006. for (uint32_t x = 0; x < numXBlocks; x++) {
  1007. auto block = blocks + x;
  1008. std::swap(block->m_row0, block->m_row1);
  1009. std::swap(block->m_row2, block->m_row3);
  1010. }
  1011. } else {
  1012. for (uint32_t y = 0; y < (numYBlocks + 1) / 2; y++) {
  1013. auto blocks0 = (BC1Block*)((uint8_t*)imageData.m_mem +
  1014. imageData.m_memPitch * y);
  1015. auto blocks1 =
  1016. (BC1Block*)((uint8_t*)imageData.m_mem +
  1017. imageData.m_memPitch * (numYBlocks - y - 1));
  1018. for (uint32_t x = 0; x < numXBlocks; x++) {
  1019. auto block0 = blocks0 + x;
  1020. auto block1 = blocks1 + x;
  1021. if (blocks0 != blocks1) {
  1022. std::swap(block0->m_color0, block1->m_color0);
  1023. std::swap(block0->m_color1, block1->m_color1);
  1024. std::swap(block0->m_row0, block1->m_row3);
  1025. std::swap(block0->m_row1, block1->m_row2);
  1026. std::swap(block0->m_row2, block1->m_row1);
  1027. std::swap(block0->m_row3, block1->m_row0);
  1028. } else {
  1029. std::swap(block0->m_row0, block0->m_row3);
  1030. std::swap(block0->m_row1, block0->m_row2);
  1031. }
  1032. }
  1033. }
  1034. }
  1035. }
  1036. void DDSFile::FlipCompressedImageBC2(ImageData& imageData) {
  1037. uint32_t numXBlocks = (imageData.m_width + 3) / 4;
  1038. uint32_t numYBlocks = (imageData.m_height + 3) / 4;
  1039. if (imageData.m_height == 1) {
  1040. } else if (imageData.m_height == 2) {
  1041. auto blocks = (BC2Block*)imageData.m_mem;
  1042. for (uint32_t x = 0; x < numXBlocks; x++) {
  1043. auto block = blocks + x;
  1044. std::swap(block->m_alphaRow0, block->m_alphaRow1);
  1045. std::swap(block->m_alphaRow2, block->m_alphaRow3);
  1046. std::swap(block->m_row0, block->m_row1);
  1047. std::swap(block->m_row2, block->m_row3);
  1048. }
  1049. } else {
  1050. for (uint32_t y = 0; y < (numYBlocks + 1) / 2; y++) {
  1051. auto blocks0 = (BC2Block*)((uint8_t*)imageData.m_mem +
  1052. imageData.m_memPitch * y);
  1053. auto blocks1 =
  1054. (BC2Block*)((uint8_t*)imageData.m_mem +
  1055. imageData.m_memPitch * (numYBlocks - y - 1));
  1056. for (uint32_t x = 0; x < numXBlocks; x++) {
  1057. auto block0 = blocks0 + x;
  1058. auto block1 = blocks1 + x;
  1059. if (block0 != block1) {
  1060. std::swap(block0->m_alphaRow0, block1->m_alphaRow3);
  1061. std::swap(block0->m_alphaRow1, block1->m_alphaRow2);
  1062. std::swap(block0->m_alphaRow2, block1->m_alphaRow1);
  1063. std::swap(block0->m_alphaRow3, block1->m_alphaRow0);
  1064. std::swap(block0->m_color0, block1->m_color0);
  1065. std::swap(block0->m_color1, block1->m_color1);
  1066. std::swap(block0->m_row0, block1->m_row3);
  1067. std::swap(block0->m_row1, block1->m_row2);
  1068. std::swap(block0->m_row2, block1->m_row1);
  1069. std::swap(block0->m_row3, block1->m_row0);
  1070. } else {
  1071. std::swap(block0->m_alphaRow0, block0->m_alphaRow3);
  1072. std::swap(block0->m_alphaRow1, block0->m_alphaRow2);
  1073. std::swap(block0->m_row0, block0->m_row3);
  1074. std::swap(block0->m_row1, block0->m_row2);
  1075. }
  1076. }
  1077. }
  1078. }
  1079. }
  1080. void DDSFile::FlipCompressedImageBC3(ImageData& imageData) {
  1081. uint32_t numXBlocks = (imageData.m_width + 3) / 4;
  1082. uint32_t numYBlocks = (imageData.m_height + 3) / 4;
  1083. if (imageData.m_height == 1) {
  1084. } else if (imageData.m_height == 2) {
  1085. auto blocks = (BC3Block*)imageData.m_mem;
  1086. for (uint32_t x = 0; x < numXBlocks; x++) {
  1087. auto block = blocks + x;
  1088. uint8_t r0 = (block->m_alphaR1 >> 4) | (block->m_alphaR2 << 4);
  1089. uint8_t r1 = (block->m_alphaR2 >> 4) | (block->m_alphaR0 << 4);
  1090. uint8_t r2 = (block->m_alphaR0 >> 4) | (block->m_alphaR1 << 4);
  1091. uint8_t r3 = (block->m_alphaR4 >> 4) | (block->m_alphaR5 << 4);
  1092. uint8_t r4 = (block->m_alphaR5 >> 4) | (block->m_alphaR3 << 4);
  1093. uint8_t r5 = (block->m_alphaR3 >> 4) | (block->m_alphaR4 << 4);
  1094. block->m_alphaR0 = r0;
  1095. block->m_alphaR1 = r1;
  1096. block->m_alphaR2 = r2;
  1097. block->m_alphaR3 = r3;
  1098. block->m_alphaR4 = r4;
  1099. block->m_alphaR5 = r5;
  1100. std::swap(block->m_row0, block->m_row1);
  1101. std::swap(block->m_row2, block->m_row3);
  1102. }
  1103. } else {
  1104. for (uint32_t y = 0; y < (numYBlocks + 1) / 2; y++) {
  1105. auto blocks0 = (BC3Block*)((uint8_t*)imageData.m_mem +
  1106. imageData.m_memPitch * y);
  1107. auto blocks1 =
  1108. (BC3Block*)((uint8_t*)imageData.m_mem +
  1109. imageData.m_memPitch * (numYBlocks - y - 1));
  1110. for (uint32_t x = 0; x < numXBlocks; x++) {
  1111. auto block0 = blocks0 + x;
  1112. auto block1 = blocks1 + x;
  1113. if (block0 != block1) {
  1114. std::swap(block0->m_alpha0, block1->m_alpha0);
  1115. std::swap(block0->m_alpha1, block1->m_alpha1);
  1116. uint8_t r0[6];
  1117. r0[0] = (block0->m_alphaR4 >> 4) | (block0->m_alphaR5 << 4);
  1118. r0[1] = (block0->m_alphaR5 >> 4) | (block0->m_alphaR3 << 4);
  1119. r0[2] = (block0->m_alphaR3 >> 4) | (block0->m_alphaR4 << 4);
  1120. r0[3] = (block0->m_alphaR1 >> 4) | (block0->m_alphaR2 << 4);
  1121. r0[4] = (block0->m_alphaR2 >> 4) | (block0->m_alphaR0 << 4);
  1122. r0[5] = (block0->m_alphaR0 >> 4) | (block0->m_alphaR1 << 4);
  1123. uint8_t r1[6];
  1124. r1[0] = (block1->m_alphaR4 >> 4) | (block1->m_alphaR5 << 4);
  1125. r1[1] = (block1->m_alphaR5 >> 4) | (block1->m_alphaR3 << 4);
  1126. r1[2] = (block1->m_alphaR3 >> 4) | (block1->m_alphaR4 << 4);
  1127. r1[3] = (block1->m_alphaR1 >> 4) | (block1->m_alphaR2 << 4);
  1128. r1[4] = (block1->m_alphaR2 >> 4) | (block1->m_alphaR0 << 4);
  1129. r1[5] = (block1->m_alphaR0 >> 4) | (block1->m_alphaR1 << 4);
  1130. block0->m_alphaR0 = r1[0];
  1131. block0->m_alphaR1 = r1[1];
  1132. block0->m_alphaR2 = r1[2];
  1133. block0->m_alphaR3 = r1[3];
  1134. block0->m_alphaR4 = r1[4];
  1135. block0->m_alphaR5 = r1[5];
  1136. block1->m_alphaR0 = r0[0];
  1137. block1->m_alphaR1 = r0[1];
  1138. block1->m_alphaR2 = r0[2];
  1139. block1->m_alphaR3 = r0[3];
  1140. block1->m_alphaR4 = r0[4];
  1141. block1->m_alphaR5 = r0[5];
  1142. std::swap(block0->m_color0, block1->m_color0);
  1143. std::swap(block0->m_color1, block1->m_color1);
  1144. std::swap(block0->m_row0, block1->m_row3);
  1145. std::swap(block0->m_row1, block1->m_row2);
  1146. std::swap(block0->m_row2, block1->m_row1);
  1147. std::swap(block0->m_row3, block1->m_row0);
  1148. } else {
  1149. uint8_t r0[6];
  1150. r0[0] = (block0->m_alphaR4 >> 4) | (block0->m_alphaR5 << 4);
  1151. r0[1] = (block0->m_alphaR5 >> 4) | (block0->m_alphaR3 << 4);
  1152. r0[2] = (block0->m_alphaR3 >> 4) | (block0->m_alphaR4 << 4);
  1153. r0[3] = (block0->m_alphaR1 >> 4) | (block0->m_alphaR2 << 4);
  1154. r0[4] = (block0->m_alphaR2 >> 4) | (block0->m_alphaR0 << 4);
  1155. r0[5] = (block0->m_alphaR0 >> 4) | (block0->m_alphaR1 << 4);
  1156. block0->m_alphaR0 = r0[0];
  1157. block0->m_alphaR1 = r0[1];
  1158. block0->m_alphaR2 = r0[2];
  1159. block0->m_alphaR3 = r0[3];
  1160. block0->m_alphaR4 = r0[4];
  1161. block0->m_alphaR5 = r0[5];
  1162. std::swap(block0->m_row0, block0->m_row3);
  1163. std::swap(block0->m_row1, block0->m_row2);
  1164. }
  1165. }
  1166. }
  1167. }
  1168. }
  1169. void DDSFile::FlipCompressedImageBC4(ImageData& imageData) {
  1170. uint32_t numXBlocks = (imageData.m_width + 3) / 4;
  1171. uint32_t numYBlocks = (imageData.m_height + 3) / 4;
  1172. if (imageData.m_height == 1) {
  1173. } else if (imageData.m_height == 2) {
  1174. auto blocks = (BC4Block*)imageData.m_mem;
  1175. for (uint32_t x = 0; x < numXBlocks; x++) {
  1176. auto block = blocks + x;
  1177. uint8_t r0 = (block->m_redR1 >> 4) | (block->m_redR2 << 4);
  1178. uint8_t r1 = (block->m_redR2 >> 4) | (block->m_redR0 << 4);
  1179. uint8_t r2 = (block->m_redR0 >> 4) | (block->m_redR1 << 4);
  1180. uint8_t r3 = (block->m_redR4 >> 4) | (block->m_redR5 << 4);
  1181. uint8_t r4 = (block->m_redR5 >> 4) | (block->m_redR3 << 4);
  1182. uint8_t r5 = (block->m_redR3 >> 4) | (block->m_redR4 << 4);
  1183. block->m_redR0 = r0;
  1184. block->m_redR1 = r1;
  1185. block->m_redR2 = r2;
  1186. block->m_redR3 = r3;
  1187. block->m_redR4 = r4;
  1188. block->m_redR5 = r5;
  1189. }
  1190. } else {
  1191. for (uint32_t y = 0; y < (numYBlocks + 1) / 2; y++) {
  1192. auto blocks0 = (BC4Block*)((uint8_t*)imageData.m_mem +
  1193. imageData.m_memPitch * y);
  1194. auto blocks1 =
  1195. (BC4Block*)((uint8_t*)imageData.m_mem +
  1196. imageData.m_memPitch * (numYBlocks - y - 1));
  1197. for (uint32_t x = 0; x < numXBlocks; x++) {
  1198. auto block0 = blocks0 + x;
  1199. auto block1 = blocks1 + x;
  1200. if (block0 != block1) {
  1201. std::swap(block0->m_red0, block1->m_red0);
  1202. std::swap(block0->m_red1, block1->m_red1);
  1203. uint8_t r0[6];
  1204. r0[0] = (block0->m_redR4 >> 4) | (block0->m_redR5 << 4);
  1205. r0[1] = (block0->m_redR5 >> 4) | (block0->m_redR3 << 4);
  1206. r0[2] = (block0->m_redR3 >> 4) | (block0->m_redR4 << 4);
  1207. r0[3] = (block0->m_redR1 >> 4) | (block0->m_redR2 << 4);
  1208. r0[4] = (block0->m_redR2 >> 4) | (block0->m_redR0 << 4);
  1209. r0[5] = (block0->m_redR0 >> 4) | (block0->m_redR1 << 4);
  1210. uint8_t r1[6];
  1211. r1[0] = (block1->m_redR4 >> 4) | (block1->m_redR5 << 4);
  1212. r1[1] = (block1->m_redR5 >> 4) | (block1->m_redR3 << 4);
  1213. r1[2] = (block1->m_redR3 >> 4) | (block1->m_redR4 << 4);
  1214. r1[3] = (block1->m_redR1 >> 4) | (block1->m_redR2 << 4);
  1215. r1[4] = (block1->m_redR2 >> 4) | (block1->m_redR0 << 4);
  1216. r1[5] = (block1->m_redR0 >> 4) | (block1->m_redR1 << 4);
  1217. block0->m_redR0 = r1[0];
  1218. block0->m_redR1 = r1[1];
  1219. block0->m_redR2 = r1[2];
  1220. block0->m_redR3 = r1[3];
  1221. block0->m_redR4 = r1[4];
  1222. block0->m_redR5 = r1[5];
  1223. block1->m_redR0 = r0[0];
  1224. block1->m_redR1 = r0[1];
  1225. block1->m_redR2 = r0[2];
  1226. block1->m_redR3 = r0[3];
  1227. block1->m_redR4 = r0[4];
  1228. block1->m_redR5 = r0[5];
  1229. } else {
  1230. uint8_t r0[6];
  1231. r0[0] = (block0->m_redR4 >> 4) | (block0->m_redR5 << 4);
  1232. r0[1] = (block0->m_redR5 >> 4) | (block0->m_redR3 << 4);
  1233. r0[2] = (block0->m_redR3 >> 4) | (block0->m_redR4 << 4);
  1234. r0[3] = (block0->m_redR1 >> 4) | (block0->m_redR2 << 4);
  1235. r0[4] = (block0->m_redR2 >> 4) | (block0->m_redR0 << 4);
  1236. r0[5] = (block0->m_redR0 >> 4) | (block0->m_redR1 << 4);
  1237. block0->m_redR0 = r0[0];
  1238. block0->m_redR1 = r0[1];
  1239. block0->m_redR2 = r0[2];
  1240. block0->m_redR3 = r0[3];
  1241. block0->m_redR4 = r0[4];
  1242. block0->m_redR5 = r0[5];
  1243. }
  1244. }
  1245. }
  1246. }
  1247. }
  1248. void DDSFile::FlipCompressedImageBC5(ImageData& imageData) {
  1249. uint32_t numXBlocks = (imageData.m_width + 3) / 4;
  1250. uint32_t numYBlocks = (imageData.m_height + 3) / 4;
  1251. if (imageData.m_height == 1) {
  1252. } else if (imageData.m_height == 2) {
  1253. auto blocks = (BC5Block*)imageData.m_mem;
  1254. for (uint32_t x = 0; x < numXBlocks; x++) {
  1255. auto block = blocks + x;
  1256. uint8_t r0 = (block->m_redR1 >> 4) | (block->m_redR2 << 4);
  1257. uint8_t r1 = (block->m_redR2 >> 4) | (block->m_redR0 << 4);
  1258. uint8_t r2 = (block->m_redR0 >> 4) | (block->m_redR1 << 4);
  1259. uint8_t r3 = (block->m_redR4 >> 4) | (block->m_redR5 << 4);
  1260. uint8_t r4 = (block->m_redR5 >> 4) | (block->m_redR3 << 4);
  1261. uint8_t r5 = (block->m_redR3 >> 4) | (block->m_redR4 << 4);
  1262. block->m_redR0 = r0;
  1263. block->m_redR1 = r1;
  1264. block->m_redR2 = r2;
  1265. block->m_redR3 = r3;
  1266. block->m_redR4 = r4;
  1267. block->m_redR5 = r5;
  1268. uint8_t g0 = (block->m_greenR1 >> 4) | (block->m_greenR2 << 4);
  1269. uint8_t g1 = (block->m_greenR2 >> 4) | (block->m_greenR0 << 4);
  1270. uint8_t g2 = (block->m_greenR0 >> 4) | (block->m_greenR1 << 4);
  1271. uint8_t g3 = (block->m_greenR4 >> 4) | (block->m_greenR5 << 4);
  1272. uint8_t g4 = (block->m_greenR5 >> 4) | (block->m_greenR3 << 4);
  1273. uint8_t g5 = (block->m_greenR3 >> 4) | (block->m_greenR4 << 4);
  1274. block->m_greenR0 = g0;
  1275. block->m_greenR1 = g1;
  1276. block->m_greenR2 = g2;
  1277. block->m_greenR3 = g3;
  1278. block->m_greenR4 = g4;
  1279. block->m_greenR5 = g5;
  1280. }
  1281. } else {
  1282. for (uint32_t y = 0; y < (numYBlocks + 1) / 2; y++) {
  1283. auto blocks0 = (BC5Block*)((uint8_t*)imageData.m_mem +
  1284. imageData.m_memPitch * y);
  1285. auto blocks1 =
  1286. (BC5Block*)((uint8_t*)imageData.m_mem +
  1287. imageData.m_memPitch * (numYBlocks - y - 1));
  1288. for (uint32_t x = 0; x < numXBlocks; x++) {
  1289. auto block0 = blocks0 + x;
  1290. auto block1 = blocks1 + x;
  1291. if (block0 != block1) {
  1292. std::swap(block0->m_red0, block1->m_red0);
  1293. std::swap(block0->m_red1, block1->m_red1);
  1294. uint8_t r0[6];
  1295. r0[0] = (block0->m_redR4 >> 4) | (block0->m_redR5 << 4);
  1296. r0[1] = (block0->m_redR5 >> 4) | (block0->m_redR3 << 4);
  1297. r0[2] = (block0->m_redR3 >> 4) | (block0->m_redR4 << 4);
  1298. r0[3] = (block0->m_redR1 >> 4) | (block0->m_redR2 << 4);
  1299. r0[4] = (block0->m_redR2 >> 4) | (block0->m_redR0 << 4);
  1300. r0[5] = (block0->m_redR0 >> 4) | (block0->m_redR1 << 4);
  1301. uint8_t r1[6];
  1302. r1[0] = (block1->m_redR4 >> 4) | (block1->m_redR5 << 4);
  1303. r1[1] = (block1->m_redR5 >> 4) | (block1->m_redR3 << 4);
  1304. r1[2] = (block1->m_redR3 >> 4) | (block1->m_redR4 << 4);
  1305. r1[3] = (block1->m_redR1 >> 4) | (block1->m_redR2 << 4);
  1306. r1[4] = (block1->m_redR2 >> 4) | (block1->m_redR0 << 4);
  1307. r1[5] = (block1->m_redR0 >> 4) | (block1->m_redR1 << 4);
  1308. block0->m_redR0 = r1[0];
  1309. block0->m_redR1 = r1[1];
  1310. block0->m_redR2 = r1[2];
  1311. block0->m_redR3 = r1[3];
  1312. block0->m_redR4 = r1[4];
  1313. block0->m_redR5 = r1[5];
  1314. block1->m_redR0 = r0[0];
  1315. block1->m_redR1 = r0[1];
  1316. block1->m_redR2 = r0[2];
  1317. block1->m_redR3 = r0[3];
  1318. block1->m_redR4 = r0[4];
  1319. block1->m_redR5 = r0[5];
  1320. std::swap(block0->m_green0, block1->m_green0);
  1321. std::swap(block0->m_green1, block1->m_green1);
  1322. uint8_t g0[6];
  1323. g0[0] = (block0->m_greenR4 >> 4) | (block0->m_greenR5 << 4);
  1324. g0[1] = (block0->m_greenR5 >> 4) | (block0->m_greenR3 << 4);
  1325. g0[2] = (block0->m_greenR3 >> 4) | (block0->m_greenR4 << 4);
  1326. g0[3] = (block0->m_greenR1 >> 4) | (block0->m_greenR2 << 4);
  1327. g0[4] = (block0->m_greenR2 >> 4) | (block0->m_greenR0 << 4);
  1328. g0[5] = (block0->m_greenR0 >> 4) | (block0->m_greenR1 << 4);
  1329. uint8_t g1[6];
  1330. g1[0] = (block1->m_greenR4 >> 4) | (block1->m_greenR5 << 4);
  1331. g1[1] = (block1->m_greenR5 >> 4) | (block1->m_greenR3 << 4);
  1332. g1[2] = (block1->m_greenR3 >> 4) | (block1->m_greenR4 << 4);
  1333. g1[3] = (block1->m_greenR1 >> 4) | (block1->m_greenR2 << 4);
  1334. g1[4] = (block1->m_greenR2 >> 4) | (block1->m_greenR0 << 4);
  1335. g1[5] = (block1->m_greenR0 >> 4) | (block1->m_greenR1 << 4);
  1336. block0->m_greenR0 = g1[0];
  1337. block0->m_greenR1 = g1[1];
  1338. block0->m_greenR2 = g1[2];
  1339. block0->m_greenR3 = g1[3];
  1340. block0->m_greenR4 = g1[4];
  1341. block0->m_greenR5 = g1[5];
  1342. block1->m_greenR0 = g0[0];
  1343. block1->m_greenR1 = g0[1];
  1344. block1->m_greenR2 = g0[2];
  1345. block1->m_greenR3 = g0[3];
  1346. block1->m_greenR4 = g0[4];
  1347. block1->m_greenR5 = g0[5];
  1348. } else {
  1349. uint8_t r0[6];
  1350. r0[0] = (block0->m_redR4 >> 4) | (block0->m_redR5 << 4);
  1351. r0[1] = (block0->m_redR5 >> 4) | (block0->m_redR3 << 4);
  1352. r0[2] = (block0->m_redR3 >> 4) | (block0->m_redR4 << 4);
  1353. r0[3] = (block0->m_redR1 >> 4) | (block0->m_redR2 << 4);
  1354. r0[4] = (block0->m_redR2 >> 4) | (block0->m_redR0 << 4);
  1355. r0[5] = (block0->m_redR0 >> 4) | (block0->m_redR1 << 4);
  1356. block0->m_redR0 = r0[0];
  1357. block0->m_redR1 = r0[1];
  1358. block0->m_redR2 = r0[2];
  1359. block0->m_redR3 = r0[3];
  1360. block0->m_redR4 = r0[4];
  1361. block0->m_redR5 = r0[5];
  1362. uint8_t g0[6];
  1363. g0[0] = (block0->m_greenR4 >> 4) | (block0->m_greenR5 << 4);
  1364. g0[1] = (block0->m_greenR5 >> 4) | (block0->m_greenR3 << 4);
  1365. g0[2] = (block0->m_greenR3 >> 4) | (block0->m_greenR4 << 4);
  1366. g0[3] = (block0->m_greenR1 >> 4) | (block0->m_greenR2 << 4);
  1367. g0[4] = (block0->m_greenR2 >> 4) | (block0->m_greenR0 << 4);
  1368. g0[5] = (block0->m_greenR0 >> 4) | (block0->m_greenR1 << 4);
  1369. block0->m_greenR0 = g0[0];
  1370. block0->m_greenR1 = g0[1];
  1371. block0->m_greenR2 = g0[2];
  1372. block0->m_greenR3 = g0[3];
  1373. block0->m_greenR4 = g0[4];
  1374. block0->m_greenR5 = g0[5];
  1375. }
  1376. }
  1377. }
  1378. }
  1379. }
  1380. } // namespace tinyddsloader
  1381. #endif // !TINYDDSLOADER_IMPLEMENTATION
  1382. #endif // !TINYDDSLOADER_H_