I have a program where it gets images from website and bind it to the list. I tested the link on my browser and it's shows the image however, when I run, it showing error:
WinRT information: The value cannot be converted to type
ImageSource.
I was previously worked on some projects with list view and I never got this error before.
<ListView Grid.Row="1" ItemsSource="{x:Bind AllSongs}"
Margin="50,20,50,0">
<ListView.ItemTemplate>
<DataTemplate x:DataType="data:SongList">
<StackPanel Orientation="Horizontal">
<Image Source="{x:Bind Image}"/>
<TextBlock Text="{x:Bind Name}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
My xaml.cs code
public sealed partial class MainPage : Page
{
ObservableCollection<SongList> AllSongs;
public MainPage()
{
this.InitializeComponent();
AllSongs = new ObservableCollection<SongList>();
}
private async void searchButton_Click(object sender, RoutedEventArgs e)
{
MyProgress.IsActive = true;
MyProgress.Visibility = Visibility.Visible;
var allSongs = await SongListManager.GetSongListsAsync(singerAlbumSearchbar.Text);
foreach (var songs in allSongs)
AllSongs.Add(songs);
MyProgress.IsActive = false;
MyProgress.Visibility = Visibility.Collapsed;
}
}
And the code I use to get the links
public class SongListManager
{
public static async Task<List<SongList>> GetSongListsAsync(string SingerName)
{
var newSongList = new List<SongList>();
HttpClient client = new HttpClient();
var jsonData = await client.GetStringAsync("https://theaudiodb.com/api/v1/json/1/searchalbum.php?s=" + SingerName);
var response = JsonConvert.DeserializeObject<Rootobject>(jsonData);
for (int i = 0; i < response.album.Length; i++)
{
newSongList.Add(new SongList() { Image = response.album[i].strAlbumThumb, Name = response.album[i].strAlbum });
}
return newSongList;
}
}
Make the variable type of the image to ImageSource in your SongList class and set bitmapimage from the url of your thumbnail image. I tried it works fine.
public sealed partial class MainPage : Page
{
ObservableCollection<SongList> AllSongs;
public MainPage()
{
this.InitializeComponent();
AllSongs = new ObservableCollection<SongList>();
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
AllSongs= new ObservableCollection<SongList>( await GetSongListsAsync("drake"));
SongListView.ItemsSource = AllSongs;
base.OnNavigatedTo(e);
}
private async Task<List<SongList>> GetSongListsAsync(string SingerName)
{
List<SongList> songs = new List<SongList>();
HttpClient client = new HttpClient();
var jsonData = await client.GetStringAsync("https://theaudiodb.com/api/v1/json/1/searchalbum.php?s=" + SingerName);
var response = JsonConvert.DeserializeObject<RootObject>(jsonData);
foreach (var song in response.album.FindAll(g => !string.IsNullOrEmpty(g.strAlbumThumb)))
{
var bytes = await new HttpClient().GetByteArrayAsync(song.strAlbumThumb);
MemoryStream stream = new MemoryStream(bytes.ToArray());
var ImageStream =stream.AsRandomAccessStream();
var bitmapimage = new BitmapImage();
await bitmapimage.SetSourceAsync(ImageStream);
songs.Add(new SongList() { Image = bitmapimage, name = song.strAlbum });
}
return songs;
}
}
public class RootObject
{
public List<Album> album { get; set; }
}
public class Album
{
public string strAlbumThumb { get; set; }
public string strAlbum { get; set; }
}
public class SongList
{
public ImageSource Image { get; set; }
public string name { get; set; }
}
ItemsSource="{x:Bind AllSongs}"
There we go. Are you sure the AllSongs type is ImageSource? From what I see it's a list, not an image.
ImageSource can't be image because of that I think below code will help you to turn your Image to ImageSource.
using (var ms = new MemoryStream())
{
image.Save(ms, ImageFormat.Bmp);
ms.Seek(0, SeekOrigin.Begin);
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = ms;
bitmapImage.EndInit();
return bitmapImage;
}
You can check this answer link.
Related
Im using WebApi to Deserialize Object on client side, witch contains some lightweight images, the code reads:
private void Button_Click(object sender, object e)
{
LoadApi();
}
private async void LoadApi()
{
using (var client = new HttpClient())
{
var responseMessage = await client.GetAsync("http://" +
TxtIP.Text + "/api/prod");
if (responseMessage.StatusCode == System.Net.HttpStatusCode.OK)
{
List<ClsProd> lstData = new List<ClsProd>();
var jsonResponse = await
responseMessage.Content.ReadAsStringAsync();
if (jsonResponse != null)
{
lstData = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ClsProd>>(jsonResponse);
}
ListView1.ItemsSource = lstData;
}
}
}
my ClsProd looks witch get all data from Web Api is:
public class ClsProd : System.ComponentModel.INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public int IAuto { get; set; }
public int IDevc { get; set; }
public string SName { get; set; }
public string SImax { get; set; }
public ImageSource ImgPg { get; set; }
public ClsProd(int auto, int devc, string name, string imax)
{
IAuto = auto;
IDevc = devc;
SName = name;
SImax = imax;
ClsImgBase64 CImg = new ClsImgBase64();
CImg.EvtResult += CImg_EvtResult;
CImg.Start(imax);
}
private void CImg_EvtResult(ImageSource e)
{
ImgPg = e;
NotifyPropertyChanged("ImgPg");
}
}
All data is properly fetch and displayed on list, including string SImax witch is image encoded as Base64 string. The only problem is image conversion from base64 string to image is not happening.
Here is my class it does not pass the 1st statment on Task.Run, please help me find what is wrong. Also same funcition works when called from async void.
public class ClsImgBase64
{
public event Action<ImageSource> EvtResult;
public ClsImgBase64()
{
}
public void Start(string s)
{
System.Threading.Tasks.Task.Run(async () =>
{
//read stream
byte[] bytes = Convert.FromBase64String(s);
var image = bytes.AsBuffer().AsStream().AsRandomAccessStream();
//decode image
//var decoder = await BitmapDecoder.CreateAsync(image);
image.Seek(0);
//create bitmap
var output = new WriteableBitmap(1, 1);
await output.SetSourceAsync(image);
if (EvtResult != null)
{
EvtResult(output);
}
});
}
}
As per async void there's probably an Exception thrown which was lost and not displayed bacause the executing code is not awaited. Let's fix it.
Web part
avoid async void in methods that's aren't event handlers, also handle all possible exceptions in async void method
HttpClient is intended to be instantiated once per app rather than per use
HttpResponseMessage is IDisposable
private async void Button_Click(object sender, object e)
{
try
{
await LoadDataAsync();
}
catch (Exception ex)
{
// show ex.Message here in UI or log it
}
}
private static readonly HttpClient _client = new HttpClient();
private async Task LoadDataAsync()
{
using var response = await _client.GetAsync($"http://{TxtIP.Text}/api/prod");
string json = await response.EnsureSuccessStatusCode().Content.ReadAsStringAsync();
List<ClsProd> data = JsonConvert.DeserializeObject<List<ClsProd>>(json);
ListView1.ItemsSource = data;
await DecodeAllImagesAsync(data);
}
// decoding all at once asynchronously, see implementation below
private Task DecodeAllImagesAsync(List<ClsProd> data)
{
return Task.WhenAll(data.Select(item => item.DecodeImageAsync()).ToArray());
}
Consider using System.Text.Json to deserealize instead of old Newtonsoft.Json. It would allow to deserealize response.Content as Stream, faster with less memory consumption e.g:
using var stream = await response.EnsureSuccessStatusCode().Content.ReadAsStreamAsync();
List<ClsProd> data = await JsonSerializer.DeserealizeAsync<List<ClsProd>>(stream);
Data part
Use using directives at the beggining of the code to attach namespaces that will help not to repeat namespaces in the code explicitly
using System.ComponentModel;
It makes possible to write INotifyPropertyChanged instead of System.ComponentModel.INotifyPropertyChanged. I'll remove inlined namespaces below.
don't start long-running job from a constructor, it's unpredictable behavior because costructor must be always successful. Start loading images later. Also constructor cannot await asynchronous tasks. Separate method can.
public class ClsProd : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private ImageSource _imgPg;
public int IAuto { get; set; }
public int IDevc { get; set; }
public string SName { get; set; }
public string SImax { get; set; }
public ImageSource ImgPg
{
get => _imgPg;
set
{
_imgPg = value;
NotifyPropertyChanged();
}
}
public ClsProd(int auto, int devc, string name, string imax)
{
IAuto = auto;
IDevc = devc;
SName = name;
SImax = imax;
}
public async Task DecodeImageAsync()
{
ImgPg = await ClsImgBase64.DecodeAsync(SImax);
}
}
Decoder
As now it's awaitable and doesn't need a callback, decoding method doesn't interact with the instance data. So, it can be static.
public static class ClsImgBase64
{
public static async Task<ImageSource> DecodeAsync(string base64)
{
byte[] bytes = Convert.FromBase64String(base64);
using var stream = bytes.AsBuffer().AsStream().AsRandomAccessStream();
// stream.Seek(0); // not sure if it needed
var decoder = await BitmapDecoder.CreateAsync(stream);
var pixelData = await decoder.GetPixelDataAsync();
var pixelArray = pixelData.DetachPixelData();
var bitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
await bitmap.PixelBuffer.AsStream().WriteAsync(pixelArray, 0, pixelArray.Length);
return bitmap;
}
}
Decoder's code based on this answer.
If it will be laggy, try to wrap 2 Decoder's lines with Task.Run. Only if it will be laggy.
using var stream = await Task.Run(() =>
{
byte[] bytes = Convert.FromBase64String(base64);
return bytes.AsBuffer().AsStream().AsRandomAccessStream();
});
Finally: give classes, methods and other things more clear names, that would make the code maintainable.
I'm trying to display a varbinary image from database, i'm converting it to byte[] with this code
Filme.cs
if (row["foto"] != DBNull.Value)
f.Foto = (byte[])row["foto"];
and this is how i'm choosing the file to send to the database
GestaoDeFilmesViewModel.cs
public async static Task<StorageFile> OpenLocalFile(params string[] types)
{
var picker = new FileOpenPicker();
picker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
Regex typeReg = new Regex(#"^\.[a-zA-Z0-9]+$");
foreach (var type in types)
{
if (type == "*" || typeReg.IsMatch(type))
picker.FileTypeFilter.Add(type);
else
throw new InvalidCastException("A extensão do ficheiro está incorreta");
}
var file = await picker.PickSingleFileAsync();
if (file != null)
return file;
else
return null;
}
and then sending it like this
GestaoDeFilmesViewModel.cs
public async Task<bool> UpdateFoto(StorageFile file)
{
if (file == null)
return false;
SelectedFilme.Foto = (await FileIO.ReadBufferAsync(file)).ToArray();
if(SelectedFilme.Foto == null)
{
return false;
}
if (SelectedFilme.UpdateFoto() == 1)
{
return true;
}
return false;
}
this is the user control i'm using to convert the image from byte[] to BitMapImage
FotoControl.xaml
<Page
x:Class="MyMovies.universal.UserControl.FotoControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyMovies.universal.UserControl"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Image x:Name="Foto"></Image>
</Grid>
</Page>
here is the code behind, an exception is thrown in Source_Changed method, i'll post a picture about it
FotoControl.xaml.cs
public sealed partial class FotoControl : UserControl
{
public FotoControl()
{
this.InitializeComponent();
}
public byte[] ImageSource
{
get { return (byte[])GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
}
public static readonly DependencyProperty ImageSourceProperty =
DependencyProperty.Register("ImageSource", typeof(byte[]), typeof(UserControlFolder.FotoControl), new PropertyMetadata(null, new PropertyChangedCallback(Source_Changed)));
private static async void Source_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != null && e.NewValue is byte[] data)
{
var instance = d as FotoControl;
BitmapImage image = new BitmapImage();
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
await stream.WriteAsync(data.AsBuffer());
await image.SetSourceAsync(stream);
}
instance.Foto.Source = image;
}
}
}
and this is the page where i'm showing the image, after the conversion
GestaoDeFilmes.xaml
<control:FotoControl ImageSource="{Binding Foto, Mode=TwoWay}"/>
You can see by the debug image that Foto has content, isn't null.
I think the exception has something to do with Windows not being able to decode the image from what other people said.
Thanks in advance.
Please check this. you seem to be miss stream.Seek(0)
public async static Task<BitmapImage> ImageFromBytes(Byte[] bytes)
{
BitmapImage image = new BitmapImage();
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
await stream.WriteAsync(bytes.AsBuffer());
stream.Seek(0);
await image.SetSourceAsync(stream);
}
return image;
}
For a WPF project I need to read a BitmapImage from a Zip file. The original fileformat is .png I know how to do this directly from a file system and that is working fine. From a Zip file, unfortunately the image is not shown, though an image seems to be read.
I created a simple test project:
public partial class MainWindow : Window
{
public BitmapImage RouteImage { get; set; }
public MainWindow()
{
InitializeComponent();
LoadBitmap();
DataContext = RouteImage;
}
public void LoadBitmap()
{
RouteImage = new BitmapImage();
var PackedFile = #"D:\Temp\MainContent.ap";
try
{
{
using (ZipArchive archive = ZipFile.OpenRead(PackedFile))
{
var file = archive.GetEntry("RouteInformation/image.png");
if (file != null)
{
using (var zipEntryStream = file.Open())
{
RouteImage.BeginInit();
RouteImage.CacheOption = BitmapCacheOption.OnLoad;
RouteImage.StreamSource = zipEntryStream;
RouteImage.EndInit();
return;
}
}
}
}
}
catch (Exception e)
{
var s = "Exception: " + e.Message;
}
}
}
}
The XAML code looks like this:
<Image Height="128" Width="256" Source="{Binding BitmapImage}"/>
In the debugger it looks like the stream is created and bound to the BitmapImage, but the width and height are set to 1. so I think something is wrong withe the reading of the data in the zip file.
Not sure about the exact reason, but it seems necessary to copy the zip stream to an intermediate MemoryStream and read the BitmapImage from there.
You should also write a view model class with property change notification:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private BitmapImage routeImage;
public BitmapImage RouteImage
{
get { return routeImage; }
set
{
routeImage = value;
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(nameof(RouteImage)));
}
}
public void LoadImage(string archiveName, string entryName)
{
using (var archive = ZipFile.OpenRead(archiveName))
{
var entry = archive.GetEntry(entryName);
if (entry != null)
{
using (var zipStream = entry.Open())
using (var memoryStream = new MemoryStream())
{
zipStream.CopyTo(memoryStream); // here
memoryStream.Position = 0;
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = memoryStream;
bitmap.EndInit();
RouteImage = bitmap;
}
}
}
}
}
Assign an instance of the view model to the DataContext of your Window:
public MainWindow()
{
InitializeComponent();
var viewModel = new ViewModel();
DataContext = viewModel;
viewModel.LoadImage(
#"D:\Games\steamapps\common\RailWorks\Content\Routes\00000036-0000-0000-0000-000000002012\MainContent.ap",
"RouteInformation/image.png");
}
and bind the RouteImage property like this:
<Image Source="{Binding RouteImage}"/>
If you are intending to load large image file from the zip archive, I'd recommend to call the view model code in an async method:
public async Task LoadImageAsync(string archiveName, string entryName)
{
RouteImage = await Task.Run(() => LoadImage(archiveName, entryName));
}
private BitmapImage LoadImage(string archiveName, string entryName)
{
BitmapImage bitmap = null;
using (var archive = ZipFile.OpenRead(archiveName))
{
var entry = archive.GetEntry(entryName);
if (entry != null)
{
using (var zipStream = entry.Open())
using (var memoryStream = new MemoryStream())
{
zipStream.CopyTo(memoryStream);
memoryStream.Position = 0;
bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = memoryStream;
bitmap.EndInit();
bitmap.Freeze(); // necessary when loaded in non-UI thread
}
}
}
return bitmap;
}
Call the method from an async Loaded event handler in your MainWindow:
Loaded += async (s, e) => await viewModel.LoadImageAsync
#"D:\Games\steamapps\common\RailWorks\Content\Routes\00000036-0000-0000-0000-000000002012\MainContent.ap",
"RouteInformation/image.png");
In my work to remove an image from a zip container, that using a middle thread as per Clemens answer only created an exception and was not tenable.
Ultimately I was able to use this code to extract a BitmapImage:
public static class StreamExtensions
{
public static BitmapImage ToImage(this Stream stream)
{
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = stream;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.EndInit();
return bitmap;
}
}
Usage
var image = zipEntry.Open().ToImage();
I have a Web image with specified URL, it can be browsed in the browser.
i tried to retrieve it from web url and when program goes to bitmapImage.SetSource(ms); i get a exception "
ex = {System.Exception: The component cannot be found. (Exception from HRESULT: 0x88982F50)
at MS.Internal.XcpImports.CheckHResult(UInt32 hr)
at MS.Internal.XcpImports.BitmapSource_SetSource(BitmapSource bitmapSource, CValue& byteStream)
at System.Wi...
"
i did searched other questions on stackoverflow...but no help on this. any one can help me?
byte array did have data, in the runtime debugging, it returns imageByteArray = {byte[1227]}; my option is that exception occurs when converting byte array to BitmapImage.
in the httpclient wrapper class:
public static async Task<Byte[]> GetWebImageByImageName(string ImageName)
{
//Uri imageServerUril = new Uri(ImageName);
var requestMessage = new HttpRequestMessage(HttpMethod.Get, ImageName);
var responseMessage = await client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead);
var responseData = await responseMessage.Content.ReadAsByteArrayAsync();
return responseData;
}
in the view model:
private async void ReadArticleList(int pageNumber)
{
string webURL = "http://....."; // the web URL is no problem
try
{
byte[] imageByteArray = await CollectionHttpClient.GetWebImageByImageName(webURL);//
//Convert it to BitmapImage
using (MemoryStream ms = new MemoryStream(imageByteArray))
{
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.CreateOptions = BitmapCreateOptions.DelayCreation;
bitmapImage.SetSource(ms); // the exception got here
item.BitImage = bitmapImage;
}
IsLoading = false;
}
catch(Exception ex)
{
if (ex.HResult == -2146233088 && ex.Message.Equals("Response status code does not indicate success: 404 ()."))
{
MessageBox.Show("The network is not set right. Internet cannot be accessed.");
}
else
{
MessageBox.Show("sorry, no data.");
}
IsLoading = false;
}
}
* for Detail *
BitImage is a instance of BitmapImage;
item.BitImage: item is a instance of Article
image format is JPEG
Article model is in below:
public class Article : INotifyPropertyChanged
{
private long _Id;
public long ID
{
get { return _Id; }
set
{
if (_Id != value)
{
_Id = value;
NotifyPropertyChanged("ID");
}
}
}
private string _subject;
public string Subject
{
get
{
return _subject;
}
set
{
if (_subject != value)
{
_subject = value;
NotifyPropertyChanged("Subject");
}
}
}
private string _words;
public string Words
{
get
{
return _words;
}
set
{
if (_words != value)
{
_words = value;
NotifyPropertyChanged("Words");
}
}
}
private DateTime _publishDate;
public DateTime PublishDate
{
get
{ return _publishDate; }
set
{
if (_publishDate != value)
{
_publishDate = value;
NotifyPropertyChanged("PublishDate");
}
}
}
public List<string> ImagePathList = new List<string>();
public BitmapImage BitImage = new BitmapImage();
private string _firstImage;
public string FirstImage
{
get
{
return _firstImage;
}
set
{
if (_firstImage != value)
{
_firstImage = value;
NotifyPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
If you just want to display an image from a remote server without saving it, do the following:
imageControl1.Source = new BitmapImage(new Uri("http://delisle.saskatooncatholic.ca/sites/delisle.saskatooncatholic.ca/files/sample-1.jpg", UriKind.Absolute));
If you want to save the image to IsolatedStorage you can do the following:
WebClient webClientImg = new WebClient();
webClientImg.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
webClientImg.OpenReadAsync(new Uri("http://delisle.saskatooncatholic.ca/sites/delisle.saskatooncatholic.ca/files/sample-1.jpg", UriKind.Absolute));
void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
isSpaceAvailable = IsSpaceIsAvailable(e.Result.Length);
if (isSpaceAvailable)
{
SaveToJpeg(e.Result);
}
else
{
MessageBox.Show("You are running low on storage space on your phone. Hence the image will be loaded from the internet and not saved on the phone.", "Warning", MessageBoxButton.OK);
}
}
Function to check if IsolatedStorage space is available or else it will not download the image.
private bool IsSpaceIsAvailable(long spaceReq)
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
long spaceAvail = store.AvailableFreeSpace;
if (spaceReq > spaceAvail)
{
return false;
}
return true;
}
}
If space was available, save as image to IsolatedStorage using the below function:
private void SaveToJpeg(Stream stream)
{
using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream isostream = iso.CreateFile("image1.jpg"))
{
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(stream);
WriteableBitmap wb = new WriteableBitmap(bitmap);
// Encode WriteableBitmap object to a JPEG stream.
Extensions.SaveJpeg(wb, isostream, wb.PixelWidth, wb.PixelHeight, 0, 85);
isostream.Close();
LoadImageFromIsolatedStorage(); //Load recently saved image into the image control
}
}
}
Load the image in image control from IsolatedStorage:
private void LoadImageFromIsolatedStorage()
{
byte[] data;
try
{
using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream isfs = isf.OpenFile("image1.jpg", FileMode.Open, FileAccess.Read))
{
data = new byte[isfs.Length];
isfs.Read(data, 0, data.Length);
isfs.Close();
}
}
MemoryStream ms = new MemoryStream(data);
BitmapImage bi = new BitmapImage();
bi.SetSource(ms);
imageControl1.Source = bi;
}
catch
{
}
}
Image taken randomly from Google Search. Credits to the image lie to the owner.
Hope this helps. :)
#Mark , you are correct, this works according to what you suggest.
i think the problem is if i used code below, i got the byte array is byte[1227]
var requestMessage = new HttpRequestMessage(HttpMethod.Get, ImageName);
var responseMessage = await client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead);
var responseData = await responseMessage.Content.ReadAsByteArrayAsync();
return responseData;
and if i use var byteArray = await client.GetByteArrayAsync(ImageName); the byte array size is byte[5996]
i do not know why this happens, but Mark's solution works.
all my code is as below:
in a MVVM pattern
// get image from URL, ImageName is an absolute Url
public static async Task<BitmapImage> GetWebImageByImageName(string ImageName)
{
//Uri imageServerUril = new Uri(ImageName);
var byteArray = await client.GetByteArrayAsync(ImageName);
//Convert byte array to BitmapImage
BitmapImage bitmapImage;
using (MemoryStream ms = new MemoryStream(byteArray))
{
bitmapImage = new BitmapImage();
bitmapImage.SetSource(ms);
}
return bitmapImage;
}
in the ViewModel
public void LoadPage(int pageNumber)
{
if (pageNumber == 1)
{
this.ArticleCollection.Clear();
}
IsLoading = true;
ReadArticleList(pageNumber);
}
private async void ReadArticleList(int pageNumber)
{
try
{
List<Article> articleList = new List<Article>();
articleList = await CollectionHttpClient.GetArticlesByPageAsync(pageNumber);
foreach (var item in articleList)
{
item.BitImage = await CollectionHttpClient.GetWebImageByImageName(item.ImagePathList[0]);
this.ArticleCollection.Add(item);
}
IsLoading = false;
}
catch(Exception ex)
{
if (ex.HResult == -2146233088 && ex.Message.Equals("Response status code does not indicate success: 404 ()."))
{
MessageBox.Show("The network is not set right. Internet cannot be accessed.");
}
else
{
MessageBox.Show("sorry, no data.");
}
IsLoading = false;
}
}
Model is:
public class Article : INotifyPropertyChanged
{
private long _Id;
public long ID
{
get { return _Id; }
set
{
if (_Id != value)
{
_Id = value;
NotifyPropertyChanged("ID");
}
}
}
private string _subject;
public string Subject
{
get
{
return _subject;
}
set
{
if (_subject != value)
{
_subject = value;
NotifyPropertyChanged("Subject");
}
}
}
private string _words;
public string Words
{
get
{
return _words;
}
set
{
if (_words != value)
{
_words = value;
NotifyPropertyChanged("Words");
}
}
}
private DateTime _publishDate;
public DateTime PublishDate
{
get
{ return _publishDate; }
set
{
if (_publishDate != value)
{
_publishDate = value;
NotifyPropertyChanged("PublishDate");
}
}
}
private ObservableCollection<string> _imagePathList = new ObservableCollection<string>();
public ObservableCollection<string> ImagePathList
{
get { return this._imagePathList; }
set
{
if (this._imagePathList != value)
{
this._imagePathList = value;
// I'm going to assume you have the NotifyPropertyChanged
// method defined on the view-model
this.NotifyPropertyChanged();
}
}
}
BitmapImage _image;
public BitmapImage BitImage
{
get
{
return _image;
}
set
{
if (ImagePathList.Any())
{
value = new BitmapImage(new Uri(ImagePathList.FirstOrDefault(), UriKind.RelativeOrAbsolute));
_image = value;
}
}
}
private Uri _firstImage;
public Uri FirstImage
{
get
{
return _firstImage;
}
set
{
if (_firstImage != value)
{
_firstImage = value;
NotifyPropertyChanged("FirstImage");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
First if you have the url you can give url to the binding paramter and it will automatically show the image or if you want to download the image and save it & then display it so here is the code for byte to image & image to byte.
{
BitmapImage image = new BitmapImage();
MemoryStream ms = new MemoryStream();
WriteableBitmap wb = new WriteableBitmap(image);
wb.SaveJpeg(ms, image.PixelWidth, image.PixelHeight, 0, 100);
imageBytes = ms.ToArray();
}
Use this to save image because i am using it my code.
I have an application that takes photos, converts them into byte arrays and saves them locally in the Isolated Storage. It then reads them out and converts them back into an BitmapImage.
However, I can't seem to show the images in a ListBox. I am using the same code I have in another page that works perfectly.
The BitmapImage has a image in it, but that is as much as I know. Whether that image is legitimate or not, I don't know or know how to check.
Any ideas would be greatly appreciated.
SEE CODE BELOW
Convert Image
public byte[] ImageToBytes(BitmapImage img)
{
using (MemoryStream ms = new MemoryStream())
{
WriteableBitmap btmMap = new WriteableBitmap(img.PixelWidth, img.PixelHeight);
// write an image into the stream
Extensions.SaveJpeg(btmMap, ms, img.PixelWidth, img.PixelHeight, 0, 100);
return ms.ToArray();
}
}
public BitmapImage BytesToImage(byte[] bytes)
{
BitmapImage bitmapImage = new BitmapImage();
MemoryStream ms = new MemoryStream(bytes);
bitmapImage.SetSource(ms);
return bitmapImage;
}
Class with image
public class NewItem
{
ObservableCollection<BitmapImage> images = new ObservableCollection<BitmapImage>();
[DataMember]
public ObservableCollection<BitmapImage> Images
{
get { return images; }
set { images = value; }
}
[DataMember]
public string Notes { get; set; }
[DataMember]
public string ItemID { get; set; }
}
Saving to storage
public static void AddOrUpdateUnsavedItems(NewItem _item)
{
var store = IsolatedStorageFile.GetUserStoreForApplication();
List<NewItem> allunsaveditems = new List<NewItem>();
if (store.FileExists("unsaveditem"))
{
allunsaveditems.Add(_item);
allunsaveditems.AddRange(LoadUnsavedItemsFromIsolatedStorage());
store.DeleteFile("unsaveditem");
}
UnsavedRegisters.Clear();
foreach (NewItem ni in allunsaveditems)
{
StoredItem newUnsavedItem = new StoredItem();
newUnsavedItem.ItemID = ni.ItemID;
newUnsavedItem.Notes = ni.Notes;
foreach (BitmapImage bmp in ni.Images)
{
newUnsavedItem.ImageBytes.Add(newUnsavedItem.ImageToBytes(bmp));
}
UnsavedRegisters.Add(newUnsavedItem);
}
using (var stream = new IsolatedStorageFileStream("unsaveditem", FileMode.OpenOrCreate, FileAccess.Write, store))
{
DataContractSerializer dcs = new DataContractSerializer(typeof(List<StoredItem>));
dcs.WriteObject(stream, UnsavedRegisters);
}
}
Loading from storage
public static List<NewItem> LoadUnsavedItemsFromIsolatedStorage()
{
List<NewItem> unsavedItems = new List<NewItem>();
try
{
var store = IsolatedStorageFile.GetUserStoreForApplication();
if (store.FileExists("unsaveditem"))
{
using (var stream = new IsolatedStorageFileStream("unsaveditem", FileMode.OpenOrCreate, FileAccess.Read, store))
{
if (stream.Length > 0)
{
DataContractSerializer dcs = new DataContractSerializer(typeof(List<StoredItem>));
List<StoredItem> storedItems = dcs.ReadObject(stream) as List<StoredItem>;
foreach (StoredItem si in storedItems)
{
NewItem ni = new NewItem();
ni.ItemID = si.ItemID;
ni.Notes = si.Notes;
foreach (byte[] imageBytes in si.ImageBytes)
{
ni.Images.Add(si.BytesToImage(imageBytes));
}
unsavedItems.Add(ni);
}
}
}
}
}
catch (Exception)
{
//MessageBox.Show("and error happened getting the unsaved items");
// handle exception
return null;
}
return unsavedItems;
}
This should not be a problem, I had this working for a BitmapSource, Which I believe BitmapImage inherits from, try the code below in your listbox
<Border Height="200" Width="200">
<Border.Background>
<ImageBrush ImageSource="{Binding ItemImage}" />
</Border.Background>
</Border>
ItemImage is the Property holding your BitmapSource image.
I don't know what has changed, but it started working.