How can I display a Progressive JPEG in WPF?

后端 未结 2 1359
深忆病人
深忆病人 2020-12-25 14:49

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 i

2条回答
  •  有刺的猬
    2020-12-25 15:07

    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:

    
      
        
        
      
    
    

    Code-behind:

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

提交回复
热议问题