Base64ToImage in Windows 8 Store App - image

In my Windows 8 app I get an image as base64 string. Now I am looking for a method that converts the string so that I can include it in my XAML image, something like this:
public static Image Base64ToImage(string s)
{
// How To?
}
I have seen many solutions but all of them use classes/methods that are not available in Windows 8 store apps. Thanks for your hints.

The method could look like this:
private async Task<BitmapImage> Base64ToImage(string base64)
{
var bitmap = new BitmapImage();
var buffer = Convert.FromBase64String(base64);
using (var stream = new InMemoryRandomAccessStream())
{
await stream.WriteAsync(buffer.AsBuffer());
stream.Seek(0);
bitmap.SetSource(stream);
}
return bitmap;
}

Related

How to load/draw an image using NGraphics?

In my Xamarin Forms app, I have an image under androidProject/Resources/drawable/myImage.png. To load these from Xamarin, you can simply do
Image myImage = new Image() { Source = ImageSource.FromFile("myImage.png") };
However, there is no way to draw an Image using NGraphics. Instead, NGraphics DrawImage(IImage) requires an IImage. As far as I can tell, there's no way to turn a Xamarin.Forms.Image into an NGraphics.IImage. In fact, the only way I could find to load IImage is
IImage myImage = Platform.LoadImage("myImage.png");
However, this doesn't work because under the hood this uses BitmapFactory.decodeFile(), which requires the absolute file path. And I couldn't find any way to get the absolute file path of a resource (if it even exists?)
So, how do I actually load and display an image using NGraphics?
NGraphics does not provide any helpers to load images from your Platforms Resource files.
You could do something as follows. However, it will add some overhead converting back and forth between bitmap -> stream -> bitmap.
Android:
Stream GetDrawableStream(Context context, int resourceId)
{
var drawable = ResourcesCompat.GetDrawable(context.Resources, resourceId, context.Theme);
if (drawable is BitmapDrawable bitmapDrawable)
{
var stream = new MemoryStream();
var bitmap = bitmapDrawable.Bitmap;
bitmap.Compress(Bitmap.CompressFormat.Png, 80, stream);
bitmap.Recycle();
return stream;
}
return null;
}
iOS:
Stream GetImageStream(string fileName)
{
using (var image = UIImage.FromFile(fileName))
using (var imageData = image.AsPNG())
{
var byteArray = new byte[imageData.Length];
System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes, byteArray, 0, Convert.ToInt32(imageData.Length));
var stream = new MemoryStream(byteArray);
return stream;
}
return null;
}
However, you could go directly from Bitmap to BitmapImage on Android instead like:
BitmapImage GetBitmapFromDrawable(Context context, int resourceId)
{
var drawable = ResourcesCompat.GetDrawable(context.Resources, resourceId, context.Theme);
if (drawable is BitmapDrawable bitmapDrawable)
{
var bitmap = bitmapDrawable.Bitmap;
return new BitmapImage(bitmap);
}
return null;
}
And on iOS:
CGImageImage GetImageStream(string fileName)
{
var iOSimage = UIImage.FromFile(fileName);
var cgImage = new CGImageImage(iOSImage.CGImage, iOSImage.Scale);
return cgImage;
}
BitmapImage and CGImageImage implement IImage in NGraphics.

