Image source to writeablebitmap in windows phone 8.1 - c#

I'm working on windows phone 8.1 application. I have different pictures locally in app and displaying those pictures in list view. Now select one picture id and pass it to detail screen, where I have to save that file .
My detail.Xaml screen contain image control named as Imaged.
I got image on detail page and press image save button. I'm using this Sample app https://code.msdn.microsoft.com/windowsapps/Save-Edited-Picture-16d910c4/sourcecode?fileId=119937&pathId=946309183 "Sample"
My detail page Code is here.
string tempimg;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var imagePath = e.Parameter as string;
imaged.Source = new BitmapImage(new Uri(imagePath, UriKind.RelativeOrAbsolute));
tempimg = imagePath;
}
My SaveImage button code is here.
if (tempimg == null)
return;
// WriteableBitmap abc = new WriteableBitmap(400, 400);
string filename = "Image-" + DateTime.Now.ToFileTime() + ".jpeg";
// await SaveWriteableBitmapAsJpeg(img, filename);
Blockquote
await SaveWriteableBitmapAsJpeg(tempimg, filename);
private static async Task SaveWriteableBitmapAsJpeg(WriteableBitmap bmp, string fileName)
{
// Create file in Pictures library and write jpeg to it
var outputFile = await KnownFolders.CameraRoll.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (var writeStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
{
await EncodeWriteableBitmap(bmp, writeStream, BitmapEncoder.JpegEncoderId);
}
}
private static async Task EncodeWriteableBitmap(WriteableBitmap bmp, IRandomAccessStream writeStream, Guid encoderId)
{
// Copy buffer to pixels
byte[] pixels;
using (var stream = bmp.PixelBuffer.AsStream())
{
pixels = new byte[(uint)stream.Length];
await stream.ReadAsync(pixels, 0, pixels.Length);
}
// Encode pixels into stream
var encoder = await BitmapEncoder.CreateAsync(encoderId, writeStream);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied,
(uint)bmp.PixelWidth, (uint)bmp.PixelHeight,
96, 96, pixels);
await encoder.FlushAsync();
}
My this function "await SaveWriteableBitmapAsJpeg(tempimg, filename);" creates a problem. I just have the image source while that require the writeablebitmap. I just want to save image and not able to proceed from here. let me know the exact solution or problem.

Related

Create a BitmapImage from a Byte array and display it on an Image object UWP Raspberry Pi 3

I'm using this code to write a Byte Array inside a file BMP:
private async void ScriviBMP()
{
using (Stream stream = immagineBitmap.PixelBuffer.AsStream())
{
await stream.WriteAsync(arrayImmagine, 0, arrayImmagine.Length);
}
StorageFolder folder = KnownFolders.PicturesLibrary;
if (folder != null)
{
StorageFile file = await folder.CreateFileAsync("area2_128x128" + ".bmp", CreationCollisionOption.ReplaceExisting);
using (var storageStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, storageStream);
var pixelStream = immagineBitmap.PixelBuffer.AsStream();
var pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)immagineBitmap.PixelWidth, (uint)immagineBitmap.PixelHeight, 48, 48, pixels);
await encoder.FlushAsync();
}
}
}
Then i'm using this code to display the BMP image in a Image object
private async void VisBMP()
{
var file = await KnownFolders.PicturesLibrary.GetFileAsync("area2_128x128.bmp");
using (var fileStream = (await file.OpenAsync(Windows.Storage.FileAccessMode.Read)))
{
var bitImg = new BitmapImage();
//bitImg.UriSource = new Uri(file.Path);
bitImg.SetSource(fileStream);
image.Source = bitImg;
}
}
these functions take about 400 milliseconds to complete the process, that's a lot of time.
Is there a way to avoid the usage of a BMP file and use only a stream to display the image on the image object?
It can be that debugging the program can slow the processes? I'm using Visual Studio 2015.
You can transfer the data buffer(arrayImmagine) to image in InMemoryRandomAccessStream.These codes take about 200ms.I tested with following pieces of code. In addition, you can reference this article to get more information.
BitmapImage biSource = new BitmapImage();
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
await stream.WriteAsync(bytes.AsBuffer());
stream.Seek(0);
await biSource.SetSourceAsync(stream);
}
image.Source = biSource;

