Beschneiden eines aufgenommenen Bildes genau so, wie es in AVCaptureVideoPreviewLayer aussieht

Ich habe eine Foto-App, die AV Foundation verwendet. Ich habe mit AVCaptureVideoPreviewLayer eine Vorschauebene eingerichtet, die die obere Hälfte des Bildschirms einnimmt. Wenn der Benutzer versucht, sein Foto aufzunehmen, sieht er nur die obere Hälfte des Bildschirms.

Dies funktioniert prima, aber wenn der Benutzer das Foto tatsächlich aufnimmt und ich versuche, das Foto als Ebeneninhalt festzulegen, wird das Bild verzerrt. Ich recherchierte und erkannte, dass ich das Bild zuschneiden musste.

Ich möchte nur das gesamte aufgenommene Bild zuschneiden, sodass nur noch genau das übrig bleibt, was der Benutzer ursprünglich in der oberen Hälfte des Bildschirms sehen konnte.

Ich habe es irgendwie geschafft, aber ich mache das, indem ich manuelle CGRect-Werte eingebe und es sieht immer noch nicht perfekt aus. Es muss einen einfacheren Weg geben, dies zu tun.

Ich habe in den letzten 2 Tagen buchstäblich jeden Beitrag über Stapelüberlauf durchgesehen, in dem es um das Zuschneiden von Bildern ging, und nichts hat funktioniert.

Es muss eine Möglichkeit geben, das aufgenommene Bild programmgesteuert zuzuschneiden, damit das endgültige Bild genau das ist, was ursprünglich in der Vorschauebene angezeigt wurde.

Hier ist meine viewDidLoad-Implementierung:

- (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];
    }

Und hier ist der Code, der ausgeführt wird, wenn der Benutzer die Taste drückt, um ein Foto aufzunehmen:

-(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];
        }
    }];
}