How to draw part of image in Maui.Graphics

75 Views Asked by At

In the IDrawable Drawable property of a MAUI.GraphicsView, I want to draw a part of an image. That is a sub rectangle of the original image.

Problem: I can't find a way nor to crop an IImage returned by PlatformImage.FromStream(stream) nor to draw only a part of an IImage, with something like this function of Skiasharp but for Maui.GraphicsView:

public void DrawImage(SkiaSharp.SKImage image, SkiaSharp.SKRect source, SkiaSharp.SKRect dest);

Can somebody propose a way to achieve this?

Just to be extensive, here is the code I want to extend:

    public class GraphicsDrawable : IDrawable
    {
        public double Scale { get; set; }
        public Point Center { get; set; }
        public Rect DisplayedRect { get; set; }
    
        private Microsoft.Maui.Graphics.IImage image;
    
        public GraphicsDrawable()
        {
            // Load image
            Assembly assembly = GetType().GetTypeInfo().Assembly;
            using (Stream stream = assembly.GetManifestResourceStream("BOBMaui.Resources.Images.bobstart.jpg"))
            {
                image = PlatformImage.FromStream(stream);
            }
        }
    
        public void Draw(ICanvas canvas, RectF containerRect)
        {
            if (image != null)
            {
                // Anyway, the output will be displayed on containerRect size which is the full size of the container
    
                // STEP 1 - Computes the clipping to apply to image
                // Computes scaled size which is the size of the part of the image to be displayed
                double scaledWidth = image.Width / Scale;
                double scaledHeight = image.Height / Scale;
    
                // Computes horizontal coordinates
                double xCenterImageOUT = Center.X * image.Width;
                double xLeft = Math.Max(0, xCenterImageOUT - scaledWidth/2);  // May not be negative
                double xRight = Math.Min(xCenterImageOUT + scaledWidth / 2, image.Width);  // May not extend outside base image
                if (xRight - xLeft < scaledWidth)
                {
                    // One of the border was forced to 0 or image.Width
                    if (xLeft == 0) xRight = scaledWidth;
                    else xLeft = image.Width - scaledWidth;
                }
    
                // Computes vertical coordinates
                double yCenterImageOUT = Center.Y * image.Height;
                double yTop = Math.Max(0, yCenterImageOUT - scaledHeight / 2);  // May not be negative
                double yBottom = Math.Min(yCenterImageOUT + scaledHeight / 2, image.Height);  // May not extend outside base image
                if (yBottom - yTop < scaledHeight)
                {
                    // One of the border was forced to 0 or image.Width
                    if (yTop == 0) yBottom = scaledHeight;
                    else yBottom = image.Height - scaledHeight;
                }
                // Define clipping rectangle
                DisplayedRect = new Rect(xLeft, yTop, scaledWidth, scaledHeight);
    
                // STEP 2 - Paint the canvas
                // There is the problem - I need to crop the image before drawing it
                // Sthg like:  canvas.DrawImage(image, source: DisplayRect, dest: containerRect);
                canvas.DrawImage(image, containerRect.X, containerRect.Y, containerRect.Width, containerRect.Height);
            }
    
        }
    }
1

There are 1 best solutions below

8
Jessie Zhang -MSFT On

Update:

image is of type Microsoft.Maui.Graphics.IImage which doesn't declare a clip function. It comes from image = PlatformImage.FromStream(stream);

Then you can use method path.AppendRectangle to achieve this.

Please refer to the following code:

  public class ClippingDrawable : IDrawable
    {
        public void Draw(ICanvas canvas, RectF dirtyRect)
        {
            IImage image;
            var assembly = GetType().GetTypeInfo().Assembly;
            using (var stream = assembly.GetManifestResourceStream("GraphicsViewDemos.Resources.Images.dotnet_bot.png"))
            {
                image = PlatformImage.FromStream(stream);
            }

            if (image != null)
            {    
                PathF path = new PathF();
                path.AppendRectangle(60, 60, 90, 90); 
                canvas.ClipPath(path);  // Must be called before DrawImage
                canvas.DrawImage(image, 10, 10, image.Width, image.Height);


            }
        }
    }

Note:

1.For more information, please check document: GraphicsView.

You can also check the official sample here: GraphicsViewDemos. The above sample code has the effect you want. Please pay attention to DrawShapesPage.xaml.

2.in Maui, you could use Clip property to crop image on MAUI.

For instance, you could use the following code to crop the image:

var clip1 = new RectangleGeometry(new Rect(100, 100, 100, 100));  
image.Clip = clip1;  

Please refer to Clip with a Geometry to get more details.