skip to Main Content

I need to crop an image to a circle in my Xamarin app.
This is platform-dependent, so it’d have to use the UIKit.

I’ve found the following Swift code (credit Cut a UIImage into a circle):

extension UIImage {
    var isPortrait:  Bool    { size.height > size.width }
    var isLandscape: Bool    { size.width > size.height }
    var breadth:     CGFloat { min(size.width, size.height) }
    var breadthSize: CGSize  { .init(width: breadth, height: breadth) }
    var breadthRect: CGRect  { .init(origin: .zero, size: breadthSize) }
    var circleMasked: UIImage? {
        guard let cgImage = cgImage?
            .cropping(to: .init(origin: .init(x: isLandscape ? ((size.width-size.height)/2).rounded(.down) : 0,
                                              y: isPortrait  ? ((size.height-size.width)/2).rounded(.down) : 0),
                                size: breadthSize)) else { return nil }
        let format = imageRendererFormat
        format.opaque = false
        return UIGraphicsImageRenderer(size: breadthSize, format: format).image { _ in
            UIBezierPath(ovalIn: breadthRect).addClip()
            UIImage(cgImage: cgImage, scale: format.scale, orientation: imageOrientation)
            .draw(in: .init(origin: .zero, size: breadthSize))
        }
    }
}

Could you help me convert it into UIKit C#?
Thanks!

P.S. There were no relevant replies, so to the best of my abilities I’ve put together a version that works. See that below.

2

Answers


  1. Chosen as BEST ANSWER

    There were no relevant replies, so to the best of my abilities I've put together a version that works:

    public UIImage cropToCircle(UIImage inimg) {
         if(null == inimg) return null;
    
         // step 1. crop to a square:
         var length = Math.Min(inimg.Size.Width, inimg.Size.Height); 
         var x = inimg.Size.Width/2 - length/2;
         var y = inimg.Size.Height/2 - length/2;
         var cropRect = new CGRect(x, y, length, length);
    
         UIGraphics.BeginImageContextWithOptions(cropRect.Size, false, 0);
         var context = UIGraphics.GetCurrentContext();
    
         context.TranslateCTM(0.0f, (float)length);
         context.ScaleCTM(1.0f, -1.0f);
         context.DrawImage(new RectangleF(0, 0,
                (float)length, (float)length), inimg.CGImage);
         context.ClipToRect(cropRect);
    
         var croppedImage = UIGraphics.GetImageFromCurrentImageContext();
                UIGraphics.EndImageContext();
    
         // step 2. crop to a circle 
         UIImageView imageView = new UIImageView(croppedImage);
         var layer = imageView.Layer;
         layer.MasksToBounds = true;
         layer.CornerRadius = 
              (nfloat)(Math.Min(imageView.Frame.Height, imageView.Frame.Width)) / 2;
         UIGraphics.BeginImageContext(imageView.Bounds.Size);
         layer.RenderInContext(UIGraphics.GetCurrentContext());
         var circleImg = UIGraphics.GetImageFromCurrentImageContext();
         UIGraphics.EndImageContext();
    
         return circleImg;
    }
    

    (The reason I've used a layer for circular cropping is I don't know how to attach UIBezierPath to the context).


  2. For a circular image I recommend using – FFImageLoading

    else trough xaml:

    <Image Source="Image">
              <Image.Clip>
                    <EllipseGeometry Center="30,30">
                        <EllipseGeometry.RadiusX>
                            <OnPlatform x:TypeArguments="x:Double"
                                        iOS="30"
                                        Android="0"/>
                        </EllipseGeometry.RadiusX>
                        <EllipseGeometry.RadiusY>
                            <OnPlatform x:TypeArguments="x:Double"
                                        iOS="30"
                                        Android="0"/>
                        </EllipseGeometry.RadiusY>
                    </EllipseGeometry>
              </Image.Clip>
    </Image>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search