Save a remote image in to Isolated Storage - c#

I tried using this code for download image:
void downloadImage(){
WebClient client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(new Uri("http://mysite/image.png"));
}
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
//how get stream of image??
PicToIsoStore(stream)
}
private void PicToIsoStore(Stream pic)
{
using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
var bi = new BitmapImage();
bi.SetSource(pic);
var wb = new WriteableBitmap(bi);
using (var isoFileStream = isoStore.CreateFile("somepic.jpg"))
{
var width = wb.PixelWidth;
var height = wb.PixelHeight;
Extensions.SaveJpeg(wb, isoFileStream, width, height, 0, 100);
}
}
}
The problem is: how get the stream of image?
Thank!

It's easy to get a stream to a file in Isolated Storage. IsolatedStorageFile has an OpenFile method that gets one.
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = store.OpenFile("somepic.jpg", FileMode.Open))
{
// do something with the stream
}
}

You need to put e.Result as a parameter when calling PicToIsoStore inside your client_DownloadStringCompleted method
void client_DownloadStringCompleted(object sender,
DownloadStringCompletedEventArgs e)
{
PicToIsoStore(e.Result);
}
The WebClient class gets response and stores it in the e.Result variable. If you look carefully, the type of e.Result is already Stream so it is ready to be passed to your method PicToIsoStore

There is an easy way
WebClient client = new WebClient();
client.OpenReadCompleted += (s, e) =>
{
PicToIsoStore(e.Result);
};
client.OpenReadAsync(new Uri("http://mysite/image.png", UriKind.Absolute));

Try the following
public static Stream ToStream(this Image image, ImageFormat formaw) {
var stream = new System.IO.MemoryStream();
image.Save(stream);
stream.Position = 0;
return stream;
}
Then you can use the following
var stream = myImage.ToStream(ImageFormat.Gif);

Related

WP8 C# // Save image from web, in isolate storage

I know how to save an image in isolate storage using the following :
private void addButton_Click(object sender, RoutedEventArgs e)
{
MemoryStream stream = new MemoryStream();
WriteableBitmap wb = new WriteableBitmap(myImage, null);
BitmapImage bi = new BitmapImage();
wb.SaveJpeg(stream, wb.PixelWidth, wb.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
string data = Convert.ToBase64String(stream.GetBuffer());
appSettings.Add("image", data);
}
I know how to load it using the following :
private void loadImage_Click(object sender, RoutedEventArgs e)
{
byte[] imageBytes = Convert.FromBase64String(appSettings["image"].ToString());
MemoryStream ms = new MemoryStream(imageBytes);
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(ms);
myImage.Source = bitmapImage;
}
But I don't know how to load and read it from a URL, how can this be accomplished?
Thx for your help.
From this Image from URL to stream:
WebClient client = new WebClient();
client.OpenReadCompleted += (s, e) =>
{
byte[] imageBytes = new byte[e.Result.Length];
e.Result.Read(imageBytes, 0, imageBytes.Length);
// Now you can use the returned stream to set the image source too
var image = new BitmapImage();
image.SetSource(e.Result);
NLBI.Thumbnail.Source = image;
};
client.OpenReadAsync(new Uri(article.ImageURL));
Edit: here is some more info on OpenReadComplete(MSDN) and how to use it

How to save images from web in Isolated Storage?

In my application I have list of urls to images. And what I need to do is download this images and save them in Isolated Storage.
What I already have:
using (IsolatedStorageFile localFile = IsolatedStorageFile.GetUserStoreForApplication()) {
...
foreach (var item in MyList)
{
Uri uri = new Uri(item.url, UriKind.Absolute);
BitmapImage bitmap = new BitmapImage(uri);
WriteableBitmap wb = new WriteableBitmap(bitmap);
using (IsolatedStorageFileStream fs = localFile.CreateFile(GetFileName(item.url)))//escape file name
{
wb.SaveJpeg(fs, wb.PixelWidth, wb.PixelHeight, 0, 85);
}
}
...
}
This code have place inside function in my App.xaml.cs file. I have tried many solutions, in this one the problem is "Invalid cross-thread access".
How can I make it work?
You get invalid cross-thread access if you create WriteableBitmap on non-UI thread. Ensure that that code is run on the main thread by using Dispatcher:
Deployment.Current.Dispatcher.BeginInvoke(() =>
// ...
);
Solution for this problem is:
foreach (var item in MyList)
{
Uri uri = new Uri(item.url, UriKind.Absolute);
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.BeginGetResponse((ar) =>
{
var response = request.EndGetResponse(ar);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
using (var stream = response.GetResponseStream())
{
var name = GetFileName(item.url);
if (localFile.FileExists(name))
{
localFile.DeleteFile(name);
}
using (IsolatedStorageFileStream fs = localFile.CreateFile(name))
{
stream.CopyTo(fs);
}
}
});
}, null);
}
#Mateusz Rogulski
You should use WebClient, and i suggest you following solution for your problem. just try.
public string YourMethod(string yoursUri)
{
BitmapImage image=new BitmapImage();
WebClient client = new WebClient();
client.OpenReadCompleted += async (o, args) =>
{
Stream stream = new MemoryStream();
await args.Result.CopyToAsync(stream);
image.SetSource(stream);
};
client.OpenReadAsync(new Uri(yoursUri));//if passing object than you can write myObj.yoursUri
return image;
}
now you have image and you can save into your isolatedStorage with valid checks wherever you call this function

System.InvalidOperationException occur when load saved Image from IsolatedStorage

