2012年2月13日 星期一

Filter4Cam 參考: 建立助手類別

since: 2012/02/11
update: 2012/02/17

reference: The iOS 5 Developer's Cookbook

A. 設定安裝此 app 之 iOS 設備需求
    1. 說明: 告訴 iTunes 使用者的 iOS 設備需要符合哪些需求, 才可安裝此 app.

    2. 先點選 Filter4Cam-Info.plist 檔案, 再點選右邊 Key 為 Required device capabilities
        的右方 "加號", 在新產生的 Item 項目中, 將其 Value 設為 still-camera, 代表:
        此 app 需要一個內建的相機, 並且可以從此相機中使用影像擷取器界面來拍攝相片.

-----------------------------------------------------------------------------------

B. 建立助手類別
    1. Xcode > File > New > New File...
        iOS > Cocoa Touch > Objective-C class > Next
        Class: Filter4CamHelper
        Subclass of: NSObject
        > Next > Create

-----------------------------------------------------------------------------------

C. 查詢與取得相機
     1. 開啓 Filter4CamHelper.h 檔案, 修改如下:
#import <Foundation/Foundation.h>
//@add
#import <AVFoundation/AVFoundation.h>

@interface Filter4CamHelper : NSObject
{
}

//@add for Available Cameras
+ (int)numberOfCameras; // 相機的數目
+ (BOOL)backCameraAvailable; // 後置相機是否可用
+ (BOOL)frontCameraAvailable; //
前置相機是否可用
+ (AVCaptureDevice *)backCamera; //
後置相機
+ (AVCaptureDevice *)frontCamera; //
前置相機

@end


     2. 開啓 Filter4CamHelper.m 檔案, 修改如下:
#import "Filter4CamHelper.h"

#pragma mark Filter4Cam Helper

@implementation Filter4CamHelper

//@add for Available Cameras
#pragma mark Available Cameras
//@add:相機的數目

+ (int)numberOfCameras
{
    return [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo].count;
}

//@add:後置相機是否可用
+ (BOOL)backCameraAvailable
{
    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];

    for (AVCaptureDevice *device in videoDevices)
        if (device.position == AVCaptureDevicePositionBack) return YES;

    return NO;
}

//@add:前置相機是否可用
+ (BOOL)frontCameraAvailable
{
    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];

    for (AVCaptureDevice *device in videoDevices)
        if (device.position == AVCaptureDevicePositionFront) return YES;

    return NO;
}

//@add:後置相機
+ (AVCaptureDevice *)backCamera
{
    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];

    for (AVCaptureDevice *device in videoDevices)
        if (device.position == AVCaptureDevicePositionBack) return device;
   
    return [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
}

//@add:前置相機
+ (AVCaptureDevice *)frontCamera
{
    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];

    for (AVCaptureDevice *device in videoDevices)
        if (device.position == AVCaptureDevicePositionFront) return device;
   
    return [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
}

@end  

-----------------------------------------------------------------------------------

D. 建立相機的 Session
   1. 開啓 Filter4CamHelper.h 檔案, 修改如下:
#import <Foundation/Foundation.h>
//@add
#import <AVFoundation/AVFoundation.h>

//@add:Cameras defined
enum {
    kCameraNone = -1, // 無相機
    kCameraFront,       // 前置相機
    kCameraBack,       // 後置相機
} availableCameras;

//@interface Filter4CamHelper : NSObject
//@update
@interface Filter4CamHelper : NSObject <AVCaptureVideoDataOutputSampleBufferDelegate>
{
    //@add
    BOOL isUsingFrontCamera;
    AVCaptureSession *session;
    CIImage *ciImage;

}

//@add
@property (readonly)BOOL isUsingFrontCamera;
@property (strong)AVCaptureSession *session;
@property (strong)CIImage *ciImage;

//@add for Available Cameras
+ (int)numberOfCameras;
+ (BOOL)backCameraAvailable;
+ (BOOL)frontCameraAvailable;
+ (AVCaptureDevice *)backCamera;
+ (AVCaptureDevice *)frontCamera;

//@add for Camera
- (void)establishCamera:(uint)whichCamera; // 建立相機 Session
- (void)startRunningSession; // 啟動相機 Session
- (void)stopRunningSession; // 停止相機 Session

   2. 開啓 Filter4CamHelper.m 檔案, 修改如下:
