Example #1
0
 public TexMetadataView(TexMetadata metadata)
 {
     _metadata = metadata;
 }
Example #2
0
        public static unsafe byte[] CompressBlock(Byte[] data, int width, int height, DDS.DXGI_FORMAT format, float AlphaRef = 0.5f, STCompressionMode CompressionMode = STCompressionMode.Normal)
        {
            long inputRowPitch   = width * 4;
            long inputSlicePitch = width * height * 4;

            if (data.Length == inputSlicePitch)
            {
                byte *buf;
                buf = (byte *)Marshal.AllocHGlobal((int)inputSlicePitch);
                Marshal.Copy(data, 0, (IntPtr)buf, (int)inputSlicePitch);

                DirectXTexNet.Image inputImage = new DirectXTexNet.Image(
                    width, height, DXGI_FORMAT.R8G8B8A8_UNORM, inputRowPitch,
                    inputSlicePitch, (IntPtr)buf, null);

                TexMetadata texMetadata = new TexMetadata(width, height, 1, 1, 1, 0, 0,
                                                          DXGI_FORMAT.R8G8B8A8_UNORM, TEX_DIMENSION.TEXTURE2D);

                ScratchImage scratchImage = TexHelper.Instance.InitializeTemporary(
                    new DirectXTexNet.Image[] { inputImage }, texMetadata, null);

                var compFlags = TEX_COMPRESS_FLAGS.DEFAULT;
                //  compFlags |= TEX_COMPRESS_FLAGS.PARALLEL;

                if (format == DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM ||
                    format == DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM_SRGB ||
                    format == DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_TYPELESS)
                {
                    if (CompressionMode == STCompressionMode.Fast)
                    {
                        compFlags |= TEX_COMPRESS_FLAGS.BC7_QUICK;
                    }
                }

                if (format == DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB ||
                    format == DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB ||
                    format == DDS.DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM_SRGB ||
                    format == DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM_SRGB ||
                    format == DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM_SRGB)
                {
                    compFlags |= TEX_COMPRESS_FLAGS.SRGB;
                }

                using (var comp = scratchImage.Compress((DXGI_FORMAT)format, compFlags, 0.5f))
                {
                    long outRowPitch;
                    long outSlicePitch;
                    TexHelper.Instance.ComputePitch((DXGI_FORMAT)format, width, height, out outRowPitch, out outSlicePitch, CP_FLAGS.NONE);

                    byte[] result = new byte[outSlicePitch];
                    Marshal.Copy(comp.GetImage(0).Pixels, result, 0, result.Length);

                    inputImage = null;
                    scratchImage.Dispose();


                    return(result);
                }
            }
            return(null);
        }
Example #3
0
        public static byte[] ConvertDDS(GUIDEntry value, DXGI_FORMAT targetFormat, ImageFormat imageFormat, int frame)
        {
            try
            {
                if (GetDataType(value) != DataType.Image)
                {
                    return(null);
                }
                teTexture texture = new teTexture(IOHelper.OpenFile(value));
                if (texture.PayloadRequired)
                {
                    ulong payload = texture.GetPayloadGUID(value.GUID);
                    if (value.APM.FirstOccurence.ContainsKey(payload))
                    {
                        texture.LoadPayload(IOHelper.OpenFile(value.APM.FirstOccurence[payload]));
                    }
                    else
                    {
                        return(null);
                    }
                }

                Stream ms = texture.SaveToDDS();

                CoInitializeEx(IntPtr.Zero, CoInit.MultiThreaded | CoInit.SpeedOverMemory);

                byte[] data = new byte[ms.Length];
                ms.Read(data, 0, data.Length);
                ScratchImage scratch = null;
                try
                {
                    unsafe
                    {
                        fixed(byte *dataPin = data)
                        {
                            scratch = TexHelper.Instance.LoadFromDDSMemory((IntPtr)dataPin, data.Length, DDS_FLAGS.NONE);
                            TexMetadata info = scratch.GetMetadata();

                            if (TexHelper.Instance.IsCompressed(info.Format))
                            {
                                ScratchImage temp = scratch.Decompress(frame, DXGI_FORMAT.UNKNOWN);
                                scratch.Dispose();
                                scratch = temp;
                            }
                            info = scratch.GetMetadata();

                            if (info.Format != targetFormat)
                            {
                                ScratchImage temp = scratch.Convert(targetFormat, TEX_FILTER_FLAGS.DEFAULT, 0.5f);
                                scratch.Dispose();
                                scratch = temp;
                            }

                            UnmanagedMemoryStream stream = null;

                            if (imageFormat == ImageFormat.TGA)
                            {
                                stream = scratch.SaveToTGAMemory(frame < 0 ? 0 : frame);
                            }
                            else
                            {
                                WICCodecs codec        = WICCodecs.PNG;
                                bool      isMultiframe = false;
                                switch (imageFormat)
                                {
                                case ImageFormat.BMP:
                                    codec = WICCodecs.BMP;
                                    break;

                                case ImageFormat.GIF:
                                    codec        = WICCodecs.GIF;
                                    isMultiframe = true;
                                    break;

                                case ImageFormat.JPEG:
                                    codec = WICCodecs.JPEG;
                                    break;

                                case ImageFormat.PNG:
                                    codec = WICCodecs.PNG;
                                    break;

                                case ImageFormat.TIF:
                                    codec        = WICCodecs.TIFF;
                                    isMultiframe = true;
                                    break;
                                }

                                if (frame < 0)
                                {
                                    if (!isMultiframe)
                                    {
                                        frame = 0;
                                    }
                                    else
                                    {
                                        stream = scratch.SaveToWICMemory(0, info.ArraySize, WIC_FLAGS.ALL_FRAMES, TexHelper.Instance.GetWICCodec(codec));
                                    }
                                }
                                if (frame >= 0)
                                {
                                    stream = scratch.SaveToWICMemory(frame, WIC_FLAGS.NONE, TexHelper.Instance.GetWICCodec(codec));
                                }

                                byte[] tex = new byte[stream.Length];
                                stream.Read(tex, 0, tex.Length);
                                scratch.Dispose();
                                return(tex);
                            }
                        }
                    }
                }
                catch
                {
                    if (scratch != null && scratch.IsDisposed == false)
                    {
                        scratch?.Dispose();
                    }
                }
            }
            catch
            {
            }
            return(null);
        }
