Exemple #1
0
        public static DDSMetadata ReadHeader(string ddsfile)
        {
            var metadata = new DDSMetadata();

            using var fs = new FileStream(ddsfile, FileMode.Open, FileAccess.Read);

            if (fs.Length < 128)
            {
                throw new InvalidParsingException(ddsfile);
            }

            using var reader = new BinaryReader(fs);

            // check if DDS file
            var buffer = reader.ReadBytes(4);

            if (!buffer.SequenceEqual(BitConverter.GetBytes(DDS_MAGIC)))
            {
                return(metadata);
            }

            var id = reader.BaseStream.ReadStruct <DDS_HEADER>();

            metadata = new DDSMetadata(id);

            return(metadata);
        }
Exemple #2
0
        public static unsafe bool TryGetMetadataFromDDSMemory(Span <byte> span, out DDSMetadata metadata)
        {
            try
            {
                var len = span.Length;
                fixed(byte *ptr = span)
                {
                    var md = DirectXTexSharp.Metadata.
                             GetMetadataFromDDSMemory(ptr, len, DirectXTexSharp.DDSFLAGS.DDS_FLAGS_NONE);
                    var bpp    = DirectXTexSharp.Format.BitsPerPixel(md.format);
                    var iscube = md.is_cubemap();

                    metadata = new DDSMetadata(md, (uint)bpp, true);
                }
            }
            catch (Exception)
            {
                metadata = default;
                return(false);
            }

            return(true);
        }
