public static unsafe byte[] Convert(Byte[] data, int width, int height, DXGI_FORMAT inputFormat, DXGI_FORMAT outputFormat) { long inputRowPitch; long inputSlicePitch; TexHelper.Instance.ComputePitch(inputFormat, width, height, out inputRowPitch, out inputSlicePitch, CP_FLAGS.NONE); 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, inputFormat, inputRowPitch, inputSlicePitch, (IntPtr)buf, null); TexMetadata texMetadata = new TexMetadata(width, height, 1, 1, 1, 0, 0, inputFormat, TEX_DIMENSION.TEXTURE2D); ScratchImage scratchImage = TexHelper.Instance.InitializeTemporary( new DirectXTexNet.Image[] { inputImage }, texMetadata, null); var convFlags = TEX_FILTER_FLAGS.DEFAULT; if (inputFormat == DXGI_FORMAT.B8G8R8A8_UNORM_SRGB || inputFormat == DXGI_FORMAT.B8G8R8X8_UNORM_SRGB || inputFormat == DXGI_FORMAT.R8G8B8A8_UNORM_SRGB) { convFlags |= TEX_FILTER_FLAGS.SRGB; } using (var decomp = scratchImage.Convert(0, outputFormat, convFlags, 0.5f)) { long outRowPitch; long outSlicePitch; TexHelper.Instance.ComputePitch(outputFormat, width, height, out outRowPitch, out outSlicePitch, CP_FLAGS.NONE); byte[] result = new byte[outSlicePitch]; Marshal.Copy(decomp.GetImage(0).Pixels, result, 0, result.Length); inputImage = null; scratchImage.Dispose(); return(result); } } return(null); }
private void Decompress(ref ScratchImage scratch) { var meta = scratch.GetMetadata(); ScratchImage decompressed; switch (meta.Format) { case DXGI_FORMAT.BC1_TYPELESS: case DXGI_FORMAT.BC1_UNORM: case DXGI_FORMAT.BC1_UNORM_SRGB: case DXGI_FORMAT.BC2_TYPELESS: case DXGI_FORMAT.BC2_UNORM: case DXGI_FORMAT.BC2_UNORM_SRGB: case DXGI_FORMAT.BC3_TYPELESS: case DXGI_FORMAT.BC3_UNORM: case DXGI_FORMAT.BC3_UNORM_SRGB: case DXGI_FORMAT.BC4_TYPELESS: case DXGI_FORMAT.BC4_UNORM: case DXGI_FORMAT.BC4_SNORM: case DXGI_FORMAT.BC5_TYPELESS: case DXGI_FORMAT.BC5_UNORM: case DXGI_FORMAT.BC5_SNORM: case DXGI_FORMAT.BC6H_TYPELESS: case DXGI_FORMAT.BC6H_UF16: case DXGI_FORMAT.BC6H_SF16: case DXGI_FORMAT.BC7_TYPELESS: case DXGI_FORMAT.BC7_UNORM: case DXGI_FORMAT.BC7_UNORM_SRGB: decompressed = scratch.Decompress(DXGI_FORMAT.B8G8R8A8_UNORM); break; default: decompressed = scratch.Convert(DXGI_FORMAT.B8G8R8A8_UNORM, TEX_FILTER_FLAGS.FANT, 0.5f); break; } scratch.Dispose(); scratch = decompressed; }
/// <summary> /// Matches a given DDS file on the disk to a D3DTX object. /// </summary> /// <param name="ddsPath"></param> /// <param name="d3dtx"></param> /// <param name="options"></param> public void Match_DDS_With_D3DTX(string ddsPath, D3DTX_Master d3dtx, DDS_Matching_Options options) { //load in the DDS image using DirectXTexNet ScratchImage scratchImage = TexHelper.Instance.LoadFromDDSFile(ddsPath, DDS_FLAGS.NONE); //create our main variables that will be used when doing conversion operations int d3dtx_width = 0; int d3dtx_height = 0; int d3dtx_mipAmount = 0; T3SurfaceFormat d3dtx_format = T3SurfaceFormat.eSurface_DXT1; T3SurfaceGamma d3dtx_gamma = T3SurfaceGamma.eSurfaceGamma_sRGB; //assign the values depending on which version is active if (d3dtx.d3dtx9 != null) { d3dtx_width = (int)d3dtx.d3dtx9.mWidth; d3dtx_height = (int)d3dtx.d3dtx9.mHeight; d3dtx_mipAmount = (int)d3dtx.d3dtx9.mNumMipLevels; d3dtx_format = d3dtx.d3dtx9.mSurfaceFormat; d3dtx_gamma = d3dtx.d3dtx9.mSurfaceGamma; } else if (d3dtx.d3dtx8 != null) { d3dtx_width = (int)d3dtx.d3dtx8.mWidth; d3dtx_height = (int)d3dtx.d3dtx8.mHeight; d3dtx_mipAmount = (int)d3dtx.d3dtx8.mNumMipLevels; d3dtx_format = d3dtx.d3dtx8.mSurfaceFormat; d3dtx_gamma = d3dtx.d3dtx8.mSurfaceGamma; } else if (d3dtx.d3dtx7 != null) { d3dtx_width = (int)d3dtx.d3dtx7.mWidth; d3dtx_height = (int)d3dtx.d3dtx7.mHeight; d3dtx_mipAmount = (int)d3dtx.d3dtx7.mNumMipLevels; d3dtx_format = d3dtx.d3dtx7.mSurfaceFormat; d3dtx_gamma = d3dtx.d3dtx7.mSurfaceGamma; } else if (d3dtx.d3dtx6 != null) { d3dtx_width = (int)d3dtx.d3dtx6.mWidth; d3dtx_height = (int)d3dtx.d3dtx6.mHeight; d3dtx_mipAmount = (int)d3dtx.d3dtx6.mNumMipLevels; d3dtx_format = d3dtx.d3dtx6.mSurfaceFormat; d3dtx_gamma = T3SurfaceGamma.eSurfaceGamma_sRGB; //this version doesn't have a surface gamma field, so give it an SRGB by default } else if (d3dtx.d3dtx5 != null) { d3dtx_width = (int)d3dtx.d3dtx5.mWidth; d3dtx_height = (int)d3dtx.d3dtx5.mHeight; d3dtx_mipAmount = (int)d3dtx.d3dtx5.mNumMipLevels; d3dtx_format = d3dtx.d3dtx5.mSurfaceFormat; d3dtx_gamma = T3SurfaceGamma.eSurfaceGamma_sRGB; //this version doesn't have a surface gamma field, so give it an SRGB by default } else if (d3dtx.d3dtx4 != null) { d3dtx_width = (int)d3dtx.d3dtx4.mWidth; d3dtx_height = (int)d3dtx.d3dtx4.mHeight; d3dtx_mipAmount = (int)d3dtx.d3dtx4.mNumMipLevels; d3dtx_format = d3dtx.d3dtx4.mSurfaceFormat; d3dtx_gamma = T3SurfaceGamma.eSurfaceGamma_sRGB; //this version doesn't have a surface gamma field, so give it an SRGB by default } //-------------------------------------- CONVERSION START -------------------------------------- //change the compression if needed if (options.MatchCompression) { DXGI_FORMAT dxgi_format = DDS_Functions.GetSurfaceFormatAsDXGI(d3dtx_format, d3dtx_gamma); scratchImage.Convert(dxgi_format, TEX_FILTER_FLAGS.DITHER, 0.0f); } //rescale the image to match if needed if (options.MatchResolution) { scratchImage.Resize(d3dtx_width, d3dtx_height, TEX_FILTER_FLAGS.CUBIC); } //generate mip maps if needed if (options.GenerateMipMaps) { if (options.MatchMipMapCount) { scratchImage.GenerateMipMaps(0, TEX_FILTER_FLAGS.CUBIC, d3dtx_mipAmount, false); } else { scratchImage.GenerateMipMaps(0, TEX_FILTER_FLAGS.CUBIC, 0, false); } } //resave the newly modified DDS scratchImage.SaveToDDSFile(DDS_FLAGS.NONE, ddsPath); }
public static unsafe byte[] ConvertDDS(Stream ddsSteam, DXGI_FORMAT targetFormat, WICCodecs codec, 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(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; var isMultiFrame = codec == WICCodecs.GIF || codec == WICCodecs.TIFF; if (info.ArraySize == 1 || !isMultiFrame) { stream = scratch.SaveToWICMemory(frame, WIC_FLAGS.NONE, TexHelper.Instance.GetWICCodec(codec)); } else { stream = scratch.SaveToWICMemory(0, info.ArraySize, WIC_FLAGS.ALL_FRAMES, 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 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); }
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); }