Example #4
0
        /// <summary>
        /// Exports the specified image.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="libraryData">The library data.</param>
        /// <param name="request">The request.</param>
        /// <exception cref="TexLibraryException">
        /// Exporting texture failed
        /// </exception>
        private void Export(TexImage image, DxtTextureLibraryData libraryData, ExportRequest request)
        {
            Log.Debug("Exporting to " + request.FilePath + " ...");

            if (request.MinimumMipMapSize > 1 && request.MinimumMipMapSize <= libraryData.Metadata.Width && request.MinimumMipMapSize <= libraryData.Metadata.Height) // if a mimimun mipmap size was requested
            {
                TexMetadata metadata = libraryData.Metadata;
                DxtImage[]  dxtImages;

                if (image.Dimension == TexImage.TextureDimension.Texture3D)
                {
                    int newMipMapCount = 0; // the new mipmap count
                    int ct             = 0; // ct will contain the number of SubImages per array element that we need to keep
                    int curDepth       = image.Depth << 1;
                    for (int i = 0; i < image.MipmapCount; ++i)
                    {
                        curDepth = curDepth > 1 ? curDepth >>= 1 : curDepth;

                        if (libraryData.DxtImages[ct].Width <= request.MinimumMipMapSize || libraryData.DxtImages[ct].Height <= request.MinimumMipMapSize)
                        {
                            ct += curDepth;
                            ++newMipMapCount;
                            break;
                        }
                        ++newMipMapCount;
                        ct += curDepth;
                    }

                    int SubImagePerArrayElement = image.SubImageArray.Length / image.ArraySize; // number of SubImage in each texture array element.

                    // Initializing library native data according to the new mipmap level
                    metadata.MipLevels = newMipMapCount;
                    dxtImages          = new DxtImage[metadata.ArraySize * ct];

                    int ct2 = 0;
                    for (int i = 0; i < image.ArraySize; ++i)
                    {
                        for (int j = 0; j < ct; ++j)
                        {
                            dxtImages[ct2] = libraryData.DxtImages[j + i * SubImagePerArrayElement];
                            ++ct2;
                        }
                    }
                }
                else
                {
                    int newMipMapCount = libraryData.Metadata.MipLevels;
                    for (int i = libraryData.Metadata.MipLevels - 1; i > 0; --i) // looking for the mipmap level corresponding to the minimum size requeted.
                    {
                        if (libraryData.DxtImages[i].Width >= request.MinimumMipMapSize || libraryData.DxtImages[i].Height >= request.MinimumMipMapSize)
                        {
                            break;
                        }
                        --newMipMapCount;
                    }

                    // Initializing library native data according to the new mipmap level
                    metadata.MipLevels = newMipMapCount;
                    dxtImages          = new DxtImage[metadata.ArraySize * newMipMapCount];

                    // Assigning the right sub images for the texture to be exported (no need for memory to be adjacent)
                    int gap = libraryData.Metadata.MipLevels - newMipMapCount;
                    int j   = 0;
                    for (int i = 0; i < dxtImages.Length; ++i)
                    {
                        if (i == newMipMapCount || (i > newMipMapCount && i % newMipMapCount == 0))
                        {
                            j += gap;
                        }
                        dxtImages[i] = libraryData.DxtImages[j];
                        ++j;
                    }
                }

                HRESULT hr = Utilities.SaveToDDSFile(dxtImages, dxtImages.Length, ref metadata, DDS_FLAGS.DDS_FLAGS_NONE, request.FilePath);

                if (hr != HRESULT.S_OK)
                {
                    Log.Error("Exporting texture failed: " + hr);
                    throw new TextureToolsException("Exporting texture failed: " + hr);
                }
            }
            else
            {
                HRESULT hr = Utilities.SaveToDDSFile(libraryData.DxtImages, libraryData.DxtImages.Length, ref libraryData.Metadata, DDS_FLAGS.DDS_FLAGS_NONE, request.FilePath);

                if (hr != HRESULT.S_OK)
                {
                    Log.Error("Exporting texture failed: " + hr);
                    throw new TextureToolsException("Exporting texture failed: " + hr);
                }
            }

            image.Save(request.FilePath);
        }
