我有5张相同像素高度和像素宽度的图像(2481 * 3508)。但是,一个是gif,一个jpeg,一个png和一个bmp。现在我将它们渲染成BitmapSource,其中(1)DecodePixelHeight的原始像素高度的三分之二和(2)DecodePixelHeight的原始像素高度。
第一种情况:
bitmapImage.BeginInit();
bitmapImage.CreateOptions = BitmapCreateOptions.IgnoreColorProfile;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.DecodePixelHeight = 2/3 * originalHeight;
bitmapImage.StreamSource = streamWithTheFile;
bitmapImage.EndInit();
bitmapImage.Freeze();
BMP和Jpeg同样缓慢。 Png和Gif只需要不到一半的时间。为什么呢?
第二种情况:
bitmapImage.BeginInit();
bitmapImage.CreateOptions = BitmapCreateOptions.IgnoreColorProfile;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = streamWithTheFile;
bitmapImage.EndInit();
bitmapImage.Freeze();
Png之前所需时间的一半。 Jpeg和BMP之前需要的时间是第5次。 Gif和以前一样。
根据documentation我会假设Png和Jpeg性能在某种程度上比其他格式更独立于实际解码大小。可能是什么原因,它不是?
答案 0 :(得分:0)
我已经实现了一种最佳,性能明智的行为。我将它用于从家庭安全摄像头流式传输实时馈送,就像具有相当大图像的魅力一样......
尝试一下,让我知道你的想法。用法非常简单,分配依赖项属性,将行为附加到图像并完成它。欢呼声。
注意:像素可能是IList,但您也可以分配一个数组,因为C#数组实现了IList。
注意2:不要分配Image Source,因为这会覆盖行为的赋值,只需绑定到行为的 Pixels 依赖项属性。
public class VideoBehavior : Behavior<Image>
{
public static readonly DependencyProperty PixelsProperty = DependencyProperty.Register(
"Pixels", typeof (IList<byte>), typeof (VideoBehavior), new PropertyMetadata(default(IList<byte>),OnPixelsChanged));
private static void OnPixelsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var b = (VideoBehavior) d;
var pixels = (IList<byte>) e.NewValue;
b.RenderPixels(pixels);
}
public IList<byte> Pixels
{
get { return (IList<byte>) GetValue(PixelsProperty); }
set { SetValue(PixelsProperty, value); }
}
public static readonly DependencyProperty PixelFormatProperty = DependencyProperty.Register(
"PixelFormat", typeof (PixelFormat), typeof (VideoBehavior), new PropertyMetadata(PixelFormats.Default,OnPixelFormatChanged));
private static void OnPixelFormatChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var b = (VideoBehavior) d;
var pixelFormat = (PixelFormat) e.NewValue;
if(pixelFormat==PixelFormats.Default)
return;
b._pixelFormat = pixelFormat;
b.InitializeBufferIfAttached();
}
public PixelFormat PixelFormat
{
get { return (PixelFormat) GetValue(PixelFormatProperty); }
set { SetValue(PixelFormatProperty, value); }
}
public static readonly DependencyProperty PixelWidthProperty = DependencyProperty.Register(
"PixelWidth", typeof (int), typeof (VideoBehavior), new PropertyMetadata(default(int),OnPixelWidthChanged));
private static void OnPixelWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var b = (VideoBehavior)d;
var value = (int)e.NewValue;
if(value<=0)
return;
b._pixelWidth = value;
b.InitializeBufferIfAttached();
}
public int PixelWidth
{
get { return (int) GetValue(PixelWidthProperty); }
set { SetValue(PixelWidthProperty, value); }
}
public static readonly DependencyProperty PixelHeightProperty = DependencyProperty.Register(
"PixelHeight", typeof (int), typeof (VideoBehavior), new PropertyMetadata(default(int),OnPixelHeightChanged));
private static void OnPixelHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var b = (VideoBehavior)d;
var value = (int)e.NewValue;
if (value <= 0)
return;
b._pixelHeight = value;
b.InitializeBufferIfAttached();
}
public int PixelHeight
{
get { return (int) GetValue(PixelHeightProperty); }
set { SetValue(PixelHeightProperty, value); }
}
public static readonly DependencyProperty DpiXProperty = DependencyProperty.Register(
"DpiX", typeof (int), typeof (VideoBehavior), new PropertyMetadata(96,OnDpiXChanged));
private static void OnDpiXChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var b = (VideoBehavior)d;
var value = (int)e.NewValue;
if (value <= 0)
return;
b._dpiX = value;
b.InitializeBufferIfAttached();
}
public int DpiX
{
get { return (int) GetValue(DpiXProperty); }
set { SetValue(DpiXProperty, value); }
}
public static readonly DependencyProperty DpiYProperty = DependencyProperty.Register(
"DpiY", typeof (int), typeof (VideoBehavior), new PropertyMetadata(96,OnDpiYChanged));
private static void OnDpiYChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var b = (VideoBehavior)d;
var value = (int)e.NewValue;
if (value <= 0)
return;
b._dpiY = value;
b.InitializeBufferIfAttached();
}
public int DpiY
{
get { return (int) GetValue(DpiYProperty); }
set { SetValue(DpiYProperty, value); }
}
[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
public static extern void CopyMemory(IntPtr destination, IntPtr source, uint length);
private IntPtr _backBuffer = IntPtr.Zero;
private int _bytesPerPixel;
private const int BitsPerByte = 8;
private int _pixelWidth;
private int _pixelHeight;
private int _dpiX;
private int _dpiY;
private PixelFormat _pixelFormat;
private Int32Rect _rect;
private uint _byteArraySize;
private WriteableBitmap _bitMap;
private bool _attached;
protected override void OnAttached()
{
_attached = true;
InitializeBufferIfAttached();
}
private void InitializeBufferIfAttached()
{
if(_attached==false)
return;
ReevaluateBitsPerPixel();
RecomputeByteArraySize();
ReinitializeImageSource();
}
private void ReevaluateBitsPerPixel()
{
if(_pixelFormat==PixelFormats.Default)
return;
_bytesPerPixel = _pixelFormat.BitsPerPixel/BitsPerByte;
}
private void ReinitializeImageSource()
{
if(_pixelHeight<=0|| _pixelHeight<=0)
return;
_bitMap = new WriteableBitmap(_pixelWidth, _pixelHeight, _dpiX, _dpiY, _pixelFormat, null);
_backBuffer = _bitMap.BackBuffer;
_rect = new Int32Rect(0, 0, _pixelWidth, _pixelHeight);
AssociatedObject.Source = _bitMap;
}
private async void RenderPixels(IList<byte> pixels)
{
if (_backBuffer == IntPtr.Zero)
return;
if (pixels == null)
{
return;
}
await Task.Factory.StartNew(() =>
{
var h = new GCHandle();
var allocated = false;
try
{
h = GCHandle.Alloc(pixels, GCHandleType.Pinned);
allocated = true;
var ptr = h.AddrOfPinnedObject();
CopyMemory(_backBuffer, ptr, _byteArraySize);
}
finally
{
if (allocated)
h.Free();
}
});
_bitMap.Lock();
_bitMap.AddDirtyRect(_rect);
_bitMap.Unlock();
}
private void RecomputeByteArraySize()
{
_byteArraySize = (uint)(_pixelWidth * _pixelHeight * _bytesPerPixel);
}
}