| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514 |
- //
- // Copyright(c) 2019 benikabocha.
- // Distributed under the MIT License (http://opensource.org/licenses/MIT)
- //
- #ifndef TINYDDSLOADER_H_
- #define TINYDDSLOADER_H_
- #include <iostream>
- #include <vector>
- namespace tinyddsloader {
- enum Result {
- Success,
- ErrorFileOpen,
- ErrorRead,
- ErrorMagicWord,
- ErrorSize,
- ErrorVerify,
- ErrorNotSupported,
- ErrorInvalidData,
- };
- class DDSFile {
- public:
- static const char Magic[4];
- enum class PixelFormatFlagBits : uint32_t {
- FourCC = 0x00000004,
- RGB = 0x00000040,
- RGBA = 0x00000041,
- Luminance = 0x00020000,
- LuminanceA = 0x00020001,
- AlphaPixels = 0x00000001,
- Alpha = 0x00000002,
- Palette8 = 0x00000020,
- Palette8A = 0x00000021,
- BumpDUDV = 0x00080000
- };
- enum class DXGIFormat : uint32_t {
- Unknown = 0,
- R32G32B32A32_Typeless = 1,
- R32G32B32A32_Float = 2,
- R32G32B32A32_UInt = 3,
- R32G32B32A32_SInt = 4,
- R32G32B32_Typeless = 5,
- R32G32B32_Float = 6,
- R32G32B32_UInt = 7,
- R32G32B32_SInt = 8,
- R16G16B16A16_Typeless = 9,
- R16G16B16A16_Float = 10,
- R16G16B16A16_UNorm = 11,
- R16G16B16A16_UInt = 12,
- R16G16B16A16_SNorm = 13,
- R16G16B16A16_SInt = 14,
- R32G32_Typeless = 15,
- R32G32_Float = 16,
- R32G32_UInt = 17,
- R32G32_SInt = 18,
- R32G8X24_Typeless = 19,
- D32_Float_S8X24_UInt = 20,
- R32_Float_X8X24_Typeless = 21,
- X32_Typeless_G8X24_UInt = 22,
- R10G10B10A2_Typeless = 23,
- R10G10B10A2_UNorm = 24,
- R10G10B10A2_UInt = 25,
- R11G11B10_Float = 26,
- R8G8B8A8_Typeless = 27,
- R8G8B8A8_UNorm = 28,
- R8G8B8A8_UNorm_SRGB = 29,
- R8G8B8A8_UInt = 30,
- R8G8B8A8_SNorm = 31,
- R8G8B8A8_SInt = 32,
- R16G16_Typeless = 33,
- R16G16_Float = 34,
- R16G16_UNorm = 35,
- R16G16_UInt = 36,
- R16G16_SNorm = 37,
- R16G16_SInt = 38,
- R32_Typeless = 39,
- D32_Float = 40,
- R32_Float = 41,
- R32_UInt = 42,
- R32_SInt = 43,
- R24G8_Typeless = 44,
- D24_UNorm_S8_UInt = 45,
- R24_UNorm_X8_Typeless = 46,
- X24_Typeless_G8_UInt = 47,
- R8G8_Typeless = 48,
- R8G8_UNorm = 49,
- R8G8_UInt = 50,
- R8G8_SNorm = 51,
- R8G8_SInt = 52,
- R16_Typeless = 53,
- R16_Float = 54,
- D16_UNorm = 55,
- R16_UNorm = 56,
- R16_UInt = 57,
- R16_SNorm = 58,
- R16_SInt = 59,
- R8_Typeless = 60,
- R8_UNorm = 61,
- R8_UInt = 62,
- R8_SNorm = 63,
- R8_SInt = 64,
- A8_UNorm = 65,
- R1_UNorm = 66,
- R9G9B9E5_SHAREDEXP = 67,
- R8G8_B8G8_UNorm = 68,
- G8R8_G8B8_UNorm = 69,
- BC1_Typeless = 70,
- BC1_UNorm = 71,
- BC1_UNorm_SRGB = 72,
- BC2_Typeless = 73,
- BC2_UNorm = 74,
- BC2_UNorm_SRGB = 75,
- BC3_Typeless = 76,
- BC3_UNorm = 77,
- BC3_UNorm_SRGB = 78,
- BC4_Typeless = 79,
- BC4_UNorm = 80,
- BC4_SNorm = 81,
- BC5_Typeless = 82,
- BC5_UNorm = 83,
- BC5_SNorm = 84,
- B5G6R5_UNorm = 85,
- B5G5R5A1_UNorm = 86,
- B8G8R8A8_UNorm = 87,
- B8G8R8X8_UNorm = 88,
- R10G10B10_XR_BIAS_A2_UNorm = 89,
- B8G8R8A8_Typeless = 90,
- B8G8R8A8_UNorm_SRGB = 91,
- B8G8R8X8_Typeless = 92,
- B8G8R8X8_UNorm_SRGB = 93,
- BC6H_Typeless = 94,
- BC6H_UF16 = 95,
- BC6H_SF16 = 96,
- BC7_Typeless = 97,
- BC7_UNorm = 98,
- BC7_UNorm_SRGB = 99,
- AYUV = 100,
- Y410 = 101,
- Y416 = 102,
- NV12 = 103,
- P010 = 104,
- P016 = 105,
- YUV420_OPAQUE = 106,
- YUY2 = 107,
- Y210 = 108,
- Y216 = 109,
- NV11 = 110,
- AI44 = 111,
- IA44 = 112,
- P8 = 113,
- A8P8 = 114,
- B4G4R4A4_UNorm = 115,
- P208 = 130,
- V208 = 131,
- V408 = 132,
- };
- enum class HeaderFlagBits : uint32_t {
- Height = 0x00000002,
- Width = 0x00000004,
- Texture = 0x00001007,
- Mipmap = 0x00020000,
- Volume = 0x00800000,
- Pitch = 0x00000008,
- LinearSize = 0x00080000,
- };
- enum class HeaderCaps2FlagBits : uint32_t {
- CubemapPositiveX = 0x00000600,
- CubemapNegativeX = 0x00000a00,
- CubemapPositiveY = 0x00001200,
- CubemapNegativeY = 0x00002200,
- CubemapPositiveZ = 0x00004200,
- CubemapNegativeZ = 0x00008200,
- CubemapAllFaces = CubemapPositiveX | CubemapNegativeX |
- CubemapPositiveY | CubemapNegativeY |
- CubemapPositiveZ | CubemapNegativeZ,
- Volume = 0x00200000,
- };
- struct PixelFormat {
- uint32_t m_size;
- uint32_t m_flags;
- uint32_t m_fourCC;
- uint32_t m_bitCount;
- uint32_t m_RBitMask;
- uint32_t m_GBitMask;
- uint32_t m_BBitMask;
- uint32_t m_ABitMask;
- };
- struct Header {
- uint32_t m_size;
- uint32_t m_flags;
- uint32_t m_height;
- uint32_t m_width;
- uint32_t m_pitchOrLinerSize;
- uint32_t m_depth;
- uint32_t m_mipMapCount;
- uint32_t m_reserved1[11];
- PixelFormat m_pixelFormat;
- uint32_t m_caps;
- uint32_t m_caps2;
- uint32_t m_caps3;
- uint32_t m_caps4;
- uint32_t m_reserved2;
- };
- enum class TextureDimension : uint32_t {
- Unknown = 0,
- Texture1D = 2,
- Texture2D = 3,
- Texture3D = 4
- };
- enum class DXT10MiscFlagBits : uint32_t { TextureCube = 0x4 };
- struct HeaderDXT10 {
- DXGIFormat m_format;
- TextureDimension m_resourceDimension;
- uint32_t m_miscFlag;
- uint32_t m_arraySize;
- uint32_t m_miscFlag2;
- };
- struct ImageData {
- uint32_t m_width;
- uint32_t m_height;
- uint32_t m_depth;
- void* m_mem;
- uint32_t m_memPitch;
- uint32_t m_memSlicePitch;
- };
- struct BC1Block {
- uint16_t m_color0;
- uint16_t m_color1;
- uint8_t m_row0;
- uint8_t m_row1;
- uint8_t m_row2;
- uint8_t m_row3;
- };
- struct BC2Block {
- uint16_t m_alphaRow0;
- uint16_t m_alphaRow1;
- uint16_t m_alphaRow2;
- uint16_t m_alphaRow3;
- uint16_t m_color0;
- uint16_t m_color1;
- uint8_t m_row0;
- uint8_t m_row1;
- uint8_t m_row2;
- uint8_t m_row3;
- };
- struct BC3Block {
- uint8_t m_alpha0;
- uint8_t m_alpha1;
- uint8_t m_alphaR0;
- uint8_t m_alphaR1;
- uint8_t m_alphaR2;
- uint8_t m_alphaR3;
- uint8_t m_alphaR4;
- uint8_t m_alphaR5;
- uint16_t m_color0;
- uint16_t m_color1;
- uint8_t m_row0;
- uint8_t m_row1;
- uint8_t m_row2;
- uint8_t m_row3;
- };
- struct BC4Block {
- uint8_t m_red0;
- uint8_t m_red1;
- uint8_t m_redR0;
- uint8_t m_redR1;
- uint8_t m_redR2;
- uint8_t m_redR3;
- uint8_t m_redR4;
- uint8_t m_redR5;
- };
- struct BC5Block {
- uint8_t m_red0;
- uint8_t m_red1;
- uint8_t m_redR0;
- uint8_t m_redR1;
- uint8_t m_redR2;
- uint8_t m_redR3;
- uint8_t m_redR4;
- uint8_t m_redR5;
- uint8_t m_green0;
- uint8_t m_green1;
- uint8_t m_greenR0;
- uint8_t m_greenR1;
- uint8_t m_greenR2;
- uint8_t m_greenR3;
- uint8_t m_greenR4;
- uint8_t m_greenR5;
- };
- public:
- static bool IsCompressed(DXGIFormat fmt);
- static uint32_t MakeFourCC(char ch0, char ch1, char ch2, char ch3);
- static DXGIFormat GetDXGIFormat(const PixelFormat& pf);
- static uint32_t GetBitsPerPixel(DXGIFormat fmt);
- Result Load(const char* filepath);
- Result Load(std::istream& input);
- Result Load(const uint8_t* data, size_t size);
- Result Load(std::vector<uint8_t>&& dds);
- const ImageData* GetImageData(uint32_t mipIdx = 0,
- uint32_t arrayIdx = 0) const {
- if (mipIdx < m_mipCount && arrayIdx < m_arraySize) {
- return &m_imageDatas[m_mipCount * arrayIdx + mipIdx];
- }
- return nullptr;
- }
- bool Flip();
- uint32_t GetWidth() const { return m_width; }
- uint32_t GetHeight() const { return m_height; }
- uint32_t GetDepth() const { return m_depth; }
- uint32_t GetMipCount() const { return m_mipCount; }
- uint32_t GetArraySize() const { return m_arraySize; }
- DXGIFormat GetFormat() const { return m_format; }
- bool IsCubemap() const { return m_isCubemap; }
- TextureDimension GetTextureDimension() const { return m_texDim; }
- private:
- void GetImageInfo(uint32_t w, uint32_t h, DXGIFormat fmt,
- uint32_t* outNumBytes, uint32_t* outRowBytes,
- uint32_t* outNumRows);
- bool FlipImage(ImageData& imageData);
- bool FlipCompressedImage(ImageData& imageData);
- void FlipCompressedImageBC1(ImageData& imageData);
- void FlipCompressedImageBC2(ImageData& imageData);
- void FlipCompressedImageBC3(ImageData& imageData);
- void FlipCompressedImageBC4(ImageData& imageData);
- void FlipCompressedImageBC5(ImageData& imageData);
- private:
- std::vector<uint8_t> m_dds;
- std::vector<ImageData> m_imageDatas;
- uint32_t m_height;
- uint32_t m_width;
- uint32_t m_depth;
- uint32_t m_mipCount;
- uint32_t m_arraySize;
- DXGIFormat m_format;
- bool m_isCubemap;
- TextureDimension m_texDim;
- };
- } // namespace tinyddsloader
- #ifdef TINYDDSLOADER_IMPLEMENTATION
- #if _WIN32
- #undef min
- #undef max
- #endif // _Win32
- #include <algorithm>
- #include <fstream>
- namespace tinyddsloader {
- const char DDSFile::Magic[4] = {'D', 'D', 'S', ' '};
- bool DDSFile::IsCompressed(DXGIFormat fmt) {
- switch (fmt) {
- case DXGIFormat::BC1_Typeless:
- case DXGIFormat::BC1_UNorm:
- case DXGIFormat::BC1_UNorm_SRGB:
- case DXGIFormat::BC2_Typeless:
- case DXGIFormat::BC2_UNorm:
- case DXGIFormat::BC2_UNorm_SRGB:
- case DXGIFormat::BC3_Typeless:
- case DXGIFormat::BC3_UNorm:
- case DXGIFormat::BC3_UNorm_SRGB:
- case DXGIFormat::BC4_Typeless:
- case DXGIFormat::BC4_UNorm:
- case DXGIFormat::BC4_SNorm:
- case DXGIFormat::BC5_Typeless:
- case DXGIFormat::BC5_UNorm:
- case DXGIFormat::BC5_SNorm:
- case DXGIFormat::BC6H_Typeless:
- case DXGIFormat::BC6H_UF16:
- case DXGIFormat::BC6H_SF16:
- case DXGIFormat::BC7_Typeless:
- case DXGIFormat::BC7_UNorm:
- case DXGIFormat::BC7_UNorm_SRGB:
- return true;
- }
- return false;
- }
- uint32_t DDSFile::MakeFourCC(char ch0, char ch1, char ch2, char ch3) {
- return (uint32_t(uint8_t(ch0)) | (uint32_t(uint8_t(ch1)) << 8) |
- (uint32_t(uint8_t(ch2)) << 16) | (uint32_t(uint8_t(ch3)) << 24));
- }
- DDSFile::DXGIFormat DDSFile::GetDXGIFormat(const PixelFormat& pf) {
- if (pf.m_flags & uint32_t(PixelFormatFlagBits::RGB)) {
- switch (pf.m_bitCount) {
- case 32:
- if (pf.m_RBitMask == 0x000000ff &&
- pf.m_GBitMask == 0x0000ff00 &&
- pf.m_BBitMask == 0x00ff0000 &&
- pf.m_ABitMask == 0xff000000) {
- return DXGIFormat::R8G8B8A8_UNorm;
- }
- if (pf.m_RBitMask == 0x00ff0000 &&
- pf.m_GBitMask == 0x0000ff00 &&
- pf.m_BBitMask == 0x000000ff &&
- pf.m_ABitMask == 0xff000000) {
- return DXGIFormat::B8G8R8A8_UNorm;
- }
- if (pf.m_RBitMask == 0x00ff0000 &&
- pf.m_GBitMask == 0x0000ff00 &&
- pf.m_BBitMask == 0x000000ff &&
- pf.m_ABitMask == 0x00000000) {
- return DXGIFormat::B8G8R8X8_UNorm;
- }
- if (pf.m_RBitMask == 0x0000ffff &&
- pf.m_GBitMask == 0xffff0000 &&
- pf.m_BBitMask == 0x00000000 &&
- pf.m_ABitMask == 0x00000000) {
- return DXGIFormat::R16G16_UNorm;
- }
- if (pf.m_RBitMask == 0xffffffff &&
- pf.m_GBitMask == 0x00000000 &&
- pf.m_BBitMask == 0x00000000 &&
- pf.m_ABitMask == 0x00000000) {
- return DXGIFormat::R32_Float;
- }
- break;
- case 24:
- break;
- case 16:
- if (pf.m_RBitMask == 0x7c00 && pf.m_GBitMask == 0x03e0 &&
- pf.m_BBitMask == 0x001f && pf.m_ABitMask == 0x8000) {
- return DXGIFormat::B5G5R5A1_UNorm;
- }
- if (pf.m_RBitMask == 0xf800 && pf.m_GBitMask == 0x07e0 &&
- pf.m_BBitMask == 0x001f && pf.m_ABitMask == 0x0000) {
- return DXGIFormat::B5G6R5_UNorm;
- }
- if (pf.m_RBitMask == 0x0f00 && pf.m_GBitMask == 0x00f0 &&
- pf.m_BBitMask == 0x000f && pf.m_ABitMask == 0xf000) {
- return DXGIFormat::B4G4R4A4_UNorm;
- }
- break;
- default:
- break;
- }
- } else if (pf.m_flags & uint32_t(PixelFormatFlagBits::Luminance)) {
- if (8 == pf.m_bitCount) {
- if (pf.m_RBitMask == 0x000000ff && pf.m_GBitMask == 0x00000000 &&
- pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) {
- return DXGIFormat::R8_UNorm;
- }
- if (pf.m_RBitMask == 0x000000ff && pf.m_GBitMask == 0x0000ff00 &&
- pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) {
- return DXGIFormat::R8G8_UNorm;
- }
- }
- if (16 == pf.m_bitCount) {
- if (pf.m_RBitMask == 0x0000ffff && pf.m_GBitMask == 0x00000000 &&
- pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) {
- return DXGIFormat::R16_UNorm;
- }
- if (pf.m_RBitMask == 0x000000ff && pf.m_GBitMask == 0x0000ff00 &&
- pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) {
- return DXGIFormat::R8G8_UNorm;
- }
- }
- } else if (pf.m_flags & uint32_t(PixelFormatFlagBits::Alpha)) {
- if (8 == pf.m_bitCount) {
- return DXGIFormat::A8_UNorm;
- }
- } else if (pf.m_flags & uint32_t(PixelFormatFlagBits::BumpDUDV)) {
- if (16 == pf.m_bitCount) {
- if (pf.m_RBitMask == 0x00ff && pf.m_GBitMask == 0xff00 &&
- pf.m_BBitMask == 0x0000 && pf.m_ABitMask == 0x0000) {
- return DXGIFormat::R8G8_SNorm;
- }
- }
- if (32 == pf.m_bitCount) {
- if (pf.m_RBitMask == 0x000000ff && pf.m_GBitMask == 0x0000ff00 &&
- pf.m_BBitMask == 0x00ff0000 && pf.m_ABitMask == 0xff000000) {
- return DXGIFormat::R8G8B8A8_SNorm;
- }
- if (pf.m_RBitMask == 0x0000ffff && pf.m_GBitMask == 0xffff0000 &&
- pf.m_BBitMask == 0x00000000 && pf.m_ABitMask == 0x00000000) {
- return DXGIFormat::R16G16_SNorm;
- }
- }
- } else if (pf.m_flags & uint32_t(PixelFormatFlagBits::FourCC)) {
- if (MakeFourCC('D', 'X', 'T', '1') == pf.m_fourCC) {
- return DXGIFormat::BC1_UNorm;
- }
- if (MakeFourCC('D', 'X', 'T', '3') == pf.m_fourCC) {
- return DXGIFormat::BC2_UNorm;
- }
- if (MakeFourCC('D', 'X', 'T', '5') == pf.m_fourCC) {
- return DXGIFormat::BC3_UNorm;
- }
- if (MakeFourCC('D', 'X', 'T', '4') == pf.m_fourCC) {
- return DXGIFormat::BC2_UNorm;
- }
- if (MakeFourCC('D', 'X', 'T', '5') == pf.m_fourCC) {
- return DXGIFormat::BC3_UNorm;
- }
- if (MakeFourCC('A', 'T', 'I', '1') == pf.m_fourCC) {
- return DXGIFormat::BC4_UNorm;
- }
- if (MakeFourCC('B', 'C', '4', 'U') == pf.m_fourCC) {
- return DXGIFormat::BC4_UNorm;
- }
- if (MakeFourCC('B', 'C', '4', 'S') == pf.m_fourCC) {
- return DXGIFormat::BC4_SNorm;
- }
- if (MakeFourCC('A', 'T', 'I', '2') == pf.m_fourCC) {
- return DXGIFormat::BC5_UNorm;
- }
- if (MakeFourCC('B', 'C', '5', 'U') == pf.m_fourCC) {
- return DXGIFormat::BC5_UNorm;
- }
- if (MakeFourCC('B', 'C', '5', 'S') == pf.m_fourCC) {
- return DXGIFormat::BC5_SNorm;
- }
- if (MakeFourCC('R', 'G', 'B', 'G') == pf.m_fourCC) {
- return DXGIFormat::R8G8_B8G8_UNorm;
- }
- if (MakeFourCC('G', 'R', 'G', 'B') == pf.m_fourCC) {
- return DXGIFormat::G8R8_G8B8_UNorm;
- }
- if (MakeFourCC('Y', 'U', 'Y', '2') == pf.m_fourCC) {
- return DXGIFormat::YUY2;
- }
- switch (pf.m_fourCC) {
- case 36:
- return DXGIFormat::R16G16B16A16_UNorm;
- case 110:
- return DXGIFormat::R16G16B16A16_SNorm;
- case 111:
- return DXGIFormat::R16_Float;
- case 112:
- return DXGIFormat::R16G16_Float;
- case 113:
- return DXGIFormat::R16G16B16A16_Float;
- case 114:
- return DXGIFormat::R32_Float;
- case 115:
- return DXGIFormat::R32G32_Float;
- case 116:
- return DXGIFormat::R32G32B32A32_Float;
- }
- }
- return DXGIFormat::Unknown;
- }
- uint32_t DDSFile::GetBitsPerPixel(DXGIFormat fmt) {
- switch (fmt) {
- case DXGIFormat::R32G32B32A32_Typeless:
- case DXGIFormat::R32G32B32A32_Float:
- case DXGIFormat::R32G32B32A32_UInt:
- case DXGIFormat::R32G32B32A32_SInt:
- return 128;
- case DXGIFormat::R32G32B32_Typeless:
- case DXGIFormat::R32G32B32_Float:
- case DXGIFormat::R32G32B32_UInt:
- case DXGIFormat::R32G32B32_SInt:
- return 96;
- case DXGIFormat::R16G16B16A16_Typeless:
- case DXGIFormat::R16G16B16A16_Float:
- case DXGIFormat::R16G16B16A16_UNorm:
- case DXGIFormat::R16G16B16A16_UInt:
- case DXGIFormat::R16G16B16A16_SNorm:
- case DXGIFormat::R16G16B16A16_SInt:
- case DXGIFormat::R32G32_Typeless:
- case DXGIFormat::R32G32_Float:
- case DXGIFormat::R32G32_UInt:
- case DXGIFormat::R32G32_SInt:
- case DXGIFormat::R32G8X24_Typeless:
- case DXGIFormat::D32_Float_S8X24_UInt:
- case DXGIFormat::R32_Float_X8X24_Typeless:
- case DXGIFormat::X32_Typeless_G8X24_UInt:
- case DXGIFormat::Y416:
- case DXGIFormat::Y210:
- case DXGIFormat::Y216:
- return 64;
- case DXGIFormat::R10G10B10A2_Typeless:
- case DXGIFormat::R10G10B10A2_UNorm:
- case DXGIFormat::R10G10B10A2_UInt:
- case DXGIFormat::R11G11B10_Float:
- case DXGIFormat::R8G8B8A8_Typeless:
- case DXGIFormat::R8G8B8A8_UNorm:
- case DXGIFormat::R8G8B8A8_UNorm_SRGB:
- case DXGIFormat::R8G8B8A8_UInt:
- case DXGIFormat::R8G8B8A8_SNorm:
- case DXGIFormat::R8G8B8A8_SInt:
- case DXGIFormat::R16G16_Typeless:
- case DXGIFormat::R16G16_Float:
- case DXGIFormat::R16G16_UNorm:
- case DXGIFormat::R16G16_UInt:
- case DXGIFormat::R16G16_SNorm:
- case DXGIFormat::R16G16_SInt:
- case DXGIFormat::R32_Typeless:
- case DXGIFormat::D32_Float:
- case DXGIFormat::R32_Float:
- case DXGIFormat::R32_UInt:
- case DXGIFormat::R32_SInt:
- case DXGIFormat::R24G8_Typeless:
- case DXGIFormat::D24_UNorm_S8_UInt:
- case DXGIFormat::R24_UNorm_X8_Typeless:
- case DXGIFormat::X24_Typeless_G8_UInt:
- case DXGIFormat::R9G9B9E5_SHAREDEXP:
- case DXGIFormat::R8G8_B8G8_UNorm:
- case DXGIFormat::G8R8_G8B8_UNorm:
- case DXGIFormat::B8G8R8A8_UNorm:
- case DXGIFormat::B8G8R8X8_UNorm:
- case DXGIFormat::R10G10B10_XR_BIAS_A2_UNorm:
- case DXGIFormat::B8G8R8A8_Typeless:
- case DXGIFormat::B8G8R8A8_UNorm_SRGB:
- case DXGIFormat::B8G8R8X8_Typeless:
- case DXGIFormat::B8G8R8X8_UNorm_SRGB:
- case DXGIFormat::AYUV:
- case DXGIFormat::Y410:
- case DXGIFormat::YUY2:
- return 32;
- case DXGIFormat::P010:
- case DXGIFormat::P016:
- return 24;
- case DXGIFormat::R8G8_Typeless:
- case DXGIFormat::R8G8_UNorm:
- case DXGIFormat::R8G8_UInt:
- case DXGIFormat::R8G8_SNorm:
- case DXGIFormat::R8G8_SInt:
- case DXGIFormat::R16_Typeless:
- case DXGIFormat::R16_Float:
- case DXGIFormat::D16_UNorm:
- case DXGIFormat::R16_UNorm:
- case DXGIFormat::R16_UInt:
- case DXGIFormat::R16_SNorm:
- case DXGIFormat::R16_SInt:
- case DXGIFormat::B5G6R5_UNorm:
- case DXGIFormat::B5G5R5A1_UNorm:
- case DXGIFormat::A8P8:
- case DXGIFormat::B4G4R4A4_UNorm:
- return 16;
- case DXGIFormat::NV12:
- case DXGIFormat::YUV420_OPAQUE:
- case DXGIFormat::NV11:
- return 12;
- case DXGIFormat::R8_Typeless:
- case DXGIFormat::R8_UNorm:
- case DXGIFormat::R8_UInt:
- case DXGIFormat::R8_SNorm:
- case DXGIFormat::R8_SInt:
- case DXGIFormat::A8_UNorm:
- case DXGIFormat::AI44:
- case DXGIFormat::IA44:
- case DXGIFormat::P8:
- return 8;
- case DXGIFormat::R1_UNorm:
- return 1;
- case DXGIFormat::BC1_Typeless:
- case DXGIFormat::BC1_UNorm:
- case DXGIFormat::BC1_UNorm_SRGB:
- case DXGIFormat::BC4_Typeless:
- case DXGIFormat::BC4_UNorm:
- case DXGIFormat::BC4_SNorm:
- return 4;
- case DXGIFormat::BC2_Typeless:
- case DXGIFormat::BC2_UNorm:
- case DXGIFormat::BC2_UNorm_SRGB:
- case DXGIFormat::BC3_Typeless:
- case DXGIFormat::BC3_UNorm:
- case DXGIFormat::BC3_UNorm_SRGB:
- case DXGIFormat::BC5_Typeless:
- case DXGIFormat::BC5_UNorm:
- case DXGIFormat::BC5_SNorm:
- case DXGIFormat::BC6H_Typeless:
- case DXGIFormat::BC6H_UF16:
- case DXGIFormat::BC6H_SF16:
- case DXGIFormat::BC7_Typeless:
- case DXGIFormat::BC7_UNorm:
- case DXGIFormat::BC7_UNorm_SRGB:
- return 8;
- default:
- return 0;
- }
- }
- Result DDSFile::Load(const char* filepath) {
- std::ifstream ifs(filepath, std::ios_base::binary);
- if (!ifs.is_open()) {
- return Result::ErrorFileOpen;
- }
- return Load(ifs);
- }
- Result DDSFile::Load(std::istream& input) {
- m_dds.clear();
- input.seekg(0, std::ios_base::beg);
- auto begPos = input.tellg();
- input.seekg(0, std::ios_base::end);
- auto endPos = input.tellg();
- input.seekg(0, std::ios_base::beg);
- auto fileSize = endPos - begPos;
- if (fileSize == 0) {
- return Result::ErrorRead;
- }
- std::vector<uint8_t> dds(fileSize);
- input.read(reinterpret_cast<char*>(dds.data()), fileSize);
- if (input.bad()) {
- return Result::ErrorRead;
- }
- return Load(std::move(dds));
- }
- Result DDSFile::Load(const uint8_t* data, size_t size) {
- std::vector<uint8_t> dds(data, data + size);
- return Load(std::move(dds));
- }
- Result DDSFile::Load(std::vector<uint8_t>&& dds) {
- m_dds.clear();
- if (dds.size() < 4) {
- return Result::ErrorSize;
- }
- for (int i = 0; i < 4; i++) {
- if (dds[i] != Magic[i]) {
- return Result::ErrorMagicWord;
- }
- }
- if ((sizeof(uint32_t) + sizeof(Header)) >= dds.size()) {
- return Result::ErrorSize;
- }
- auto header =
- reinterpret_cast<const Header*>(dds.data() + sizeof(uint32_t));
- if (header->m_size != sizeof(Header) ||
- header->m_pixelFormat.m_size != sizeof(PixelFormat)) {
- return Result::ErrorVerify;
- }
- bool dxt10Header = false;
- if ((header->m_pixelFormat.m_flags &
- uint32_t(PixelFormatFlagBits::FourCC)) &&
- (MakeFourCC('D', 'X', '1', '0') == header->m_pixelFormat.m_fourCC)) {
- if ((sizeof(uint32_t) + sizeof(Header) + sizeof(HeaderDXT10)) >=
- dds.size()) {
- return Result::ErrorSize;
- }
- dxt10Header = true;
- }
- ptrdiff_t offset = sizeof(uint32_t) + sizeof(Header) +
- (dxt10Header ? sizeof(HeaderDXT10) : 0);
- m_height = header->m_height;
- m_width = header->m_width;
- m_texDim = TextureDimension::Unknown;
- m_arraySize = 1;
- m_format = DXGIFormat::Unknown;
- m_isCubemap = false;
- m_mipCount = header->m_mipMapCount;
- if (0 == m_mipCount) {
- m_mipCount = 1;
- }
- if (dxt10Header) {
- auto dxt10Header = reinterpret_cast<const HeaderDXT10*>(
- reinterpret_cast<const char*>(header) + sizeof(Header));
- m_arraySize = dxt10Header->m_arraySize;
- if (m_arraySize == 0) {
- return Result::ErrorInvalidData;
- }
- switch (dxt10Header->m_format) {
- case DXGIFormat::AI44:
- case DXGIFormat::IA44:
- case DXGIFormat::P8:
- case DXGIFormat::A8P8:
- return Result::ErrorNotSupported;
- default:
- if (GetBitsPerPixel(dxt10Header->m_format) == 0) {
- return Result::ErrorNotSupported;
- }
- }
- m_format = dxt10Header->m_format;
- switch (dxt10Header->m_resourceDimension) {
- case TextureDimension::Texture1D:
- if ((header->m_flags & uint32_t(HeaderFlagBits::Height) &&
- (m_height != 1))) {
- return Result::ErrorInvalidData;
- }
- m_height = m_depth = 1;
- break;
- case TextureDimension::Texture2D:
- if (dxt10Header->m_miscFlag &
- uint32_t(DXT10MiscFlagBits::TextureCube)) {
- m_arraySize *= 6;
- m_isCubemap = true;
- }
- m_depth = 1;
- break;
- case TextureDimension::Texture3D:
- if (!(header->m_flags & uint32_t(HeaderFlagBits::Volume))) {
- return Result::ErrorInvalidData;
- }
- if (m_arraySize > 1) {
- return Result::ErrorNotSupported;
- }
- break;
- default:
- return Result::ErrorNotSupported;
- }
- m_texDim = dxt10Header->m_resourceDimension;
- } else {
- m_format = GetDXGIFormat(header->m_pixelFormat);
- if (m_format == DXGIFormat::Unknown) {
- return Result::ErrorNotSupported;
- }
- if (header->m_flags & uint32_t(HeaderFlagBits::Volume)) {
- m_texDim = TextureDimension::Texture3D;
- } else {
- auto caps2 = header->m_caps2 &
- uint32_t(HeaderCaps2FlagBits::CubemapAllFaces);
- if (caps2) {
- if (caps2 != uint32_t(HeaderCaps2FlagBits::CubemapAllFaces)) {
- return Result::ErrorNotSupported;
- }
- m_arraySize = 6;
- m_isCubemap = true;
- }
- m_depth = 1;
- m_texDim = TextureDimension::Texture2D;
- }
- }
- std::vector<ImageData> imageDatas(m_mipCount * m_arraySize);
- uint8_t* srcBits = dds.data() + offset;
- uint8_t* endBits = dds.data() + dds.size();
- uint32_t idx = 0;
- for (uint32_t j = 0; j < m_arraySize; j++) {
- uint32_t w = m_width;
- uint32_t h = m_height;
- uint32_t d = m_depth;
- for (uint32_t i = 0; i < m_mipCount; i++) {
- uint32_t numBytes;
- uint32_t rowBytes;
- GetImageInfo(w, h, m_format, &numBytes, &rowBytes, nullptr);
- imageDatas[idx].m_width = w;
- imageDatas[idx].m_height = h;
- imageDatas[idx].m_depth = d;
- imageDatas[idx].m_mem = srcBits;
- imageDatas[idx].m_memPitch = rowBytes;
- imageDatas[idx].m_memSlicePitch = numBytes;
- idx++;
- if (srcBits + (numBytes * d) > endBits) {
- return Result::ErrorInvalidData;
- }
- srcBits += numBytes * d;
- w = std::max<uint32_t>(1, w / 2);
- h = std::max<uint32_t>(1, h / 2);
- d = std::max<uint32_t>(1, d / 2);
- }
- }
- m_dds = std::move(dds);
- m_imageDatas = std::move(imageDatas);
- return Result::Success;
- }
- void DDSFile::GetImageInfo(uint32_t w, uint32_t h, DXGIFormat fmt,
- uint32_t* outNumBytes, uint32_t* outRowBytes,
- uint32_t* outNumRows) {
- uint32_t numBytes = 0;
- uint32_t rowBytes = 0;
- uint32_t numRows = 0;
- bool bc = false;
- bool packed = false;
- bool planar = false;
- uint32_t bpe = 0;
- switch (fmt) {
- case DXGIFormat::BC1_Typeless:
- case DXGIFormat::BC1_UNorm:
- case DXGIFormat::BC1_UNorm_SRGB:
- case DXGIFormat::BC4_Typeless:
- case DXGIFormat::BC4_UNorm:
- case DXGIFormat::BC4_SNorm:
- bc = true;
- bpe = 8;
- break;
- case DXGIFormat::BC2_Typeless:
- case DXGIFormat::BC2_UNorm:
- case DXGIFormat::BC2_UNorm_SRGB:
- case DXGIFormat::BC3_Typeless:
- case DXGIFormat::BC3_UNorm:
- case DXGIFormat::BC3_UNorm_SRGB:
- case DXGIFormat::BC5_Typeless:
- case DXGIFormat::BC5_UNorm:
- case DXGIFormat::BC5_SNorm:
- case DXGIFormat::BC6H_Typeless:
- case DXGIFormat::BC6H_UF16:
- case DXGIFormat::BC6H_SF16:
- case DXGIFormat::BC7_Typeless:
- case DXGIFormat::BC7_UNorm:
- case DXGIFormat::BC7_UNorm_SRGB:
- bc = true;
- bpe = 16;
- break;
- case DXGIFormat::R8G8_B8G8_UNorm:
- case DXGIFormat::G8R8_G8B8_UNorm:
- case DXGIFormat::YUY2:
- packed = true;
- bpe = 4;
- break;
- case DXGIFormat::Y210:
- case DXGIFormat::Y216:
- packed = true;
- bpe = 8;
- break;
- case DXGIFormat::NV12:
- case DXGIFormat::YUV420_OPAQUE:
- planar = true;
- bpe = 2;
- break;
- case DXGIFormat::P010:
- case DXGIFormat::P016:
- planar = true;
- bpe = 4;
- break;
- default:
- break;
- }
- if (bc) {
- uint32_t numBlocksWide = 0;
- if (w > 0) {
- numBlocksWide = std::max<uint32_t>(1, (w + 3) / 4);
- }
- uint32_t numBlocksHigh = 0;
- if (h > 0) {
- numBlocksHigh = std::max<uint32_t>(1, (h + 3) / 4);
- }
- rowBytes = numBlocksWide * bpe;
- numRows = numBlocksHigh;
- numBytes = rowBytes * numBlocksHigh;
- } else if (packed) {
- rowBytes = ((w + 1) >> 1) * bpe;
- numRows = h;
- numBytes = rowBytes * h;
- } else if (fmt == DXGIFormat::NV11) {
- rowBytes = ((w + 3) >> 2) * 4;
- numRows = h * 2;
- numBytes = rowBytes + numRows;
- } else if (planar) {
- rowBytes = ((w + 1) >> 1) * bpe;
- numBytes = (rowBytes * h) + ((rowBytes * h + 1) >> 1);
- numRows = h + ((h + 1) >> 1);
- } else {
- uint32_t bpp = GetBitsPerPixel(fmt);
- rowBytes = (w * bpp + 7) / 8;
- numRows = h;
- numBytes = rowBytes * h;
- }
- if (outNumBytes) {
- *outNumBytes = numBytes;
- }
- if (outRowBytes) {
- *outRowBytes = rowBytes;
- }
- if (outNumRows) {
- *outNumRows = numRows;
- }
- }
- bool DDSFile::Flip() {
- if (IsCompressed(m_format)) {
- for (auto& imageData : m_imageDatas) {
- if (!FlipCompressedImage(imageData)) {
- return false;
- }
- }
- } else {
- for (auto& imageData : m_imageDatas) {
- if (!FlipImage(imageData)) {
- return false;
- }
- }
- }
- return true;
- }
- bool DDSFile::FlipImage(ImageData& imageData) {
- for (uint32_t y = 0; y < imageData.m_height / 2; y++) {
- auto line0 = (uint8_t*)imageData.m_mem + y * imageData.m_memPitch;
- auto line1 = (uint8_t*)imageData.m_mem +
- (imageData.m_height - y - 1) * imageData.m_memPitch;
- for (uint32_t i = 0; i < imageData.m_memPitch; i++) {
- std::swap(*line0, *line1);
- line0++;
- line1++;
- }
- }
- return true;
- }
- bool DDSFile::FlipCompressedImage(ImageData& imageData) {
- if (DXGIFormat::BC1_Typeless == m_format ||
- DXGIFormat::BC1_UNorm == m_format ||
- DXGIFormat::BC1_UNorm_SRGB == m_format) {
- FlipCompressedImageBC1(imageData);
- return true;
- } else if (DXGIFormat::BC2_Typeless == m_format ||
- DXGIFormat::BC2_UNorm == m_format ||
- DXGIFormat::BC2_UNorm_SRGB == m_format) {
- FlipCompressedImageBC2(imageData);
- return true;
- } else if (DXGIFormat::BC3_Typeless == m_format ||
- DXGIFormat::BC3_UNorm == m_format ||
- DXGIFormat::BC3_UNorm_SRGB == m_format) {
- FlipCompressedImageBC3(imageData);
- return true;
- } else if (DXGIFormat::BC4_Typeless == m_format ||
- DXGIFormat::BC4_UNorm == m_format ||
- DXGIFormat::BC4_SNorm == m_format) {
- FlipCompressedImageBC4(imageData);
- return true;
- } else if (DXGIFormat::BC5_Typeless == m_format ||
- DXGIFormat::BC5_UNorm == m_format ||
- DXGIFormat::BC5_SNorm == m_format) {
- FlipCompressedImageBC5(imageData);
- return true;
- }
- return false;
- }
- void DDSFile::FlipCompressedImageBC1(ImageData& imageData) {
- uint32_t numXBlocks = (imageData.m_width + 3) / 4;
- uint32_t numYBlocks = (imageData.m_height + 3) / 4;
- if (imageData.m_height == 1) {
- } else if (imageData.m_height == 2) {
- auto blocks = (BC1Block*)imageData.m_mem;
- for (uint32_t x = 0; x < numXBlocks; x++) {
- auto block = blocks + x;
- std::swap(block->m_row0, block->m_row1);
- std::swap(block->m_row2, block->m_row3);
- }
- } else {
- for (uint32_t y = 0; y < (numYBlocks + 1) / 2; y++) {
- auto blocks0 = (BC1Block*)((uint8_t*)imageData.m_mem +
- imageData.m_memPitch * y);
- auto blocks1 =
- (BC1Block*)((uint8_t*)imageData.m_mem +
- imageData.m_memPitch * (numYBlocks - y - 1));
- for (uint32_t x = 0; x < numXBlocks; x++) {
- auto block0 = blocks0 + x;
- auto block1 = blocks1 + x;
- if (blocks0 != blocks1) {
- std::swap(block0->m_color0, block1->m_color0);
- std::swap(block0->m_color1, block1->m_color1);
- std::swap(block0->m_row0, block1->m_row3);
- std::swap(block0->m_row1, block1->m_row2);
- std::swap(block0->m_row2, block1->m_row1);
- std::swap(block0->m_row3, block1->m_row0);
- } else {
- std::swap(block0->m_row0, block0->m_row3);
- std::swap(block0->m_row1, block0->m_row2);
- }
- }
- }
- }
- }
- void DDSFile::FlipCompressedImageBC2(ImageData& imageData) {
- uint32_t numXBlocks = (imageData.m_width + 3) / 4;
- uint32_t numYBlocks = (imageData.m_height + 3) / 4;
- if (imageData.m_height == 1) {
- } else if (imageData.m_height == 2) {
- auto blocks = (BC2Block*)imageData.m_mem;
- for (uint32_t x = 0; x < numXBlocks; x++) {
- auto block = blocks + x;
- std::swap(block->m_alphaRow0, block->m_alphaRow1);
- std::swap(block->m_alphaRow2, block->m_alphaRow3);
- std::swap(block->m_row0, block->m_row1);
- std::swap(block->m_row2, block->m_row3);
- }
- } else {
- for (uint32_t y = 0; y < (numYBlocks + 1) / 2; y++) {
- auto blocks0 = (BC2Block*)((uint8_t*)imageData.m_mem +
- imageData.m_memPitch * y);
- auto blocks1 =
- (BC2Block*)((uint8_t*)imageData.m_mem +
- imageData.m_memPitch * (numYBlocks - y - 1));
- for (uint32_t x = 0; x < numXBlocks; x++) {
- auto block0 = blocks0 + x;
- auto block1 = blocks1 + x;
- if (block0 != block1) {
- std::swap(block0->m_alphaRow0, block1->m_alphaRow3);
- std::swap(block0->m_alphaRow1, block1->m_alphaRow2);
- std::swap(block0->m_alphaRow2, block1->m_alphaRow1);
- std::swap(block0->m_alphaRow3, block1->m_alphaRow0);
- std::swap(block0->m_color0, block1->m_color0);
- std::swap(block0->m_color1, block1->m_color1);
- std::swap(block0->m_row0, block1->m_row3);
- std::swap(block0->m_row1, block1->m_row2);
- std::swap(block0->m_row2, block1->m_row1);
- std::swap(block0->m_row3, block1->m_row0);
- } else {
- std::swap(block0->m_alphaRow0, block0->m_alphaRow3);
- std::swap(block0->m_alphaRow1, block0->m_alphaRow2);
- std::swap(block0->m_row0, block0->m_row3);
- std::swap(block0->m_row1, block0->m_row2);
- }
- }
- }
- }
- }
- void DDSFile::FlipCompressedImageBC3(ImageData& imageData) {
- uint32_t numXBlocks = (imageData.m_width + 3) / 4;
- uint32_t numYBlocks = (imageData.m_height + 3) / 4;
- if (imageData.m_height == 1) {
- } else if (imageData.m_height == 2) {
- auto blocks = (BC3Block*)imageData.m_mem;
- for (uint32_t x = 0; x < numXBlocks; x++) {
- auto block = blocks + x;
- uint8_t r0 = (block->m_alphaR1 >> 4) | (block->m_alphaR2 << 4);
- uint8_t r1 = (block->m_alphaR2 >> 4) | (block->m_alphaR0 << 4);
- uint8_t r2 = (block->m_alphaR0 >> 4) | (block->m_alphaR1 << 4);
- uint8_t r3 = (block->m_alphaR4 >> 4) | (block->m_alphaR5 << 4);
- uint8_t r4 = (block->m_alphaR5 >> 4) | (block->m_alphaR3 << 4);
- uint8_t r5 = (block->m_alphaR3 >> 4) | (block->m_alphaR4 << 4);
- block->m_alphaR0 = r0;
- block->m_alphaR1 = r1;
- block->m_alphaR2 = r2;
- block->m_alphaR3 = r3;
- block->m_alphaR4 = r4;
- block->m_alphaR5 = r5;
- std::swap(block->m_row0, block->m_row1);
- std::swap(block->m_row2, block->m_row3);
- }
- } else {
- for (uint32_t y = 0; y < (numYBlocks + 1) / 2; y++) {
- auto blocks0 = (BC3Block*)((uint8_t*)imageData.m_mem +
- imageData.m_memPitch * y);
- auto blocks1 =
- (BC3Block*)((uint8_t*)imageData.m_mem +
- imageData.m_memPitch * (numYBlocks - y - 1));
- for (uint32_t x = 0; x < numXBlocks; x++) {
- auto block0 = blocks0 + x;
- auto block1 = blocks1 + x;
- if (block0 != block1) {
- std::swap(block0->m_alpha0, block1->m_alpha0);
- std::swap(block0->m_alpha1, block1->m_alpha1);
- uint8_t r0[6];
- r0[0] = (block0->m_alphaR4 >> 4) | (block0->m_alphaR5 << 4);
- r0[1] = (block0->m_alphaR5 >> 4) | (block0->m_alphaR3 << 4);
- r0[2] = (block0->m_alphaR3 >> 4) | (block0->m_alphaR4 << 4);
- r0[3] = (block0->m_alphaR1 >> 4) | (block0->m_alphaR2 << 4);
- r0[4] = (block0->m_alphaR2 >> 4) | (block0->m_alphaR0 << 4);
- r0[5] = (block0->m_alphaR0 >> 4) | (block0->m_alphaR1 << 4);
- uint8_t r1[6];
- r1[0] = (block1->m_alphaR4 >> 4) | (block1->m_alphaR5 << 4);
- r1[1] = (block1->m_alphaR5 >> 4) | (block1->m_alphaR3 << 4);
- r1[2] = (block1->m_alphaR3 >> 4) | (block1->m_alphaR4 << 4);
- r1[3] = (block1->m_alphaR1 >> 4) | (block1->m_alphaR2 << 4);
- r1[4] = (block1->m_alphaR2 >> 4) | (block1->m_alphaR0 << 4);
- r1[5] = (block1->m_alphaR0 >> 4) | (block1->m_alphaR1 << 4);
- block0->m_alphaR0 = r1[0];
- block0->m_alphaR1 = r1[1];
- block0->m_alphaR2 = r1[2];
- block0->m_alphaR3 = r1[3];
- block0->m_alphaR4 = r1[4];
- block0->m_alphaR5 = r1[5];
- block1->m_alphaR0 = r0[0];
- block1->m_alphaR1 = r0[1];
- block1->m_alphaR2 = r0[2];
- block1->m_alphaR3 = r0[3];
- block1->m_alphaR4 = r0[4];
- block1->m_alphaR5 = r0[5];
- std::swap(block0->m_color0, block1->m_color0);
- std::swap(block0->m_color1, block1->m_color1);
- std::swap(block0->m_row0, block1->m_row3);
- std::swap(block0->m_row1, block1->m_row2);
- std::swap(block0->m_row2, block1->m_row1);
- std::swap(block0->m_row3, block1->m_row0);
- } else {
- uint8_t r0[6];
- r0[0] = (block0->m_alphaR4 >> 4) | (block0->m_alphaR5 << 4);
- r0[1] = (block0->m_alphaR5 >> 4) | (block0->m_alphaR3 << 4);
- r0[2] = (block0->m_alphaR3 >> 4) | (block0->m_alphaR4 << 4);
- r0[3] = (block0->m_alphaR1 >> 4) | (block0->m_alphaR2 << 4);
- r0[4] = (block0->m_alphaR2 >> 4) | (block0->m_alphaR0 << 4);
- r0[5] = (block0->m_alphaR0 >> 4) | (block0->m_alphaR1 << 4);
- block0->m_alphaR0 = r0[0];
- block0->m_alphaR1 = r0[1];
- block0->m_alphaR2 = r0[2];
- block0->m_alphaR3 = r0[3];
- block0->m_alphaR4 = r0[4];
- block0->m_alphaR5 = r0[5];
- std::swap(block0->m_row0, block0->m_row3);
- std::swap(block0->m_row1, block0->m_row2);
- }
- }
- }
- }
- }
- void DDSFile::FlipCompressedImageBC4(ImageData& imageData) {
- uint32_t numXBlocks = (imageData.m_width + 3) / 4;
- uint32_t numYBlocks = (imageData.m_height + 3) / 4;
- if (imageData.m_height == 1) {
- } else if (imageData.m_height == 2) {
- auto blocks = (BC4Block*)imageData.m_mem;
- for (uint32_t x = 0; x < numXBlocks; x++) {
- auto block = blocks + x;
- uint8_t r0 = (block->m_redR1 >> 4) | (block->m_redR2 << 4);
- uint8_t r1 = (block->m_redR2 >> 4) | (block->m_redR0 << 4);
- uint8_t r2 = (block->m_redR0 >> 4) | (block->m_redR1 << 4);
- uint8_t r3 = (block->m_redR4 >> 4) | (block->m_redR5 << 4);
- uint8_t r4 = (block->m_redR5 >> 4) | (block->m_redR3 << 4);
- uint8_t r5 = (block->m_redR3 >> 4) | (block->m_redR4 << 4);
- block->m_redR0 = r0;
- block->m_redR1 = r1;
- block->m_redR2 = r2;
- block->m_redR3 = r3;
- block->m_redR4 = r4;
- block->m_redR5 = r5;
- }
- } else {
- for (uint32_t y = 0; y < (numYBlocks + 1) / 2; y++) {
- auto blocks0 = (BC4Block*)((uint8_t*)imageData.m_mem +
- imageData.m_memPitch * y);
- auto blocks1 =
- (BC4Block*)((uint8_t*)imageData.m_mem +
- imageData.m_memPitch * (numYBlocks - y - 1));
- for (uint32_t x = 0; x < numXBlocks; x++) {
- auto block0 = blocks0 + x;
- auto block1 = blocks1 + x;
- if (block0 != block1) {
- std::swap(block0->m_red0, block1->m_red0);
- std::swap(block0->m_red1, block1->m_red1);
- uint8_t r0[6];
- r0[0] = (block0->m_redR4 >> 4) | (block0->m_redR5 << 4);
- r0[1] = (block0->m_redR5 >> 4) | (block0->m_redR3 << 4);
- r0[2] = (block0->m_redR3 >> 4) | (block0->m_redR4 << 4);
- r0[3] = (block0->m_redR1 >> 4) | (block0->m_redR2 << 4);
- r0[4] = (block0->m_redR2 >> 4) | (block0->m_redR0 << 4);
- r0[5] = (block0->m_redR0 >> 4) | (block0->m_redR1 << 4);
- uint8_t r1[6];
- r1[0] = (block1->m_redR4 >> 4) | (block1->m_redR5 << 4);
- r1[1] = (block1->m_redR5 >> 4) | (block1->m_redR3 << 4);
- r1[2] = (block1->m_redR3 >> 4) | (block1->m_redR4 << 4);
- r1[3] = (block1->m_redR1 >> 4) | (block1->m_redR2 << 4);
- r1[4] = (block1->m_redR2 >> 4) | (block1->m_redR0 << 4);
- r1[5] = (block1->m_redR0 >> 4) | (block1->m_redR1 << 4);
- block0->m_redR0 = r1[0];
- block0->m_redR1 = r1[1];
- block0->m_redR2 = r1[2];
- block0->m_redR3 = r1[3];
- block0->m_redR4 = r1[4];
- block0->m_redR5 = r1[5];
- block1->m_redR0 = r0[0];
- block1->m_redR1 = r0[1];
- block1->m_redR2 = r0[2];
- block1->m_redR3 = r0[3];
- block1->m_redR4 = r0[4];
- block1->m_redR5 = r0[5];
- } else {
- uint8_t r0[6];
- r0[0] = (block0->m_redR4 >> 4) | (block0->m_redR5 << 4);
- r0[1] = (block0->m_redR5 >> 4) | (block0->m_redR3 << 4);
- r0[2] = (block0->m_redR3 >> 4) | (block0->m_redR4 << 4);
- r0[3] = (block0->m_redR1 >> 4) | (block0->m_redR2 << 4);
- r0[4] = (block0->m_redR2 >> 4) | (block0->m_redR0 << 4);
- r0[5] = (block0->m_redR0 >> 4) | (block0->m_redR1 << 4);
- block0->m_redR0 = r0[0];
- block0->m_redR1 = r0[1];
- block0->m_redR2 = r0[2];
- block0->m_redR3 = r0[3];
- block0->m_redR4 = r0[4];
- block0->m_redR5 = r0[5];
- }
- }
- }
- }
- }
- void DDSFile::FlipCompressedImageBC5(ImageData& imageData) {
- uint32_t numXBlocks = (imageData.m_width + 3) / 4;
- uint32_t numYBlocks = (imageData.m_height + 3) / 4;
- if (imageData.m_height == 1) {
- } else if (imageData.m_height == 2) {
- auto blocks = (BC5Block*)imageData.m_mem;
- for (uint32_t x = 0; x < numXBlocks; x++) {
- auto block = blocks + x;
- uint8_t r0 = (block->m_redR1 >> 4) | (block->m_redR2 << 4);
- uint8_t r1 = (block->m_redR2 >> 4) | (block->m_redR0 << 4);
- uint8_t r2 = (block->m_redR0 >> 4) | (block->m_redR1 << 4);
- uint8_t r3 = (block->m_redR4 >> 4) | (block->m_redR5 << 4);
- uint8_t r4 = (block->m_redR5 >> 4) | (block->m_redR3 << 4);
- uint8_t r5 = (block->m_redR3 >> 4) | (block->m_redR4 << 4);
- block->m_redR0 = r0;
- block->m_redR1 = r1;
- block->m_redR2 = r2;
- block->m_redR3 = r3;
- block->m_redR4 = r4;
- block->m_redR5 = r5;
- uint8_t g0 = (block->m_greenR1 >> 4) | (block->m_greenR2 << 4);
- uint8_t g1 = (block->m_greenR2 >> 4) | (block->m_greenR0 << 4);
- uint8_t g2 = (block->m_greenR0 >> 4) | (block->m_greenR1 << 4);
- uint8_t g3 = (block->m_greenR4 >> 4) | (block->m_greenR5 << 4);
- uint8_t g4 = (block->m_greenR5 >> 4) | (block->m_greenR3 << 4);
- uint8_t g5 = (block->m_greenR3 >> 4) | (block->m_greenR4 << 4);
- block->m_greenR0 = g0;
- block->m_greenR1 = g1;
- block->m_greenR2 = g2;
- block->m_greenR3 = g3;
- block->m_greenR4 = g4;
- block->m_greenR5 = g5;
- }
- } else {
- for (uint32_t y = 0; y < (numYBlocks + 1) / 2; y++) {
- auto blocks0 = (BC5Block*)((uint8_t*)imageData.m_mem +
- imageData.m_memPitch * y);
- auto blocks1 =
- (BC5Block*)((uint8_t*)imageData.m_mem +
- imageData.m_memPitch * (numYBlocks - y - 1));
- for (uint32_t x = 0; x < numXBlocks; x++) {
- auto block0 = blocks0 + x;
- auto block1 = blocks1 + x;
- if (block0 != block1) {
- std::swap(block0->m_red0, block1->m_red0);
- std::swap(block0->m_red1, block1->m_red1);
- uint8_t r0[6];
- r0[0] = (block0->m_redR4 >> 4) | (block0->m_redR5 << 4);
- r0[1] = (block0->m_redR5 >> 4) | (block0->m_redR3 << 4);
- r0[2] = (block0->m_redR3 >> 4) | (block0->m_redR4 << 4);
- r0[3] = (block0->m_redR1 >> 4) | (block0->m_redR2 << 4);
- r0[4] = (block0->m_redR2 >> 4) | (block0->m_redR0 << 4);
- r0[5] = (block0->m_redR0 >> 4) | (block0->m_redR1 << 4);
- uint8_t r1[6];
- r1[0] = (block1->m_redR4 >> 4) | (block1->m_redR5 << 4);
- r1[1] = (block1->m_redR5 >> 4) | (block1->m_redR3 << 4);
- r1[2] = (block1->m_redR3 >> 4) | (block1->m_redR4 << 4);
- r1[3] = (block1->m_redR1 >> 4) | (block1->m_redR2 << 4);
- r1[4] = (block1->m_redR2 >> 4) | (block1->m_redR0 << 4);
- r1[5] = (block1->m_redR0 >> 4) | (block1->m_redR1 << 4);
- block0->m_redR0 = r1[0];
- block0->m_redR1 = r1[1];
- block0->m_redR2 = r1[2];
- block0->m_redR3 = r1[3];
- block0->m_redR4 = r1[4];
- block0->m_redR5 = r1[5];
- block1->m_redR0 = r0[0];
- block1->m_redR1 = r0[1];
- block1->m_redR2 = r0[2];
- block1->m_redR3 = r0[3];
- block1->m_redR4 = r0[4];
- block1->m_redR5 = r0[5];
- std::swap(block0->m_green0, block1->m_green0);
- std::swap(block0->m_green1, block1->m_green1);
- uint8_t g0[6];
- g0[0] = (block0->m_greenR4 >> 4) | (block0->m_greenR5 << 4);
- g0[1] = (block0->m_greenR5 >> 4) | (block0->m_greenR3 << 4);
- g0[2] = (block0->m_greenR3 >> 4) | (block0->m_greenR4 << 4);
- g0[3] = (block0->m_greenR1 >> 4) | (block0->m_greenR2 << 4);
- g0[4] = (block0->m_greenR2 >> 4) | (block0->m_greenR0 << 4);
- g0[5] = (block0->m_greenR0 >> 4) | (block0->m_greenR1 << 4);
- uint8_t g1[6];
- g1[0] = (block1->m_greenR4 >> 4) | (block1->m_greenR5 << 4);
- g1[1] = (block1->m_greenR5 >> 4) | (block1->m_greenR3 << 4);
- g1[2] = (block1->m_greenR3 >> 4) | (block1->m_greenR4 << 4);
- g1[3] = (block1->m_greenR1 >> 4) | (block1->m_greenR2 << 4);
- g1[4] = (block1->m_greenR2 >> 4) | (block1->m_greenR0 << 4);
- g1[5] = (block1->m_greenR0 >> 4) | (block1->m_greenR1 << 4);
- block0->m_greenR0 = g1[0];
- block0->m_greenR1 = g1[1];
- block0->m_greenR2 = g1[2];
- block0->m_greenR3 = g1[3];
- block0->m_greenR4 = g1[4];
- block0->m_greenR5 = g1[5];
- block1->m_greenR0 = g0[0];
- block1->m_greenR1 = g0[1];
- block1->m_greenR2 = g0[2];
- block1->m_greenR3 = g0[3];
- block1->m_greenR4 = g0[4];
- block1->m_greenR5 = g0[5];
- } else {
- uint8_t r0[6];
- r0[0] = (block0->m_redR4 >> 4) | (block0->m_redR5 << 4);
- r0[1] = (block0->m_redR5 >> 4) | (block0->m_redR3 << 4);
- r0[2] = (block0->m_redR3 >> 4) | (block0->m_redR4 << 4);
- r0[3] = (block0->m_redR1 >> 4) | (block0->m_redR2 << 4);
- r0[4] = (block0->m_redR2 >> 4) | (block0->m_redR0 << 4);
- r0[5] = (block0->m_redR0 >> 4) | (block0->m_redR1 << 4);
- block0->m_redR0 = r0[0];
- block0->m_redR1 = r0[1];
- block0->m_redR2 = r0[2];
- block0->m_redR3 = r0[3];
- block0->m_redR4 = r0[4];
- block0->m_redR5 = r0[5];
- uint8_t g0[6];
- g0[0] = (block0->m_greenR4 >> 4) | (block0->m_greenR5 << 4);
- g0[1] = (block0->m_greenR5 >> 4) | (block0->m_greenR3 << 4);
- g0[2] = (block0->m_greenR3 >> 4) | (block0->m_greenR4 << 4);
- g0[3] = (block0->m_greenR1 >> 4) | (block0->m_greenR2 << 4);
- g0[4] = (block0->m_greenR2 >> 4) | (block0->m_greenR0 << 4);
- g0[5] = (block0->m_greenR0 >> 4) | (block0->m_greenR1 << 4);
- block0->m_greenR0 = g0[0];
- block0->m_greenR1 = g0[1];
- block0->m_greenR2 = g0[2];
- block0->m_greenR3 = g0[3];
- block0->m_greenR4 = g0[4];
- block0->m_greenR5 = g0[5];
- }
- }
- }
- }
- }
- } // namespace tinyddsloader
- #endif // !TINYDDSLOADER_IMPLEMENTATION
- #endif // !TINYDDSLOADER_H_
|