public TexMetadataView(TexMetadata metadata) { _metadata = metadata; }
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); }
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); }
/// <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); }
/// <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; } } }
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); }
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); }
public static ScratchImage LoadFromWICFile(string path, ref TexMetadata info) { return(null); }
public static ScratchImage LoadFromPortablePixMapHDR(string path, ref TexMetadata info) { return(null); }
public static ScratchImage LoadFromTGAFile(string path, TGA_FLAGS flags, ref TexMetadata info) { return(null); }
public static ScratchImage LoadFromBMPEx(string path, WIC_FLAGS flags, ref TexMetadata info) { return(null); }