Search code examples
c#mauimaui-blazor

.net Maui blazor server-side: Crop Image


In a .net maui blazor project I do have a base64 string representing an image. For simplification (it doesn't matter how I receive it):

string imageValue = "sdfghjkhgjkjhgj" // Just an example, no real image data

Now I want to get a certain area of this image, the area is defined by four values:

int x = 20; // The area I want starts 20px from the original image's left border
int y = 30; // The area I want starts 30px from the original image's top border
int width = 150; // The area shall be 150px wide
int width = 180; // The area shall be 180px high

I found different ways to get the base64 into some kind of image container:

Microsoft.Maui.Graphics.Iimage image = PlatformImage.FromStream(new MemoryStream(Convert.FromBase64String(imageValue)))
Android.Graphics.Bitmap bitmap = image.AsBitmap();
ImagePaint imagePaint = new ImagePaint() {Image = image};

And now I'm stuck. Nether for Iimage nor for Android.Graphics.Bitmap or ImagePaint I find a way to get an area of the image. Solutions I found for Microsoft.Drawing.Bitmap(?) won't work with Android.Graphics.Bitmap.

I don't need to show the result anywhere. I just need a new base64 string containing the cropped image. Also, there is no need to take other platforms beside Android into account.


Solution

  • So now I had a look at SkiaSharp and it works fine. This is what I did:

    // The original image (example text)
    string imageValue = "sdfghjkhgjkjhgj"
    
    // Here I will store the cropped image as base64 string
    string croppedImage;
    
    private void CropImage(int x, int y, int width, int height)
        {
            SkiaSharp.SKBitmap bm = SkiaSharp.SKBitmap.Decode(new MemoryStream(Convert.FromBase64String(imageValue)));
            using SkiaSharp.SKPixmap skPixmap = new SkiaSharp.SKPixmap(bm.Info, bm.GetPixels());
            SkiaSharp.SKPixmap subset = skPixmap.ExtractSubset(new SkiaSharp.SKRectI(x, y, x + width, y + height));
            SkiaSharp.SKData skData = subset.Encode(SkiaSharp.SKEncodedImageFormat.Png, 100);
            System.IO.MemoryStream stream = new System.IO.MemoryStream();
            skData.SaveTo(stream);
            croppedImage = Convert.ToBase64String(stream.ToArray());
        }
    

    The function does all what I need: I get the an area out of the original image, defined by top left coordinate, width and height, it gets encoded into png (something what I would have had to take care of afterwards otherwise) and it is saved to a memory stream for further usage.

    Thanks, @Jason and @Alexandar May - MSFT.