WoistdasNiveau
WoistdasNiveau

Reputation: 83

Skiasharp DrawBitmap only White

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

Answers (1)

Liqun Shen-MSFT
Liqun Shen-MSFT

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

Related Questions