#import "Filter4CamHelper.h"

@implementation Filter4CamHelper

//@add
@synthesize isUsingFrontCamera;
@synthesize session;
@synthesize ciImage;

....

#pragma mark Capture
//@add:實作 <AVCaptureVideoDataOutputSampleBufferDelegate> 的方法
 - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
 {    //@TODO
}

//@add for Setup
#pragma mark Setup

//@add:啟動相機 Session
- (void)startRunningSession
{
    if (session.running) return;
    [session startRunning];
}

//@add:停止相機 Session
- (void)stopRunningSession
{
    [session stopRunning];
}

//@add:建立相機 Session
- (void)establishCamera:(uint)whichCamera
{
    NSError *error;
  
    // Is a camera available
    if (![Filter4CamHelper numberOfCameras]) return;
  
    // Create a session
    self.session = [[AVCaptureSession alloc] init];
  
    //@begin
    [session beginConfiguration];
    [session setSessionPreset:AVCaptureSessionPreset640x480];
  
    // Choose camera
    isUsingFrontCamera = NO;
    if ((whichCamera == kCameraFront) && [Filter4CamHelper frontCameraAvailable])
        isUsingFrontCamera = YES;
  
    //@設定輸入設備
    // Retrieve the selected camera
    AVCaptureDevice *device = isUsingFrontCamera ? [Filter4CamHelper frontCamera] : [Filter4CamHelper backCamera];
  
    // Create the capture input
    AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
    if (!captureInput)
    {  
        NSLog(@"Error establishing device input: %@", error);
        return;
    }
  
    [session addInput:captureInput];
  
  
    //@設定輸出設備
    AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init];
    [captureOutput setAlwaysDiscardsLateVideoFrames:YES];
  
    // Establish settings
    NSDictionary *settings = [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA] forKey:(NSString *)kCVPixelBufferPixelFormatTypeKey];

    [captureOutput setVideoSettings:settings];
  
    // Create capture output: not to use the main queue
    char *queueName = "com.blogspot.Filter4Cam.grabFrames";
    dispatch_queue_t queue = dispatch_queue_create(queueName, NULL);
    [captureOutput setSampleBufferDelegate:self queue:queue];
  
    [session addOutput:captureOutput];
  
  
    //@commit
    [session commitConfiguration];
}
 
-----------------------------------------------------------------------------------

E. 建立初始化方法
    1. 開啓 Filter4CamHelper.h 檔案, 修改如下:
....
//@add:init method 
+ (id)helperWithCamera:(uint)whichCamera;
....

    2. 開啓 Filter4CamHelper.m 檔案, 修改如下:
....
#pragma mark Creation
//@add
- (id)init
{
    if (!(self = [super init])) return self;
    [self establishCamera: kCameraBack];
    return self;


//@add
- (id)initWithCamera:(uint)whichCamera
{
    if (!(self = [super init])) return self;   
    [self establishCamera: whichCamera];
    return self;
}

//@add:init method 
+ (id)helperWithCamera:(uint)whichCamera
{
    Filter4CamHelper *helper = [[Filter4CamHelper alloc] initWithCamera:(uint) whichCamera];

    return helper;
}
....

-----------------------------------------------------------------------------------

F. 切換相機
    1. 開啓 Filter4CamHelper.h 檔案, 修改如下:
....
//@add for Camera
- (void)establishCamera:(uint)whichCamera; // 建立相機 Session
- (void)startRunningSession; // 啟動相機 Session
- (void)stopRunningSession;  // 停止相機 Session
- (void)switchCameras; // 切換相機
....

    2. 開啓 Filter4CamHelper.m 檔案, 修改如下:
....
//@add:切換相機
- (void)switchCameras
{
    if (![Filter4CamHelper numberOfCameras] > 1) return;
   
    isUsingFrontCamera = !isUsingFrontCamera;

    AVCaptureDevice *newDevice = isUsingFrontCamera ? [Filter4CamHelper frontCamera] : [Filter4CamHelper backCamera];
   
    [session beginConfiguration];
   
    // Remove existing inputs
    for (AVCaptureInput *input in [session inputs])
        [session removeInput:input];
   
    // Change the input
    AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:newDevice error:nil];

    [session addInput:captureInput];
   
    [session commitConfiguration];
}
....

沒有留言:

張貼留言

注意:只有此網誌的成員可以留言。