Windows 8 How to open a BitmapImage as a stream? - c#

In a Windows 8 app, how do I convert a BitmapImage to a Stream? I have a List of BitmapImages and I'm going to use that List to upload each image to a server and I need to use a Stream to do that. So is there a way to convert each individual BitmapImage into a Stream?

No, there isn't. You need to track the original sources or use a WriteableBitmap instead.

Retrieve the bitmap image:
public async void ContinueFileOpenPicker(FileOpenPickerContinuationEventArgs args)
{
if (args.Files.Count > 0)
{
var imageFile = args.Files[0] as StorageFile;
// Ensure the stream is disposed once the image is loaded
using (IRandomAccessStream fileStream = await imageFile.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
// Set the image source to the selected bitmap
BitmapImage bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(fileStream);
ImageControl.Source = bitmapImage;
await _viewModel.Upload(imageFile);
}
}
}
Create the file stream:
internal async Task Upload(Windows.Storage.StorageFile file)
{
var fileStream = await file.OpenAsync(FileAccessMode.Read);
fileStream.Seek(0);
var reader = new Windows.Storage.Streams.DataReader(fileStream.GetInputStreamAt(0));
await reader.LoadAsync((uint)fileStream.Size);
Globals.MemberId = ApplicationData.Current.LocalSettings.Values[Globals.PROFILE_KEY];
var userName = "Rico";
var sex = 1;
var url = string.Format("{0}{1}?memberid={2}&name={3}&sex={4}", Globals.URL_PREFIX, "api/Images", Globals.MemberId, userName,sex);
byte[] image = new byte[fileStream.Size];
await UploadImage(image, url);
}
Create a memory stream from the image:
public async Task UploadImage(byte[] image, string url)
{
Stream stream = new System.IO.MemoryStream(image);
HttpStreamContent streamContent = new HttpStreamContent(stream.AsInputStream());
Uri resourceAddress = null;
Uri.TryCreate(url.Trim(), UriKind.Absolute, out resourceAddress);
Windows.Web.Http.HttpRequestMessage request = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Post, resourceAddress);
request.Content = streamContent;
var httpClient = new Windows.Web.Http.HttpClient();
var cts = new CancellationTokenSource();
Windows.Web.Http.HttpResponseMessage response = await httpClient.SendRequestAsync(request).AsTask(cts.Token);
}

Related

How to get IRandomAccessStream from StorageFile

First I declared
private MediaCapture _mediaCapture;
StorageFile capturedPhoto;
IRandomAccessStream imageStream;
Second I am capturing
var lowLagCapture = await _mediaCapture.PrepareLowLagPhotoCaptureAsync(ImageEncodingProperties.CreateUncompressed(MediaPixelFormat.Bgra8));
var capturedPhoto = await lowLagCapture.CaptureAsync();
await lowLagCapture.FinishAsync();
Third I am setting the image source:
var softwareBitmap = capturedPhoto.Frame.SoftwareBitmap;
SoftwareBitmap softwareBitmapBGRB = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
SoftwareBitmapSource bitmapSource = new SoftwareBitmapSource();
await bitmapSource.SetBitmapAsync(softwareBitmapBGRB);
image.Source = bitmapSource;
How can i get imageStream? I used CaptureElement tool in xaml .
It's quite simple, the question is what do you want to do with that IRandomAccessStreem. Below is some code I think you'll need:
public void HandleImageFileOperations(StorageFile file)
{
if (file != null)
{
//converts the StorageFile to IRandomAccessStream
var stream = await file.OpenAsync(FileAccessMode.Read);
//creates the stream to an Image just in-case you want to show it
var image = new Windows.UI.Xaml.Media.Imaging.BitmapImage();
image.SetSource(stream);
//creates the image into byte array just in-case you need it to store the image
byte[] bitmapImageBytes = null;
var reader = new Windows.Storage.Streams.DataReader(stream.GetInputStreamAt(0));
bitmapImageBytes = new byte[stream.Size];
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(bitmapImageBytes);
}
}

WinRt - FileSavePicker, save image from URI to file

I would like to ask how I can save image from stream to file. I have created this FileSavePicker, but I don not know how i can save image from Uri
Thanks
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadLine(); // URi with image
private async void saveClick(object sender, RoutedEventArgs e)
{
var Picker = new FileSavePicker();
Picker.FileTypeChoices.Add("Image", new List<string>() { ".jpg" });
StorageFile file = await Picker.PickSaveFileAsync();
}
I assume you already have downloaded the image into dataStream. If not you can do so with the HttpClient class:
var uri = new Uri("http://cdn.sstatic.net/stackexchange/img/logos/so/so-logo-med.png");
Windows.Web.Http.HttpClient httpClient = new HttpClient();
var stream = await httpClient.GetInputStreamAsync(uri);
Stream dataStream = stream.AsStreamForRead();
You can get a writeable stream to your picked file by calling OpenStreamForWriteAsync on the StorageFile. With two streams you can call CopyTo to copy from the dataStream to the save stream.
var Picker = new FileSavePicker();
Picker.FileTypeChoices.Add("Image", new List<string>() { ".jpg" });
StorageFile file = await Picker.PickSaveFileAsync();
using (Stream saveStream = await file.OpenStreamForWriteAsync())
{
dataStream.Seek(0, SeekOrigin.Begin);
await dataStream.CopyToAsync(saveStream);
}

WriteableBitmap SaveJpeg missing for universal apps

