none
Speed up Image loading from a thread

    Question

  • HI all,

    I am facing a sluggish update on my Image control. I am using MVVM and the binding update to the Image control is pretty slow. Is there any way I can speed this process up?

    I have a background thread that sends me a jpg image buffer every 100 ms. I then create an ImageSource and set that to my binding property. Other datas from the background thread seems to be up to par except for the image. Does anyone have any idea on how to improve this?

    Friday, October 22, 2010 8:58 PM

All replies

  • This is how I am using to create an Image source

    BitmapSource

     

    .Create(1200, 800, 96, 96, PixelFormats.Gray16, null, e.EventArgs.Buffer, 1200 * 2);

    Friday, October 22, 2010 9:00 PM
  • Hi Johny,

    So the first thing we need to make sure: is it the BitmapSource.Create method that takes a lot of time to make the image update 'sluggish'?

    And it sounds to me like your desired update rate is 10 images per second, am I right? Do you mean at this time, your app is not able to reach this rate, so called 'sluggish'?

    What is the source of the image buffer? Is it guaranteed to provide the updates every 100ms in a stable manner?

    Regards,
    Jie
    MSDN Subscriber Support in Forum
    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    If you have any feedback, please tell us.

    The All-In-One Code Framework Project
    My Blog (in Simplified Chinese)
    Monday, October 25, 2010 5:15 PM
  • Hi Jie,

    Thanks for replying. So I figured out that the BitmapSource.Create method and the MVVM binding property is not the cause of it. It seems like the Image control rending/updating process in the GUI is slow because the INotifyPropertyChanged getter int the property is just about as fast as the creatiion of the image.

    Yes, the desire is to have about 10 images per second and the image buffer is always guarantee to have a valid image buffer every 100ms (for the meantime but may be faster).

    Are there any properties that can be set on the Image to update the image as soon as possible? The updating of the image seems to be the one that is slow.

    Monday, October 25, 2010 6:02 PM
  • The WriteableBitmap class might be faster
    Tuesday, October 26, 2010 3:15 AM
  • What are you doing with the images, are you showing a list of images? Or replacing the previous image on the Image control every 100ms?
    Tuesday, October 26, 2010 4:07 AM
  • Had to have a crack hehe... this seems to work...

     

    XAML

     <Image Source="{Binding WritableBitmap}"></Image>

    C#

     

    public partial class Window1 : Window
    {
     WriteableBitmap _writableBitmap;
     DispatcherTimer _timer = new DispatcherTimer();
     int _imageIndex = 0;
    
     public WriteableBitmap WritableBitmap
     {
      get { return _writableBitmap; }
      set { _writableBitmap = value; }
     }
    
     List<BitmapImage> _images = new List<BitmapImage>()
     {
      new BitmapImage(new Uri(@"C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg")),
      new BitmapImage(new Uri(@"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg")),
      new BitmapImage(new Uri(@"C:\Users\Public\Pictures\Sample Pictures\Hydrangeas.jpg")),
    
     };
    
     public Window1()
     {
      InitializeComponent();
    
      this.DataContext = this;
    
      _writableBitmap = new WriteableBitmap(_images[0]);
    
      _timer.Interval = TimeSpan.FromMilliseconds(100);
      _timer.Tick += new EventHandler(_timer_Tick);
      _timer.Start();
     }
    
     void _timer_Tick(object sender, EventArgs e)
     {
      byte[] copy = new byte[3145728];
    
      _writableBitmap.Lock();
    
      _images[_imageIndex].CopyPixels(Int32Rect.Empty, copy, 4096, 0);
    
      _writableBitmap.WritePixels(new Int32Rect(0, 0, (int)_images[_imageIndex].Width, (int)_images[_imageIndex].Height), copy, 4096, 0);
      _writableBitmap.AddDirtyRect(new Int32Rect(0, 0, (int)_images[_imageIndex].Width, (int)_images[_imageIndex].Height));
      _writableBitmap.Unlock();   
      
    
      _imageIndex++;
      if (_imageIndex == _images.Count) _imageIndex = 0;
     }
    }
    
    

     

    I guess just replace that List<BitmapImage> stuff with the image from the background thread.

     

    Warm regards,

    Matt

    Tuesday, October 26, 2010 4:43 AM
  • I am replacing the previous image with a new image every 100ms on the same image control, as if it is a video.
    Wednesday, October 27, 2010 3:34 PM
  • Hi Matt,

    I implemented the WritableBitmap and it still is slow. Here is my implementation:  

     

        WriteableBitmap _writableImage = null;
    
        public WriteableBitmap WritableImage
        {
          get 
          { 
            if (_writableImage == null)
              _writableImage = new WriteableBitmap(1024, 800, 96, 96, PixelFormats.Gray16, null);
    
            return _writableImage; 
          }
          set
          {
            _writableImage = value;
            base.OnPropertyChanged("WritableImage");
          }
        }
    
      WritableImage.Lock();
      WritableImage.WritePixels(new Int32Rect(0, 0, 1024, 800), e.EventViewArgs.imageBuffer, 1024 * 2, 0);
      WritableImage.AddDirtyRect(new Int32Rect(0, 0, 1024, 800));
      WritableImage.Unlock();
    
    

     

    Wednesday, October 27, 2010 3:58 PM
  • Adding this may help a little

     

    RenderOptions.SetBitmapScalingMode(MyImage, BitmapScalingMode.LowQuality);

    And maybe take a look at the System.Windows.Media.ImageDrawing class?

    Thursday, October 28, 2010 12:00 AM
  • Matt,

    I have tried the RenderOptions on the Image control itself and that didn't seem to make any difference. I also tried your suggestion with the same results.

    As for the ImageDrawing class, how do I set the ImageDrawing to my Image control?

    Thursday, October 28, 2010 4:29 PM
  • Theres an example here

     

    http://msdn.microsoft.com/en-us/library/system.windows.media.imagedrawing.aspx

     

    Hope its of some use, cuz if not, I'm all out of ideas except for using the GDI or DirectX/Direct3D API

    Friday, October 29, 2010 12:51 AM
  • Hi Johny,

     I realize this is quite old, But I have an insight which may prove useful to others searching for this.  I have found that for some reason using "PixelFormats.Gray16" is very slow.  Using something like "PixelFormats.Bgr32" is much much faster.  I don't know why.  Unfortunately for me, my data is 16bit grayscale data so I'd like to find a way to make the Gray16 format work better.


    • Edited by Jesse Pascoe Wednesday, November 28, 2012 7:31 PM Spelling
    Wednesday, November 28, 2012 7:29 PM