reviving image through sockets [Windows Store Apps - C# ]

I'm receiving an image on a Metro app through network socket every 1 second, loading it in an array of bytes, then convert it to a BitmapImage and display it later. All of this work fine.
The image is changing constantly on the other side. For some reason, it throws an OutOfMemory exceptions from now and then(like 1 in 10) . I fixed it by clearing the array of bytes every time the image is received. Now it works like charm.
See below for my main issue:
public static BitmapImage imag;
public static byte[] save = new byte[1];
if(recieved)
{
await reader.LoadAsync(4);
var sz = reader.ReadUInt32(); //read size
await reader.LoadAsync(sz); //read content
save = new byte[sz];
reader.ReadBytes(save);
await ImgSrcFromBytes(save)
Array.Clear(save, 0, save.Length); //issue here !!
}
public async Task<ImageSource> ImgSrcFromBytes(byte[] a)
{
imag = new BitmapImage();
var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
await stream.WriteAsync(a.AsBuffer());
stream.Seek(0);
imag.SetSource(stream);
return imag;
}
Now, i'm implementing a new function to save the image as a file if requested by the user with the code below, however, if i clear the array of bytes above, i get an unreadable image, but if i don't clear the array, i get a perfect image.
Note that no exceptions are thrown and both images have the same size.
FileSavePicker picker = new FileSavePicker();
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
picker.SuggestedFileName = "capture.png";
picker.FileTypeChoices.Add("Png File", new List<string>() { ".png" });
StorageFile file = await picker.PickSaveFileAsync();
if (file != null)
{
CachedFileManager.DeferUpdates(file);
await FileIO.WriteBytesAsync(file, save);
await CachedFileManager.CompleteUpdatesAsync(file);
await new Windows.UI.Popups.MessageDialog("Image Saved Successfully !").ShowAsync();
}
I hope i'm clear. It's a trade-off, if i clear the array, i will get no exceptions while receiving streams over sockets, but i won't be able to get a readable image when saving. and vice versa.

Image processing for windows phone

im searching for a good imaging SDK for windows phone ...
i tried to use Nokia SDK but it didn't work for me, it keeps showing as exception:
"Operation Is Not Valid Due To The Current State Of The Object."
here is my test code:
The processImage method is used to apply the filter on the image.
private async void processImage()
{
WriteableBitmap writeableBitmap = new WriteableBitmap((int)bitmapImage.PixelWidth, (int)bitmapImage.PixelHeight);
try
{
using (var imageStream = new StreamImageSource(photoStream))
{
// Applying the custom filter effect to the image stream
using (var customEffect = new NegateFilter(imageStream))
{
// Rendering the resulting image to a WriteableBitmap
using (var renderer = new WriteableBitmapRenderer(customEffect, writeableBitmap))
{
// Applying the WriteableBitmap to our xaml image control
await renderer.RenderAsync();
imageGrid.Source = writeableBitmap;
}
}
}
}
catch (Exception exc) { MessageBox.Show(exc.Message + exc.StackTrace, exc.Source, MessageBoxButton.OK); }
}
This is the NegateFilter class:
namespace ImagingTest
{
class NegateFilter : CustomEffectBase
{
public NegateFilter(IImageProvider source) : base(source){}
protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
{
sourcePixelRegion.ForEachRow((index, width, pos) =>
{
for (int x = 0; x < width; ++x, ++index)
{
targetPixelRegion.ImagePixels[index] = 255 - sourcePixelRegion.ImagePixels[index];
}
});
}
}
}
any ideas for a good imaging SDK? like ImageJ on java for example, or OpenCV ..
i will be better to use Nokia SDK ..
thx :)
I looked in to you code and did a quick test.
The code worked fine when I just made sure that the bitmapImage.PixelWidth and bitmapImage.PixelHeight > 0.
I did not get and image on the screen but when I remove your custom filter the image is show.
I hope you will continue to use the SDK since it is a great product.
What about emguCV?
I am not try it yet but looks like it's possible with phone's camera.

Getting stream from file absolute path

This may sound very simple but I've lost a lot of time looking for answer
In my Windows phone 8 app I use the PhotoChooserTask to let the user choose the photo, and i get the path of the photo by using
string FileName = e.OriginalFileName;
where e is the PhotoResult argument of the Task. , let's say: FileName=
"C:\Data\SharedData\Comms\Unistore\data\18\k\2000000a00000018700b.dat" (selected from the cloud) or
"D:\Pictures\Camera Roll\WP_20140110_10_40_42_1_Smart.jpg" (from camera roll)
I want to save that string path and open it up and show the image again when the users reopen the app. But I cannot find a method to convert those string into Image data (BitmapImage or Stream)
Any idea?
private void PhotoChooserTaskCompleted(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
var image = new BitmapImage();
image.SetSource(e.ChosenPhoto);
SaveImageAsync(image);
}
}
public async void SaveImageAsync(BitmapImage image)
{
await Task.Run(SaveImage(image));
}
public async Task SaveImage(BitmapImage image)
{
IStorageFolder folder = await ApplicationData.Current.LocalFolder
.CreateFolderAsync("Images", CreationCollisionOption.OpenIfExists);
IStorageFile file = await folder.CreateFileAsync(
imageFileName, CreationCollisionOption.ReplaceExisting);
using (Stream stream = await file.OpenStreamForWriteAsync())
{
var wrBitmap = new WriteableBitmap(image);
wrBitmap.SaveJpeg(stream, image.PixelWidth, image.PixelHeight, 100, 100);
}
}
At Windows Phone 8.1 you can try "StorageFolder.GetFolderFromPathAsync" static method (if this API is available at your app flavor) and then get a stream for a necessary file from that folder.