Create Tiff File from multiple BitmapImage

Background:
I'm developing Win 10 Universal App, have list of BitmapImage:
List<BitmapImage> ImagesList = new List<BitmapImage>();
Each list item is created by converting byte[] to BitmapImage by this code:
public async Task<BitmapImage> GetBitmapImage(byte[] array)
{
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
using (DataWriter writer = new DataWriter(stream.GetOutputStreamAt(0)))
{
writer.WriteBytes(array);
await writer.StoreAsync();
}
BitmapImage image = new BitmapImage();
List<BitmapImage> ImagesList = new List<BitmapImage>();
await image.SetSourceAsync(stream);
return image;
}
}
Question:
How to convert this list to single multi-page Tiff file?
Notes:
I've found many related answers like this but all are based on System.Drawing library which is not supported in Windows 10 Universal Apps, so as you can see in my code, I'm using Windows.Ui.Xaml.Media.Imaging.BitmapImage object instead of System.Drawing.Bitmap to get the image.
How to convert this list to single multi-page Tiff file
In UWP app, we can use BitmapEncoder to encode a Tiff image file to contain several frames. BitmapEncoder.SetPixelData method can be used for setting pixel data on one frame and then BitmapEncoder.GoToNextFrameAsync can asynchronously commits the current frame data and appends a new empty frame to be edited. So the Tiff image can be created by multiply images.
Suppose I want to create a Tiff image file from three images that are located on my local folder, I decode and read pixel data from them and set to the Tiff image. Sample code as follows:
private async void btnConvert_Click(object sender, RoutedEventArgs e)
{
StorageFolder localfolder = ApplicationData.Current.LocalFolder;
StorageFile image1 = await localfolder.GetFileAsync("caffe1.jpg");
StorageFile image2 = await localfolder.GetFileAsync("caffe2.jpg");
StorageFile image3 = await localfolder.GetFileAsync("caffe3.jpg");
StorageFile targettiff = await localfolder.CreateFileAsync("temp.tiff", CreationCollisionOption.ReplaceExisting);
WriteableBitmap writeableimage1;
WriteableBitmap writeableimage2;
WriteableBitmap writeableimage3;
using (IRandomAccessStream stream = await image1.OpenAsync(FileAccessMode.Read))
{
SoftwareBitmap softwareBitmap;
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
softwareBitmap = await decoder.GetSoftwareBitmapAsync();
writeableimage1 = new WriteableBitmap(softwareBitmap.PixelWidth, softwareBitmap.PixelHeight);
writeableimage1.SetSource(stream);
}
using (IRandomAccessStream stream = await image2.OpenAsync(FileAccessMode.Read))
{
SoftwareBitmap softwareBitmap;
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
softwareBitmap = await decoder.GetSoftwareBitmapAsync();
writeableimage2 = new WriteableBitmap(softwareBitmap.PixelWidth, softwareBitmap.PixelHeight);
writeableimage2.SetSource(stream);
}
using (IRandomAccessStream stream = await image3.OpenAsync(FileAccessMode.Read))
{
SoftwareBitmap softwareBitmap;
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
softwareBitmap = await decoder.GetSoftwareBitmapAsync();
writeableimage3 = new WriteableBitmap(softwareBitmap.PixelWidth, softwareBitmap.PixelHeight);
writeableimage3.SetSource(stream);
}
using (IRandomAccessStream ras = await targettiff.OpenAsync(FileAccessMode.ReadWrite, StorageOpenOptions.None))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.TiffEncoderId, ras);
var stream = writeableimage1.PixelBuffer.AsStream();
byte[] buffer = new byte[stream.Length];
await stream.ReadAsync(buffer, 0, buffer.Length);
var stream2 = writeableimage2.PixelBuffer.AsStream();
byte[] buffer2 = new byte[stream2.Length];
await stream2.ReadAsync(buffer2, 0, buffer2.Length);
var stream3 = writeableimage3.PixelBuffer.AsStream();
byte[] buffer3 = new byte[stream3.Length];
await stream3.ReadAsync(buffer3, 0, buffer3.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)writeableimage1.PixelWidth, (uint)writeableimage1.PixelHeight, 96.0, 96.0, buffer);
await encoder.GoToNextFrameAsync();
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)writeableimage2.PixelWidth, (uint)writeableimage2.PixelHeight, 96.0, 96.0, buffer2);
await encoder.GoToNextFrameAsync();
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)writeableimage3.PixelWidth, (uint)writeableimage3.PixelHeight, 96.0, 96.0, buffer3);
await encoder.FlushAsync();
}
}
The temp.tiff will be created successfully. I'm not sure how you got the image byte array, but BitmapImage cannot be directly written to or updated, you need to got WriteableBitmap object from your byte array. If you don't know how to get the WriteableBitmap please try to reference the following code or save the BitmapImage to local folder and using the code I provided above.
public async Task<WriteableBitmap> SaveToImageSource(byte[] imageBuffer)
{
using (MemoryStream stream = new MemoryStream(imageBuffer))
{
var ras = stream.AsRandomAccessStream();
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(BitmapDecoder.JpegDecoderId, ras);
var provider = await decoder.GetPixelDataAsync();
byte[] buffer = provider.DetachPixelData();
WriteableBitmap ablebitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
await ablebitmap.PixelBuffer.AsStream().WriteAsync(buffer, 0, buffer.Length);
return ablebitmap;
}
}
More details please reference the official sample.

