Can I convert image/bitmap to writeablebitmap?
Here I am giving you the code to merge two images. WinRT's WriteableBitmap is different, the constructor of it takes height and width as argument. I have used WriteableBitmapEx for some functions.
XAML
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Canvas x:Name="BaseCanvas" Width="683" Height="768">
<Image Source="Assets/img1.png" />
<Image Source="Assets/img2.png" Canvas.Top="308" />
</Canvas>
<Image x:Name="imgTarget" Grid.Column="1" Stretch="None"/>
</Grid>
C#
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
StorageFile destiFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("Merged.png", CreationCollisionOption.ReplaceExisting);
WriteableBitmap wb;
wb = await Render();
using (IRandomAccessStream stream = await destiFile.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(
BitmapEncoder.PngEncoderId, stream);
Stream pixelStream = wb.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
(uint)wb.PixelWidth, (uint)wb.PixelHeight, 96.0, 96.0, pixels);
await encoder.FlushAsync();
}
var bitmp = new BitmapImage();
using (var strm = await destiFile.OpenReadAsync())
{
bitmp.SetSource(strm);
imgTarget.Source = bitmp;
}
}
private async Task<WriteableBitmap> Render()
{
var Assets = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Assets");
StorageFile file1 = await Assets.GetFileAsync("img1.png");
StorageFile file2 = await Assets.GetFileAsync("img2.png");
BitmapImage i1 = new BitmapImage();
BitmapImage i2 = new BitmapImage();
using (IRandomAccessStream strm = await file1.OpenReadAsync())
{
i1.SetSource(strm);
}
using (IRandomAccessStream strm = await file2.OpenReadAsync())
{
i2.SetSource(strm);
}
WriteableBitmap img1 = new WriteableBitmap(i1.PixelWidth, i1.PixelHeight);
WriteableBitmap img2 = new WriteableBitmap(i2.PixelWidth, i2.PixelHeight);
using (IRandomAccessStream strm = await file1.OpenReadAsync())
{
img1.SetSource(strm);
}
using (IRandomAccessStream strm = await file2.OpenReadAsync())
{
img2.SetSource(strm);
}
WriteableBitmap destination = new WriteableBitmap((int)(img1.PixelWidth > img2.PixelWidth ? img1.PixelWidth : img2.PixelWidth), (int)(img1.PixelHeight + img1.PixelHeight));
destination.Clear(Colors.White);
destination.Blit(new Rect(0, 0, (int)img1.PixelWidth, (int)img1.PixelHeight),img1,new Rect(0, 0, (int)img1.PixelWidth, (int)img1.PixelHeight));
destination.Blit(new Rect(0, (int)img1.PixelHeight, (int)img2.PixelWidth, (int)img2.PixelHeight), img2, new Rect(0, 0, (int)img2.PixelWidth, (int)img2.PixelHeight));
return destination;
}
Please note you have to add System.Runtime.InteropServices.WindowsRuntime
namespace.
UPDATE 1
Suppose if you have already two BitmapImage
img1
and img2
, then do like this
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
StorageFile destiFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("Merged.png", CreationCollisionOption.ReplaceExisting);
WriteableBitmap wb;
wb = await Render();
using (IRandomAccessStream stream = await destiFile.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(
BitmapEncoder.PngEncoderId, stream);
Stream pixelStream = wb.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
(uint)wb.PixelWidth, (uint)wb.PixelHeight, 96.0, 96.0, pixels);
await encoder.FlushAsync();
}
var bitmp = new BitmapImage();
using (var strm = await destiFile.OpenReadAsync())
{
bitmp.SetSource(strm);
imgTarget.Source = bitmp;
}
}
private async Task<WriteableBitmap> Render()
{
WriteableBitmap destination = new WriteableBitmap((int)(img1.PixelWidth > img2.PixelWidth ? img1.PixelWidth : img2.PixelWidth), (int)(img1.PixelHeight + img1.PixelHeight));
destination.Clear(Colors.White);
destination.Blit(new Rect(0, 0, (int)img1.PixelWidth, (int)img1.PixelHeight),img1,new Rect(0, 0, (int)img1.PixelWidth, (int)img1.PixelHeight));
destination.Blit(new Rect(0, (int)img1.PixelHeight, (int)img2.PixelWidth, (int)img2.PixelHeight), img2, new Rect(0, 0, (int)img2.PixelWidth, (int)img2.PixelHeight));
return destination;
}
Tehreem
Updated on July 24, 2022Comments
-
Tehreem almost 2 years
I have two bitmap images that i would like to merge together. I found that I can do that with writeablebitmap but how do I first convert these images to writeablebitmaps?
UPDATE: I could not find out a way to convert bitmaps to writeable bitmap directly so what I did was to write my bitmap in isolated storage and read it again in a stream object. After which the code given below by Xyroid can be used to merge the images and convert the merged image to bitmap.
-
Tehreem about 11 yearsI tried this and I am getting these two errors: 1. 'Windows.UI.Xaml.Media.Imaging.WriteableBitmap' is a 'type' but is used like a 'variable' 2. 'Windows.UI.Xaml.Media.Imaging.BitmapSource' is a 'type' but is used like a 'variable'
-
Tehreem about 11 yearsThe constructor you are talking about does not work. I don't know why.. I have already implemented the library you have given me link of.
-
James Wilkins about 11 yearsOk, sorry, it figures that Microsoft would continue down the path of inconsistency. I know it works in Silverlight (also XAML). :/
-
Tehreem about 11 yearsThanks you so much for trying to help. I really appreciate that :)
-
Tehreem about 11 yearsThankyou so much for this code. It runs perfectly fine. I will be able to achieve what I want with some editing. Thanks again :)
-
Farhan Ghumra about 11 yearsYour'e welcome, Tehreem. Please upvote my answer, I will feel glad.
-
Tehreem about 11 yearsI would have done that without your saying it but I can't yet as I am a new user..
-
Tehreem about 11 yearsIn this example you are getting two images in file1 and file2 from assets folder. While the images I have are already stored in two BitmapImage objects by application. Any idea how can i convert them to writeablebitmap or stream of pixels or byte array?
-
Farhan Ghumra about 11 yearsI am creating
BitmapImage
fromStorageFile
, so you can skip that part. What are you facing problem ? -
Tehreem about 11 yearsIf I skip that part how will I convert bitmap to writeable bitmap? i.e. the following lines of code will not work: using (IRandomAccessStream strm = await file1.OpenReadAsync()) { img1.SetSource(strm); }
-
Tehreem about 11 yearsWhat is file1 and file2 here?
-
Farhan Ghumra about 11 yearsYou first tell me how are you getting bitmaps ? What's the source of it ?
-
Tehreem about 11 yearsI have image controls in my application which get images through some other function. I do not have access to the actual files anymore.
-
Tehreem about 11 yearsIt gives me this error: 'Windows.UI.Xaml.Media.Imaging.WriteableBitmap' does not contain a definition for 'Blit' and the best extension method overload 'Windows.UI.Xaml.Media.Imaging.WriteableBitmapExtensions.Blit(Windows.UI.Xaml.Media.Imaging.WriteableBitmap, Windows.Foundation.Rect, Windows.UI.Xaml.Media.Imaging.WriteableBitmap, Windows.Foundation.Rect)' has some invalid arguments
-
Tehreem about 11 yearsI am giving up on conversion from Bitmap to WriteableBitmap... I think I should save the images in isolated storage when they are rendered the very first time so that I can retrieve them later and simply read them to writeableBitmaps
-
rism over 9 years@Xyroid I have to agree with Tehreem. The code you have supplied makes no sense because the Blit method takes a WritableBitMap as the second positional argument after Rectangle, not a BitMapImage. So for Update 1 when you say "Suppose if you have already two BitmapImage img1 and img2" it won't compile because "Argument type BitMapImage is not assignable to parameter type WritableBitMap". Have you actually tested this code or did you just write it off the cuff? If you have tested then pls advise how you managed to supply BitMapImages to the Blit method as per Update 1? thx
-
rism over 9 yearsAlso note that in your first answer "WriteableBitmap img1" and in the Update 1 "BitMapImage img1. So you've mixed up your types and thus haven't actually answered the question which is why I think Tehreem was confused. He's asked how to convert a BitMapImage to a WritableBitmap and you've given him some code in the first pass to combine two WritableBitMaps into one larger WritableBitMap. That code runs but doesn't answer the question and in the Update 1 which looks like an answer to his question, you've mixed types such that it wont actually compile. Hope Im wrong becos I want to do this too.
-
hellodear over 6 years@Xyroid It is really helpful for me. I am stuck a problem which is very similar to the non availability of writablebitmap constructor for UIelement. I have Xaml control image which is created programtically not in UI. How can I convert it in writeablebitmap? Please help.