2012-10-24 29 views
6

Tôi có 5 hình ảnh có cùng chiều rộng pixel và chiều rộng pixel (2481 * 3508 cho vấn đề đó). Nhưng, một là gif, một jpeg, một png và một bmp. Bây giờ tôi đưa chúng vào một BitmapSource với (1) hai phần ba chiều cao pixel ban đầu cho DecodePixelHeight và (2) chiều cao pixel ban đầu cho DecodePixelHeight.Hiệu suất tốc độ giải mã bitmapImage wpf

kịch bản đầu tiên:

bitmapImage.BeginInit(); 
bitmapImage.CreateOptions = BitmapCreateOptions.IgnoreColorProfile; 
bitmapImage.CacheOption = BitmapCacheOption.OnLoad; 
bitmapImage.DecodePixelHeight = 2/3 * originalHeight; 
bitmapImage.StreamSource = streamWithTheFile; 
bitmapImage.EndInit(); 
bitmapImage.Freeze(); 

BMP và Jpeg là như nhau chậm. Png và Gif cần ít hơn một nửa thời gian. Tại sao?

kịch bản thứ hai:

bitmapImage.BeginInit(); 
bitmapImage.CreateOptions = BitmapCreateOptions.IgnoreColorProfile; 
bitmapImage.CacheOption = BitmapCacheOption.OnLoad; 
bitmapImage.StreamSource = streamWithTheFile; 
bitmapImage.EndInit(); 
bitmapImage.Freeze(); 

Png một nửa số thời gian cần thiết trước. Jpeg và BMP một phần năm thời gian cần thiết trước đây. Gif cùng thời điểm như trước.

Theo documentation Tôi đã giả định rằng hiệu suất Png và Jpeg bằng cách nào đó sẽ độc lập hơn với kích thước giải mã thực tế so với các định dạng khác. Điều gì có thể là lý do, rằng nó không phải là?

+0

Câu hỏi hay - có ai có bất kỳ đầu mối nào tại sao BitmapImage hoạt động như vậy không? –

+2

Có thể RenderOptions.BitmapScalingMode bất động sản (áp dụng cho bất kỳ điều khiển thực sự cho thấy hình ảnh, thông thường nó là yếu tố XAML ) giúp với tốc độ? Tôi nghĩ rằng theo mặc định nó được thiết lập để chất lượng cao trong .NET 3.5 và LowQuality cho .NET 4, nhưng cả hai đều phải chịu một hình phạt của các loại trong tốc độ rendering ... – Marko

+0

Tôi đã làm việc trên một ứng dụng chơi trong loạt một số lượng lớn (hàng ngàn) hình ảnh - jpg hoặc bmp và tôi đã cố gắng tối ưu hóa tốc độ cho tốc độ phát lại nhanh hơn. Một mặt, các bitmap lớn hơn và mất nhiều thời gian hơn để tải lên từ đĩa hoặc bộ nhớ cache mem, nhưng chúng không cần giải mã. Với các jpg, ngược lại là đúng - giải mã chậm nhưng tải từ đĩa nhanh. Cuối cùng tôi đã chọn định dạng gốc của hình ảnh (jpg) vì nó yêu cầu ít công việc ban đầu hơn. Vấn đề là, bộ nhớ đệm và tải đĩa có thể ảnh hưởng đến thời gian. – Dean

Trả lời

0

tôi đã thực hiện một hành vi đó là tối ưu, hiệu suất khôn ngoan .. Tôi sử dụng nó cho luồng thức ăn trực tiếp từ máy ảnh chủ an ninh, hoạt động như một nét duyên dáng với những hình ảnh khá lớn ..

Hãy thử điều này và cho tôi biết bạn nghĩ gì. Cách sử dụng khá đơn giản, Gán các thuộc tính phụ thuộc, đính kèm hành vi vào một hình ảnh và được thực hiện với nó. cổ vũ.

Lưu ý: Các pixel có thể là IList, nhưng bạn cũng có thể gán một mảng vì mảng C# triển khai thực hiện IList.

Lưu ý 2: Không chỉ định Nguồn hình ảnh vì điều này sẽ ghi đè nhiệm vụ của hành vi, chỉ cần liên kết với thuộc tính phụ thuộc Pixels của hành vi.

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); 
    } 
}