Category Archives: Objective-C

AVFoundation (AVCaptureVideoDataOutput)

■ヘッダファイル
※デリゲートの設定を忘れずに

#import <UIKit/UIKit.h>
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>

@interface ViewController : UIViewController<AVCaptureVideoDataOutputSampleBufferDelegate>

■実行ファイル

#import "ViewController.h"

@interface ViewController ()
{
    AVCaptureSession* session;
    UIImageView* imageView;
    CGRect rect;
    NSMutableArray * images;
    BOOL takeStatus;
}

@end


@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 初期値設定
    takeStatus = NO;
    images = [[NSMutableArray alloc] init];
    
    // 画面取得
    UIScreen *sc = [UIScreen mainScreen];
    rect = sc.bounds;
    
    // AVCaptureセットアップ
    [self AVCaptureSetup];
    
    // ボタンを生成
    [self setButton];
}



// AVCaputureSetup
- (void)AVCaptureSetup
{
    // imageView生成
    imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,rect.size.width,rect.size.height)];
    [self.view addSubview:imageView];
    
    // セッション作成
    session = [[AVCaptureSession alloc] init];
    session.sessionPreset = AVCaptureSessionPresetHigh;  // セッション画質設定
    
    // デバイス取得
    AVCaptureDevice* device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    // 入力作成
    AVCaptureDeviceInput* deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:NULL];
    [session addInput:deviceInput];  // セッションに追加
    
    // ビデオデータ出力作成
    NSDictionary* settings = @{(id)kCVPixelBufferPixelFormatTypeKey:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA]};
    AVCaptureVideoDataOutput* dataOutput = [[AVCaptureVideoDataOutput alloc] init];
    dataOutput.videoSettings = settings;
    [dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
    [session addOutput:dataOutput]; //セッションに追加
    
    // ビデオ入力のコネクションを取得
    AVCaptureConnection *videoConnection = NULL;
    videoConnection.videoMinFrameDuration = CMTimeMake(1, 1);
    
    // カメラの向きなどを設定する
    [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];
    }
    
    [session commitConfiguration];  // セッション設定完了
    
    // セッションをスタートする
    [session startRunning];
}



// delegateメソッド。各フレームにおける処理
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    // 画像の表示
    imageView.image = [self imageFromSampleBufferRef:sampleBuffer];
    
    // 画像をNSArrayに入れる
    if(takeStatus == YES)
    {
        [images addObject:imageView.image];
    }
}

// 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;
}


// ボタン生成メソッド
- (void)setButton
{
    // カスタムでボタン作成
    UIButton * button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    
    // セレクター設定
    [button addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];
    
    // ボタン押下時のハイライトをOFFに変更
    button.adjustsImageWhenHighlighted = YES;
    
    // サイズ位置設定
    [button setFrame:CGRectMake(rect.size.width/2 -50, rect.size.height - 100, 100, 50)];
    
    // 色設定
    [button setBackgroundColor:[UIColor redColor]];
    
    // テキスト設定
    [button setTitle:@"Take" forState:UIControlStateNormal];
    
    // 画面に表示
    [self.view addSubview:button];
}


// ボタンタップ時のアクション
- (void)action:(UIButton *)sender
{
    AudioServicesPlaySystemSound(1108);
    
    // アルバムに画像を保存
    //UIImageWriteToSavedPhotosAlbum(imageView.image, self, nil, nil);
    
    //image取得開始
    if(takeStatus == NO)
    {
        takeStatus = YES;
    }else{
        takeStatus = NO;
        NSLog(@"imagesCount:%d", [images count]);
    }
    
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

UIButton生成

- (void)viewDidLoad
{
    [super viewDidLoad];

    // カスタムでボタン作成
    UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
    
    // セレクター設定
    [button addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];
    
    // ボタン押下時のハイライトをOFFに変更
    button.adjustsImageWhenHighlighted = YES;
    
    // サイズ位置設定
    [button setFrame:CGRectMake(10, 10, 50, 50)];
    
    // 色設定
    [button setBackgroundColor:[UIColor redColor]];
    
    // 画面に表示
    [self.view addSubview:button];
}

// ボタンタップ時のアクション
- (void)action:(UIButton *)sender
{
    NSLog(@"tapped");
}

UIImageViewにUIImageViewを追加&削除

- (void)viewDidLoad
{
    [super viewDidLoad];

    // imageView生成
    UIImageView * image1 = [[UIImageView alloc]init];
    UIImageView * image2 = [[UIImageView alloc]init];
    
    // 背景色設定
    image1.backgroundColor = [UIColor redColor];
    image2.backgroundColor = [UIColor blueColor];
    
    // サイズ位置設定
    image1.frame = CGRectMake(0, 0, 100, 100);
    image2.frame = CGRectMake(50, 50, 100, 100);
    
    // image1にimage2をaddsubview
    [image1 addSubview:image2];
    
    // image1をビューに追加
    [self.view addSubview:image1];
    
    // image1をビューから削除
    [image1 removeFromSuperview]; //image2もまとめて削除されていることを確認
}

タグを指定してUIButtonの画像を変更

setBackgroundImageだと、画像がリサイズされない。setImageを使用。

× → [myButton setBackgroundImage:image forState:UIControlStateNormal];
○ → [myButton setImage:image forState:UIControlStateNormal];

#import "ViewController.h"
 
@interface ViewController ()
 
@end
 
@implementation ViewController
 
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // WEB上の画像の読み込み
    NSURL *url = [NSURL URLWithString:@"https://s-media-cache-ak0.pinimg.com/originals/8e/06/5c/8e065c7a30d4724aeed6e5f9484b54ad.jpg"];
    NSData *data = [NSData dataWithContentsOfURL:url];
    UIImage *image = [[UIImage alloc] initWithData:data];
    
    // 画像のサイズ確認
    CGSize size = [image size];
    float height = size.height/2;
    float width = size.width/2;
    
    // ボタンを生成
    UIButton * myButton = [[UIButton alloc] init];
    myButton.tag = 1;
    myButton.frame = CGRectMake(0, 0, width, height) ;
 
    // 画面に貼り付け
    [self.view addSubview:myButton];
    
    // 画像を設定
    UIButton * myButton2 = [self.view viewWithTag:1];
    [myButton2 setImage:image forState:UIControlStateNormal];
}
 
 
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
 
