Обрезка захваченного изображения в точности так, как оно выглядит в AVCaptureVideoPreviewLayer

У меня есть приложение для фотографий, которое использует AV Foundation. Я настроил слой предварительного просмотра, используя AVCaptureVideoPreviewLayer, который занимает верхнюю половину экрана. Поэтому, когда пользователь пытается сделать свою фотографию, он видит только то, что видит верхняя часть экрана.

Это прекрасно работает, но когда пользователь на самом деле делает фотографию, и я пытаюсь установить фотографию в качестве содержимого слоя, изображение искажается. Я провел исследование и понял, что мне нужно обрезать изображение.

Все, что я хочу сделать, это обрезать полностью захваченное изображение так, чтобы все, что осталось, было именно тем, что пользователь мог изначально видеть в верхней половине экрана.

Я был в состоянии что-то сделать, но я делаю это, вводя вручную значения CGRect, и это все еще не выглядит идеально. Должен быть более простой способ сделать это.

За последние 2 дня я буквально просматривал все сообщения о переполнении стека, и ничего не получалось.

Должен быть способ программной обрезки захваченного изображения, чтобы конечное изображение было в точности таким, каким оно было первоначально в слое предварительного просмотра.

Вот моя реализация 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];
    }

А вот код, который запускается, когда пользователь нажимает кнопку, чтобы сделать снимок:

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

Ответы на вопрос(3)

Ваш ответ на вопрос