Exemple #3
0
        private static (DDS_HEADER, DDS_HEADER_DXT10) GenerateHeader(DDSMetadata metadata)
        {
            var  height    = metadata.Height;
            var  width     = metadata.Width;
            var  mipscount = metadata.Mipscount;
            var  iscubemap = metadata.Iscubemap;
            var  format    = metadata.Format;
            bool dxt10     = /*metadata.Format == EFormat.BC7_UNORM;*/ metadata.Dx10; //TODO
            // for BC7_UNORM, R8_UINT

            var ddspf = new DDS_PIXELFORMAT()
            {
                dwSize        = PIXELFORMAT_SIZE,
                dwFlags       = 0,
                dwFourCC      = 0,
                dwRGBBitCount = 0,
                dwRBitMask    = 0,
                dwGBitMask    = 0,
                dwBBitMask    = 0,
                dwABitMask    = 0
            };

            var header = new DDS_HEADER()
            {
                dwSize              = HEADER_SIZE,
                dwFlags             = DDS_HEADER_FLAGS_TEXTURE,
                dwHeight            = height,
                dwWidth             = width,
                dwPitchOrLinearSize = 0,
                dwDepth             = 0,
                dwMipMapCount       = 0,
                dwReserved1         = 0,
                dwReserved2         = 0,
                dwReserved3         = 0,
                dwReserved4         = 0,
                dwReserved5         = 0,
                dwReserved6         = 0,
                dwReserved7         = 0,
                dwReserved8         = 0,
                dwReserved9         = 0,
                dwReserved10        = 0,
                dwReserved11        = 0,
                ddspf        = ddspf,
                dwCaps       = DDSCAPS_TEXTURE,
                dwCaps2      = 0,
                dwCaps3      = 0,
                dwCaps4      = 0,
                dwReserved12 = 0,
            };

            var dx10header = new DDS_HEADER_DXT10()
            {
                dxgiFormat        = DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM,
                resourceDimension = D3D10_RESOURCE_DIMENSION.D3D10_RESOURCE_DIMENSION_TEXTURE2D,
                miscFlag          = 0,
                arraySize         = metadata.Slicecount,
                miscFlags2        = 0
            };

            if (mipscount > 0)
            {
                header.dwMipMapCount = mipscount;
            }

            // pixelformat
            {
                // dwFourCC
                if (dxt10)
                {
                    ddspf.dwFourCC = MAKEFOURCC('D', 'X', '1', '0');
                }
                else
                {
                    switch (format)
                    {
                    case EFormat.R32G32B32A32_FLOAT:
                        ddspf.dwFourCC = 116;
                        break;

                    case EFormat.R16G16B16A16_FLOAT:
                        ddspf.dwFourCC = 113;
                        break;

                    case EFormat.R10G10B10A2_UNORM:
                        throw new NotImplementedException();

                    case EFormat.R32_UINT:
                        throw new NotImplementedException();

                    case EFormat.R8G8_UNORM:
                        SetPixelmask(DDSPF_A8L8, ref ddspf);
                        break;

                    case EFormat.R16_FLOAT:
                        ddspf.dwFourCC = 111;
                        break;

                    case EFormat.R8_UNORM:
                    case EFormat.R8_UINT:
                        SetPixelmask(DDSPF_L8, ref ddspf);
                        break;

                    case EFormat.A8_UNORM:
                        SetPixelmask(DDSPF_A8, ref ddspf);
                        break;

                    case EFormat.R8G8B8A8_UNORM:
                        SetPixelmask(DDSPF_A8R8G8B8, ref ddspf);
                        break;

                    case EFormat.BC1_UNORM:
                        ddspf.dwFourCC = MAKEFOURCC('D', 'X', 'T', '1');
                        break;

                    case EFormat.BC2_UNORM:
                        ddspf.dwFourCC = MAKEFOURCC('D', 'X', 'T', '3');
                        break;

                    case EFormat.BC3_UNORM:
                        ddspf.dwFourCC = MAKEFOURCC('D', 'X', 'T', '5');
                        break;

                    case EFormat.BC4_UNORM:
                        ddspf.dwFourCC = MAKEFOURCC('B', 'C', '4', 'U');
                        break;

                    case EFormat.BC5_UNORM:
                        ddspf.dwFourCC = MAKEFOURCC('B', 'C', '5', 'U');
                        break;

                    case EFormat.BC7_UNORM:
                        dxt10 = true;
                        break;

                    default:
                        throw new MissingFormatException($"Missing format: {format}");
                    }
                }

                // dwflags
                if (ddspf.dwABitMask != 0) // check this
                {
                    ddspf.dwFlags |= DDPF_ALPHAPIXELS;
                }

                /*if (ddspf.dwABitMask != 0)
                 *  ddspf.dwFlags |= DDPF_ALPHA;*///old
                if (ddspf.dwFourCC != 0)
                {
                    ddspf.dwFlags |= DDPF_FOURCC;
                }
                if (ddspf.dwRGBBitCount != 0 && ddspf.dwRBitMask != 0 && ddspf.dwGBitMask != 0 && ddspf.dwBBitMask != 0)
                {
                    ddspf.dwFlags |= DDPF_RGB;
                }
                if (ddspf.dwRBitMask != 0 && ddspf.dwGBitMask == 0 && ddspf.dwBBitMask == 0 && ddspf.dwABitMask == 0)
                {
                    ddspf.dwFlags |= DDPF_LUMINANCE;
                }

                header.ddspf = ddspf;
            }

            // dwPitchOrLinearSize
            uint p   = 0;
            var  bpp = ddspf.dwRGBBitCount;

            switch (format)
            {
            case EFormat.R8_UNORM:
                header.dwPitchOrLinearSize = (width * bpp + 7) / 8;
                break;

            case EFormat.R32G32B32A32_FLOAT:
            case EFormat.R16G16B16A16_FLOAT:
            case EFormat.R10G10B10A2_UNORM:
            case EFormat.R32_UINT:
            case EFormat.R8_UINT:
            case EFormat.R8G8_UNORM:
            case EFormat.R16_FLOAT:
            case EFormat.A8_UNORM:
            case EFormat.R8G8B8A8_UNORM:
                header.dwPitchOrLinearSize = (width * bpp + 7) / 8;
                header.dwFlags            |= DDSD_PITCH;
                break;

            case EFormat.BC1_UNORM:
            case EFormat.BC4_UNORM:
                p = width * height / 2;     //max(1,width ?4)x max(1,height ?4)x 8 (DXT1)
                header.dwPitchOrLinearSize = (uint)(p);
                header.dwFlags            |= DDSD_LINEARSIZE;
                break;

            case EFormat.BC2_UNORM:
            case EFormat.BC3_UNORM:
            case EFormat.BC5_UNORM:
            case EFormat.BC7_UNORM:
                p = width * height;         //max(1,width ?4)x max(1,height ?4)x 16 (DXT2-5)
                header.dwPitchOrLinearSize = (uint)(p);
                header.dwFlags            |= DDSD_LINEARSIZE;
                break;

            default:
                throw new MissingFormatException($"Missing format: {format}");
            }
            // unused R8G8_B8G8, G8R8_G8B8, legacy UYVY-packed, and legacy YUY2-packed formats,
            // header.dwPitchOrLinearSize = ((width + 1) >> 1) * 4;

            // depth
            //if (slicecount > 0  && !iscubemap)
            //    header.dwDepth = slicecount;

            // caps
            if (iscubemap || mipscount > 0)
            {
                header.dwCaps |= DDSCAPS_COMPLEX;
            }
            if (mipscount > 0)
            {
                header.dwCaps |= DDSCAPS_MIPMAP;
            }

            // caps2
            if (iscubemap)
            {
                header.dwCaps2 |= DDSCAPS2_CUBEMAP_ALL_FACES | DDSCAPS2_CUBEMAP;
            }
            //if (slicecount > 0)
            //    header.dwCaps2 |= DDSCAPS2_VOLUME;

            // flags
            //if (slicecount > 0)
            //    header.dwFlags |= DDSD_DEPTH;
            if (mipscount > 0)
            {
                header.dwFlags |= DDSD_MIPMAPCOUNT;
            }

            // DXT10
            if (dxt10)
            {
                // dxgiFormat
                switch (format)
                {
                case EFormat.R32G32B32A32_FLOAT:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT;
                    break;

                case EFormat.R16G16B16A16_FLOAT:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_FLOAT;
                    break;

                case EFormat.R10G10B10A2_UNORM:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_R10G10B10A2_UNORM;
                    break;

                case EFormat.R8G8B8A8_UNORM:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM;
                    break;

                case EFormat.R32_UINT:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_R32_UINT;
                    break;

                case EFormat.R8G8_UNORM:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_R8G8_UNORM;
                    break;

                case EFormat.R16_FLOAT:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_R16_FLOAT;
                    break;

                case EFormat.R8_UINT:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_R8_UINT;
                    break;

                case EFormat.R8_UNORM:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_R8_UNORM;
                    break;

                case EFormat.A8_UNORM:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_A8_UNORM;
                    break;

                case EFormat.BC1_UNORM:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM;
                    break;

                case EFormat.BC2_UNORM:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM;
                    break;

                case EFormat.BC3_UNORM:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM;
                    break;

                case EFormat.BC4_UNORM:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM;
                    break;

                case EFormat.BC7_UNORM:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM;
                    break;

                case EFormat.BC5_UNORM:
                    dx10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM;
                    break;

                default:
                {
                    throw new MissingFormatException($"Missing format: {format}");
                }
                }
                // resourceDimension
                //if (slicecount > 0)
                //    dxt10header.resourceDimension = D3D10_RESOURCE_DIMENSION.D3D10_RESOURCE_DIMENSION_TEXTURE3D;
                //misc flag
                //if (iscubemap)
                //    dxt10header.miscFlag |= DDS_RESOURCE_MISC_TEXTURECUBE;
                //if (mipscount > 0)
                //    dxt10header.miscFlag |= D3D10_RESOURCE_MISC_GENERATE_MIPS;
                // array size
                //if (iscubemap)
                //    dxt10header.arraySize = metadata.Slicecount;
                // miscFlags2
            }

            return(header, dx10header);
        }
Exemple #4
0
 public static void GenerateAndWriteHeader(Stream stream, DDSMetadata metadata)
 {
     var(header, dxt10header) = GenerateHeader(metadata);
     WriteHeader(stream, header, dxt10header);
 }