2011-05-14 20 views
18

Bir web URL'sinden yüklendiği için aşamalı bir JPEG nasıl görüntülenir? WPF'de bir görüntü kontrolünde bir Google Haritalar resmi görüntülemeye çalışıyorum, ancak görüntünün avantajlı bir JPG olma avantajını korumak istiyorum.WPF'de Progressive JPEG nasıl görüntüleyebilirim?

WPF'de aşamalı JPG nasıl yüklenir?

Image imgMap; 
BitmapImage mapLoader = new BitmapImage(); 

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

imgMap.Source = mapLoader; 

Şu anda bununla da başarım. Sadece görüntü tamamen yüklendikten sonra gösterecektir. Bunu kademeli olarak göstermek istiyorum.

cevap

12

Çok basit bir örnek. Optimizasyonlar için yer olduğundan eminim, ve çok sayıda isteği yerine getirebilen, ancak en azından çalıştığı ve bunu sizin ihtiyaçlarınıza göre şekillendirebileceğiniz ayrı bir sınıf yapabilirsiniz. Ayrıca, bu örnekte her ilerleme kaydettiğimizde bir görüntü oluşturduğunu, bundan kaçınmanız gerektiğini unutmayın! Büyük bir genel masraftan kaçınmak için her% 5 veya üzeri bir resim yapın.

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> 

kod arkadaki:

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

@TFD Size Google Progressive JPeG'i öneririm. Ne olduğu konusunda çok fazla kaynak var .. ama gerçekten bunları nasıl halledebileceğin değil. Özellikle .net'de .net .net'te bir tane yazmak önemsiz bir iş değildir. – Mel

+4

Progressive olayını gerçekten atlarken, kendimi biraz savunmaya çalışacağım: Temel sorun, görüntünün sadece indirme işlemi tamamlandığında gösterilmesi ve OP'nin, görüntüyü kopyalarken görüntü bölümlerini göstermek istemesiydi. Örnek kodum bunu yapıyor. Onun bir soruna bir çözümü ve yukarıda okuyabileceğiniz bir arzunun cevabı: “Bunu kademeli olarak göstermek istiyorum.”. Ve _question_'a bir cevap yokken, sorun çözüldü: son kullanıcı, indirme görüntüsünün bazı ilerleyişini görebilir. Belki OP'nin cevabımı kabul etmesini hak edemem ama ben de -1'i hak etmiyorum. – Ben

+0

@BoltClock Ilerici bir JPG'nin ne olduğunu biliyorum. Hangi ilerleme çubuğu? Bu örnek kod, "İlerleme: {0}" kullanarak görüntüyü ve yüzde tamamlanmış sayacı gösterir. Görüntü, mevcut kısmi akışı verilen görüntüler. OP istediği bu muydu? Tek hata, örnek aşamalı JPG'ye bağlantı kurmak değildi. URL'yi büyük bir aşamalı olarak değiştirin ve iyi çalıştığını görebilirsiniz. Lütfen teknik açıdan doğru olan -1 mesaj göndermeyin. – TFD

1

Bu Görüntü kontrolünün bir eksiklik olarak görünmektedir. Belki de, Image'den miras alan, akış içinde arka plandaki baytları okuyan, yeterli miktarda olduğunda, "baytlar" ile içsel bir "bulanık görüntü" oluşturup, şu ana kadar okunan bir StreamImage yaratabilirsiniz. Tüm baytları olana kadar yinelemeli olarak. Aşamalı bir JPEG'in baytının nasıl gönderildiğini anlamak zorunda kalacaksınız - bunun basit olduğunu düşünmüyorum.

+0

@Patrick_Szalapski Anlamıyorum Yorumunuz nereden geliyor. WPF Görüntü tamamen aşamalı jpg desteği. Kısıtlama yok. Sadece işe yarıyor.Bakınız @ben 'nin cevabı – TFD

+1

@TFD Halen kısmi görüntüyü her 5%' de sıfırdan yeniden oluşturuyor. Tam destek, yüklendikçe bir seferde onu oluşturuyordu. – Rup

+0

Doğru - Tüm @ Ben'in kodunun kontrolüne sahip olduğu özel bir kontrolün olduğunu düşünüyordum. Bu kodu dışarıdan bakarsanız, o zaman kesinlikle özel bir kontrole ihtiyacınız yoktur. –

İlgili konular