Reputation: 83
I want to cut a part out of a SkBitmap and paint it to a new Bitmap. Therefore i tried to adopt the tutorial stated here: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/bitmaps/drawing with the difference that i do not want to display the Canvas but just get the new bitmap and transform it into a byte[] so that i can send it to the backend to. When i ignore the painting part and just convert the sourceMap back to a byte[] i get the image i uploaded as expected, however when i use the canvas and draw on the new BHitmap i just get white space and thats it. Nothing on there and i do not understand why. I also tried copying the Bitmap of the uploaded Image to check if at least then any Image would appear but still i get only blank white space.
public async void UploadImage()
{
FileResult im = await FilePicker.PickAsync(new PickOptions()
{
FileTypes = FilePickerFileType.Images,
});
byte[] bytes = null;
using (Stream ms = await im.OpenReadAsync())
{
bytes = new byte[ms.Length];
ms.Read(bytes, 0, bytes.Length);
}
SKBitmap sourceMap = null;
using (MemoryStream stream = new MemoryStream(bytes))
{
sourceMap = SKBitmap.Decode(stream);
}
//SKBitmap destination = new SKBitmap(sourceMap.Width,sourceMap.Height);
SKBitmap destination = sourceMap.Copy();
SKRect dest = new SKRect(sourceMap.Height / 4, sourceMap.Height / 4, sourceMap.Width / 4, -sourceMap.Height / 4);
SKRect source = new SKRect(sourceMap.Height/4,sourceMap.Height/4,sourceMap.Width/4,-sourceMap.Height/4);
using (SKCanvas canvas = new SKCanvas(destination))
{
canvas.Clear();
canvas.DrawBitmap(sourceMap, source, dest);
}
SKImage skImage = SKImage.FromBitmap(destination);
SKData encoded = skImage.Encode();
using(MemoryStream memory = new MemoryStream())
{
encoded.AsStream().CopyTo(memory);
Image = memory.ToArray();
}
}
The View:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:ImageCroppingTry2="clr-namespace:ImageCroppingTry2"
x:DataType="ImageCroppingTry2:MainPageViewModel"
x:Class="ImageCroppingTry2.MainPage">
<ContentPage.Resources>
<ResourceDictionary>
<toolkit:ByteArrayToImageSourceConverter x:Key="ByteArrayToImageSourceConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<VerticalStackLayout>
<Image x:Name="displayImage" Source="{Binding Image, Converter={StaticResource ByteArrayToImageSourceConverter}}"/>
<Button Command="{Binding UploadImageCommand}"></Button>
</VerticalStackLayout>
Upvotes: 1
Views: 445
Reputation: 8220
You could set a HeightRequest property for Image to see if it works.
I also made a small demo based on my picture which works well. You could have a try:
private byte[] image;
public byte[] Image
{
get
{
return image;
}
set
{
image = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Image)));
}
}
[RelayCommand]
public async void UploadImage()
{
//Well i pick a photo for convenience
FileResult im = await MediaPicker.Default.PickPhotoAsync();
// here I think what you do is a little bit complicated, you don't have to convert stream => byte => stream => skbitmap
SKBitmap sourceMap;
using (Stream s = await im.OpenReadAsync())
{
using (MemoryStream ms = new MemoryStream())
{
await s.CopyToAsync(ms);
ms.Seek(0, SeekOrigin.Begin);
sourceMap = SKBitmap.Decode(ms);
}
}
// i don't know the image you use, please make sure the pixel you get is valid
SKBitmap destination = new SKBitmap(100, 100);
SKRect dest = new SKRect(0, 0, 100, 100);
SKRect source = new SKRect(0, 0, 100, 100);
using (SKCanvas canvas = new SKCanvas(destination))
{
canvas.Clear();
canvas.DrawBitmap(sourceMap, source, dest);
}
SKImage skImage = SKImage.FromBitmap(destination);
SKData encoded = skImage.Encode();
using (MemoryStream memory = new MemoryStream())
{
encoded.AsStream().CopyTo(memory);
Image = memory.ToArray();
}
}
I think your project have more details and need more debug. Just make sure each output is valid.
Hope it works for you.
Upvotes: 1