How to crop an image from AVCapture to a rect seen on the display

后端 未结 4 1303
梦谈多话
梦谈多话 2021-01-30 08:59

This is driving me crazy because I can\'t get it to work. I have the following scenario:

I\'m using an AVCaptureSession and an AVCaptureVideoPreviewLa

相关标签:
4条回答
  • 2021-01-30 09:19

    In Swift 3:

    private func cropToPreviewLayer(originalImage: UIImage) -> UIImage {
        let outputRect = previewLayer.metadataOutputRectConverted(fromLayerRect: previewLayer.bounds)
        var cgImage = originalImage.cgImage!
        let width = CGFloat(cgImage.width)
        let height = CGFloat(cgImage.height)
        let cropRect = CGRect(x: outputRect.origin.x * width, y: outputRect.origin.y * height, width: outputRect.size.width * width, height: outputRect.size.height * height)
        
        cgImage = cgImage.cropping(to: cropRect)!
        let croppedUIImage = UIImage(cgImage: cgImage, scale: 1.0, orientation: originalImage.imageOrientation)
        
        return croppedUIImage
    }
    
    0 讨论(0)
  • AVMakeRectWithAspectRatioInsideRect this api is from AVFoundation, it will return the crop region for the image given the crop size.

    0 讨论(0)
  • 2021-01-30 09:30

    In Swift 4:

    I prefer to never force-unwrap to avoid crashes, so I use optionals and guards in mine.

    private func cropToPreviewLayer(originalImage: UIImage) -> UIImage? {
        guard let cgImage = originalImage.cgImage else { return nil }
    
        let outputRect = previewLayer.metadataOutputRectConverted(fromLayerRect: previewLayer.bounds)
    
        let width = CGFloat(cgImage.width)
        let height = CGFloat(cgImage.height)
        let cropRect = CGRect(x: outputRect.origin.x * width, y: outputRect.origin.y * height, width: outputRect.size.width * width, height: outputRect.size.height * height)
    
        if let croppedCGImage = cgImage.cropping(to: cropRect) {
            return UIImage(cgImage: croppedCGImage, scale: 1.0, orientation: originalImage.imageOrientation)
        }
    
        return nil
    }
    
    0 讨论(0)
  • 2021-01-30 09:34

    I've solved this problem by using metadataOutputRectOfInterestForRect function.

    It works with any orientation.

    [_stillImageOutput captureStillImageAsynchronouslyFromConnection:stillImageConnection
                                                   completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error)
     {
         if (error)
         {
             [_delegate cameraView:self error:@"Take picture failed"];
         }
         else
         {
    
             NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
             UIImage *takenImage = [UIImage imageWithData:jpegData];
    
             CGRect outputRect = [_previewLayer metadataOutputRectOfInterestForRect:_previewLayer.bounds];
             CGImageRef takenCGImage = takenImage.CGImage;
             size_t width = CGImageGetWidth(takenCGImage);
             size_t height = CGImageGetHeight(takenCGImage);
             CGRect cropRect = CGRectMake(outputRect.origin.x * width, outputRect.origin.y * height, outputRect.size.width * width, outputRect.size.height * height);
    
             CGImageRef cropCGImage = CGImageCreateWithImageInRect(takenCGImage, cropRect);
             takenImage = [UIImage imageWithCGImage:cropCGImage scale:1 orientation:takenImage.imageOrientation];
             CGImageRelease(cropCGImage);
    
         }
     }
     ];
    

    The takenImage is still imageOrientation dependent image. You can delete orientation information for further image processing.

    UIGraphicsBeginImageContext(takenImage.size);
    [takenImage drawAtPoint:CGPointZero];
    takenImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    0 讨论(0)
提交回复
热议问题