BAD_ACCESS

おもにiOS、ときどき変な電子工作、ガジェット話。

#12 パスデータをモーフィングしてみたーC4のパスであそぶ(1)

この記事は「一人アドベントカレンダー2013〜Lonely Advent Calender 2013〜」の13日目の記事です。

今回からはパスデータを使ったアニメーションを試してみたいと思います。

Morphing C4Shapes from [C4] on Vimeo.

この動画を見て、C4だと手軽にパスアニメーションを作れるということもあり、ひと通り試してみたいと思います。 パスデータを使ったモーションはObjective-Cでゴリゴリ書いていくのも大変そうなので、これは使えそうですね。

C4Shapeを初期化

ひとつのC4Shapeオブジェクトをつくり、そのオブジェクトに形のデータを与えていくことでモーフィングのアニメーションを作り出しています。 まずはsetupでC4Shapeオブジェクトを矩形として初期化してcanvasに配置します。

-(void)setup {
    
    //setup up the initial shape
    theShape = [C4Shape rect:CGRectMake(0,0,240,240)];
    theShape.center = self.canvas.center;
    
    //set its animation duration which will be used for all animations
    theShape.animationDuration = 1.0f;
    
    //add it to the canvas
    [self.canvas addShape:theShape];
}

変化する先の形

次に形を変化させるためのメソッドを追加します。 C4Shapeクラスのインスタンスメソッドであるellipse:を呼び出します。 ellipse:は文字通り、楕円形にするためのメソッドです。引数に矩形を渡し、その矩形内に楕円を描きます。

-(void)ellipse {
    [theShape ellipse:theShape.frame];
}

これを先ほどのsetupの一番最後に呼び出します。

-(void)setup {
    
   (略)
    [self ellipse];
}

チュートリアル通りですが、たったこれだけでモーフィングができちゃいました。

#11 撮影した画像をカメラロールに保存するーC4でエフェクト付きカメラをつくる(3)

この記事は「一人アドベントカレンダー2013〜Lonely Advent Calender 2013〜」の12日目の記事です。

前回はほんの1行でカメラで撮影した画像にエフェクトをかけるという例を紹介しました。

今回、はせっかく撮影した画像をカメラロールに保存する実装までを紹介しようと思います。

フル画面で撮影

カメラのプレビューをフル画面に設定します。 以前作成したシンプルなカメラアプリをもとに作ります。

-(void)setup {
    cam = [C4Camera cameraWithFrame:CGRectMake(0, 0, 320, 568)];
    cam.cameraPosition = CAMERABACK;
    [self.canvas addCamera:cam];
    [cam initCapture];
    cam.captureQuality = C4CameraQualityiFrame1280x720;
    
    [self addGesture:TAP name:@"capture" action:@"captureImage"];
    [self listenFor:@"imageWasCaptured" fromObject:cam andRunMethod:@"putCapturedImageOnCanvas"];
}

撮影した結果もフル画面で表示

-(void)captureImage {
    
    [cam captureImage];
}

-(void)putCapturedImageOnCanvas {
    if (image)
    {
        [image removeFromSuperview];
    }
    image = cam.capturedImage;
    image.width = 320;
    image.origin = CGPointMake(0, 0);
    
    NSLog(@"image rect%@",NSStringFromCGRect(image.frame));
    [self.canvas addImage:image];
}

撮影した結果をカメラロールに保存

通常のiOSのアプリも同様ですが、C4ImageクラスのUIImageプロパティをわたしてあげないとうまくいきません。 こんな感じです。

-(void)saveImageToLibrary 
{ 
    UIImageWriteToSavedPhotosAlbum(image.UIImage, nil, nil, nil);
}

あとはこのメソッドを撮影後に呼んであげればカメラロールに保存されているはずです。

-(void)putCapturedImageOnCanvas {
   (省略)
    NSLog(@"image rect%@",NSStringFromCGRect(image.frame));
    [self.canvas addImage:image];

    (追加)
    [self saveImageToLibrary];
}

これでカメラアプリとしての最低限の機能をみたすことができました。

#10 使えるエフェクトはまだ限られているーC4でエフェクト付きカメラをつくる(2)

この記事は「一人アドベントカレンダー2013〜Lonely Advent Calender 2013〜」の11日目の記事です。