Windows phone 8.1 save StorageFile as image

I want to save StorageFile as image that can be seen in gallery and use later. StorageFile contain image taken by camera or taken from gallery and converted in StorageFile.
private async void SaveCroppedImage(object sender, RoutedEventArgs e)
{
StorageFile file = await KnownFolders.CameraRoll.CreateFileAsync("edited.jpg", CreationCollisionOption.ReplaceExisting);
using (IRandomAccessStream stream =await file.OpenAsync(FileAccessMode.ReadWrite))
{
await EncodeWriteableBitmap(WB_CroppedImage, stream, BitmapEncoder.JpegEncoderId);
}
}
private static async Task EncodeWriteableBitmap(WriteableBitmap bmp, IRandomAccessStream writeStream, Guid encoderId)
{
// Copy buffer to pixels
byte[] pixels;
using (var stream = bmp.PixelBuffer.AsStream())
{
pixels = new byte[(uint)stream.Length];
await stream.ReadAsync(pixels, 0, pixels.Length);
}
// Encode pixels into stream
var encoder = await BitmapEncoder.CreateAsync(encoderId, writeStream);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied,
(uint)bmp.PixelWidth, (uint)bmp.PixelHeight,
96, 96, pixels);
await encoder.FlushAsync();
}
Save the storagefile with known image extensions (like .jpg or .png) in the public folder, it will show up in the gallery.

How to share filtered image in UWP C#

I have an image processing windows 10 application. I am applying filters on that image and showing it on the image element. This is how I am applyting filter and setting it as a source to MainImage element.
ProcessImage processImage = new ProcessImage(sourcePixels, width, height);
byte[] blurEffect = processImage.BlurEffect(width, height);
WriteableBitmap blurImage = new WriteableBitmap((int)width, (int)height);
using (Stream stream = blurImage.PixelBuffer.AsStream())
{
await stream.WriteAsync(blurEffect, 0, blurEffect.Length);
MainImage.Source = blurImage;
}
Up till now I have set the WriteableBitmap image to the source. Now I want to share this image using DataTransferManager's Data requested event as shown
dataTransferManager = DataTransferManager.GetForCurrentView();
dataTransferManager.DataRequested += DataTransferManager_DataRequested;
The body of its event containing this code
DataPackage dataPackage = args.Request.Data;
dataPackage.Properties.Title = "App Name";
dataPackage.Properties.Description = "My description";
dataPackage.SetBitmap();
On the share button click event, i am calling showshareUI like this
DataTransferManager.ShowShareUI();
I am trying to share image using fourth line above that is SetBitmap method, but the problem here is this method want RandomAccessStreamReference value and I have a filtered image of type writeablebitmap. How can I get this thing done?
You can write your WriteableBitmap to an InMemoryRandomAccessStream
I don't have access to my dev machine so I can't test it but here's a quick sample:
private async Task<IRandomAccessStream> Convert(WriteableBitmap writeableBitmap)
{
var stream = new InMemoryRandomAccessStream();
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
Stream pixelStream = writeableBitmap.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)writeableBitmap.PixelWidth, (uint)writeableBitmap.PixelHeight, 96.0, 96.0, pixels);
await encoder.FlushAsync();
return stream;
}
Since dataPackage.SetBitmap() expects a RandomAccessStreamReference object you will need to obtain one based on the IRandomAccessStream that the above method returns. Fortunately that is pretty easy:
var streamRef = RandomAccessStreamReference.CreateFromStream(stream)
Hope that works.

