【问题标题】:Capture image with bounds?捕获有边界的图像?
【发布时间】:2012-12-31 22:41:15
【问题描述】:

我能够从 iOS 后置摄像头捕捉图像。除了我希望它按照我的UIView 中的边界拍摄照片之外,一切都完美无缺。

我的代码如下:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    session = [[AVCaptureSession alloc] init];

    session.sessionPreset = AVCaptureSessionPresetMedium;

    captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
    captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    captureVideoPreviewLayer.frame = vImagePreview.bounds;
    [vImagePreview.layer addSublayer:captureVideoPreviewLayer];

    AVCaptureDevice *device = [self backFacingCameraIfAvailable];
    NSError *error = nil;
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
    if (!input) {
        // Handle the error appropriately.
        NSLog(@"ERROR: trying to open camera: %@", error);
    }
    [session addInput:input];

    stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
    NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
    [stillImageOutput setOutputSettings:outputSettings];
    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;
        }
    }

    [session startRunning];

    [session addOutput:stillImageOutput];
}

-(AVCaptureDevice *)backFacingCameraIfAvailable{

    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    AVCaptureDevice *captureDevice = nil;
    for (AVCaptureDevice *device in videoDevices){
        if (device.position == AVCaptureDevicePositionBack){
            captureDevice = device;
            break;
        }
    }

    //  couldn't find one on the back, so just get the default video device.
    if (!captureDevice){
        captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    }
    return captureDevice;
}

下面是捕获图像的代码:

- (IBAction)captureTask {
    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 imageSampleBuffer, NSError *error)
     {
         CFDictionaryRef exifAttachments = CMGetAttachment(imageSampleBuffer, kCGImagePropertyExifDictionary, NULL);
         if (exifAttachments) {
             // Do something with the attachments.
             NSLog(@"attachements: %@", exifAttachments);
         } else {
             NSLog(@"no attachments");
         }

         NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
         UIImage *image = [[UIImage alloc] initWithData:imageData];
         stillImage = image;

     }];
}

我面临的问题是它正在拍照并保存到stillImage,但是,据我所知,该图像适用于整个 iPhone 屏幕。它不在我创建的UIView *vImagePreview 的范围内。有没有办法裁剪捕获的图像的边界??

[编辑]

阅读文档后,我意识到图像的分辨率合适,如下所示:session.sessionPreset = AVCaptureSessionPresetMedium;。有没有办法让图像像一个正方形?就像Instagram如何制作他们的图片一样?根据文档的所有会话预设都不是正方形:(

我尝试了以下方法:

captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResize;

但是,它只会调整图像大小以适合当前视图,不会制作方形图像。

【问题讨论】:

    标签: ios objective-c camera avcapturesession


    【解决方案1】:

    我理解您的沮丧,预设应该是可定制的或有更多选项!我对图像所做的就是围绕中心裁剪它们,为此我编写了以下代码:

    - (UIImage *)crop:(UIImage *)image from:(CGSize)src to:(CGSize)dst
    {
        CGPoint cropCenter = CGPointMake((src.width/2), (src.height/2));
        CGPoint cropStart = CGPointMake((cropCenter.x - (dst.width/2)), (cropCenter.y - (dst.height/2)));
        CGRect cropRect = CGRectMake(cropStart.x, cropStart.y, dst.width, dst.height);
        CGImageRef cropRef = CGImageCreateWithImageInRect(image.CGImage, cropRect);
        UIImage* cropImage = [UIImage imageWithCGImage:cropRef];
        CGImageRelease(cropRef);
    
        return cropImage;
    }
    

    其中src代表原始尺寸,dst代表裁剪后的尺寸; image 当然是您要裁剪的图像。

    【讨论】:

    • 虽然不理想,但您的解决方案有效。希望他们通过拍照解决其中的一些问题
    【解决方案2】:

    如果设备是视网膜显示器, 那么这个屏幕截图的工作原理如下:

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] == YES && [[UIScreen mainScreen] scale] == 2.00)
    {
        CGPoint cropCenter = CGPointMake((src.width), (src.height));
        CGPoint cropStart = CGPointMake((cropCenter.x - (dst.width)), (cropCenter.y - (dst.height)));
        CGRect cropRect = CGRectMake(cropStart.x, cropStart.y, dst.width*2, dst.height*2);
        CGImageRef cropRef = CGImageCreateWithImageInRect(image.CGImage, cropRect);
        UIImage* cropImage = [UIImage imageWithCGImage:cropRef];
        CGImageRelease(cropRef);
        return cropImage;
    }
    else
    {
        CGPoint cropCenter = CGPointMake((src.width/2), (src.height/2));
        CGPoint cropStart = CGPointMake((cropCenter.x - (dst.width/2)), (cropCenter.y - (dst.height/2)));
        CGRect cropRect = CGRectMake(cropStart.x, cropStart.y, dst.width, dst.height);
        CGImageRef cropRef = CGImageCreateWithImageInRect(image.CGImage, cropRect);
        UIImage* cropImage = [UIImage imageWithCGImage:cropRef];
        CGImageRelease(cropRef);
    
        return cropImage;
    }
    

    【讨论】:

      猜你喜欢
      • 2019-10-18
      • 2019-05-11
      • 2019-02-02
      • 1970-01-01
      • 2019-06-29
      • 1970-01-01
      • 2019-07-28
      • 1970-01-01
      • 2020-12-31
      相关资源
      最近更新 更多