Example #5
0
        /// <summary>
        /// Generates a DDS Header, and if requires, a DX10 Header
        /// </summary>
        /// <param name="metaData">Meta Data</param>
        /// <param name="flags">Flags</param>
        /// <param name="header">DDS Header Output</param>
        /// <param name="dx10Header">DX10 Header Output</param>
        public static void GenerateDDSHeader(TexMetadata metaData, DDSFlags flags, out DDSHeader header, out DX10Header dx10Header)
        {
            // Check array size
            if (metaData.ArraySize > 1)
            {
                // Check if we have an array and whether we're cube maps/non-2D
                if (metaData.ArraySize != 6 || metaData.Dimension != TexDimension.TEXTURE2D || !metaData.IsCubeMap())
                {
                    // Texture1D arrays, Texture2D arrays, and Cubemap arrays must be stored using 'DX10' extended header
                    flags |= DDSFlags.FORCEDX10EXT;
                }
            }

            // Check for DX10 Ext
            if (flags.HasFlag(DDSFlags.FORCEDX10EXTMISC2))
            {
                flags |= DDSFlags.FORCEDX10EXT;
            }
            // Create DDS Header
            header = new DDSHeader
            {
                // Set Data
                Size        = (uint)Marshal.SizeOf <DDSHeader>(),
                Flags       = DDSHeader.HeaderFlags.TEXTURE,
                Caps        = (uint)DDSHeader.SurfaceFlags.TEXTURE,
                PixelFormat = new DDSHeader.DDSPixelFormat(0, 0, 0, 0, 0, 0, 0, 0)
            };
            // Create DX10 Header
            dx10Header = new DX10Header();
            // Switch format
            switch (metaData.Format)
            {
            case DXGIFormat.R8G8B8A8UNORM:
                header.PixelFormat = PixelFormats.A8B8G8R8;
                break;

            case DXGIFormat.R16G16UNORM:
                header.PixelFormat = PixelFormats.G16R16;
                break;

            case DXGIFormat.R8G8UNORM:
                header.PixelFormat = PixelFormats.A8L8;
                break;

            case DXGIFormat.R16UNORM:
                header.PixelFormat = PixelFormats.L16;
                break;

            case DXGIFormat.R8UNORM:
                header.PixelFormat = PixelFormats.L8;
                break;

            case DXGIFormat.A8UNORM:
                header.PixelFormat = PixelFormats.A8;
                break;

            case DXGIFormat.R8G8B8G8UNORM:
                header.PixelFormat = PixelFormats.R8G8B8G8;
                break;

            case DXGIFormat.G8R8G8B8UNORM:
                header.PixelFormat = PixelFormats.G8R8G8B8;
                break;

            case DXGIFormat.BC1UNORM:
                header.PixelFormat = PixelFormats.DXT1;
                break;

            case DXGIFormat.BC2UNORM:
                header.PixelFormat = metaData.IsPMAlpha() ? (PixelFormats.DXT2) : (PixelFormats.DXT3);
                break;

            case DXGIFormat.BC3UNORM:
                header.PixelFormat = metaData.IsPMAlpha() ? (PixelFormats.DXT4) : (PixelFormats.DXT5);
                break;

            case DXGIFormat.BC4UNORM:
                header.PixelFormat = PixelFormats.BC4UNORM;
                break;

            case DXGIFormat.BC4SNORM:
                header.PixelFormat = PixelFormats.BC4SNORM;
                break;

            case DXGIFormat.BC5UNORM:
                header.PixelFormat = PixelFormats.BC5UNORM;
                break;

            case DXGIFormat.BC5SNORM:
                header.PixelFormat = PixelFormats.BC5SNORM;
                break;

            case DXGIFormat.B5G6R5UNORM:
                header.PixelFormat = PixelFormats.R5G6B5;
                break;

            case DXGIFormat.B5G5R5A1UNORM:
                header.PixelFormat = PixelFormats.A1R5G5B5;
                break;

            case DXGIFormat.R8G8SNORM:
                header.PixelFormat = PixelFormats.V8U8;
                break;

            case DXGIFormat.R8G8B8A8SNORM:
                header.PixelFormat = PixelFormats.Q8W8V8U8;
                break;

            case DXGIFormat.R16G16SNORM:
                header.PixelFormat = PixelFormats.V16U16;
                break;

            case DXGIFormat.B8G8R8A8UNORM:
                header.PixelFormat = PixelFormats.A8R8G8B8;
                break;

            case DXGIFormat.B8G8R8X8UNORM:
                header.PixelFormat = PixelFormats.X8R8G8B8;
                break;

            case DXGIFormat.B4G4R4A4UNORM:
                header.PixelFormat = PixelFormats.A4R4G4B4;
                break;

            case DXGIFormat.YUY2:
                header.PixelFormat = PixelFormats.YUY2;
                break;

            // Legacy D3DX formats using D3DFMT enum value as FourCC
            case DXGIFormat.R32G32B32A32FLOAT:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 116;                          // D3DFMTA32B32G32R32F
                break;

            case DXGIFormat.R16G16B16A16FLOAT:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 113;                          // D3DFMTA16B16G16R16F
                break;

            case DXGIFormat.R16G16B16A16UNORM:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 36;                          // D3DFMTA16B16G16R16
                break;

            case DXGIFormat.R16G16B16A16SNORM:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 110;                          // D3DFMTQ16W16V16U16
                break;

            case DXGIFormat.R32G32FLOAT:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 115;                          // D3DFMTG32R32F
                break;

            case DXGIFormat.R16G16FLOAT:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 112;                          // D3DFMTG16R16F
                break;

            case DXGIFormat.R32FLOAT:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 114;                          // D3DFMTR32F
                break;

            case DXGIFormat.R16FLOAT:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 111;                          // D3DFMTR16F
                break;

            default:
                break;
            }
            // Check for mips
            if (metaData.MipLevels > 0)
            {
                // Set flag
                header.Flags |= DDSHeader.HeaderFlags.MIPMAP;
                // Check size
                if (metaData.MipLevels > UInt16.MaxValue)
                {
                    throw new ArgumentException(String.Format("Too many mipmaps: {0}. Max: {1}", metaData.MipLevels, UInt16.MaxValue));
                }
                // Set
                header.MipMapCount = (uint)metaData.MipLevels;
                // Check count
                if (header.MipMapCount > 1)
                {
                    header.Caps |= (uint)DDSHeader.SurfaceFlags.MIPMAP;
                }
            }

            // Switch Dimension
            switch (metaData.Dimension)
            {
            case TexDimension.TEXTURE1D:
            {
                // Check size
                if (metaData.Width > Int32.MaxValue)
                {
                    throw new ArgumentException(String.Format("Image Width too large: {0}. Max: {1}", metaData.Width, Int32.MaxValue));
                }
                // Set
                header.Width  = (uint)metaData.Width;
                header.Height = header.Depth = 1;
                // Check size
                break;
            }

            case TexDimension.TEXTURE2D:
            {
                // Check size
                if (metaData.Width > Int32.MaxValue || metaData.Height > Int32.MaxValue)
                {
                    throw new ArgumentException(String.Format("Image Width and/or Height too large: {0}x{1}. Max: {2}",
                                                              metaData.Width,
                                                              metaData.Height,
                                                              Int32.MaxValue));
                }
                // Set
                header.Width  = (uint)metaData.Width;
                header.Height = (uint)metaData.Height;
                header.Depth  = 1;
                // Check size
                break;
            }

            case TexDimension.TEXTURE3D:
            {
                // Check size
                if (metaData.Width > Int32.MaxValue || metaData.Height > Int32.MaxValue)
                {
                    throw new ArgumentException(String.Format("Image Width and/or Height too large: {0}x{1}. Max: {2}",
                                                              metaData.Width,
                                                              metaData.Height,
                                                              Int32.MaxValue));
                }
                // Check size
                if (metaData.Depth > UInt16.MaxValue)
                {
                    throw new ArgumentException(String.Format("Image Depth too large: {0}. Max: {1}", metaData.Depth, UInt16.MaxValue));
                }
                // Set
                header.Flags |= DDSHeader.HeaderFlags.VOLUME;
                header.Caps2 |= 0x00200000;
                header.Width  = (uint)metaData.Width;
                header.Height = (uint)metaData.Height;
                header.Depth  = (uint)metaData.Depth;
                // Check size
                break;
            }

            default:
                throw new ArgumentException("Invalid Texture Dimension.");
            }
            // Calculate the Pitch
            ComputePitch(metaData.Format, metaData.Width, metaData.Height, out long rowPitch, out long slicePitch, CPFLAGS.NONE);
            // Validate results
            if (slicePitch > UInt32.MaxValue || rowPitch > UInt32.MaxValue)
            {
                throw new ArgumentException("Failed to calculate row and/or slice pitch, values returned were too large");
            }
            // Check is it compressed
            if (IsCompressed(metaData.Format))
            {
                header.Flags            |= DDSHeader.HeaderFlags.LINEARSIZE;
                header.PitchOrLinearSize = (uint)slicePitch;
            }
            else
            {
                header.Flags            |= DDSHeader.HeaderFlags.PITCH;
                header.PitchOrLinearSize = (uint)rowPitch;
            }

            // Check for do we need to create the DX10 Header
            if (header.PixelFormat.Size == 0)
            {
                // Check size
                if (metaData.ArraySize > UInt16.MaxValue)
                {
                    throw new ArgumentException(String.Format("Array Size too large: {0}. Max: {1}", metaData.ArraySize, UInt16.MaxValue));
                }
                // Set Pixel format
                header.PixelFormat = PixelFormats.DX10;
                // Set Data
                dx10Header.Format            = metaData.Format;
                dx10Header.ResourceDimension = metaData.Dimension;
                dx10Header.MiscFlag          = metaData.MiscFlags & ~TexMiscFlags.TEXTURECUBE;
                dx10Header.ArraySize         = (uint)metaData.ArraySize;
                // Check for Cube Maps
                if (metaData.MiscFlags.HasFlag(TexMiscFlags.TEXTURECUBE))
                {
                    // Check array size, must be a multiple of 6 for cube maps
                    if ((metaData.ArraySize % 6) != 0)
                    {
                        throw new ArgumentException("Array size must be a multiple of 6");
                    }
                    // Set Flag
                    dx10Header.MiscFlag  |= TexMiscFlags.TEXTURECUBE;
                    dx10Header.ArraySize /= 6;
                }
                // Check for mist flags
                if (flags.HasFlag(DDSFlags.FORCEDX10EXTMISC2))
                {
                    // This was formerly 'reserved'. D3DX10 and D3DX11 will fail if this value is anything other than 0
                    dx10Header.MiscFlags2 = (uint)metaData.MiscFlags2;
                }
            }
        }