@end

変数のポインタ変数の確認

別々のアドレスに格納される。

- (void)viewDidLoad
{
    [super viewDidLoad];
 
    // ポインタ型変数の生成
    int * myPtr1;
    int * myPtr2;
    
    //変数生成
    int myInt1 = 5;
    int myInt2 = myInt1;
    
    //ポインタを代入
    myPtr1 = &myInt1;
    myPtr2 = &myInt2;
    
    //別々のアドレスに格納されている
    NSLog(@"%p",myPtr1);  //結果:0x7fff5f0dfa2c
    NSLog(@"%p",myPtr2);  //結果:0x7fff5f0dfa28
}

NSArrayを別のNSArrayに代入

NSArrayを他の配列に代入。代入元の配列要素を正しく抽出できることを確認。

// NSArray生成
NSArray *src = [NSArray arrayWithObjects:
                @"Snoopy", @"Spike", @"Olaf", nil];

// 他の配列に代入
NSArray *dst = src;

// ログ出力
NSLog(@"%@",dst[1]);  //結果:Spike

CMTime生成(CMTimeMake, CMTimeMakeWithSeconds)

■Import Statement
@import CoreMedia;
※AVFoundationのサブクラス

AVFoundation stack

■Declaration
CMTimeMake(int64_t, value, int32_t timescale)
CMTimeMakeWithSeconds(Float64 seconds, int32_t preferredTimeScale)

■Example

// CMTime生成
CMTime cmtime1 = CMTimeMake(100, 1000);
CMTime cmtime2 = CMTimeMakeWithSeconds(0.1, 10);

// 秒数確認
NSLog(@"cmtime1_value:%0.2lld", cmtime1.value);  // 結果:100
NSLog(@"cmtime1_timescale:%0.2d", cmtime1.timescale);  //結果:1000
NSLog(@"cmtime1_second:%0.2f", CMTimeGetSeconds(cmtime1));  //結果:0.1秒

NSLog(@"cmtime2_value:%0.2lld", cmtime2.value);  // 結果:01
NSLog(@"cmtime2_timescale:%0.2d", cmtime2.timescale);  //結果:10
NSLog(@"cmtime2_second:%0.2f", CMTimeGetSeconds(cmtime2)); //結果:0.1秒

CMTime 動画の長さを確認

1秒の動画をプロジェクトから読み込み。長さを確認。

◼︎結果
2015-03-25 00:07:59.173 CMTime[28451:4877468] 1.000000
→1秒と正しく判定

#import "ViewController.h"
 
@interface ViewController ()
 
@end
 
@implementation ViewController
 
- (void)viewDidLoad
{
    [super viewDidLoad];
 
    //プロジェクト内の動画読み込み
    NSString *path = [[NSBundle mainBundle] pathForResource:@"Movie_Sample" ofType:@"mp4"];
    NSURL *url = [NSURL fileURLWithPath:path];
    AVURLAsset * asset = [[AVURLAsset alloc] initWithURL:url options:nil];
    
    //動画の長さを確認
    CMTime cmtime = asset.duration;
    Float64 sec = CMTimeGetSeconds(cmtime);
    NSLog(@"%f",sec);
}
 
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
 
@end