Binding Image stored in the Isolated Storage to Image Control in Windows Phone

Is it possible to bind the image present in the Isolates storage to image control through xaml. I found some implementations like getting the image through the property and binding that into xaml control. But this is not the implementation what I am searching for. My question is like, writing an attach property and helper method to fetch the content from Isolated storage. I found a similar implementation in LowProfileImage class, used in windows phone 7. But I think it is deprecated now. If anyone tried similar implementations please help me to achieve the same. Also if implementation have any performance drains please mention that info too.
Yes, it is possible to use images from isolated storage in the app UI. It requires loading the image from the file into the BitmapImage and then binding ImageSource of your control to that BitmapImage. I'm using the following approach:
First, there's a method to load image asynchronously:
private Task<Stream> LoadImageAsync(string filename)
{
return Task.Factory.StartNew<Stream>(() =>
{
if (filename == null)
{
throw new ArgumentException("one of parameters is null");
}
Stream stream = null;
using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
if (isoStore.FileExists(filename))
{
stream = isoStore.OpenFile(filename, System.IO.FileMode.Open, FileAccess.Read);
}
}
return stream;
});
}
Then it can be used like this:
public async Task<BitmapSource> FetchImage()
{
BitmapImage image = null;
using (var imageStream = await LoadImageAsync(doc.ImagePath))
{
if (imageStream != null)
{
image = new BitmapImage();
image.SetSource(imageStream);
}
}
return image;
}
And finally you just assign return value of FetchImage() method to some of your view model's property, to which the UI element is bound. Of course, your view model should properly implement INotifyPropertyChanged interface for this approach to work reliably.
If you want to use attached properties approach, here's how you do it:
public class IsoStoreImageSource : DependencyObject
{
public static void SetIsoStoreFileName(UIElement element, string value)
{
element.SetValue(IsoStoreFileNameProperty, value);
}
public static string GetIsoStoreFileName(UIElement element)
{
return (string)element.GetValue(IsoStoreFileNameProperty);
}
// Using a DependencyProperty as the backing store for IsoStoreFileName. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsoStoreFileNameProperty =
DependencyProperty.RegisterAttached("IsoStoreFileName", typeof(string), typeof(IsoStoreImageSource), new PropertyMetadata("", Changed));
private static void Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Image img = d as Image;
if (img != null)
{
var path = e.NewValue as string;
SynchronizationContext uiThread = SynchronizationContext.Current;
Task.Factory.StartNew(() =>
{
using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
if (isoStore.FileExists(path))
{
var stream = isoStore.OpenFile(path, System.IO.FileMode.Open, FileAccess.Read);
uiThread.Post(_ =>
{
var _img = new BitmapImage();
_img.SetSource(stream);
img.Source = _img;
}, null);
}
}
});
}
}
}
And then in XAML:
<Image local:IsoStoreImageSource.IsoStoreFileName="{Binding Path}" />
Some limitations of this approach:
It only works on Image control, though you can change this to a whichever type you want. It's just not very generic.
Performance-wise, it will use a thread from the threadpool every time image source is changed. It's the only way to do asynchronous read from isolated storage on Windows Phone 8 right now. And you definitely don't want to do this synchronously.
But it has one one important advantage:
It works! :)
I like the above approach but there is a simpler more hacky way of doing it if you are interested.
You can go into your xaml and bind the image source to an string property then put the file path into the property dynamically.
<!-- XAML CODE -->
<Image Source="{Binding imagePath}"/>
//Behind property
public String imagePath { get; set; }
load your path into the image path then bind the image source to the image path string. You might have to do an INotifyPropertyChanged but this method should work with proper binding.

Resources