1
我需要在WPF應用程序中提供來自SharpDX的WIC Bitmap
。 WIC位圖繼承自BitmapSource
,但它與WPF使用的BitmapSource
不同,儘管類名相同。我怎樣才能從一個轉換到另一個?如何在WPF應用程序中使用SharpDX.WIC.Bitmap?
我需要在WPF應用程序中提供來自SharpDX的WIC Bitmap
。 WIC位圖繼承自BitmapSource
,但它與WPF使用的BitmapSource
不同,儘管類名相同。我怎樣才能從一個轉換到另一個?如何在WPF應用程序中使用SharpDX.WIC.Bitmap?
你可以做的是從WPF的BitmapSource創建一個自定義的派生類。
例如,對於這個XAML:
<Window x:Class="SharpDXWpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Image Name="MyImage"></Image>
</Grid>
</Window>
這個窗口代碼使用定製的 「WicBitmapSource」。
public partial class MainWindow : Window
{
private WicBitmapSource _bmp;
public MainWindow()
{
InitializeComponent();
_bmp = new WicBitmapSource(@"c:\path\killroy_was_here.png");
MyImage.Source = _bmp;
}
protected override void OnClosed(EventArgs e)
{
_bmp.Dispose();
}
}
下面是該SharpDX/WIC定製的BitmapSource一些示例代碼(有些信息都是從這裏抓起:https://blogs.msdn.microsoft.com/dwayneneed/2008/06/20/implementing-a-custom-bitmapsource/)。
public class WicBitmapSource : System.Windows.Media.Imaging.BitmapSource, IDisposable
{
public WicBitmapSource(string filePath)
{
if (filePath == null)
throw new ArgumentNullException(nameof(filePath));
using (var fac = new ImagingFactory())
{
using (var dec = new SharpDX.WIC.BitmapDecoder(fac, filePath, DecodeOptions.CacheOnDemand))
{
Frame = dec.GetFrame(0);
}
}
}
public WicBitmapSource(BitmapFrameDecode frame)
{
if (frame == null)
throw new ArgumentNullException(nameof(frame));
Frame = frame;
}
public BitmapFrameDecode Frame { get; }
public override int PixelWidth => Frame.Size.Width;
public override int PixelHeight => Frame.Size.Height;
public override double Height => PixelHeight;
public override double Width => PixelWidth;
public override double DpiX
{
get
{
Frame.GetResolution(out double dpix, out double dpiy);
return dpix;
}
}
public override double DpiY
{
get
{
Frame.GetResolution(out double dpix, out double dpiy);
return dpiy;
}
}
public override System.Windows.Media.PixelFormat Format
{
get
{
// this is a hack as PixelFormat is not public...
// it would be better to do proper matching
var ct = typeof(System.Windows.Media.PixelFormat).GetConstructor(
BindingFlags.Instance | BindingFlags.NonPublic,
null,
new[] { typeof(Guid) },
null);
return (System.Windows.Media.PixelFormat)ct.Invoke(new object[] { Frame.PixelFormat });
}
}
// mostly for GIFs support (indexed palette of 256 colors)
public override BitmapPalette Palette
{
get
{
using (var fac = new ImagingFactory())
{
var palette = new Palette(fac);
try
{
Frame.CopyPalette(palette);
}
catch
{
// no indexed palette (PNG, JPG, etc.)
// it's a pity SharpDX throws here,
// it would be better to return null more gracefully as this is not really an error
// if you only want to support non indexed palette images, just return null for the property w/o trying to get a palette
return null;
}
var list = new List<Color>();
foreach (var c in palette.GetColors<int>())
{
var bytes = BitConverter.GetBytes(c);
var color = Color.FromArgb(bytes[3], bytes[2], bytes[1], bytes[0]);
list.Add(color);
}
return new BitmapPalette(list);
}
}
}
public override void CopyPixels(Int32Rect sourceRect, Array pixels, int stride, int offset)
{
if (offset != 0)
throw new NotSupportedException();
Frame.CopyPixels(
new SharpDX.Mathematics.Interop.RawRectangle(sourceRect.X, sourceRect.Y, sourceRect.Width, sourceRect.Height),
(byte[])pixels, stride);
}
public void Dispose() => Frame.Dispose();
public override event EventHandler<ExceptionEventArgs> DecodeFailed;
public override event EventHandler DownloadCompleted;
public override event EventHandler<ExceptionEventArgs> DownloadFailed;
public override event EventHandler<DownloadProgressEventArgs> DownloadProgress;
protected override Freezable CreateInstanceCore() => throw new NotImplementedException();
}
謝謝,但應該''而不是'WicBitmapSource'? –
Image是標準的WPF FrameworkElement,可以顯示BitmapSource實例,無論BitmapSource的類型是什麼。 –
謝謝,這個工程。現在,有沒有辦法避免編碼解碼步驟? –