AVFoundation之如何从摄像头获取图像

前言:

最近项目有个需求是对试图对手机密码进行强破解的人进行拍照(通过摄像头截图),因为之前没做过,所以一堆坑。现在就把我的经验都分享出来,希望后来人不用再踏上坑途中。

直接上代码:

  // 创建会话

  self.session = [[AVCaptureSession alloc] init];

   // 获取摄像头的权限信息,判断是否有开启权限

    AVAuthorizationStatus status    = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];

    if (status == AVAuthorizationStatusAuthorized)

    {

        self.setupResult = AVCamSetupResultSuccess;

    }

    if ( self.setupResult != AVCamSetupResultSuccess )

         return;

    self.backgroundRecordingID = UIBackgroundTaskInvalid;

    NSError *error = nil;

    // 创建输入设备

    AVCaptureDevice *videoDevice = [self deviceWithMediaType:AVMediaTypeVideo preferringPosition:AVCaptureDevicePositionFront];

    AVCaptureDeviceInput *videoDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];

 

    // beginConfiguration这个很重要,在addInput或者addOutput的时候一定要调用这个,add之后再调用commitConfiguration

    [self.session beginConfiguration];

    

    if ([self.session canAddInput:videoDeviceInput])

      {

        [self.session addInput:videoDeviceInput];

        self.videoDeviceInput = videoDeviceInput;

       }

   // 为会话加入output设备

    dispatch_queue_t videoDataOutputQueue = dispatch_queue_create("VideoDataOutputQueue", DISPATCH_QUEUE_SERIAL);

        AVCaptureVideoDataOutput *videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];

        videoDataOutput.videoSettings =[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA]forKey:               (id)kCVPixelBufferPixelFormatTypeKey];

    // 设置self的AVCaptureVideoDataOutputSampleBufferDelegate

        [videoDataOutput setSampleBufferDelegate:self queue:videoDataOutputQueue];

        if ([self.session canAddOutput:videoDataOutput])

        {

            [self.session addOutput:videoDataOutput];

 

        }

        [self.session commitConfiguration];

       

 

     // 获取前置摄像头

- (AVCaptureDevice *)deviceWithMediaType:(NSString *)mediaType preferringPosition:(AVCaptureDevicePosition)position{

    NSArray *devices = [AVCaptureDevice devicesWithMediaType:mediaType];

    AVCaptureDevice *captureDevice = devices.firstObject;

    

    for ( AVCaptureDevice *device in devices ) {

        if ( device.position == position ) {

            captureDevice = device;

            break;

        }

    }

     return captureDevice;

}

    // 实现代理方法并获取图片

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{

    if (takephoto.isShutScreen)

    {

        NSLog(@"didOutputSampleBuffer");

        UIImage *image  = [self getImageBySampleBufferref:sampleBuffer];

    }

}

    // 将获取的数据转换成图片,网上很多转换方式转出来的图片都是错误的,最后找到这个方法

- (UIImage *)getImageBySampleBufferref:(CMSampleBufferRef)sampleBuffer

{

    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

    /*Lock the image buffer*/

    CVPixelBufferLockBaseAddress(imageBuffer,0);

    /*Get information about the image*/

    uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);

    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);

    size_t width = CVPixelBufferGetWidth(imageBuffer);

    size_t height = CVPixelBufferGetHeight(imageBuffer);

    

    /*We unlock the  image buffer*/

    CVPixelBufferUnlockBaseAddress(imageBuffer,0);

    

    /*Create a CGImageRef from the CVImageBufferRef*/

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);

    CGImageRef newImage = CGBitmapContextCreateImage(newContext);

    

    /*We release some components*/

    CGContextRelease(newContext);

    CGColorSpaceRelease(colorSpace);

    

    UIImage *image= [UIImage imageWithCGImage:newImage scale:1.0 orientation:UIImageOrientationRight];

    NSLog(@"%@", image);

    

    /*We relase the CGImageRef*/

    CGImageRelease(newImage);

 

    return image;

}

  

    只要照着我的思路走,就可以达到摄像机截屏的效果,希望能帮到需要的人,如有其他意见,请留言。

原文地址:https://www.cnblogs.com/destiLaugh/p/6552569.html