Category Archives: Objective-C

端末の向きの確認

◼︎端末の向き確認

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

◼︎向きに応じて処理を実行

switch (_takephotoOrientation)
{        
    case UIDeviceOrientationPortrait:
        // iPhoneを縦にして、ホームボタンが下にある状態
        
    case UIDeviceOrientationPortraitUpsideDown:
        // iPhoneを縦にして、ホームボタンが上にある状態
        break;
        
    case UIDeviceOrientationLandscapeLeft:
        // iPhoneを横にして、ホームボタンが右にある状態
        
    case UIDeviceOrientationLandscapeRight:
        // iPhoneを横にして、ホームボタンが左にある状態
        
    case UIDeviceOrientationFaceUp:
        // iPhoneの液晶面を天に向けた状態
        break;
        
    case UIDeviceOrientationFaceDown:
        // iPhoneの液晶面を地に向けた状態
        break;
        
    case UIDeviceOrientationUnknown:
    default:
        // 向きが分からない状態
        break;
}

AVFoundation (AVCaptureVideoDataOutput)

◼︎ヘッダーファイル

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

@interface ViewController : UIViewController<AVCaptureVideoDataOutputSampleBufferDelegate> // デリゲート設定


@end

◼︎実行ファイル

#import "ViewController.h"

@interface ViewController ()
{
    AVCaptureSession* session;
    AVCaptureVideoDataOutput * videoDataOutput;
    UIImageView * previewImage;
}

@end

@implementation ViewController

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


// AVCaputureSetup
- (void)AVCaptureSetup
{
    // セッション作成
    session = [[AVCaptureSession alloc] init];
    session.sessionPreset = AVCaptureSessionPresetHigh;  // セッション画質設定
    
    // デバイス取得
    AVCaptureDevice* device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    // 入力作成
    AVCaptureDeviceInput* deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:NULL];
    [session addInput:deviceInput];  // セッションに追加
    
    // 出力作成
    videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
    [session addOutput:videoDataOutput];
    
    // ビデオ出力のキャプチャの画像情報のキューを設定
    dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
    [videoDataOutput setAlwaysDiscardsLateVideoFrames:TRUE];
    [videoDataOutput setSampleBufferDelegate:self queue:queue];
    
    // ビデオへの出力の画像は、BGRAで出力
    videoDataOutput.videoSettings = @{
                                           (id)kCVPixelBufferPixelFormatTypeKey : [NSNumber numberWithInt:kCVPixelFormatType_32BGRA]
                                           };
    
    // ビデオ入力のAVCaptureConnectionを取得
    AVCaptureConnection *videoConnection = [videoDataOutput connectionWithMediaType:AVMediaTypeVideo];
    
    // 1秒あたり4回画像をキャプチャ
    videoConnection.videoMinFrameDuration = CMTimeMake(1, 30);
    

    // プレビュー設定
    previewImage = [[UIImageView alloc]initWithFrame:self.view.bounds];
    [self.view addSubview:previewImage];
    
    // セッション開始
    [session startRunning];
}



// デリゲートメソッド
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
       fromConnection:(AVCaptureConnection *)connection
{
    // キャプチャしたフレームからCGImageを作成
    UIImage *image = [self imageFromSampleBuffer:sampleBuffer];
    
    // 画像を画面に表示
    dispatch_async(dispatch_get_main_queue(), ^{
        previewImage.image = image;
    });
}


// サンプルバッファのデータからCGImageRefを生成する
- (UIImage *)imageFromSampleBuffer:(CMSampleBufferRef)sampleBuffer
{
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    
    // ピクセルバッファのベースアドレスをロックする
    CVPixelBufferLockBaseAddress(imageBuffer, 0);
    
    // Get information of the image
    uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);
    
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);
    
    // RGBの色空間
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
    CGContextRef newContext = CGBitmapContextCreate(baseAddress,
                                                    width,
                                                    height,
                                                    8,
                                                    bytesPerRow,
                                                    colorSpace,
                                                    kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
    
    CGImageRef cgImage = CGBitmapContextCreateImage(newContext);
    
    CGContextRelease(newContext);
    CGColorSpaceRelease(colorSpace);
    CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
    
    UIImage *image = [UIImage imageWithCGImage:cgImage scale:1.0 orientation:UIImageOrientationRight];
    
    CGImageRelease(cgImage);
    
    return image;
}



// 撮影ボタンメソッド
- (IBAction)takeButton:(UIButton *)sender
{
    
    // アルバムに画像を保存
    UIImageWriteToSavedPhotosAlbum(previewImage.image, self, nil, nil);
}




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

@end

AVFoundation (AVCaptureStillImageOutput)

◼︎ヘッダー

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