前回はわずか数行でハードウェアのカメラを使ったアプリを実装できるという例を紹介しました。

今回、カメラに使うエフェクトを紹介しようと調べていたところ、まだ開発フェーズで使えるフィルタの種類が限られているようです。

適用できるフィルタとブレンド

C4で利用できるエフェクトにはフィルタともう一枚の画像をあわせて加工するブレンドの大きく二種類があります。

フィルタはパラメータを指定するだけのほんの一行です。 画像の色を逆にするのを試したければ、下記のコードを一行追加するだけで加工ができてしまいます。

[image colorInvert];

 2013-12-13 0.59.58.png 2013-12-13 1.00.17.png

しかしretinaの解像度で試すとうまくいかないという残念な結果になってしまいます。(iPadのnon-retinaのシミュレータではうまくいきます。) ※後日、ソースコードの中をのぞいて原因を探ってみます。

また、ブレンドも手軽です。

ブレンドするための二枚の画像を用意しておきます。  2013-12-13 0.59.58.png 2013-12-13 1.21.58.png

ブレンドする方法(ここではオーバーレイ)を選び、下記のコードだけで済んでしまいます。

-(void)setup {
    
    C4Image *sushi = [C4Image imageNamed:@"sushi"];
    sushi.center = self.canvas.center;
    C4Image *shine = [C4Image imageNamed:@"shine"];
    shine.alpha = 0.6f;
    [self.canvas addImage:sushi];
    
    [sushi overlayBlend:shine];
}

 2013-12-13 1.20.58.png

最後はえげつない画像になってしまいましたが、C4なら画像エフェクトもあまりにも簡単にできてしまいます。 今回紹介しきれなかった部分ではExamplesImage Filtersの部分に掲載されいているフィルターだと動くことが確認できています。ドキュメントに記載されいているフィルターはどうやらまだ開発をすすめている途中のようです。

#9 とにかく簡単にカメラで撮影してみるーC4でエフェクト付きカメラをつくる(1)

この記事は「一人アドベントカレンダー2013〜Lonely Advent Calender 2013〜」の10日目の記事です。

前回まではAudio Playerをつくるということで書いてまいりましたが、今回からは画像関連を扱うということでC4を使ってエフェクト付きカメラをつくってみようと思います。

今回はとにかく、とにかく簡単にカメラ撮影ができるようになればいいということで、画面をタップしたら撮影というこれ以上ないシンプルなカメラを作ります。

ほんとに簡単すぎてこれだけ…ってなってる。

まずはメンバ変数にC4Cameraを追加します。

@implementation C4WorkSpace {
    C4Camera *cam;
}

setupでまず、カメラの大きさを指定して初期化してやります。

-(void)setup {
    cam = [C4Camera cameraWithFrame:CGRectMake(0, 0, 240, 320)];
    [self.canvas addCamera:cam];
    cam.center = se
    [cam initCapture];
    (つづく)

そのあと、tapジェスチャを追加します。

    (つづき)
    [self addGesture:TAP name:@"capture" action:@"captureImage"];
    (つづく)

カメラ撮影のアクションを受け、画面に表示させるためのリスナーを追加します。

    (つづき)
    [self listenFor:@"imageWasCaptured" fromObject:cam andRunMethod:@"putCapturedImageOnCanvas"];
}

あとは撮影メソッドと、

-(void)captureImage {
    [cam captureImage];
}

撮影アクション後の配置メソッドを。

-(void)putCapturedImageOnCanvas {
    C4Image *img = cam.capturedImage;
    img.width = 240.0f;
    img.center = self.canvas.center;
    [self.canvas addImage:img];
}

はい!以上です。

画面をタップするとパシャっと撮れます!カメラロールに保存はできてませんが、簡単すぎて拍子抜けしますね。 次回はもう少しカメラっぽい機能を追加していく予定です。

#8 複数の音源から再生したい音源を選ぶ(補足)ーC4でAudio Playerをつくる(6)

この記事は「一人アドベントカレンダー2013〜Lonely Advent Calender 2013〜」の9日目の記事です。

前回、音源リストのビューを追加に関して1点補足いたします。

C4Buttonクラスのtag

