| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- /******************************************************************************/
- #include "stdafx.h"
- namespace EE{
- /******************************************************************************/
- #define DDSCAPS2_CUBEMAP 0x200
- #define DDSCAPS2_CUBEMAP_POSITIVEX 0x400
- #define DDSCAPS2_CUBEMAP_NEGATIVEX 0x800
- #define DDSCAPS2_CUBEMAP_POSITIVEY 0x1000
- #define DDSCAPS2_CUBEMAP_NEGATIVEY 0x2000
- #define DDSCAPS2_CUBEMAP_POSITIVEZ 0x4000
- #define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x8000
- #define DDSCAPS2_VOLUME 0x200000
- #define DDPF_FOURCC 0x4
- #define DDPF_LUMINANCE 0x20000
- /******************************************************************************/
- #pragma pack(push, 4)
- struct DDS_PIXELFORMAT
- {
- UInt Size, Flags, FourCC, RGBBitCount, RBitMask, GBitMask, BBitMask, ABitMask;
- IMAGE_TYPE type()
- {
- if(!(Flags&DDPF_FOURCC))FourCC=0;
- if(FourCC==CC4('D', 'X', '1', '0'))return IMAGE_NONE; // special DX10+ format
- if(FourCC==CC4('D', 'X', 'T', '1'))return IMAGE_DXT1;
- if(FourCC==CC4('D', 'X', 'T', '2'))return IMAGE_DXT3;
- if(FourCC==CC4('D', 'X', 'T', '3'))return IMAGE_DXT3;
- if(FourCC==CC4('D', 'X', 'T', '4'))return IMAGE_DXT5;
- if(FourCC==CC4('D', 'X', 'T', '5'))return IMAGE_DXT5;
- // fix 'RGBBitCount' for these formats, because it may be 0
- if(FourCC==111){RGBBitCount=16 ; return IMAGE_F16 ;}
- if(FourCC==112){RGBBitCount=16*2; return IMAGE_F16_2;}
- if(FourCC==113){RGBBitCount=16*4; return IMAGE_F16_4;}
- if(FourCC==114){RGBBitCount=32 ; return IMAGE_F32 ;}
- if(FourCC==115){RGBBitCount=32*2; return IMAGE_F32_2;}
- if(FourCC==116){RGBBitCount=32*4; return IMAGE_F32_4;}
- if(Flags&DDPF_LUMINANCE)
- {
- if(RGBBitCount== 8 && RBitMask==0x000000FF && GBitMask==0x00000000 && BBitMask==0x00000000 && ABitMask==0x00000000)return IMAGE_L8;
- if(RGBBitCount==16 && RBitMask==0x000000FF && GBitMask==0x00000000 && BBitMask==0x00000000 && ABitMask==0x0000FF00)return IMAGE_L8A8;
- if(RGBBitCount==16 && RBitMask==0x0000FFFF && GBitMask==0x00000000 && BBitMask==0x00000000 && ABitMask==0x00000000)return IMAGE_I16;
- }
- if(RGBBitCount==32 && RBitMask==0x00FF0000 && GBitMask==0x0000FF00 && BBitMask==0x000000FF && ABitMask==0xFF000000)return IMAGE_B8G8R8A8;
- if(RGBBitCount==32 && RBitMask==0x000000FF && GBitMask==0x0000FF00 && BBitMask==0x00FF0000 && ABitMask==0xFF000000)return IMAGE_R8G8B8A8;
- if(RGBBitCount==24 && RBitMask==0x000000FF && GBitMask==0x0000FF00 && BBitMask==0x00FF0000 && ABitMask==0x00000000)return IMAGE_R8G8B8;
- if(RGBBitCount==16 && RBitMask==0x000000FF && GBitMask==0x0000FF00 && BBitMask==0x00000000 && ABitMask==0x00000000)return IMAGE_R8G8;
- if(RGBBitCount== 8 && RBitMask==0x000000FF && GBitMask==0x00000000 && BBitMask==0x00000000 && ABitMask==0x00000000)return IMAGE_R8;
- if(RGBBitCount== 8 && RBitMask==0x00000000 && GBitMask==0x00000000 && BBitMask==0x00000000 && ABitMask==0x000000FF)return IMAGE_A8;
- if(RGBBitCount==16 && RBitMask==0x00000F00 && GBitMask==0x000000F0 && BBitMask==0x0000000F && ABitMask==0x00000000)return IMAGE_B4G4R4X4;
- if(RGBBitCount==16 && RBitMask==0x00000F00 && GBitMask==0x000000F0 && BBitMask==0x0000000F && ABitMask==0x0000F000)return IMAGE_B4G4R4A4;
- if(RGBBitCount==16 && RBitMask==0x00007C00 && GBitMask==0x000003E0 && BBitMask==0x0000001F && ABitMask==0x00000000)return IMAGE_B5G5R5X1;
- if(RGBBitCount==16 && RBitMask==0x00007C00 && GBitMask==0x000003E0 && BBitMask==0x0000001F && ABitMask==0x00008000)return IMAGE_B5G5R5A1;
- if(RGBBitCount==16 && RBitMask==0x0000F800 && GBitMask==0x000007E0 && BBitMask==0x0000001F && ABitMask==0x00000000)return IMAGE_B5G6R5;
- if(RGBBitCount==24 && RBitMask==0x00FF0000 && GBitMask==0x0000FF00 && BBitMask==0x000000FF && ABitMask==0x00000000)return IMAGE_B8G8R8;
- if(RGBBitCount==32 && RBitMask==0x00FF0000 && GBitMask==0x0000FF00 && BBitMask==0x000000FF && ABitMask==0x00000000)return IMAGE_B8G8R8X8;
- if(RGBBitCount==32 && RBitMask==0x000000FF && GBitMask==0x0000FF00 && BBitMask==0x00FF0000 && ABitMask==0x00000000)return IMAGE_R8G8B8X8;
- if(RGBBitCount==32 && RBitMask==0x000003FF && GBitMask==0x000FFC00 && BBitMask==0x3FF00000 && ABitMask==0xC0000000)return IMAGE_R10G10B10A2;
- return IMAGE_NONE;
- }
- };
- struct DDS_HEADER
- {
- UInt Size, Flags, Height, Width, PitchOrLinearSize, Depth, MipMapCount, Reserved1[11];
- DDS_PIXELFORMAT pf;
- UInt Caps, Caps2, Caps3, Caps4, Reserved2;
- IMAGE_TYPE load(File &f)
- {
- ASSERT(SIZE(DDS_HEADER)==124 && SIZE(DDS_PIXELFORMAT)==32);
- if(f.getFast(T))
- if(Size==SIZE(DDS_HEADER) && pf.Size==SIZE(DDS_PIXELFORMAT))
- if(!(Caps2&DDSCAPS2_CUBEMAP) && !(Caps2&DDSCAPS2_VOLUME)) // Cube and Volume textures are not currently supported
- if(IMAGE_TYPE type=pf.type())
- {
- switch(type) // many DDS writers incorrectly setup 'PitchOrLinearSize', so we have to adjust it manually, according to https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dx-graphics-dds-pguide#dds-file-layout
- {
- case IMAGE_BC1: PitchOrLinearSize=DivCeil4(Width)* 8; break;
- case IMAGE_BC2: case IMAGE_BC3: case IMAGE_BC7: PitchOrLinearSize=DivCeil4(Width)*16; break;
- default: PitchOrLinearSize=DivCeil8(Width*pf.RGBBitCount); break;
- }
- return type;
- }
- return IMAGE_NONE;
- }
- };
- #pragma pack(pop)
- /******************************************************************************/
- Bool Image::ImportDDS(File &f, Int type, Int mode, Int mip_maps)
- {
- if(mode>=0 && mode!=IMAGE_2D && mode!=IMAGE_SOFT)return false; // if mode is specified, and not SOFT/2D then fail
- if(f.getUInt()==CC4('D','D','S',' '))
- {
- DDS_HEADER header; if(IMAGE_TYPE t=header.load(f))
- {
- if(type <=0)type =t; if(type>=IMAGE_TYPES)type=IMAGE_R8G8B8A8;
- if(mode < 0)mode =IMAGE_SOFT; // always default to SOFT like all other file formats
- if(mip_maps< 0)mip_maps=((header.MipMapCount>1 && mode==IMAGE_2D) ? 0 : 1);
- if(t==type && createTry(header.Width, header.Height, 1, t, IMAGE_MODE(mode), mip_maps, false) // if conversion is not required, then try desired values
- || createTry(header.Width, header.Height, 1, t, IMAGE_SOFT , 1, false)) // otherwise import as soft
- if(lock(LOCK_WRITE))
- {
- Int pitch =ImagePitch (w(), h(), 0, hwType()), // use "w(), h()" instead of "hwW(), hwH()" because we want to read only valid pixels and zero others
- blocks_y=ImageBlocksY(w(), h(), 0, hwType()); // use "w(), h()" instead of "hwW(), hwH()" because we want to read only valid pixels and zero others
- if(header.PitchOrLinearSize>=pitch)
- {
- Int skip=header.PitchOrLinearSize-pitch, zero=T.pitch()-pitch;
- Byte *data=T.data();
- FREPD(y, blocks_y)
- {
- f.getFast(data, pitch);
- f.skip(skip);
- Zero(data+pitch, zero);
- data+=T.pitch();
- }
- Zero(data, T.pitch2()-blocks_y*T.pitch());
- unlock();
- if(f.ok())
- {
- if(type!=T.type() || mode!=T.mode())
- {
- if(!copyTry(T, -1, -1, -1, type, mode, mip_maps))goto error;
- }else updateMipMaps();
- return true;
- }
- }
- }
- }
- }
- error:
- del(); return false;
- }
- Bool Image::ImportDDS(C Str &name, Int type, Int mode, Int mip_maps)
- {
- File f; if(f.readTry(name))return ImportDDS(f, type, mode, mip_maps);
- del(); return false;
- }
- Bool Image::ImportDDS(C Str &name) {return ImportDDS(name, -1);}
- Bool Image::ImportDDS( File &f ) {return ImportDDS(f , -1);}
- /******************************************************************************/
- //Bool ExportDX (C Str &name, GPU_API(D3DXIMAGE_FILEFORMAT, D3DX11_IMAGE_FILE_FORMAT, UInt) format)C; // export using DirectX
- //Bool Image::ExportDDS(C Str &name)C {return ExportDX(name, GPU_API(D3DXIFF_DDS, D3DX11_IFF_DDS, 0));}
- Bool Image::ExportDDS(C Str &name)C {return false;}
- /******************************************************************************/
- }
- /******************************************************************************/
|