I have found a class from the link ImageCaching
but when i load from isolated storage i got an exeption "System.InvalidOperationException"
here is my code
public static object DownloadFromWeb(Uri imageFileUri)
{
WebClient m_webClient = new WebClient(); //Load from internet
BitmapImage bm = new BitmapImage();
m_webClient.OpenReadCompleted += (o, e) =>
{
if (e.Error != null || e.Cancelled) return;
WriteToIsolatedStorage(IsolatedStorageFile.GetUserStoreForApplication(), e.Result, GetFileNameInIsolatedStorage(imageFileUri));
bm.SetSource(e.Result);
e.Result.Close();
};
m_webClient.OpenReadAsync(imageFileUri);
return bm;
}
public static object ExtractFromLocalStorage(Uri imageFileUri)
{
byte[] data;
string isolatedStoragePath = GetFileNameInIsolatedStorage(imageFileUri); //Load from local storage
if (null == _storage)
{
_storage = IsolatedStorageFile.GetUserStoreForApplication();
}
using (IsolatedStorageFileStream sourceFile = _storage.OpenFile(isolatedStoragePath, FileMode.Open, FileAccess.Read))
{
// Read the entire file and then close it
sourceFile.Read(data, 0, data.Length);
sourceFile.Close();
BitmapImage bm = new BitmapImage();
bm.SetSource(sourceFile);///here got the exeption
return bm;
}
}
so that i can't set the image.
I'm using the converter you mentioned and it works but you modified the method.
Your ExtractFromLocalStorage method isn't the same. You close your stream before to use it with the SetSource method.
Here is the original method code:
private static object ExtractFromLocalStorage(Uri imageFileUri)
{
string isolatedStoragePath = GetFileNameInIsolatedStorage(imageFileUri); //Load from local storage
using (var sourceFile = _storage.OpenFile(isolatedStoragePath, FileMode.Open, FileAccess.Read))
{
BitmapImage bm = new BitmapImage();
bm.SetSource(sourceFile);
return bm;
}
}

Windows Phone - Image cache - wait for download an image

I made a project to Cache Images. I want to wait in main thread for complete DownloadImage function and then return that saved bitmap. Is that possible?
Am I doing it even properly?
public static ImageSource GetImage(int id)
{
BitmapImage bitmap = new BitmapImage();
String fileName=string.Format("ImageCache/{0}.jpg", id);
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!myIsolatedStorage.DirectoryExists("ImageCache"))
{
myIsolatedStorage.CreateDirectory("ImageCache");
}
if (myIsolatedStorage.FileExists(fileName))
{
using (IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile(fileName, FileMode.Open, FileAccess.Read))
{
bitmap.SetSource(fileStream);
}
}
else
{
DownloadImage(id);
//HERE - how to wait for end of DownloadImage and then do that below??
using (IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile(fileName, FileMode.Open, FileAccess.Read))
{
bitmap.SetSource(fileStream);
}
}
}
return bitmap;
}
Here is DownloadImage function:
private static void DownloadImage(Object id)
{
WebClient client = new WebClient();
client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
client.OpenReadAsync(new Uri(string.Format("http://example.com/{0}.jpg", id)), id);
}
private static void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (e.Error == null && !e.Cancelled)
{
try
{
string fileName = string.Format("ImageCache/{0}.jpg", e.UserState);
IsolatedStorageFileStream fileStream = myIsolatedStorage.CreateFile(fileName);
BitmapImage image = new BitmapImage();
image.SetSource(e.Result);
WriteableBitmap wb = new WriteableBitmap(image);
// Encode WriteableBitmap object to a JPEG stream.
Extensions.SaveJpeg(wb, fileStream, wb.PixelWidth, wb.PixelHeight, 0, 85);
fileStream.Close();
}
catch (Exception ex)
{
//Exception handle appropriately for your app
}
}
}
}
You have many way to achieve what you want. It is possible to wait with async await command which is part of Visual Studio Async.
You can download the latest CTP from here. More how to use it.
Personally I would use events.
This one contains some details and code example: http://www.ben.geek.nz/2010/07/one-time-cached-images-in-windows-phone-7/

Download an image from url and opening it in an image control in wp7

I am making a WP7 app which download all my twitter feed. In this I want to download all the profile images and store them locally and use them, so that they would be downloaded every time i open the app. Please suggest any of the methods to do so.
What I am doing: using a WebClient to download the image
public MainPage()
{
InitializeComponent();
WebClient client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(new Uri("http://www.libpng.org/pub/png/img_png/pnglogo-blk.jpg"));
}
and store it to a file.
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (myIsolatedStorage.FileExists(fileName1))
myIsolatedStorage.DeleteFile(fileName1);
var fileName1 = "Image.jpg";
using (var fileStream = new IsolatedStorageFileStream(fileName1, FileMode.Create, myIsolatedStorage))
{
using (var writer = new StreamWriter(fileStream))
{
var length = e.Result.Length;
writer.WriteLine(e.Result);
}
var fileStreamLength = fileStream.Length;
fileStream.Close();
}
}
Now I am trying to set the image to a BitMapImage
BitmapImage bi = new BitmapImage();
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile(fileName1, FileMode.Open, FileAccess.Read))
{
var fileStreamLength2 = fileStream.Length;
bi.SetSource(fileStream);
}
}
But I am not able to set source of the BitmapImage. It is throwing System.Exception and nothing specific. Am I doing it the right way? I mean the procedure.
EDIT Another observation is the fileStreamLength and fileStreamLength2 are different.
You're not supposed to use DownloadString to download a binary file. Use OpenReadAsync instead, and save the binary array to the isolated storage.
DownloadString will try to convert your data to UTF-16 text, which of course can't be right when dealing with a picture.

Categories