実はC4ButtonクラスにはUIButtonクラスのようにtagプロパティを持っていません。 ですので、前回の記述の際に、

songButton = [C4Button buttonWithType:CUSTOM];
songButton.tag = i;
(略)
[songButton runMethod:@"onSongButton:" target:self forEvent:TOUCHUPINSIDE];

と書いてしまうと、

-(void)onSongButton:(id)sender
{
    UIButton *selectSongButton = (UIButton *)sender;
    _currentSongTag = selectSongButton.tag;
    [self.delegate selectedSong:_currentSongTag];
}

onSongButton:メソッドでtagの情報を受け取ることができません。

ですので前回のサンプルで記述していたように、UIButtonプロパティのさらにtagプロパティに値をいれてやる必要があります。

songButton = [C4Button buttonWithType:CUSTOM];
songButton.UIButton.tag = i; <ーUIButtonプロパティのtagプロパティ
(略)
[songButton runMethod:@"onSongButton:" target:self forEvent:TOUCHUPINSIDE];

#7 複数の音源から再生したい音源を選ぶ(その2)ーC4でAudio Playerをつくる(5)

この記事は「一人アドベントカレンダー2013〜Lonely Advent Calender 2013〜」の8日目の記事です。

前回、音源リストのビューを追加しただけで終わってしまっていたので、引き続き実装をすすめます。

Xibファイル上のViewの取り扱いについて

通常のUIViewとして待ち受けていてもうまくビューが表示されません。 下図のようにXib上でViewを選択し、カスタムクラスのC4Viewを選択します。

音源リストの実装

SongListWorkSpace.h

SongListWorkSpace.m

C4WorkSpace側からの呼び出し

まずC4WorkSpace上でSongListWorkSpaceを初期化します。

-(void)createSongList
{
    songList = [[SongListWorkSpace alloc] initWithNibName:@"SongListWorkSpace" bundle:[NSBundle mainBundle]];
    songList.delegate = self;
    songList.canvas.frame = self.canvas.frame;
    [songList setup];
    currentSongTag = songList.currentSongTag;
}

SongListWorkSpaceをもとのC4WorkSpaceから呼び出します。

-(void) onPlaylistButton
{
    [sample pause];
    UIViewAnimationOptions options = UIViewAnimationOptionTransitionFlipFromLeft;
    [self switchToView:(C4View*)songList.canvas transitionOptions:options];
}

-(void)switchToView:(C4View *)view transitionOptions:(UIViewAnimationOptions)options {
    if(![currentView isEqual:view]) {
        [UIView transitionFromView:currentView toView:view duration:0.75f options:options completion:^(BOOL finished) {
            currentView = view;
            finished = YES;
        }];
    }
    currentView.userInteractionEnabled = YES;
}

これでC4WorkSpaceから音源リストを表示できるようになりました。 あとは音源を選択すると自動的にC4WorkSpaceの画面に戻るdelegateメソッドを実装すればOKです。

#【番外編】tech.kayac.com Advent Calendar 2013に投稿しました

「一人アドベントカレンダー2013〜Lonely Advent Calender 2013〜」に追われる中、tech.kayac.comのAdvent Calendar 2013にも投稿しました。

内容はParse.comをできるかぎり無料で使いつづけるためのひと工夫を紹介しています。(ひと工夫という割には結構なボリュームですが)

以下、tech.kayac.com Advent Calendar 2013に投稿したぼっちiOS開発者がParse(Parse.com)使った結果wwwwwwwww tech.kayac.com Advent Calendar 2013 | tech.kayac.com - KAYAC engineers' blogの補足記事になります。 量が多かったので全部で4つの記事に分けています。

Parse.com上に自分のプロジェクトを作成して、いくつかのデータを追加する。ーParseでローカルキャッシュ(1)

Xcode上でプロジェクトを作成し、"ParseSDK"と"AFNetworking"を導入する。ーParseでローカルキャッシュ(2)

同期用のクラス"SyncEngine"とCoreData周りの処理を追加する ーParseでローカルキャッシュ(3)

アプリ起動時に同期の処理を行う。ーParseでローカルキャッシュ(4)

この記事に関するサンプルコードをこちらのレポジトリにアップしております。 GitHub:somtd / LocalCacheSample