iOS 獲取照相機實時預覽圖片

使用Objective-C實現
AVController.h頭文件

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <CoreVideo/CoreVideo.h>
#import <CoreMedia/CoreMedia.h>

@interface AVController : UIViewController<AVCaptureVideoDataOutputSampleBufferDelegate> {
  AVCaptureSession *_captureSession;
  UIImageView *_imageView;
  CALayer *_customLayer;
  AVCaptureVideoPreviewLayer *_prevLayer;
}

@property (nonatomic, retain) AVCaptureSession *captureSession;
@property (nonatomic, retain) UIImageView *imageView;
@property (nonatomic, retain) CALayer *customLayer;
@property (nonatomic, retain) AVCaptureVideoPreviewLayer *prevLayer;

@end

AVController.m實現

@implementation AVController

//@synthesize captureSession = _captureSession;
//@synthesize imageView = _imageView;
//@synthesize customLayer = _customLayer;
//@synthesize prevLayer = _prevLayer;

- (void)viewDidLoad
{
  [super viewDidLoad];
  [self initCapture];
}

/**
 * 初始化攝像頭
 */
- (void)initCapture {
  AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
  AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:device  error:nil];
  AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc]
                                             init];
  captureOutput.alwaysDiscardsLateVideoFrames = YES;
  // captureOutput.minFrameDuration = CMTimeMake(1, 10);

  dispatch_queue_t queue = dispatch_queue_create("cameraQueue", NULL);
  [captureOutput setSampleBufferDelegate:self queue:queue];
  NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;
  NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
  NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];
  [captureOutput setVideoSettings:videoSettings];
  self.captureSession = [[AVCaptureSession alloc] init];
  [self.captureSession addInput:captureInput];
  [self.captureSession addOutput:captureOutput];
  [self.captureSession startRunning];

  self.customLayer = [CALayer layer];
  CGRect frame = self.view.bounds;
  frame.origin.y = 64;
  frame.size.height = frame.size.height - 64;

  self.customLayer.frame = frame;
  self.customLayer.transform = CATransform3DRotate(CATransform3DIdentity, M_PI/2.0f, 0, 0, 1);
  self.customLayer.contentsGravity = kCAGravityResizeAspectFill;
  [self.view.layer addSublayer:self.customLayer];

  self.imageView = [[UIImageView alloc] init];
  self.imageView.frame = CGRectMake(0, 64, 100, 100);
  [self.view addSubview:self.imageView];
  self.prevLayer = [AVCaptureVideoPreviewLayer layerWithSession: self.captureSession];
  self.prevLayer.frame = CGRectMake(100, 64, 100, 100);
  self.prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; 
  [self.view.layer addSublayer: self.prevLayer];

  UIButton *back = [[UIButton alloc]init];
  [back setTitle:@"Back" forState:UIControlStateNormal];
  [back setTitleColor:[UIColor redColor] forState:UIControlStateNormal];

  [back sizeToFit];
  frame = back.frame;
  frame.origin.y = 25;
  back.frame = frame;
  [self.view addSubview:back];
  [back addTarget:self action:@selector(back:) forControlEvents:UIControlEventTouchUpInside];
}

-(void)back:(id)sender{
  [self dismissViewControllerAnimated:true completion:nil];
}

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
       fromConnection:(AVCaptureConnection *)connection
{
  CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
  CVPixelBufferLockBaseAddress(imageBuffer,0);
  uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
  size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
  size_t width = CVPixelBufferGetWidth(imageBuffer);
  size_t height = CVPixelBufferGetHeight(imageBuffer);

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

  CGImageRef newImage = CGBitmapContextCreateImage(newContext);

  CGContextRelease(newContext);
  CGColorSpaceRelease(colorSpace);

  id object = (__bridge id)newImage;
  // http://www.cnblogs.com/zzltjnh/p/3885012.html
  [self.customLayer performSelectorOnMainThread:@selector(setContents:) withObject: object waitUntilDone:YES];

  UIImage *image= [UIImage imageWithCGImage:newImage scale:1.0 orientation:UIImageOrientationRight];
  // release
  CGImageRelease(newImage);

  [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];

  CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
}

- (void)viewDidUnload {
  [self.captureSession stopRunning];
  self.imageView = nil;
  self.customLayer = nil;
  self.prevLayer = nil;
}

- (void) dealloc {
//  [self.captureSession release];
}

@end

使用Swift實現

import UIKit

class MyAVController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {

  var captureSession:AVCaptureSession!

  var customLayer:CALayer!

  var imageView:UIImageView!

  var previewLayer:AVCaptureVideoPreviewLayer!

  override func viewDidLoad() {
    let device = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
    let captureInput = try? AVCaptureDeviceInput(device: device[0] as! AVCaptureDevice)

    let captureOutput = AVCaptureVideoDataOutput()
    captureOutput.alwaysDiscardsLateVideoFrames = true

    let queue = dispatch_queue_create("cameraQueue", nil)
    captureOutput.setSampleBufferDelegate(self, queue: queue)

    let key = kCVPixelBufferPixelFormatTypeKey as NSString
    let value = NSNumber(unsignedInt: kCVPixelFormatType_32BGRA)
    let videoSettings = [key: value]
    captureOutput.videoSettings = videoSettings

    captureSession = AVCaptureSession()
    captureSession.addInput(captureInput)
    captureSession.addOutput(captureOutput)
    captureSession.startRunning()

    customLayer = CALayer()
    var frame = self.view.bounds
    frame.origin.y = 64
    frame.size.height = frame.size.height - 64
    customLayer.frame = frame
    customLayer.transform = CATransform3DRotate(CATransform3DIdentity, CGFloat(M_PI) / 2.0, 0, 0, 1)
    customLayer.contentsGravity = kCAGravityResizeAspectFill
    self.view.layer.addSublayer(customLayer)

    imageView = UIImageView()
    imageView.frame = CGRectMake(0, 64, 100, 100)
    self.view.addSubview(imageView)

    previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    previewLayer.frame = CGRectMake(100, 64, 100, 100)
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
    self.view.layer.addSublayer(previewLayer)

    let btn = UIButton()
    btn.setTitle("Back", forState: .Normal)
    btn.setTitleColor(UIColor.redColor(), forState: .Normal)
    btn.sizeToFit()
    frame = btn.frame
    frame.origin.y = 25
    btn.frame = frame
    self.view.addSubview(btn)
    btn.addTarget(self, action: "back:", forControlEvents: .TouchUpInside)
  }

  func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!){

    let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!

    CVPixelBufferLockBaseAddress(imageBuffer, 0)

    let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer)
    let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer)
    let width = CVPixelBufferGetWidth(imageBuffer)
    let height = CVPixelBufferGetHeight(imageBuffer)

    let colorSpace = CGColorSpaceCreateDeviceRGB()
//    let bmpInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedFirst.rawValue|CGBitmapInfo.ByteOrder32Little.rawValue)
    let newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, CGImageAlphaInfo.PremultipliedFirst.rawValue|CGBitmapInfo.ByteOrder32Little.rawValue)
    let newImage = CGBitmapContextCreateImage(newContext)

    customLayer.performSelectorOnMainThread("setContents:", withObject: newImage, waitUntilDone: true)

    let image = UIImage(CGImage: newImage!, scale: 1.0, orientation: UIImageOrientation.Right)
    imageView.performSelectorOnMainThread("setImage:", withObject: image, waitUntilDone: true)

    CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
  }

  func back(sender:AnyObject) {
    self.dismissViewControllerAnimated(true, completion: nil)
  }

  override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    captureSession.stopRunning()
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章