I am developing an universal app, in my shared code i am trying to download the image from net and save the image to LocalFolder.
I am using HttpClient to download the images from user given urls and reading the client response to save the image. I am using below code to save, but couldn't able to find Writeable SaveJpeg method.
HttpResponseMessage response = await httpClient.GetAsync(imageUri);
await Task.Run(async () =>
{
if (response.IsSuccessStatusCode)
{
// save image locally
StorageFolder folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("Images", CreationCollisionOption.OpenIfExists);
BitmapImage bmp = new BitmapImage();
var buffer = await response.Content.ReadAsBufferAsync();
InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream();
DataWriter writer = new DataWriter(ras.GetOutputStreamAt(0));
writer.WriteBuffer(buffer);
bmp.SetSource(ras);
}
});
What is the best way to save the imageresponse to localfolder with image quality % (for both WP and Windows).
You should save the stream directly instead of saving the BitmapImage.
Something like this.
var ras = new InMemoryRandomAccessStream();
var writer = new DataWriter(ras);
writer.WriteBuffer(buffer);
await writer.StoreAsync();
var inputStream = ras.GetInputStreamAt(0);
// you can still use this to display it on the UI though
//bmp.SetSource(ras);
// write the picture into this folder
var storageFile = await folder.CreateFileAsync("image1.jpg", CreationCollisionOption.GenerateUniqueName);
using (var storageStream = await storageFile.OpenAsync(FileAccessMode.ReadWrite))
{
await RandomAccessStream.CopyAndCloseAsync(inputStream, storageStream.GetOutputStreamAt(0));
}
Update
You can use BitmapEncoder and when pass in property dpi values in SetPixelData.
using (var storageStream = await storageFile.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, storageStream);
var pixelStream = yourWriteableBitmap.PixelBuffer.AsStream();
var pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)yourWriteableBitmap.PixelWidth, (uint)yourWriteableBitmap.PixelHeight, 48, 48, pixels);
await encoder.FlushAsync();
}

Converting an Image to Byte Array in Windows Store App

In WindowsStoreApps i want to convert an Local Image from solution explorer to byte array and then to base64 string.please guide me.The code I have tried so far is as below.
public async Task<string> ToBase64()
{
Byte[] ByteResult = null;
string bs64 = null;
if (url != null)
{
HttpClient client = new HttpClient();
ByteResult = await client.GetByteArrayAsync(url);
}
bs64 = Convert.ToBase64String(ByteResult);
return bs64;
}
Suppose you want to convert an image named MyImage.png from Assets folder then below code will return the base64 string of that image.
private async Task DoWork()
{
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/MyImage.png"));
var b64 = await ConvertStorageFileToBase64String(file);
}
private async Task<string> ConvertStorageFileToBase64String(StorageFile File)
{
var stream = await File.OpenReadAsync();
using (var dataReader = new DataReader(stream))
{
var bytes = new byte[stream.Size];
await dataReader.LoadAsync((uint)stream.Size);
dataReader.ReadBytes(bytes);
return Convert.ToBase64String(bytes);
}
}
Try this piece of code
StorageFile file = <Your File>;
var bytes = new Byte[0];
using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read))
{
var reader = new DataReader(fileStream.GetInputStreamAt(0));
bytes = new Byte[fileStream.Size];
await reader.LoadAsync((uint)fileStream.Size);
reader.ReadBytes(bytes);
}
string imageInStringFormat = Convert.ToBase64String(bytes);

How to share a screenshot?

I want to share the screenshot of the app on Twitter, Facebook, etc. This is my code: it saves the picture, but doesn't open the share media task. I know the problem is in the path :{
var wb = new WriteableBitmap(LayoutRoot, new TranslateTransform());
using (var mediaLibrary = new MediaLibrary()) {
using (var stream = new MemoryStream()) {
var fileName = string.Format("{0}.jpg", DateTime.Now.ToString("yyyy-MM-dd-hh-mm-ss"));
wb.SaveJpeg(stream, wb.PixelWidth, wb.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
mediaLibrary.SavePicture(fileName, stream);
shareMediaTask = new ShareMediaTask();
shareMediaTask.FilePath = fileName;
shareMediaTask.Show();
}
}
How can I get the saved picture's path?
Isn't it possible to just simply take a screenshot and share it without saving it on the phone?
To get the real path for the MediaLibrary file, you'll need to use the GetPath() extension method, something like;
using Microsoft.Xna.Framework.Media.PhoneExtensions;
...
var picture = mediaLibrary.SavePicture(fileName, stream);
shareMediaTask = new ShareMediaTask();
shareMediaTask.FilePath = picture.GetPath();
shareMediaTask.Show();
For sharing the screen shot it is not required to save the image , in windows 8.1 it is very easy.
Here is the code, enjoy!
async void dataTransferMgr_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
DataRequest request = args.Request;
request.Data.Properties.Title = "Title";
request.Data.Properties.Description = "brief description";
request.Data.SetText("detailed information");
RandomAccessStreamReference imageStreamRef = await ScreenshotToStreamReferenceAsync(yourChartControlName);
request.Data.Properties.Thumbnail = imageStreamRef;
request.Data.SetBitmap(imageStreamRef);
}
private async Task ScreenshotToStreamAsync(FrameworkElement element, IRandomAccessStream stream)
{
var renderTargetBitmap = new Windows.UI.Xaml.Media.Imaging.RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(element);
var pixelBuffer = await renderTargetBitmap.GetPixelsAsync();
var dpi = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi;
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
(uint)renderTargetBitmap.PixelWidth,
(uint)renderTargetBitmap.PixelHeight,
dpi,
dpi,
pixelBuffer.ToArray());
await encoder.FlushAsync();
}
private async Task<RandomAccessStreamReference> ScreenshotToStreamReferenceAsync(FrameworkElement element)
{
var ms = new InMemoryRandomAccessStream();
await ScreenshotToStreamAsync(element, ms);
ms.Seek(0);
return RandomAccessStreamReference.CreateFromStream(ms);
}

Categories