/// <summary> /// decode to image as an asynchronous operation. /// </summary> /// <param name="file">The file.</param> /// <returns>Image<Rgba32>[].</returns> public async Task <Image <Rgba32> > DecodeToImageAsync(DdsFile file) { Image <Rgba32> image = null; var decoder = new BcDecoder(); if (file.Faces.Count == 6) { // Cubemap var right = ColorMemoryToImage(await decoder.DecodeRaw2DAsync(file.Faces[0].MipMaps[0].Data, Convert.ToInt32(file.Faces[0].Width), Convert.ToInt32(file.Faces[0].Height), GetCompressionFormat(file, decoder.InputOptions))); var left = ColorMemoryToImage(await decoder.DecodeRaw2DAsync(file.Faces[1].MipMaps[0].Data, Convert.ToInt32(file.Faces[1].Width), Convert.ToInt32(file.Faces[1].Height), GetCompressionFormat(file, decoder.InputOptions))); var top = ColorMemoryToImage(await decoder.DecodeRaw2DAsync(file.Faces[2].MipMaps[0].Data, Convert.ToInt32(file.Faces[2].Width), Convert.ToInt32(file.Faces[2].Height), GetCompressionFormat(file, decoder.InputOptions))); var bottom = ColorMemoryToImage(await decoder.DecodeRaw2DAsync(file.Faces[3].MipMaps[0].Data, Convert.ToInt32(file.Faces[3].Width), Convert.ToInt32(file.Faces[3].Height), GetCompressionFormat(file, decoder.InputOptions))); var front = ColorMemoryToImage(await decoder.DecodeRaw2DAsync(file.Faces[4].MipMaps[0].Data, Convert.ToInt32(file.Faces[4].Width), Convert.ToInt32(file.Faces[4].Height), GetCompressionFormat(file, decoder.InputOptions))); var back = ColorMemoryToImage(await decoder.DecodeRaw2DAsync(file.Faces[5].MipMaps[0].Data, Convert.ToInt32(file.Faces[5].Width), Convert.ToInt32(file.Faces[5].Height), GetCompressionFormat(file, decoder.InputOptions))); var width = left.Width + front.Width + right.Width + back.Width; var height = top.Height + front.Height + bottom.Height; image = new Image <Rgba32>(width, height); image.Mutate(i => { i.DrawImage(top, new Point(left.Width, 0), 1f); i.DrawImage(left, new Point(0, top.Height), 1f); i.DrawImage(front, new Point(left.Width, top.Height), 1f); i.DrawImage(right, new Point(left.Width + front.Width, top.Height), 1f); i.DrawImage(back, new Point(left.Width + front.Width + right.Width, top.Height), 1f); i.DrawImage(bottom, new Point(left.Width, top.Height + front.Height), 1f); }); } else { var bcnImage = await decoder.Decode2DAsync(file); image = ColorMemoryToImage(bcnImage); } return(image); }
public void GetPreview() { var ddsReadSuccess = false; try { Preview = null; BCnEncoder.Shared.ImageFiles.DdsFile bcDds; using (var ms = new MemoryStream()) { var dds = Texture.ToDdsFile(false); dds.Write(ms, -1); ddsReadSuccess = true; ms.Seek(0, SeekOrigin.Begin); bcDds = BCnEncoder.Shared.ImageFiles.DdsFile.Load(ms); } var width = (int)bcDds.header.dwWidth; var height = (int)bcDds.header.dwHeight; var decoder = new BcDecoder(); if (decoder.IsHdrFormat(bcDds)) { var pixels = new byte[width * height * 3]; var pixelsSpan = MemoryMarshal.Cast <byte, Bgr24>(pixels); decoder.DecodeDdsToPixels(bcDds, pixelsSpan); var bmSource = BitmapSource.Create(width, height, 96.0, 96.0, PixelFormats.Bgr24, null, pixels, width * 3); Preview = bmSource; } else { var pixels = new byte[width * height * 4]; var pixelsSpan = MemoryMarshal.Cast <byte, Bgra32>(pixels); decoder.DecodeDdsToPixels(bcDds, pixelsSpan); var bmSource = BitmapSource.Create(width, height, 96.0, 96.0, PixelFormats.Bgra32, null, pixels, width * 4); Preview = bmSource; } PreviewErrorVisibility = Visibility.Collapsed; OnPropertyChanged(nameof(Width)); OnPropertyChanged(nameof(Height)); OnPropertyChanged(nameof(TextureInfo)); } catch (Exception ex) { Preview = null; if (ddsReadSuccess) { PreviewError = "Could not create preview! Export/Import may still work." + Environment.NewLine + Environment.NewLine + ex.Message; } else { PreviewError = "Could not create preview! Failed to convert pssg texture to dds." + Environment.NewLine + Environment.NewLine + ex.Message; } PreviewErrorVisibility = Visibility.Visible; } }
public void GetPreview() { Image <Rgba32> image = null; bool ddsReadSuccess = false; try { Preview = null; // Write and decode dds using (var ms = new MemoryStream()) { var dds = Texture.ToDdsFile(false); dds.Write(ms, -1); ddsReadSuccess = true; ms.Seek(0, SeekOrigin.Begin); var decoder = new BcDecoder(); image = decoder.DecodeToImageRgba32(ms); } // Copy pixels to WPF format var pixels = new byte[image.Width * image.Height * 4]; var pixelsSpan = MemoryMarshal.Cast <byte, Bgra32>(pixels); for (int r = 0; r < image.Height; ++r) { var destRow = pixelsSpan.Slice(r * image.Width, image.Width); var sorcRow = image.GetPixelRowSpan(r); PixelOperations <Rgba32> .Instance.ToBgra32(Configuration.Default, sorcRow, destRow); } var bmSource = BitmapSource.Create(image.Width, image.Height, 96.0, 96.0, PixelFormats.Bgra32, null, pixels, image.Width * 4); this.Preview = bmSource; this.PreviewErrorVisibility = Visibility.Collapsed; OnPropertyChanged(nameof(Width)); OnPropertyChanged(nameof(Height)); OnPropertyChanged(nameof(TextureInfo)); } catch (Exception ex) { Preview = null; if (ddsReadSuccess) { this.PreviewError = "Could not create preview! Export/Import may still work." + Environment.NewLine + Environment.NewLine + ex.Message; } else { this.PreviewError = "Could not create preview! Failed to convert pssg texture to dds." + Environment.NewLine + Environment.NewLine + ex.Message; } this.PreviewErrorVisibility = Visibility.Visible; } finally { image?.Dispose(); } }
public static float DecodeCheckPSNR(string filename, Image <Rgba32> original) { using FileStream fs = File.OpenRead(filename); var ktx = KtxFile.Load(fs); var decoder = new BcDecoder(); using var img = decoder.Decode(ktx); var pixels = original.GetPixelSpan(); var pixels2 = img.GetPixelSpan(); return(ImageQuality.PeakSignalToNoiseRatio(pixels, pixels2, true)); }
public void ReadBc7() { using FileStream fs = File.OpenRead(@"../../../testImages/test_decompress_bc7.dds"); BcDecoder decoder = new BcDecoder(); var images = decoder.DecodeAllMipMaps(fs); for (int i = 0; i < images.Length; i++) { using FileStream outFs = File.OpenWrite($"decoding_test_dds_bc7_mip{i}.png"); images[i].SaveAsPng(outFs); images[i].Dispose(); } }
public void Bc4Decode() { using FileStream fs = File.OpenRead(@"../../../testImages/test_decompress_bc4_unorm.ktx"); KtxFile file = KtxFile.Load(fs); Assert.True(file.Header.VerifyHeader()); Assert.Equal((uint)1, file.Header.NumberOfFaces); BcDecoder decoder = new BcDecoder(); using var image = decoder.Decode(file); Assert.Equal((uint)image.Width, file.Header.PixelWidth); Assert.Equal((uint)image.Height, file.Header.PixelHeight); using FileStream outFs = File.OpenWrite("decoding_test_bc4.png"); image.SaveAsPng(outFs); }
public void ReadRgba() { using FileStream fs = File.OpenRead(@"../../../testImages/test_decompress_rgba.dds"); DdsFile file = DdsFile.Load(fs); Assert.Equal(DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM, file.Header.ddsPixelFormat.DxgiFormat); Assert.Equal(file.Header.dwMipMapCount, (uint)file.Faces[0].MipMaps.Length); BcDecoder decoder = new BcDecoder(); var images = decoder.DecodeAllMipMaps(file); Assert.Equal((uint)images[0].Width, file.Header.dwWidth); Assert.Equal((uint)images[0].Height, file.Header.dwHeight); for (int i = 0; i < images.Length; i++) { using FileStream outFs = File.OpenWrite($"decoding_test_dds_rgba_mip{i}.png"); images[i].SaveAsPng(outFs); images[i].Dispose(); } }
private BcDecoder GetDecoder() { var decoder = new BcDecoder(); switch (_format) { case BcFormat.Ati1A: decoder.OutputOptions.Bc4Component = ColorComponent.A; break; case BcFormat.Ati1L: decoder.OutputOptions.Bc4Component = ColorComponent.Luminance; break; case BcFormat.Ati2AL: decoder.OutputOptions.Bc5Component1 = ColorComponent.Luminance; decoder.OutputOptions.Bc5Component2 = ColorComponent.A; break; } return(decoder); }
public void ReadBc1a() { using FileStream fs = File.OpenRead(@"../../../testImages/test_decompress_bc1a.dds"); DdsFile file = DdsFile.Load(fs); Assert.Equal(DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM, file.Header.ddsPixelFormat.DxgiFormat); Assert.Equal(file.Header.dwMipMapCount, (uint)file.Faces[0].MipMaps.Length); BcDecoder decoder = new BcDecoder(); decoder.InputOptions.ddsBc1ExpectAlpha = true; var image = decoder.Decode(file); Assert.Equal((uint)image.Width, file.Header.dwWidth); Assert.Equal((uint)image.Height, file.Header.dwHeight); Assert.Contains(image.GetPixelSpan().ToArray(), x => x.A == 0); using FileStream outFs = File.OpenWrite($"decoding_test_dds_bc1a.png"); image.SaveAsPng(outFs); image.Dispose(); }
public static void DecodeDdsToPixels <TPixel>(this BcDecoder decoder, DdsFile dds, Span <TPixel> pixels) where TPixel : unmanaged, IPixel <TPixel> { var width = (int)dds.header.dwWidth; var height = (int)dds.header.dwHeight; if (decoder.IsHdrFormat(dds)) { var source = decoder.DecodeHdr(dds).AsSpan(); for (var r = 0; r < height; ++r) { var start = r * width; var destRow = pixels.Slice(start, width); var sorcRow = source.Slice(start, width); for (var c = 0; c < destRow.Length; ++c) { ref var destPixel = ref destRow[c]; ref var sorcPixel = ref sorcRow[c]; var rgbVal = sorcPixel.ToVector3(); destPixel.FromScaledVector4(new Vector4(rgbVal, 1)); } }
/// <summary> /// decode to image as an asynchronous operation. /// </summary> /// <param name="file">The file.</param> /// <returns>Image<Rgba32>[].</returns> public async Task <Image> DecodeToImageAsync(DdsFile file) { var decoder = new BcDecoder(); Image <Rgba32> image; if (file.Faces.Count == 6) { // Cubemap var right = ColorMemoryToImage(await decoder.DecodeRaw2DAsync(file.Faces[0].MipMaps[0].Data, Convert.ToInt32(file.Faces[0].Width), Convert.ToInt32(file.Faces[0].Height), GetCompressionFormat(file, decoder.InputOptions))); var left = ColorMemoryToImage(await decoder.DecodeRaw2DAsync(file.Faces[1].MipMaps[0].Data, Convert.ToInt32(file.Faces[1].Width), Convert.ToInt32(file.Faces[1].Height), GetCompressionFormat(file, decoder.InputOptions))); var top = ColorMemoryToImage(await decoder.DecodeRaw2DAsync(file.Faces[2].MipMaps[0].Data, Convert.ToInt32(file.Faces[2].Width), Convert.ToInt32(file.Faces[2].Height), GetCompressionFormat(file, decoder.InputOptions))); var bottom = ColorMemoryToImage(await decoder.DecodeRaw2DAsync(file.Faces[3].MipMaps[0].Data, Convert.ToInt32(file.Faces[3].Width), Convert.ToInt32(file.Faces[3].Height), GetCompressionFormat(file, decoder.InputOptions))); var front = ColorMemoryToImage(await decoder.DecodeRaw2DAsync(file.Faces[4].MipMaps[0].Data, Convert.ToInt32(file.Faces[4].Width), Convert.ToInt32(file.Faces[4].Height), GetCompressionFormat(file, decoder.InputOptions))); var back = ColorMemoryToImage(await decoder.DecodeRaw2DAsync(file.Faces[5].MipMaps[0].Data, Convert.ToInt32(file.Faces[5].Width), Convert.ToInt32(file.Faces[5].Height), GetCompressionFormat(file, decoder.InputOptions))); return(GetCubeMap(right, left, top, bottom, front, back)); } else { var bcnImage = await decoder.Decode2DAsync(file); image = ColorMemoryToImage(bcnImage); } return(image); }
static async Task <MemoryStream> getDDS(Stream stream) { if (stream.CanSeek) { stream.Seek(0, SeekOrigin.Begin); } var exceptions = new List <Exception>(); MemoryStream ms = null; try { ms = new MemoryStream(); var file = DdsFile.Load(stream); var decoder = new BcDecoder(); var image = decoder.Decode(file); await image.SaveAsPngAsync(ms); } catch (Exception ex) { if (ms != null) { ms.Close(); await ms.DisposeAsync(); } ms = null; exceptions.Add(ex); } // fallback if (ms == null) { if (stream.CanSeek) { stream.Seek(0, SeekOrigin.Begin); } try { using var pfimImage = Dds.Create(stream, new PfimConfig()); if (pfimImage.Compressed) { pfimImage.Decompress(); } if (pfimImage.Format == ImageFormat.Rgba32) { ms = new MemoryStream(); using var image = Image.LoadPixelData <Bgra32>(tightData(pfimImage), pfimImage.Width, pfimImage.Height); await image.SaveAsPngAsync(ms); } else if (pfimImage.Format == ImageFormat.Rgb24) { ms = new MemoryStream(); using var image = Image.LoadPixelData <Bgr24>(tightData(pfimImage), pfimImage.Width, pfimImage.Height); await image.SaveAsPngAsync(ms); } } catch (Exception ex) { if (ms != null) { ms.Close(); await ms.DisposeAsync(); } ms = null; exceptions.Add(ex); } } // Fallback can result in memory stream being empty so throw aggregate exception only if both attempts failed if (ms == null && exceptions.Count == 2) { throw new AggregateException(exceptions); } return(ms); }