Example #6
0
        public static ScratchImage LoadFromFile(string pathToFile, List <OPTION> options)
        {
            FileInfo fInfo = new FileInfo(pathToFile);

            if (!fInfo.Exists)
            {
                return(null);
            }
            ulong              width                    = 0;
            ulong              height                   = 0;
            ulong              mipLevels                = 0;
            DXGI_FORMAT        format                   = DXGI_FORMAT.DXGI_FORMAT_UNKNOWN;
            TEX_FILTER_FLAGS   dwFilter                 = TEX_FILTER_FLAGS.TEX_FILTER_DEFAULT;
            TEX_FILTER_FLAGS   dwSRGB                   = TEX_FILTER_FLAGS.TEX_FILTER_DEFAULT;
            TEX_FILTER_FLAGS   dwConvert                = TEX_FILTER_FLAGS.TEX_FILTER_DEFAULT;
            TEX_COMPRESS_FLAGS dwCompress               = TEX_COMPRESS_FLAGS.TEX_COMPRESS_DEFAULT;
            TEX_FILTER_FLAGS   dwFilterOpts             = TEX_FILTER_FLAGS.TEX_FILTER_DEFAULT;
            ulong              fileType                 = CODEC_DDS;
            float              alphaThreshold           = TEX_THRESHOLD_DEFAULT;
            float              alphaWeight              = 1.0f;
            CNMAP_FLAGS        dwNormalMap              = CNMAP_FLAGS.CNMAP_DEFAULT;
            float              nmapAmplitude            = 1.0f;
            float              wicQuality               = -1.0f;
            ulong              colorKey                 = 0;
            ulong              dwRotateColor            = 0;
            float              paperWhiteNits           = 200.0f;
            float              preserveAlphaCoverageRef = 0.0f;

            uint[] swizzleElements = { 0, 1, 2, 3 };

            ulong dwOptions = 0;

            foreach (OPTION opt in options)
            {
                switch (opt.option)
                {
                case OPTIONS.OPT_WIDTH:
                {
                    if (!ulong.TryParse(opt.value, out width))
                    {
                        return(null);
                    }
                }
                break;

                case OPTIONS.OPT_HEIGHT:
                {
                    if (!ulong.TryParse(opt.value, out height))
                    {
                        return(null);
                    }
                }
                break;

                case OPTIONS.OPT_MIPLEVELS:
                {
                    if (!ulong.TryParse(opt.value, out mipLevels))
                    {
                        return(null);
                    }
                }
                break;

                case OPTIONS.OPT_FORMAT:
                {
                    format = (DXGI_FORMAT)LookupByName(opt.value, pFormats);
                    if (format == DXGI_FORMAT.DXGI_FORMAT_UNKNOWN)
                    {
                        format = (DXGI_FORMAT)LookupByName(opt.value, pFormatAliases);
                        if (format == DXGI_FORMAT.DXGI_FORMAT_UNKNOWN)
                        {
                            return(null);
                        }
                    }
                }
                break;

                case OPTIONS.OPT_FILTER:
                {
                    dwFilter = (TEX_FILTER_FLAGS)LookupByName(opt.value, pFilters);
                    if (dwFilter == TEX_FILTER_FLAGS.TEX_FILTER_DEFAULT)
                    {
                        return(null);
                    }
                }
                break;

                case OPTIONS.OPT_ROTATE_COLOR:
                {
                    dwRotateColor = LookupByName(opt.value, pRotateColor);
                    if (dwRotateColor == 0)
                    {
                        return(null);
                    }
                }
                break;

                case OPTIONS.OPT_SRGBI:
                    dwSRGB |= TEX_FILTER_FLAGS.TEX_FILTER_SRGB_IN;
                    break;

                case OPTIONS.OPT_SRGBO:
                    dwSRGB |= TEX_FILTER_FLAGS.TEX_FILTER_SRGB_OUT;
                    break;

                case OPTIONS.OPT_SRGB:
                    dwSRGB |= TEX_FILTER_FLAGS.TEX_FILTER_SRGB;
                    break;

                case OPTIONS.OPT_SEPALPHA:
                    dwFilterOpts |= TEX_FILTER_FLAGS.TEX_FILTER_SEPARATE_ALPHA;
                    break;

                case OPTIONS.OPT_NO_WIC:
                    dwFilterOpts |= TEX_FILTER_FLAGS.TEX_FILTER_FORCE_NON_WIC;
                    break;

                //case OPTIONS.OPT_FILETYPE:
                //    {
                //        fileType = LookupByName(opt.value, pSaveFileTypes);
                //        if (fileType == 0)
                //            return null;
                //    }
                //    break;
                case OPTIONS.OPT_PREMUL_ALPHA:
                {
                    if (TexUtils.HasFlag(dwOptions, 1UL << (int)OPTIONS.OPT_DEMUL_ALPHA))
                    {
                        return(null);
                    }
                    //dwOptions |= (1UL << (int)OPTIONS.OPT_PREMUL_ALPHA);
                }
                break;

                case OPTIONS.OPT_DEMUL_ALPHA:
                {
                    if (TexUtils.HasFlag(dwOptions, 1UL << (int)OPTIONS.OPT_PREMUL_ALPHA))
                    {
                        return(null);
                    }
                    //dwOptions |= (1UL << (int)OPTIONS.OPT_DEMUL_ALPHA);
                }
                break;

                case OPTIONS.OPT_TA_WRAP:
                {
                    if (TexUtils.HasFlag(dwFilterOpts, TEX_FILTER_FLAGS.TEX_FILTER_MIRROR))
                    {
                        return(null);
                    }
                    dwFilterOpts |= TEX_FILTER_FLAGS.TEX_FILTER_WRAP;
                }
                break;

                case OPTIONS.OPT_TA_MIRROR:
                {
                    if (TexUtils.HasFlag(dwFilterOpts, TEX_FILTER_FLAGS.TEX_FILTER_WRAP))
                    {
                        return(null);
                    }
                    dwFilterOpts |= TEX_FILTER_FLAGS.TEX_FILTER_MIRROR;
                }
                break;

                case OPTIONS.OPT_NORMAL_MAP:
                {
                    dwNormalMap = CNMAP_FLAGS.CNMAP_DEFAULT;

                    if (opt.value.Contains('l'))
                    {
                        dwNormalMap |= CNMAP_FLAGS.CNMAP_CHANNEL_LUMINANCE;
                    }
                    else if (opt.value.Contains('r'))
                    {
                        dwNormalMap |= CNMAP_FLAGS.CNMAP_CHANNEL_RED;
                    }
                    else if (opt.value.Contains('g'))
                    {
                        dwNormalMap |= CNMAP_FLAGS.CNMAP_CHANNEL_GREEN;
                    }
                    else if (opt.value.Contains('b'))
                    {
                        dwNormalMap |= CNMAP_FLAGS.CNMAP_CHANNEL_BLUE;
                    }
                    else if (opt.value.Contains('a'))
                    {
                        dwNormalMap |= CNMAP_FLAGS.CNMAP_CHANNEL_ALPHA;
                    }
                    else
                    {
                        return(null);
                    }

                    if (opt.value.Contains('m'))
                    {
                        dwNormalMap |= CNMAP_FLAGS.CNMAP_MIRROR;
                    }
                    else
                    {
                        if (opt.value.Contains('u'))
                        {
                            dwNormalMap |= CNMAP_FLAGS.CNMAP_MIRROR_U;
                        }
                        if (opt.value.Contains('v'))
                        {
                            dwNormalMap |= CNMAP_FLAGS.CNMAP_MIRROR_V;
                        }
                    }

                    if (opt.value.Contains('i'))
                    {
                        dwNormalMap |= CNMAP_FLAGS.CNMAP_INVERT_SIGN;
                    }
                    if (opt.value.Contains('o'))
                    {
                        dwNormalMap |= CNMAP_FLAGS.CNMAP_COMPUTE_OCCLUSION;
                    }
                }
                break;

                case OPTIONS.OPT_NORMAL_MAP_AMPLITUDE:
                {
                    if (dwNormalMap == 0)
                    {
                        return(null);
                    }
                    else if (!float.TryParse(opt.value, out nmapAmplitude))
                    {
                        return(null);
                    }
                    else if (nmapAmplitude < 0.0f)
                    {
                        return(null);
                    }
                }
                break;

                case OPTIONS.OPT_ALPHA_THRESHOLD:
                {
                    if (!float.TryParse(opt.value, out alphaThreshold))
                    {
                        return(null);
                    }
                    else if (alphaThreshold < 0.0f)
                    {
                        return(null);
                    }
                }
                break;

                case OPTIONS.OPT_ALPHA_WEIGHT:
                {
                    if (!float.TryParse(opt.value, out alphaWeight))
                    {
                        return(null);
                    }
                    else if (alphaWeight < 0.0f)
                    {
                        return(null);
                    }
                }
                break;

                case OPTIONS.OPT_BC_COMPRESS:
                {
                    dwCompress = TEX_COMPRESS_FLAGS.TEX_COMPRESS_DEFAULT;

                    bool found = false;
                    if (opt.value.Contains('u'))
                    {
                        dwCompress |= TEX_COMPRESS_FLAGS.TEX_COMPRESS_UNIFORM;
                        found       = true;
                    }
                    if (opt.value.Contains('d'))
                    {
                        dwCompress |= TEX_COMPRESS_FLAGS.TEX_COMPRESS_DITHER;
                        found       = true;
                    }
                    if (opt.value.Contains('q'))
                    {
                        dwCompress |= TEX_COMPRESS_FLAGS.TEX_COMPRESS_BC7_QUICK;
                        found       = true;
                    }
                    if (opt.value.Contains('x'))
                    {
                        dwCompress |= TEX_COMPRESS_FLAGS.TEX_COMPRESS_BC7_USE_3SUBSETS;
                        found       = true;
                    }

                    if (TexUtils.HasFlag(dwCompress, TEX_COMPRESS_FLAGS.TEX_COMPRESS_BC7_USE_3SUBSETS | TEX_COMPRESS_FLAGS.TEX_COMPRESS_BC7_QUICK))
                    {
                        return(null);
                    }

                    if (!found)
                    {
                        return(null);
                    }
                }
                break;

                case OPTIONS.OPT_WIC_QUALITY:
                {
                    if (!float.TryParse(opt.value, out wicQuality))
                    {
                        return(null);
                    }
                    else if (wicQuality < 0.0f || wicQuality > 1.0f)
                    {
                        return(null);
                    }
                }
                break;

                case OPTIONS.OPT_COLORKEY:
                {
                    if (!ulong.TryParse(opt.value, out colorKey))
                    {
                        if (!ulong.TryParse(opt.value, System.Globalization.NumberStyles.HexNumber, null, out colorKey))
                        {
                            return(null);
                        }
                    }
                    colorKey &= 0xFFFFFF;
                }
                break;

                case OPTIONS.OPT_X2_BIAS:
                    dwConvert |= TEX_FILTER_FLAGS.TEX_FILTER_FLOAT_X2BIAS;
                    break;

                case OPTIONS.OPT_PAPER_WHITE_NITS:
                {
                    if (!float.TryParse(opt.value, out paperWhiteNits))
                    {
                        return(null);
                    }
                    else if (paperWhiteNits > 10000.0f || paperWhiteNits <= 0.0f)
                    {
                        return(null);
                    }
                }
                break;

                case OPTIONS.OPT_PRESERVE_ALPHA_COVERAGE:
                {
                    if (float.TryParse(opt.value, out preserveAlphaCoverageRef))
                    {
                        return(null);
                    }
                    else if (preserveAlphaCoverageRef < 0.0f || preserveAlphaCoverageRef > 1.0f)
                    {
                        return(null);
                    }
                }
                break;

                case OPTIONS.OPT_SWIZZLE:
                {
                    if (opt.value == null || opt.value.Length > 4)
                    {
                        return(null);
                    }
                    else if (!ParseSwizzleMask(opt.value, out swizzleElements))
                    {
                        return(null);
                    }
                }
                break;
                }
            }

            var fileTypeName = LookupByValue(fileType, pSaveFileTypes);

            if (fileType != CODEC_DDS)
            {
                mipLevels = 1;
            }

            var ext = Path.GetExtension(fInfo.FullName).ToLower();

            TexMetadata  info = new TexMetadata();
            ScratchImage image;

            if (ext == ".dds")
            {
                DDS_FLAGS ddsFlags = DDS_FLAGS.DDS_FLAGS_ALLOW_LARGE_FILES;
                if (TexUtils.HasFlag(dwOptions, 1U << (int)OPTIONS.OPT_DDS_DWORD_ALIGN))
                {
                    ddsFlags |= DDS_FLAGS.DDS_FLAGS_LEGACY_DWORD;
                }
                if (TexUtils.HasFlag(dwOptions, 1U << (int)OPTIONS.OPT_EXPAND_LUMINANCE))
                {
                    ddsFlags |= DDS_FLAGS.DDS_FLAGS_EXPAND_LUMINANCE;
                }
                if (TexUtils.HasFlag(dwOptions, 1U << (int)OPTIONS.OPT_DDS_BAD_DXTN_TAILS))
                {
                    ddsFlags |= DDS_FLAGS.DDS_FLAGS_BAD_DXTN_TAILS;
                }

                image = LoadFromDDSFile(pathToFile, ddsFlags, ref info);

                if (image == null)
                {
                    return(null);
                }

                if (IsTypeless(info.format))
                {
                    if (TexUtils.HasFlag(dwOptions, 1U << (int)OPTIONS.OPT_TYPELESS_UNORM))
                    {
                        info.format = MakeTypelessUNORM(info.format);
                    }
                    else if (TexUtils.HasFlag(dwOptions, 1U << (int)OPTIONS.OPT_TYPELESS_FLOAT))
                    {
                        info.format = MakeTypelessFLOAT(info.format);
                    }

                    if (IsTypeless(info.format))
                    {
                        return(null);
                    }

                    image.OverrideFormat(info.format);
                }
            }
            else if (ext == ".bmp")
            {
                image = LoadFromBMPEx(pathToFile, WIC_FLAGS.WIC_FLAGS_NONE | (WIC_FLAGS)dwFilter, ref info);

                if (image == null)
                {
                    return(null);
                }
            }
            else if (ext == ".tga")
            {
                image = LoadFromTGAFile(pathToFile, TGA_FLAGS.TGA_FLAGS_NONE, ref info);
                if (image == null)
                {
                    return(null);
                }
            }
            else if (ext == ".hdr")
            {
                image = LoadFromHDRFile(pathToFile, ref info);
                if (image == null)
                {
                    return(null);
                }
            }
            else if (ext == ".ppm")
            {
                image = LoadFromPortablePixMap(pathToFile, ref info);
                if (image == null)
                {
                    return(null);
                }
            }
            else if (ext == ".pfm")
            {
                image = LoadFromPortablePixMapHDR(pathToFile, ref info);
                if (image == null)
                {
                    return(null);
                }
            }
            else if (ext == ".exr")
            {
                image = LoadFromEXRFile(pathToFile, ref info);
                if (image == null)
                {
                    return(null);
                }
            }
            else
            {
                WIC_FLAGS wicFlags = WIC_FLAGS.WIC_FLAGS_NONE | (WIC_FLAGS)dwFilter;
                if (fileType == CODEC_DDS)
                {
                    wicFlags |= WIC_FLAGS.WIC_FLAGS_ALL_FRAMES;
                }

                image = LoadFromWICFile(pathToFile, ref info);
                if (image == null)
                {
                    return(null);
                }
            }

            return(null);
        }
