AVFoundationでカメラアプリを作るほうが、UIImagePickerControllerを使うより拡張性が高いということで、さくっと表示させるサンプルを用意しました。
準備
プロジェクトに以下を追加。
- AVFoundation.framework
- CoreVideo.framework
- CoreMedia.framework
- QuartzCore.framework
- MobileCoreService.framework
画像のキャプチャ
まず以下をヘッダファイルに追記。
ただし、別にここに書かなくとも良いけども。
ViewController.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface ViewController : UIViewController<AVCaptureVideoDataOutputSampleBufferDelegate>
@property (nonatomic, strong) AVCaptureSession* session;
@property (nonatomic, strong) IBOutlet UIImageView* imageView;
@end
次に、ViewController.xibにUImageViewを追加して、ヘッダファイルのimageViewとリンクしておくこと。
AVFoundationは、
- AVCaptureSessionを作る
- sessionをスタートさせる
- delegateで取得したデータを受け取る
の流れでとりあえず画像を取得できます。
まず、captureSessionを作り、スタートさせる。
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
//デバイス取得
AVCaptureDevice* device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//入力作成
AVCaptureDeviceInput* deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:NULL];
//ビデオデータ出力作成
NSDictionary* settings = @{(id)kCVPixelBufferPixelFormatTypeKey:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA]};
AVCaptureVideoDataOutput* dataOutput = [[AVCaptureVideoDataOutput alloc] init];
dataOutput.videoSettings = settings;
[dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
//セッション作成
self.session = [[AVCaptureSession alloc] init];
[self.session addInput:deviceInput];
[self.session addOutput:dataOutput];
self.session.sessionPreset = AVCaptureSessionPresetHigh;
AVCaptureConnection *videoConnection = NULL;
// カメラの向きなどを設定する
[self.session beginConfiguration];
for ( AVCaptureConnection *connection in [dataOutput connections] )
{
for ( AVCaptureInputPort *port in [connection inputPorts] )
{
if ( [[port mediaType] isEqual:AVMediaTypeVideo] )
{
videoConnection = connection;
}
}
}
if([videoConnection isVideoOrientationSupported]) // **Here it is, its always false**
{
[videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait];
}
[self.session commitConfiguration];
// セッションをスタートする
[self.session startRunning];
}
その後、delegateメソッドを実装し、その中でCMSampleBufferRefをUIImageに変換する。
ViewController.m
//delegateメソッド。各フレームにおける処理
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
// 画像の表示
self.imageView.image = [self imageFromSampleBufferRef:sampleBuffer];
}
// CMSampleBufferRefをUIImageへ
- (UIImage *)imageFromSampleBufferRef:(CMSampleBufferRef)sampleBuffer
{
// イメージバッファの取得
CVImageBufferRef buffer;
buffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// イメージバッファのロック
CVPixelBufferLockBaseAddress(buffer, 0);
// イメージバッファ情報の取得
uint8_t* base;
size_t width, height, bytesPerRow;
base = CVPixelBufferGetBaseAddress(buffer);
width = CVPixelBufferGetWidth(buffer);
height = CVPixelBufferGetHeight(buffer);
bytesPerRow = CVPixelBufferGetBytesPerRow(buffer);
// ビットマップコンテキストの作成
CGColorSpaceRef colorSpace;
CGContextRef cgContext;
colorSpace = CGColorSpaceCreateDeviceRGB();
cgContext = CGBitmapContextCreate(
base, width, height, 8, bytesPerRow, colorSpace,
kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(colorSpace);
// 画像の作成
CGImageRef cgImage;
UIImage* image;
cgImage = CGBitmapContextCreateImage(cgContext);
image = [UIImage imageWithCGImage:cgImage scale:1.0f
orientation:UIImageOrientationUp];
CGImageRelease(cgImage);
CGContextRelease(cgContext);
// イメージバッファのアンロック
CVPixelBufferUnlockBaseAddress(buffer, 0);
return image;
}
参考:
https://developer.apple.com/jp/devcenter/ios/library/documentation/AVFoundationPG.pdf
http://news.mynavi.jp/column/iphone/040/index.html