Recortar una imagen capturada exactamente como se ve en AVCaptureVideoPreviewLayer

Tengo una aplicación de fotos que usa AV Foundation. He configurado una capa de vista previa usando AVCaptureVideoPreviewLayer que ocupa la mitad superior de la pantalla. Entonces, cuando el usuario intenta tomar su foto, todo lo que puede ver es lo que ve la mitad superior de la pantalla.

Esto funciona muy bien, pero cuando el usuario realmente toma la foto y trato de configurar la foto como el contenido de la capa, la imagen se distorsiona. Investigué y me di cuenta de que necesitaría recortar la imagen.

Todo lo que quiero hacer es recortar la imagen capturada completa para que todo lo que quede sea exactamente lo que el usuario pudo ver originalmente en la mitad superior de la pantalla.

He podido lograr esto, pero lo estoy haciendo ingresando los valores manuales de CGRect y todavía no se ve perfecto. Tiene que haber una manera más fácil de hacer esto.

Literalmente, he revisado cada publicación en el desbordamiento de pila durante los últimos 2 días sobre el recorte de imágenes y nada ha funcionado.

Tiene que haber una manera de recortar mediante programación la imagen capturada para que la imagen final sea exactamente lo que se vio originalmente en la capa de vista previa.

Aquí está mi implementación viewDidLoad:

- (void)viewDidLoad
{
    [super viewDidLoad];

    AVCaptureSession *session =[[AVCaptureSession alloc]init];
    [session setSessionPreset:AVCaptureSessionPresetPhoto];

    AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    NSError *error = [[NSError alloc]init];
    AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:&error];

    if([session canAddInput:deviceInput])
        [session addInput:deviceInput];

    CALayer *rootLayer = [[self view]layer];
    [rootLayer setMasksToBounds:YES];

    _previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:session];
    [_previewLayer setFrame:CGRectMake(0, 0, rootLayer.bounds.size.width, rootLayer.bounds.size.height/2)];
    [_previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];

    [rootLayer insertSublayer:_previewLayer atIndex:0];

    _stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
    [session addOutput:_stillImageOutput];

    [session startRunning];
    }

Y aquí está el código que se ejecuta cuando el usuario presiona el botón para capturar una foto:

-(IBAction)stillImageCapture {
    AVCaptureConnection *videoConnection = nil;
    for (AVCaptureConnection *connection in _stillImageOutput.connections){
        for (AVCaptureInputPort *port in [connection inputPorts]){
            if ([[port mediaType] isEqual:AVMediaTypeVideo]){
                videoConnection = connection;
                break;
            }
        }
        if (videoConnection) {
            break;
        }
    }

    NSLog(@"about to request a capture from: %@", _stillImageOutput);

    [_stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
        if(imageDataSampleBuffer) {
            NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];

            UIImage *image = [[UIImage alloc]initWithData:imageData];
            CALayer *subLayer = [CALayer layer];
            subLayer.frame = _previewLayer.frame;
            image = [self rotate:image andOrientation:image.imageOrientation];

            //Below is the crop that is sort of working for me, but as you can see I am manually entering in values and just guessing and it still does not look perfect.
            CGRect cropRect = CGRectMake(0, 650, 3000, 2000);
            CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect);

            subLayer.contents = (id)[UIImage imageWithCGImage:imageRef].CGImage;
            subLayer.frame = _previewLayer.frame;

            [_previewLayer addSublayer:subLayer];
        }
    }];
}

Respuestas a la pregunta(3)

Su respuesta a la pregunta