Windows 8 - Save Image in XAML as local file ( inside Application folder )

In my Windows store application, i am displaying a picture using Image control in XAML. Source of the Image control is set, code wise using WriteableBitmap. I am trying to send this image as attachment in email. Is there any easy way for that? I am trying to save that image locally( within application ) and attach that saved image to email. But not able to save locally. Any help is appreciated.
Here is the code.
bitmap = await WriteableBitmapRenderExtensions.Render(dataCanvas);
image.Source = bitmap;
dataCanvas is a Canvas control consists of two images, one place above another. Actually i have to place a sunglass top of users face and display it as another image in xaml. Also email that image.
Check out the WriteableBitmapSaveExtensions class in WinRT XAML Toolkit for all the SaveToFile() extension methods you can use to save your WriteableBitmap.
The core one is this:
public static async Task SaveToFile(
this WriteableBitmap writeableBitmap,
StorageFile outputFile,
Guid encoderId)
{
Stream stream = writeableBitmap.PixelBuffer.AsStream();
byte[] pixels = new byte[(uint)stream.Length];
await stream.ReadAsync(pixels, 0, pixels.Length);
using (var writeStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(encoderId, writeStream);
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Premultiplied,
(uint)writeableBitmap.PixelWidth,
(uint)writeableBitmap.PixelHeight,
96,
96,
pixels);
await encoder.FlushAsync();
using (var outputStream = writeStream.GetOutputStreamAt(0))
{
await outputStream.FlushAsync();
}
}
}
You can get the encoder ID using an overload of the method:
public static async Task<StorageFile> SaveToFile(
this WriteableBitmap writeableBitmap,
StorageFolder storageFolder,
string fileName,
CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
{
StorageFile outputFile =
await storageFolder.CreateFileAsync(
fileName,
options);
Guid encoderId;
var ext = Path.GetExtension(fileName);
if (new[] { ".bmp", ".dib" }.Contains(ext))
{
encoderId = BitmapEncoder.BmpEncoderId;
}
else if (new[] { ".tiff", ".tif" }.Contains(ext))
{
encoderId = BitmapEncoder.TiffEncoderId;
}
else if (new[] { ".gif" }.Contains(ext))
{
encoderId = BitmapEncoder.GifEncoderId;
}
else if (new[] { ".jpg", ".jpeg", ".jpe", ".jfif", ".jif" }.Contains(ext))
{
encoderId = BitmapEncoder.JpegEncoderId;
}
else if (new[] { ".hdp", ".jxr", ".wdp" }.Contains(ext))
{
encoderId = BitmapEncoder.JpegXREncoderId;
}
else //if (new [] {".png"}.Contains(ext))
{
encoderId = BitmapEncoder.PngEncoderId;
}
await writeableBitmap.SaveToFile(outputFile, encoderId);
return outputFile;
}
Any subclass of BitmapSource (including WritableBitmap) can be passed to a BitmapEncoder. A BitmapEncoder takes a Stream to which the encoded JPEG, PNG or other image is written.
You can then use a mailer library to reference the stream used by the encoder, or use the Share contract, and pass the stream directly.
Example:
var bitmap = new WritableBitmap();
// ... draw your bitmap
var tempPath = // path to where you want to save (probably in your appx temp);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(bitmap);
using (var fs = new FileStream(tempPath))
{
encoder.Save(fs);
}
// use the image saved to tempPath
// http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh871370.aspx

Categories

Resources