1

I am trying to create a "live-view" from my webcam with WPF, which only gives me JPG snapshots over HTTP. Every time I update the image source, it flickers. Anyone has an idea how to fix this?

XAML:

     <Grid>
        <Image Name="img"/>
    </Grid>

C#:

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DispatcherTimer timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(1000.0);
            timer.Tick += timer_Tick;
            timer.Start();

        }

        void timer_Tick(object sender, EventArgs e)
        {

            BitmapImage _image = new BitmapImage();
            _image.BeginInit();
            _image.CacheOption = BitmapCacheOption.None;
            _image.UriCachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
            _image.CacheOption = BitmapCacheOption.OnLoad;
            _image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
            _image.UriSource = new Uri(@"http://0.0.0.0/api/camera/snapshot?width=640&height=480", UriKind.RelativeOrAbsolute);
            _image.EndInit();
            img.Source = _image;
        }
    }
Le Flo
  • 77
  • 7
  • 1
    Reduce the resolution which will also reduce the processing. Also decreasing the Interval from 1 second to 1/30 of a second. You eye will not see the flickering if the time is faster than ~1/30 second. That why movie frames are 60 pictures a second. – jdweng Feb 20 '20 at 10:11
  • 1
    The flicker is because the BitmapImage is loaded asynchronously, i.e. after you have assigned it to the Image's Source property. The Image element first becomes empty, and will show an image only after downloading has finished. – Clemens Feb 20 '20 at 10:15
  • yeah, every update, the backgroundcolor shows up for a few milliseconds, which causes the flicker. But i dont know how to fix this. – Le Flo Feb 20 '20 at 10:22

2 Answers2

2

The flicker is because the BitmapImage is loaded asynchronously, i.e. after you have assigned it to the Image's Source property. The Image element first becomes empty, and will show an image only after downloading has finished.

In this case you may set the Source property in a DownloadCompleted event handler:

void timer_Tick(object sender, EventArgs e)
{
    var uri = "http://0.0.0.0/api/camera/snapshot?width=640&height=480";
    var image = new BitmapImage();
    image.BeginInit();
    image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
    image.UriCachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
    image.UriSource = new Uri(uri);
    image.EndInit();

    if (image.IsDownloading)
    {
        image.DownloadCompleted += (s, ev) => img.Source = image;
    }
    else
    {
        img.Source = image;
    }
}
Clemens
  • 123,504
  • 12
  • 155
  • 268
1

Thanks @all for helping. Got the solution from Update BitmapImage every second flickers

Converted to async HttpClient API instead of WebClient, it looks like:

private readonly HttpClient httpClient = new HttpClient();

private async void timer_Tick(object sender, EventArgs e)
{
    var uri = "http://0.0.0.0/api/camera/snapshot?width=640&height=480";

    using (var responseStream = await httpClient.GetStreamAsync(uri))
    using (var memoryStream = new MemoryStream())
    {
        await responseStream.CopyToAsync(memoryStream); // ensure full download

        BitmapImage image = new BitmapImage();
        image.BeginInit();
        image.CacheOption = BitmapCacheOption.OnLoad;
        image.StreamSource = memoryStream;
        image.EndInit();
        img.Source = image;
    }
}
Clemens
  • 123,504
  • 12
  • 155
  • 268
Le Flo
  • 77
  • 7