source example wpf image bitmapimage

source - image wpf example



¿Cómo puedo mostrar un JPEG progresivo en WPF? (2)

Esto parece ser un defecto del control de imagen. Tal vez podría crear un StreamImage que herede de Image, tome un flujo en el constructor, lea los bytes en segundo plano del fondo, calcule cuándo tiene suficiente, construye una "imagen borrosa" interna con los bytes leídos hasta el momento y hace que iterativamente hasta que tenga todos los bytes. Tendrías que entender cómo se envían los bytes de un JPEG progresivo, no creo que sea simple.

¿Cómo mostrar un JPEG progresivo a medida que se carga desde una URL web? Estoy tratando de mostrar una imagen de Google Maps en un control de imagen en WPF, pero quiero mantener la ventaja de que la imagen sea un JPG progresivo.

¿Cómo cargar un JPG progresivo en WPF?

Image imgMap; BitmapImage mapLoader = new BitmapImage(); mapLoader.BeginInit(); mapLoader.UriSource = new Uri(URL); mapLoader.EndInit(); imgMap.Source = mapLoader;

Actualmente, me conformo con esto. Solo mostrará la imagen después de que se cargue por completo. Quiero mostrarlo progresivamente.


Una muestra muy básica. Estoy seguro de que hay espacio para las optimizaciones, y puede hacer una clase separada de la que puede manejar numerosas solicitudes, pero al menos está funcionando, y puede configurarlo para sus necesidades. También tenga en cuenta que esta muestra crea una imagen cada vez que informamos un progreso, ¡debe evitarlo! Haz una imagen de aproximadamente cada 5% para evitar una gran sobrecarga.

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>

Código detrás:

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