title: How to crop an image from AVCapture to a rect seen on the display
body: <p>This is driving me crazy because I can't get it to work. I have the following scenario:</p>
  
  <p>I'm using an <code>AVCaptureSession</code> and an <code>AVCaptureVideoPreviewLayer</code> to create my own camera interface. The interface shows a rectangle. Below is the <code>AVCaptureVideoPreviewLayer</code> that fills the whole screen.</p>
  
  <p>I want to the captured image to be cropped in a way, that the resulting image shows exactly the content seen in the rect on the display. </p>
  
  <p>My setup looks like this:</p>
  
  <pre><code>_session = [[AVCaptureSession alloc] init];
  AVCaptureSession *session = _session;
  session.sessionPreset = AVCaptureSessionPresetPhoto;
  
  AVCaptureDevice *camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
  if (camera == nil) {
      [self showImagePicker];
      _isSetup = YES;
      return;
  }
  AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
  captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
  
  captureVideoPreviewLayer.frame = self.liveCapturePlaceholderView.bounds;
  [self.liveCapturePlaceholderView.layer addSublayer:captureVideoPreviewLayer];
  
  NSError *error;
  AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:camera error:&amp;error];
  if (error) {
      HGAlertViewWrapper *av = [[HGAlertViewWrapper alloc] initWithTitle:kFailedConnectingToCameraAlertViewTitle message:kFailedConnectingToCameraAlertViewMessage cancelButtonTitle:kFailedConnectingToCameraAlertViewCancelButtonTitle otherButtonTitles:@[kFailedConnectingToCameraAlertViewRetryButtonTitle]];
      [av showWithBlock:^(NSString *buttonTitle){
          if ([buttonTitle isEqualToString:kFailedConnectingToCameraAlertViewCancelButtonTitle]) {
              [self.delegate gloameCameraViewControllerDidCancel:self];
          }
          else {
              [self setupAVSession];
          }
      }];
  }
  [session addInput:input];
  
  NSDictionary *options = @{ AVVideoCodecKey : AVVideoCodecJPEG };
  _stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
  [_stillImageOutput setOutputSettings:options];
  
  [session addOutput:_stillImageOutput];
  
  [session startRunning];
  _isSetup = YES;
  </code></pre>
  
  <p>I'm capturing the image like this:</p>
  
  <pre><code>[_stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
   {
       if (error) {
           MWLogDebug(@"Error capturing image from camera. %@, %@", error, [error userInfo]);
           _capturePreviewLayer.connection.enabled = YES;
       }
       else
       {
           NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
           UIImage *image = [[UIImage alloc] initWithData:imageData];
  
           CGRect cropRect = [self createCropRectForImage:image];
           UIImage *croppedImage;// = [self cropImage:image toRect:cropRect];
           UIGraphicsBeginImageContext(cropRect.size);
           [image drawAtPoint:CGPointMake(-cropRect.origin.x, -cropRect.origin.y)];
           croppedImage = UIGraphicsGetImageFromCurrentImageContext();
           UIGraphicsEndImageContext();
           self.capturedImage = croppedImage;
           [_session stopRunning];             
       }
   }];
  </code></pre>
  
  <p>In the <code>createCropRectForImage:</code> method I've tried various ways to calculate the rect to cut out of the image, but with no success so far.</p>
  
  <pre><code>- (CGRect)createCropRectForImage:(UIImage *)image
  {
      CGPoint maskTopLeftCorner = CGPointMake(self.maskRectView.frame.origin.x, self.maskRectView.frame.origin.y);
      CGPoint maskBottomRightCorner = CGPointMake(self.maskRectView.frame.origin.x + self.maskRectView.frame.size.width, self.maskRectView.frame.origin.y + self.maskRectView.frame.size.height);
  
      CGPoint maskTopLeftCornerInLayerCoords = [_capturePreviewLayer convertPoint:maskTopLeftCorner fromLayer:self.maskRectView.layer.superlayer];
      CGPoint maskBottomRightCornerInLayerCoords = [_capturePreviewLayer convertPoint:maskBottomRightCorner fromLayer:self.maskRectView.layer.superlayer];
      CGPoint maskTopLeftCornerInDeviceCoords = [_capturePreviewLayer captureDevicePointOfInterestForPoint:maskTopLeftCornerInLayerCoords];
      CGPoint maskBottomRightCornerInDeviceCoords = [_capturePreviewLayer captureDevicePointOfInterestForPoint:maskBottomRightCornerInLayerCoords];
  
      float x = maskTopLeftCornerInDeviceCoords.x * image.size.width;
      float y = (1 - maskTopLeftCornerInDeviceCoords.y) * image.size.height;
      float width = fabsf(maskTopLeftCornerInDeviceCoords.x - maskBottomRightCornerInDeviceCoords.x) * image.size.width;
      float height = fabsf(maskTopLeftCornerInDeviceCoords.y - maskBottomRightCornerInDeviceCoords.y) * image.size.height;
  
      return CGRectMake(x, y, width, height);
  }
  </code></pre>
  
  <p>That is my current version but doesn't even get the proportions right. Could some one please help me!</p>
  
  <p>I have also tried using this method to crop my image:</p>
  
  <pre><code>- (UIImage*)cropImage:(UIImage*)originalImage toRect:(CGRect)rect{
  
      CGImageRef imageRef = CGImageCreateWithImageInRect([originalImage CGImage], rect);
  
      CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
      CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
      CGContextRef bitmap = CGBitmapContextCreate(NULL, rect.size.width, rect.size.height, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
  
      if (originalImage.imageOrientation == UIImageOrientationLeft) {
          CGContextRotateCTM (bitmap, radians(90));
          CGContextTranslateCTM (bitmap, 0, -rect.size.height);
  
      } else if (originalImage.imageOrientation == UIImageOrientationRight) {
          CGContextRotateCTM (bitmap, radians(-90));
          CGContextTranslateCTM (bitmap, -rect.size.width, 0);
  
      } else if (originalImage.imageOrientation == UIImageOrientationUp) {
          // NOTHING
      } else if (originalImage.imageOrientation == UIImageOrientationDown) {
          CGContextTranslateCTM (bitmap, rect.size.width, rect.size.height);
          CGContextRotateCTM (bitmap, radians(-180.));
      }
  
      CGContextDrawImage(bitmap, CGRectMake(0, 0, rect.size.width, rect.size.height), imageRef);
      CGImageRef ref = CGBitmapContextCreateImage(bitmap);
  
      UIImage *resultImage=[UIImage imageWithCGImage:ref];
      CGImageRelease(imageRef);
      CGContextRelease(bitmap);
      CGImageRelease(ref);
  
      return resultImage;
  }
  </code></pre>
  
  <p>Does anybody have the 'right combination' of methods to make this work? :)</p>