前言:
最近项目有个需求是对试图对手机密码进行强破解的人进行拍照(通过摄像头截图),因为之前没做过,所以一堆坑。现在就把我的经验都分享出来,希望后来人不用再踏上坑途中。
直接上代码:
// 创建会话
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;
}
只要照着我的思路走,就可以达到摄像机截屏的效果,希望能帮到需要的人,如有其他意见,请留言。