Example #7
0
        public static unsafe byte[] ConvertDDS(Stream ddsSteam, DXGI_FORMAT targetFormat, ImageFormat imageFormat, int frame)
        {
            try {
                CoInitializeEx(IntPtr.Zero, CoInit.MultiThreaded | CoInit.SpeedOverMemory);

                byte[] data = new byte[ddsSteam.Length];
                ddsSteam.Read(data, 0, data.Length);
                ScratchImage scratch = null;
                try
                {
                    fixed(byte *dataPin = data)
                    {
                        scratch = TexHelper.Instance.LoadFromDDSMemory((IntPtr)dataPin, data.Length, DDS_FLAGS.NONE);
                        TexMetadata info = scratch.GetMetadata();

                        if (TexHelper.Instance.IsCompressed(info.Format))
                        {
                            ScratchImage temp = scratch.Decompress(frame, DXGI_FORMAT.UNKNOWN);
                            scratch.Dispose();
                            scratch = temp;
                        }

                        info = scratch.GetMetadata();

                        if (info.Format != targetFormat)
                        {
                            ScratchImage temp = scratch.Convert(targetFormat, TEX_FILTER_FLAGS.DEFAULT, 0.5f);
                            scratch.Dispose();
                            scratch = temp;
                        }

                        UnmanagedMemoryStream stream = null;

                        if (imageFormat == ImageFormat.TGA)
                        {
                            stream = scratch.SaveToTGAMemory(frame < 0 ? 0 : frame);
                        }
                        else
                        {
                            WICCodecs codec        = WICCodecs.PNG;
                            bool      isMultiFrame = false;
                            switch (imageFormat)
                            {
                            case ImageFormat.BMP:
                                codec = WICCodecs.BMP;
                                break;

                            case ImageFormat.GIF:
                                codec        = WICCodecs.GIF;
                                isMultiFrame = true;
                                break;

                            case ImageFormat.JPEG:
                                codec = WICCodecs.JPEG;
                                break;

                            case ImageFormat.PNG:
                                codec = WICCodecs.PNG;
                                break;

                            case ImageFormat.TIF:
                                codec        = WICCodecs.TIFF;
                                isMultiFrame = true;
                                break;

                            case ImageFormat.TGA:
                                break;

                            default:
                                throw new ArgumentOutOfRangeException(nameof(imageFormat), imageFormat, null);
                            }

                            if (frame < 0)
                            {
                                if (!isMultiFrame)
                                {
                                    frame = 0;
                                }
                                else
                                {
                                    stream = scratch.SaveToWICMemory(0, info.ArraySize, WIC_FLAGS.ALL_FRAMES, TexHelper.Instance.GetWICCodec(codec));
                                }
                            }

                            if (frame >= 0)
                            {
                                stream = scratch.SaveToWICMemory(frame, WIC_FLAGS.NONE, TexHelper.Instance.GetWICCodec(codec));
                            }
                        }

                        if (stream == null)
                        {
                            return(null);
                        }

                        byte[] tex = new byte[stream.Length];
                        stream.Read(tex, 0, tex.Length);
                        scratch.Dispose();
                        return(tex);
                    }
                } catch {
                    if (scratch != null && scratch.IsDisposed == false)
                    {
                        scratch.Dispose();
                    }
                }
            } catch {
                // ignored
            }

            return(null);
        }
Example #8
0
 public static ScratchImage LoadFromWICFile(string path, ref TexMetadata info)
 {
     return(null);
 }
Example #9
0
 public static ScratchImage LoadFromPortablePixMapHDR(string path, ref TexMetadata info)
 {
     return(null);
 }
Example #10
0
 public static ScratchImage LoadFromTGAFile(string path, TGA_FLAGS flags, ref TexMetadata info)
 {
     return(null);
 }
Example #11
0
 public static ScratchImage LoadFromBMPEx(string path, WIC_FLAGS flags, ref TexMetadata info)
 {
     return(null);
 }