如何在WPF中显示渐进式JPEG? [英] How can I display a Progressive JPEG in WPF?

查看:172
本文介绍了如何在WPF中显示渐进式JPEG?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在从网址加载时显示渐进式JPEG?我试图在WPF中的图像控件中显示Google地图图像,但我希望保持图像的优势是渐进式JPG。

How to display a progressive JPEG as it loads from a web URL? I am trying to display a Google Maps image in a image control in WPF, but I want to keep the advantage of the image being a progressive JPG.

如何加载WPF中的渐进式JPG?

How to load a progressive JPG in WPF?

Image imgMap;
BitmapImage mapLoader = new BitmapImage();

mapLoader.BeginInit();
mapLoader.UriSource = new Uri(URL);
mapLoader.EndInit();

imgMap.Source = mapLoader;

目前,我这样做了。它只会在完全加载后显示图像。我希望逐步显示它。

Currently, I make do with this. It will only shows the image after it loads completely. I want to show it progressively.

推荐答案

一个非常基本的样本。我确定有优化的空间,你可以从它做一个单独的类,可以处理大量的请求,但至少它的工作,你可以根据自己的需要塑造它。另请注意,每次我们报告进度时,此示例都会创建一个图像,您应该避免它!做一个大约每5%左右的图像,以避免很大的开销。

A very basic sample. Im sure there are room for optimizations, and you can do a separate class from it that can handle numerous request, but at least its working, and you can shape it for your needs. Also note that this sample creates an image every time that we report a progress, you should avoid it! Do an image about every 5% or so to avoid a big overhead.

Xaml:

<Window x:Class="ScrollViewerTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
  <StackPanel>
    <TextBlock Text="{Binding Path=Progress, StringFormat=Progress: {0}}" />
    <Image Source="{Binding Path=Image}" />
  </StackPanel>
</Window>

代码隐藏:

public partial class MainWindow : Window, INotifyPropertyChanged
{

  #region Public Properties

  private int _progress;
  public int Progress
  {
    get { return _progress; }
    set
    {
      if (_progress != value)
      {
        _progress = value;

        if (PropertyChanged != null)
          PropertyChanged(this, new PropertyChangedEventArgs("Progress"));
      }
    }
  }

  private BitmapImage image;
  public BitmapImage Image
  {
    get { return image; }
    set
    {
      if (image != value)
      {
        image = value;
        if (PropertyChanged != null)
          PropertyChanged(this, new PropertyChangedEventArgs("Image"));
      }
    }
  }

  #endregion

  BackgroundWorker worker = new BackgroundWorker();

  public MainWindow()
  {
    InitializeComponent();

    worker.DoWork += backgroundWorker1_DoWork;
    worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
    worker.WorkerReportsProgress = true;
    worker.RunWorkerAsync(@"http://Tools.CentralShooters.co.nz/Images/ProgressiveSample1.jpg");
  }

  // This function is based on code from
  //   http://devtoolshed.com/content/c-download-file-progress-bar
  private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
  {
    // the URL to download the file from
    string sUrlToReadFileFrom = e.Argument as string;

    // first, we need to get the exact size (in bytes) of the file we are downloading
    Uri url = new Uri(sUrlToReadFileFrom);
    System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
    System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
    response.Close();
    // gets the size of the file in bytes
    Int64 iSize = response.ContentLength;

    // keeps track of the total bytes downloaded so we can update the progress bar
    Int64 iRunningByteTotal = 0;

    // use the webclient object to download the file
    using (System.Net.WebClient client = new System.Net.WebClient())
    {
      // open the file at the remote URL for reading
      using (System.IO.Stream streamRemote = client.OpenRead(new Uri(sUrlToReadFileFrom)))
      {
        using (Stream streamLocal = new MemoryStream((int)iSize))
        {
          // loop the stream and get the file into the byte buffer
          int iByteSize = 0;
          byte[] byteBuffer = new byte[iSize];
          while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
          {
            // write the bytes to the file system at the file path specified
            streamLocal.Write(byteBuffer, 0, iByteSize);
            iRunningByteTotal += iByteSize;

            // calculate the progress out of a base "100"
            double dIndex = (double)(iRunningByteTotal);
            double dTotal = (double)byteBuffer.Length;
            double dProgressPercentage = (dIndex / dTotal);
            int iProgressPercentage = (int)(dProgressPercentage * 100);

            // update the progress bar, and we pass our MemoryStream, 
            //  so we can use it in the progress changed event handler
            worker.ReportProgress(iProgressPercentage, streamLocal);
          }

          // clean up the file stream
          streamLocal.Close();
        }

        // close the connection to the remote server
        streamRemote.Close();
      }
    }
  }

  void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
  {
    Dispatcher.BeginInvoke(
         System.Windows.Threading.DispatcherPriority.Normal,
         new Action(delegate()
         {
           MemoryStream stream = e.UserState as MemoryStream;

           BitmapImage bi = new BitmapImage();
           bi.BeginInit();
           bi.StreamSource = new MemoryStream(stream.ToArray());
           bi.EndInit();

           this.Progress = e.ProgressPercentage;
           this.Image = bi;
         }
       ));
  }

  public event PropertyChangedEventHandler PropertyChanged;
}

这篇关于如何在WPF中显示渐进式JPEG?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