title: Crop image displayed in UIScrollview to rect displayed in overlay
body: <p>I have been looking around and cant find an answer to my issue. I have a scroll view with an embedded image view. You can rotate and zoom the image.</p>
  
  <p>The view hierarchy looks like this:</p>
  
  <pre><code>|-&gt; UIViewController
  |--&gt; UIView
  |---&gt; UIScrollView
  |----&gt; UIImageView
  </code></pre>
  
  <p>The UIView is just the default view added when you drop a controller on the storyboard. </p>
  
  <p>I also draw an overlay onto the top view, its looks like this:</p>
  
  <p><a href="https://i.stack.imgur.com/0kqbQm.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/0kqbQm.png" alt="enter image description here"></a></p>
  
  <p>What i need to do is is crop the image to the size of the overlay. The overlay is created pragmatically but i keep a reference to the rect used for the square centre. The code used to generate the overlay is:</p>
  
  <pre><code> private void DrawOverlay()
      {
          var overlayPath = UIBezierPath.FromRect(View.Bounds);
  
          // Calculate the size of the transparent area we need.
          var rectSize = View.Frame.Width * 80 / 100;
          nfloat clearStartX = View.Frame.GetMidX() - (rectSize / 2);
          nfloat clearWidth = View.Frame.Size.Width - (clearStartX * 2);
          nfloat clearStartY = View.Frame.GetMidY() - ((GetTopBarHeight() + rectSize) / 2);
          nfloat clearHeight = clearWidth;
  
          // Create the rectange for out transparent area;
          TransparentRect = new CGRect(clearStartX, clearStartY, clearWidth, clearHeight);
  
          var transparentPath = UIBezierPath.FromRect(TransparentRect);
  
          // Apply the transparent box to our overall view.
          overlayPath.AppendPath(transparentPath);
          overlayPath.UsesEvenOddFillRule = true;
  
          // Set the full colour.
          var fillLayer = new CAShapeLayer();
          fillLayer.Path = overlayPath.CGPath;
          fillLayer.FillRule = CAShapeLayer.FillRuleEvenOdd;
          fillLayer.FillColor = Colours.TransparentBackground.CGColor;
  
          View.Layer.AddSublayer(fillLayer);
  
          // Calculate the length of the white line we want.
          var lineWidth = rectSize * 20 / 100;
  
          // Create a bezier path based on the transparent rect we defined earlier, that and a combination of the line
          // width we can plot each point to draw the lines. Each MoveTo defines the start of a new corner.
          UIBezierPath path = new UIBezierPath();
          path.MoveTo(new CGPoint(clearStartX, clearStartY + lineWidth));
          path.AddLineTo(new CGPoint(clearStartX, clearStartY));
          path.AddLineTo(new CGPoint(clearStartX + lineWidth, clearStartY));
  
          path.MoveTo(new CGPoint((clearStartX + rectSize) - lineWidth, clearStartY));
          path.AddLineTo(new CGPoint(clearStartX + rectSize, clearStartY));
          path.AddLineTo(new CGPoint(clearStartX + rectSize, clearStartY + lineWidth));
  
          path.MoveTo(new CGPoint(clearStartX, (clearStartY + rectSize) - lineWidth));
          path.AddLineTo(new CGPoint(clearStartX, (clearStartY + rectSize)));
          path.AddLineTo(new CGPoint(clearStartX + lineWidth, (clearStartY + rectSize)));
  
          path.MoveTo(new CGPoint((clearStartX + rectSize) - lineWidth, (clearStartY + rectSize)));
          path.AddLineTo(new CGPoint((clearStartX + rectSize), (clearStartY + rectSize)));
          path.AddLineTo(new CGPoint((clearStartX + rectSize), (clearStartY + rectSize) - lineWidth));
  
          // Apply the path and set the width and colour.
          CAShapeLayer pathLayer = new CAShapeLayer();
          pathLayer.Path = path.CGPath;
          pathLayer.StrokeColor = UIColor.White.CGColor;
          pathLayer.LineWidth = 5.0f;
          pathLayer.FillColor = null;
  
          View.Layer.AddSublayer(pathLayer);
      }
  </code></pre>
  
  <p>I have tried cropping the image like this:</p>
  
  <pre><code> var imageref = ImageView.Image.CGImage.WithImageInRect(TransparentRect);
   UIImage croppedImage = new UIImage(imageref);
  </code></pre>
  
  <p>This appears to be the way most answers on here point too. However this does not work for me. Firstly the transforms are applied to the scrollview not the image view, because the gestures are bound to it as you can see below.</p>
  
  <pre><code>    public override void ViewDidLoad()
      { 
         base.ViewDidLoad();
         NavigationItem.Title = "Crop Image";
  
         var ButtonDone = new UIBarButtonItem("Done", 
         UIBarButtonItemStyle.Plain, (sender, e) =&gt;
         {
            CropImage();
         });  
  
         this.NavigationItem.SetRightBarButtonItem(ButtonDone, true);
  
         DrawOverlay();
  
         ScrollView.MinimumZoomScale = 1.0f;
         ScrollView.MaximumZoomScale = 5.0f;
         ScrollView.Delegate = this;
         ScrollView.ContentSize = new CGSize(ImageView.Frame.Size.Width, ImageView.Frame.Size.Height);
         var rotateGesture = new UIRotationGestureRecognizer((g) =&gt;
         {
            g.View.Transform = CGAffineTransform.Rotate(g.View.Transform, g.Rotation);
            g.Rotation = 0;
         });
         rotateGesture.Delegate = this;
  
  
         ScrollView.AddGestureRecognizer(rotateGesture);
      }
  
      [Export("viewForZoomingInScrollView:")]
      public UIView ViewForZoomingInScrollView(UIScrollView scrollView)
      {
         return ImageView;
      }
  
  [Export("gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:")]
      public bool ShouldRecognizeSimultaneously(UIGestureRecognizer gestureRecognizer, UIGestureRecognizer otherGestureRecognizer)
      {
          return true;
      }
  </code></pre>
  
  <p>So how can i crop the image to the transparent overlay rect and keep the zoom and rotation transforms? </p>
  
  <p>Thank you for any help with this issue.</p>