How can I display a Progressive JPEG in WPF?

后端 未结 2 1360
深忆病人
深忆病人 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:06

    This does seem to be a shortcoming of the Image control. Maybe you could create a StreamImage that inherits from Image, takes a stream in the constructor, reads bytes in the background from the stream, figures out when it has enough, constructs an internal "fuzzy image" with the bytes read so far and renders that iteratively until it has all the bytes. You'd have to understand how bytes of a progressive JPEG are sent--I don't imagine it is simple.

    0 讨论(0)
  • 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:

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

    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;
    }
    
    0 讨论(0)
提交回复
热议问题