2012-10-24 13 views
6

मेरे पास 5 छवियां समान पिक्सेल ऊंचाई और पिक्सेल चौड़ाई (उस मामले के लिए 2481 * 3508) हैं। लेकिन, एक gif, एक jpeg, एक पीएनजी और एक बीएमपी है। अब मैं उन्हें डीकोड पिक्सेलहेइट के लिए (1) मूल पिक्सेल ऊंचाई के दो तिहाई (और) डीकोड पिक्सेलहेइट के लिए मूल पिक्सेल ऊंचाई के साथ बिटमैप स्रोत में प्रस्तुत करता हूं।बिटमैप छवि डिकोडिंग गति प्रदर्शन wpf

पहले परिदृश्य:

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

बीएमपी और Jpeg समान रूप से धीमी गति से कर रहे हैं। पीएनजी और गिफ को आधा समय से कम की जरूरत है। क्यूं कर?

दूसरा परिदृश्य:

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

Png समय से पहले की जरूरत का आधा। जेपीईजी और बीएमपी उस समय के 5 वें समय पहले जरूरी थे। पहले के रूप में एक ही समय उपहार।

documentation के अनुसार मुझे लगता है कि पीएनजी और जेपीईजी प्रदर्शन अन्य प्रारूपों की तुलना में वास्तविक डीकोड आकार से अधिक स्वतंत्र होगा। कारण क्या हो सकता है, यह नहीं है?

+0

अच्छा सवाल - क्या किसी के पास कोई सुराग है कि बिटमैप छवि इस तरह क्यों व्यवहार करती है? –

+2

RenderOptions.BitmapScalingMode प्रॉपर्टी (जो भी नियंत्रण वास्तव में छवि को दिखाता है, पर लागू होता है, सामान्यतः यह XAML तत्व) गति के साथ मदद करता है? मुझे लगता है कि डिफ़ॉल्ट रूप से यह .NET 3.5 के लिए .NET 3.5 और निम्न गुणवत्ता में उच्च गुणवत्ता पर सेट है, लेकिन दोनों को गति प्रदान करने में प्रकार का जुर्माना लगाया जाता है ... – Marko

+0

मैं श्रृंखला में खेले गए एप्लिकेशन पर बड़ी संख्या (हजारों) छवियों - या तो jpg या bmp, और मैं एक तेज प्लेबैक गति के लिए गति को अनुकूलित करने की कोशिश कर रहा था। एक तरफ, बिटमैप्स बड़ा होता है और डिस्क या मेम कैश से लोड होने में अधिक समय लगता है, लेकिन उन्हें कोई डिकोडिंग की आवश्यकता नहीं होती है। Jpgs के साथ, विपरीत सत्य था - डिकोडिंग धीमी है लेकिन डिस्क से लोड करना तेज़ है। अंत में मैं छवियों (jpg) के मूल प्रारूप को चुनने के लिए समाप्त हुआ क्योंकि इसके लिए कम प्रारंभिक कार्यप्रणाली की आवश्यकता होती है। बिंदु, कैशिंग और डिस्क लोडिंग समय के साथ हस्तक्षेप कर सकते हैं। – Dean

उत्तर

0

मैं एक व्यवहार जो इष्टतम है को लागू किया है, प्रदर्शन बुद्धिमान .. मैं इसे घर सुरक्षा कैमरे से लाइव फ़ीड स्ट्रीमिंग के लिए उपयोग करते हैं, काफी बड़ी छवियों के साथ एक आकर्षण की तरह काम करता ..

इस बाहर की कोशिश करो और मुझे पता है आपको क्या लगता है। उपयोग बहुत सरल है, निर्भरता गुणों को असाइन करें, व्यवहार को एक छवि से संलग्न करें और इसके साथ किया जाए। खुश होती है।

नोट: पिक्सेल IList हो सकता है, लेकिन आप सी # सरणी लागू करने के बाद से एक सरणी भी असाइन कर सकते हैं।

नोट 2: छवि स्रोत असाइन न करें क्योंकि यह व्यवहार के असाइनमेंट को ओवरराइड करेगा, केवल पिक्सेल व्यवहार की निर्भरता संपत्ति से जुड़ें।

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); 
    } 
} 
संबंधित मुद्दे