@interface ViewController : UIViewController
- (IBAction)takeButton:(UIButton *)sender;

@end

◼︎実行ファイル

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
{
    AVCaptureSession* session;
    AVCaptureStillImageOutput * stillImageOutput;
    UIView * previewView;
}


- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [self AVCaptureSetup];

}


// AVCaputureSetup
- (void)AVCaptureSetup
{
    // セッション作成
    session = [[AVCaptureSession alloc] init];
    session.sessionPreset = AVCaptureSessionPresetHigh;  // セッション画質設定
    
    // デバイス取得
    AVCaptureDevice* device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    // 入力作成
    AVCaptureDeviceInput* deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:NULL];
    [session addInput:deviceInput];  // セッションに追加
    
    // 出力作成
    stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
    [session addOutput:stillImageOutput]; // セッションに追加
    
    // プレビュー作成
    AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
    captureVideoPreviewLayer.frame = self.view.bounds;
    captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    
    // プレビューを表示
    previewView = [[UIView alloc]initWithFrame:self.view.bounds]; // 初期化
    [self.view addSubview:previewView]; // ビューを画面に貼り付け
    [self.view sendSubviewToBack:previewView]; // ビューを最背面に移動

    // プレビューに画像表示
    CALayer *previewLayer = previewView.layer;
    previewLayer.masksToBounds = YES; // マスク設定(Viewからはみ出た部分を削除)
    [previewLayer addSublayer:captureVideoPreviewLayer];

    // セッション開始
    [session startRunning];
}


// 撮影メソッド
- (void)takePhoto
{
    // ビデオコネクションを取得
    AVCaptureConnection * connection = [stillImageOutput connectionWithMediaType:AVMediaTypeVideo];
    
    // 画像撮影
    [stillImageOutput captureStillImageAsynchronouslyFromConnection:connection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error)
     {
         NSData *data = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
         UIImage * image = [[UIImage alloc]initWithData:data];
         
         // カメラロールに保存
         UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
         
     }];
}



// 撮影ボタンメソッド
- (IBAction)takeButton:(UIButton *)sender
{
    [self takePhoto];

}



@end

並列処理(NSOperation)

Operation1とOperation2が同時に走る。
Operation2の処理が先に終わる。

■ログ
2015-04-08 22:42:34.422 NSOperation_test[11170:1223456] Finish Operation2
2015-04-08 22:42:39.427 NSOperation_test[11170:1223457] Finish Operation1

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    [queue addOperationWithBlock:^{
        [NSThread sleepForTimeInterval:5];
        NSLog(@"Finish Operation1");
    }];
    
    [queue addOperationWithBlock:^{
        NSLog(@"Finish Operation2");
    }];
    
}

BlurEffect

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 元画像生成
    UIImageView * myImage = [[UIImageView alloc]initWithFrame:self.view.bounds];
    myImage.image = [UIImage imageNamed:@"bird.jpg"];
    [self.view addSubview:myImage];

    //ブラースタイルの決定
    UIVisualEffect * blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];

    //VisualEffectViewにVisualEffectを設定
    UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];

    //VisualEffectViewを_blurViewと同じサイズに設定
    effectView.frame = myImage.bounds;

    //_blurViewにVisualEffectViewを追加
    [myImage addSubview:effectView];
}

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

@end

※端末のOSの設定で、
General > Accessbility > Reduced > Increase Contrast > Reduce Transparency
が設定されている場合は、機能しないので注意

ステータスバーの消し方

1. プロジェクト設定のTARGETS > General > Development Info > Status Bar StyleのHide during application launchのチェックを入れる。

2.プロジェクト設定のTARGETS > Infoで+を押して(もしくは、右クリックで追加)行を追加、
View controller-based status bar appearance
を選択してvalueにNOを入れる。

画像クリッピング

- (void)viewDidLoad {
    [super viewDidLoad];

    // 画像取り込み
    UIImage * image = [UIImage imageNamed:@"cat.jpg"];
    
    // UIImageView生成
    UIImageView * imageView = [[UIImageView alloc] init];
    
    // コンテンツモードをAspectFillに設定
    imageView.contentMode = UIViewContentModeScaleAspectFill;
    
    // サイズ設定
    imageView.frame = CGRectMake(0, 0, 200, 200);
    
    // ビューからはみ出た部分をクリッピングする
    imageView.clipsToBounds = YES;
    
    imageView.image = image;
    
    [self.view addSubview:imageView]; // 画像がクリッピングされて表示される
}

画面サイズ取得

// 画面取得
UIScreen *sc = [UIScreen mainScreen];
CGRect rect = sc.bounds;

// 画面サイズを取得してUIImage生成
UIImageView * imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,rect.size.width,rect.size.height)];

[self.view addSubview:imageView];