Archive for the ‘iPhoneアプリの開発入門’ Category

iDOFの使い方

木曜日, 2月 24th, 2011
このエントリーを含むはてなブックマークはてなブックマーク - iDOFの使い方

*この記事はAppBank様に寄稿させていただいた記事の一部を抜粋&変更して使用しております。詳しい説明はこちらを御覧ください。

 

iDOFの特徴

iDOFは、iPhoneで撮影した画像を一眼レフカメラで撮影されたような写真に加工することができるアプリです。

iDOFでは、一眼トイカメラやTiltShift Generatorと違い、ピントをあわせる部分とぼかす部分を手動で選択できるため、より自然な写真を作成することが出来ます。

 

iDOFの使い方

この画像をiDOFで処理してみたいと思います。


 
 
画像を読み込むと、読み込んだ画像が画面に表示されるので、焦点を当てたい部分を指でなぞっていきます。すると選択された範囲に赤いマスクがかかります。また、Paintボタンをタップするとペンの太さなどが変更できます。操作を取り消したい場合は右上のUndoボタンを利用してください。


 
 
 
細かい部分を選択したい場合、画面上でピンチイン・アウトのジェスチャを行うことで画像の拡大縮小ができます。また、ConfigボタンやColorボタンでぼかしの強さや焦点サイズ、画像の色調補正などが行えます。
 

 
 
右端のPreviewボタンを押すと結果が表示されます。気に入った場合はSaveボタンを、修正したい場合は各操作に戻ってください。結果はこのようになりました。
 

 
 

Tips: ミニチュア風写真の作成方法

ぼかしを少し弱めて焦点サイズを最大にし、彩度とコントラストをプラス、明度をマイナスにすることでミニチュア風の写真へと加工することができます。
 
 
 
 
 

ご購入はこちらから

iDOFを購入したい方は下の画像をクリックしていただくと、iTunesのページへジャンプすることが出来ます。

UITabBarで吹出しメニューを実装

木曜日, 2月 3rd, 2011
このエントリーを含むはてなブックマークはてなブックマーク - UITabBarで吹出しメニューを実装

 

UITabBarを使って、上の図のような吹出しメニューを作る方法を説明します。動作は次のようになります。TabBarItemを選択すると対応するメニューが出現し、もう一度押すと消えます。また、べつのTabBarItemを選択すると、現在のメニューが消えて対応するメニューが出現します。
 
 

親画面を作成する

まずはプロジェクトを作成します。今回もView-Based Applicationのテンプレートを使用します。プロジェクト名はTestにしました。


 
 
プロジェクトが作成できたら親画面を作成するため、TestViewController.xibファイルをダブルクリックしてInterface Builderを起動します。次にViewにライブラリからUITabBarをD&Dし、そのUITabBarにUITabBarItemをD&Dし、タブを3つ作成します。
 

吹出しメニュー画面を作成する

次に、各メニュー画面を作成します。メニュー画面1つに対して、1つのxibファイルを作成します。まずはResourceフォルダ上で「メニュー」→「追加」→「新規追加」を選択し、空のxibファイルを選択します。今回は3つのメニュー画面をつくるため、それぞれtab0.xib, tab1.xib, tab2.xibという名前でxibファイルを作成しました。

まずは、xibファイルにViewを配置するため、ライブラリからViewコンポーネントをD&Dしてきます。

つぎに、配置したViewをカスタマイズしていきます。Viewを選択肢た状態でインスペクタで高さを410(画面の高さからTabBarの高さを引いたもの)に設定します。また、Backgroundの背景色を透明に、OpaqueとUser Interaction Enabledのチェックを外します。ここまでで、透明なViewが完成しました。

 

つぎに、作成したView上にImageVIewを配置し、そこに吹出しの画像をのせます。下図の白い部分がimageViewを配置した場所になります。

このようなxibファイルを、メニューごとに3つ作成します。
 

メニュー画面をプログラムから呼び出す

ヘッダファイルではUITabBarへのアウトレットと吹出しメニュー用のviewを3つ宣言しています。UITabBarのアウトレットはIBを使って接続しておいてください。

TestViewController.h

@interface TestViewController : UIViewController
<UITabBarDelegate>{
	IBOutlet UITabBar *tabBar;
	UIView *views[3];
}

 
 
viewDIdLoad内では、作成した3つのxibファイルをロードしてviewsの配列にそれぞれ格納し、同時にaddSubViewで親画面に吹出しメニュー画面を登録しています。ただ、alpha値を0.0に設定しているため、画面上には表示されません。

tabBar:didSelectItem:メソッドでタブバーが押されたときの処理を行っています。このメソッドでは押されたタブによって、吹出しメニューの表示・非表示を制御しています。

TestViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];
	
	tabBar.delegate = self;
	
	for(int i = 0; i < 3; ++i){
		NSString *nibName = &#91;NSString stringWithFormat:@"tab%d", i&#93;;
		views&#91;i&#93; = &#91;&#91;&#91;NSBundle mainBundle&#93; loadNibNamed:nibName owner:self options:nil&#93; objectAtIndex:0&#93;;	
		views&#91;i&#93;.alpha = 0.0f;
		&#91;self.view addSubview:views&#91;i&#93;&#93;;		
	}
}


- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{	
	for(int i = 0; i < 3; i++){
		if( i != item.tag ){
			views&#91;i&#93;.alpha = 0.0;
		} else {
			views&#91;i&#93;.alpha = 1.0 - views&#91;i&#93;.alpha;
		}
	}
}
&#91;/cpp&#93;
 
 
<h3>メニュー上のコントロールに対応する</h3>

最後に吹出しメニュー画面上のコントロール(ボタンやスライダ)のイベントをひろえるようにしましょう。まずはボタンが押された際に呼び出される関数を作成します。ヘッダファイルにも忘れず宣言を書いておいてください。

<b>TestViewController.m</b>
[cpp]
-(IBAction)buttonPressed:(id)sender
{
	NSLog(@"button pressed!");
}

次に、Interface Builderを使ってtab0.xibを開き、吹出しメニュー上にボタンを配置します。

通常でしたら、このボタンとFile’s OwnerのIBActionを接続して終わりなのですが、作成したtab0.xibファイルではFile’s OwnerがNSObjectに設定されているため、接続することが出来ません。

そこで、File’s Ownerを選択した状態でインスペクタを使ってFile’s OwnerのクラスをTestViewControllerクラスへと変更します。

クラスを変更すれば、Interface Builderから、ソースファイルで設定したIBOutletとIBActionが見えるようになるので接続を行ってください。
 
ソースファイル一式をココにおいておくので参考にしてください。
参考ソースファイル

 

アイデアを生み出す13の方法

木曜日, 1月 13th, 2011
このエントリーを含むはてなブックマークはてなブックマーク - アイデアを生み出す13の方法

 


 
 

アイデアを出すときには、自分の中にある情報雲とでも言うべき”もやもや”っとしたモノから数カ所をちぎりとり、型を変えて、見方を変えて、姿をかえて、そして本質をつくりだす。その火種となる情報雲を絶やさないように・・・。
 
 
 

ちょっと慣れてきた人の為のハテブの使い方

効率よく人気記事を探すためには、はてなブックマークの人気エントリーや注目エントリーを利用するのが一番便利だと思います。このサイトでは、これらのエントリーだけでなく、一歩踏み込んだ使い方まで解説されているので、はてなブックマークをさらに利用したい方にはオススメです!
 
 
 

今さら聞けない?初心者に送る「Twitter」の始め方・使い方

インスタントでライトなコミュニケーションはもとより、研究や技術といった深〜い情報の交換までできてしまう優れもの。ただ、RTや@や#など、使われる用語が特殊なため、少し敷居が高いと感じてしまう人も多いはず。そこで、このサイトを読んで、Twitterの世界へ飛び込んでみてはいかがでしょう?
 
 
 

ウェブを保存して後で読む「Instapaper」のある快適生活の始め方

ウェブの情報を保存しておいて、後からモバイルデバイスで読むことができるようにする「Instapaper」。オフラインでも閲覧可能なため、大量の情報を読みこなすには必須のアイテムです。このサイトではInstapaperの設定方法から使い方まで詳しく説明されています。
 
 
 

整理するということは、ものに属性をつけ、カテゴリで縛ること。そうやって、整理していけば、どんどん自由度が失われて、どんどん不自由に、そしてどんどん明快になっていく。すべてを曖昧なまま、そして、自由なままにしておきたい。そうすれば、いろんな物がいろんな次元で繋がり始める。
 
 

机の上も頭の中もスッキリ!?Evernoteの使い方みつけたよ!

Evernoteは気に入ったもの、気になったもの、ピンと来たもの、何でも全て放り込める道具箱のような存在。このサイトでは、そんなEvernoteの様々な利用方法が紹介されています。
 
 
 

素敵BOXという名のフォルダ

Evernoteも便利なんですけれども、やはりフォルダの手軽さには及びません。僕のデスクトップの左上にはいつも素敵BOXという名のフォルダがあって、綺麗なものを全部キャプチャしてほうりこんでいます。
 
 
 

RHODIA

メモ帳といえば、Windows・・・じゃなくてRHODIAのメモ帳です。このメモにとにかくアイデアを走り書きしています。方眼紙になっているので、図を描きやすいのが特徴ですね。
 
 
 

 
電車でぼ〜っと流れる景色を眺めているとき、風呂でぼ〜っと天井を眺めているとき、そんな時にアイデアは降ってくる、決して必死で考えているときには得られない素晴らしいインスピレーションが。たまにはゆとりを持って映画や本やアニメを見るのも一興です。
 
 
 

ヒックとドラゴン

2010年に見た映画ではイチオシ。いつも映画は予告編が一番面白い!と言っているのですが、予告編よりも遥かに面白かった希少な映画。主役のドラゴンが猫にしか見えない(笑)猫好きなら絶対見とけ、的な映画です。
 
 
 

イリヤの空、UFOの夏

「イリヤの空、UFOの夏」は僕が初めて読んだライトノベルス。毎年、夏になると無性に読みたくなる本です。とにかくこの作家さん、情景を書くのが上手くて本を読んでいても映像として入ってくるのがすごい!
 
 
 

電脳コイル

日本のAR(Augmented Reality)研究者でこのアニメを知らなかったらモグリだろ?っていうくらい有名なアニメ。Webとバーチャルの世界に生きる現代人に痛快なメッセージを届けてくれます。そしてなにより、素晴らしく面・白・い!!
 
 
 

先人のアイデアにインスパイアされてみよう。 優れたものを見たとき、確実に自分の中の想像力、もしくは発想力の根源がざわつく。それは聞こえないほど微小かもしれない、触れられないほど微細かもしれない。でもきっと。
 
  
 

インターネットミュージアム

家の近くにある美術館や博物館を検索できるほか、ジャンル別でイベント情報なども検索したり、タイムリーなニュースを読むことも出来ます。
 
 
 

Klimt HD

グスタフクリムトの画集がiPadで鑑賞できるアプリ。他にもゴッホの作品を見ることが出来るVincent van Gogh – Classic Painters Galleryや、1000以上の有名な芸術家による4万点の絵画や彫像を鑑賞することができるArt Authority for iPadなどのアプリもあります。
 
  

画像処理に使えるUIImageのTips10個

木曜日, 1月 6th, 2011
このエントリーを含むはてなブックマークはてなブックマーク - 画像処理に使えるUIImageのTips10個

 
 
 
(1) 画像をUIImageに読み込む

指定したファイルから画像を読み込み、UIImageに格納するためにはUIImageのクラスメソッドであるimageNameメソッドを使います。このメソッドはinitWithContentsOfFileよりも高速です。

//画像を読み込む
UIImage *image = [UIImage imageNamed:@"test.jpg"];

 
 
 
 
(2) 画像をファイルパスから読み込む

ファイルパスを指定して画像を読み込むためには、NSBundleクラスを用いてパスを作成し、そのパスをinitWithContentsOfFileの引数にしてわたします。ただし、initWithContentsOfFileで作成したUIImageの描画は非常に遅いので注意。

NSString *filePath 
= [[NSBundle mainBundle] pathForResource:@"test" ofType:@"jpg"];
	
UIImage *img
= [[UIImage alloc] initWithContentsOfFile:filePath];

 
[参考]

  • UIImage#imageNamed:は読み込みも描画もUIImage#imageWithContentsOfFile:やそれ以外のメソッドより5~6倍速い
  • Sun Limited Mt. UIImage#ImageWithContentsOfData: などは描画が激遅
  •  
     
      
     
     
    (3) UIImageをカメラロールに保存する

    作成したUIImageをカメラロールに保存するためにはUIImageWriteToSavedPhotosAlbum関数を利用します。引数には保存画像、デリゲート、完了を知らせるコールバック関数を指定します。

    このメソッドで指定した画像はJPG形式に変換され保存されるため、画質の劣化は避けられません。画質は93%の圧縮画像になるようです。今のところ、このメソッドがカメラロールに保存する唯一の方法です。

    - (void) finishExport:(UIImage *)image
    didFinishSavingWithError:(NSError *)error
    contextInfo:(void *)contextInfo
    {
      NSLog(@"save image successfully"); 
    }
    
    UIImageWriteToSavedPhotosAlbum(image, self, @selector(finishExport:didFinishSavingWithError:contextInfo:),
    nil);
    
    

    [参考]

  • iPhoneアプリ開発ブログ UIViewのスクリーンショットの画質を良くしたい
  • Unnamed Red UIImage をカメラロールに保存する
  •  
     
     
     
    (4) UIImageを拡大縮小する

    第一引数に元画像を、第二引数にリサイズ後のサイズを渡すことで、画像のアスペクトを保持したままリサイズを行い、その画像を返してくれるメソッド。アスペクトを保持するため、始めの4行で拡大率を固定している。

    リサイズを行うため、まずはUIGraphicsBeginImageContextメソッドで指定サイズのグラフィックスコンテキストを取得し、そこに画像を描画する。グラフィックスコンテキストに描画された画像を再びUIGraphicsGetImageFromCurrentImageContextメソッドで取得してUIImage型に再合成している。
     

    - (UIImage*)resizedImage:(UIImage *)img size:(CGSize)size
    {
    	CGFloat widthRatio  = size.width  / img.size.width;
    	CGFloat heightRatio = size.height / img.size.height;
    	CGFloat ratio = (widthRatio < heightRatio) ? widthRatio : heightRatio;
    	CGSize resizedSize = CGSizeMake(img.size.width*ratio, img.size.height*ratio);
    	
    	UIGraphicsBeginImageContext(resizedSize);
    	
    	&#91;img drawInRect:CGRectMake(0, 0, resizedSize.width, resizedSize.height)&#93;;	
    	UIImage* resizedImage = UIGraphicsGetImageFromCurrentImageContext();
    	
    	UIGraphicsEndImageContext();
    	
    	return resizedImage;
    }
    &#91;/cpp&#93;
    
    &#91;参考&#93;
    <li><a href="http://i.studio23c.com/?p=612">iPhoneメモ UIImageの縮小 〜比率を保持して/カテゴリでメソッドを追加編〜</a></li>
     
     
     
     
    <span style="font-size:large;color:RoyalBlue"><strong>(5) UIImageを回転させる</strong></span>
    
    <a href="http://iphone.moo.jp/app/wp-content/uploads/rotateuiimage.jpg"><img src="http://iphone.moo.jp/app/wp-content/uploads/rotateuiimage.jpg" alt="" title="rotateuiimage" width="382" height="102" class="alignnone size-full wp-image-803" /></a>
    
    第一引数に元画像を、第二引数に回転角度を渡すことで、回転した画像を返してくれるメソッド。回転角度には90, 180, 270度のみ指定可能。
    
    こちらも画像の拡大縮小と同様、グラフィックスコンテキストに一度描画を行い、そのグラフィックスコンテキストに対して回転処理をほどこした後、UIImage型に再合成しています。
     
    [cpp]
    - (UIImage *) rotateImage:(UIImage *)img angle:(int)angle
    {
    	CGImageRef imgRef = [img CGImage];
    	CGContextRef context;
    	
        switch (angle) {  
    		case 90:  
    			UIGraphicsBeginImageContext(CGSizeMake(img.size.height, img.size.width));					
    			context = UIGraphicsGetCurrentContext();  			
    			CGContextTranslateCTM(context, img.size.height, img.size.width);  
    			CGContextScaleCTM(context, 1.0, -1.0);  
    			CGContextRotateCTM(context, M_PI/2.0);  
    			break; 
    		case 180:
    			UIGraphicsBeginImageContext(CGSizeMake(img.size.width, img.size.height));					
    			context = UIGraphicsGetCurrentContext();  
    			CGContextTranslateCTM(context, img.size.width, 0);  
    			CGContextScaleCTM(context, 1.0, -1.0);  
    			CGContextRotateCTM(context, -M_PI);  
    			break;  
    		case 270:  
    			UIGraphicsBeginImageContext(CGSizeMake(img.size.height, img.size.width));					
    			context = UIGraphicsGetCurrentContext();  
    			CGContextScaleCTM(context, 1.0, -1.0);  
    			CGContextRotateCTM(context, -M_PI/2.0);  
    			break;  
    		default:
    			NSLog(@"you can select an angle of 90, 180, 270");
    			return nil;
        }  
    	
        CGContextDrawImage(context, CGRectMake(0, 0, img.size.width, img.size.height), imgRef);  
        UIImage *ret = UIGraphicsGetImageFromCurrentImageContext();  
        
        UIGraphicsEndImageContext();  
    	return ret;
    }
    
    

    [参考]

  • 琴線探査 iPhoneで画像を回転させて保存するには?
  •  
     
     
     
    (7) UIImageのピクセルにアクセスする

    UIImageに対して独自の画像処理を行う場合には、UIImageのピクセルにアクセスする必要があります。下の例はUIImageのピクセルにアクセスして、画像をグレースケール化しています。

    具体的にはUIImageからCGImage型を経てピクセル配列へと分解し、ピクセルに対して画像処理を行ったあと、分解とは逆の操作を行うことでUIImageまで再合成しています。
     

    	// pixel値の抽出
    	UIImage *img = [UIImage imageNamed:@"test.jpg"];	
    	CGImageRef cgImage = [img CGImage];
    	size_t bytesPerRow = CGImageGetBytesPerRow(cgImage);
    	CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImage);
    	CFDataRef data = CGDataProviderCopyData(dataProvider);
    	UInt8* pixels = (UInt8*)CFDataGetBytePtr(data);
    	
    	// 画像処理(グレースケール化)
    	for (int y = 0 ; y < img.size.height; y++){
    		for (int x = 0; x < img.size.width; x++){
    			UInt8* buf = pixels + y * bytesPerRow + x * 4;		
    			UInt8 r, g, b;
    			r = *(buf + 0);
    			g = *(buf + 1);
    			b = *(buf + 2);
    			UInt8 gray = (77 * r + 28 * g + 151 * b)>>8;
    			*(buf + 0) = gray;
    			*(buf + 1) = gray;
    			*(buf + 2) = gray;
    		}
    	}
    	
    	// pixel値からUIImageの再合成
    	CFDataRef resultData = CFDataCreate(NULL, pixels, CFDataGetLength(data));
    	CGDataProviderRef resultDataProvider = CGDataProviderCreateWithCFData(resultData);
    	CGImageRef resultCgImage = CGImageCreate(
    						   CGImageGetWidth(cgImage), CGImageGetHeight(cgImage), 
    						   CGImageGetBitsPerComponent(cgImage), CGImageGetBitsPerPixel(cgImage), bytesPerRow, 
    						   CGImageGetColorSpace(cgImage), CGImageGetBitmapInfo(cgImage), resultDataProvider, 
    						   NULL, CGImageGetShouldInterpolate(cgImage), CGImageGetRenderingIntent(cgImage));
    	UIImage* result = [[[UIImage alloc] initWithCGImage:resultCgImage] autorelease];
    	
    	// 後処理
    	CGImageRelease(resultCgImage);
    	CFRelease(resultDataProvider);
    	CFRelease(resultData);
    	CFRelease(data);
    

    [参考]

  • sonson@Picture&Software UIImageでピクセルを扱う
  • iPhoneアプリで稼げるのか カメラアプリ系の画像処理をする
  •  
     
     
     
    (8) UIImageでアニメーションを作る

    animation

    UIImageの配列を作成し、それをImageVIewクラスに登録することでアニメーション表示することができます。animationDurationでアニメの実行時間を指定できます。

        NSArray *imageArray = [[NSArray alloc] initWithObjects:
    						 [UIImage imageNamed:@"test.jpg"],
    						 [UIImage imageNamed:@"test2.jpg"],
    						 [UIImage imageNamed:@"test3.jpg"],	
    						 [UIImage imageNamed:@"test4.jpg"],	
    						 [UIImage imageNamed:@"test5.jpg"],	 
    						 nil];
    
        imageView.animationImages = imageArray;
        imageView.animationDuration = 1.0f;
      
        [imageView startAnimating];
    

     

    [参考]

  • UIImageで手っ取り早くアニメーションを作ってしまう方法
  •  
      
     
     
    (9) マスク処理で角丸画像を作成する

    UIImageの画像にマスクをかけるにはCGImageCreateWithMaskメソッドを使用します。引数として与えるマスク画像はCGImageMaskCreateメソッドを使って作成しています。この際、角丸のマスク画像を使用することで、元画像を角丸画像に変換することが出来ます。

    - (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
     
    	CGImageRef maskRef = maskImage.CGImage; 
     
    	CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
    		CGImageGetHeight(maskRef),
    		CGImageGetBitsPerComponent(maskRef),
    		CGImageGetBitsPerPixel(maskRef),
    		CGImageGetBytesPerRow(maskRef),
    		CGImageGetDataProvider(maskRef), NULL, false);
     
    	CGImageRef masked = CGImageCreateWithMask([image CGImage], mask);
    	return [UIImage imageWithCGImage:masked];
     
    }
    

      

    [参考]

  • [iOS developer:tips]; How to Mask an Image
  •  
     
     
     
    (10) IplImageとUIImageの相互変換

    opencvuiimage

    ここまでは、UIImageに対して直接処理を行って来ましたが、本格的な画像処理を行う場合にはOpenCVを使ったほうが簡単に行なえます。しかし、iPhoneプログラミングではcvLoadImge関数を使って画像を読み込むことは出来ないので、

    • imageNamedメソッドで画像読み込み
    • UIImage から IplImage型に変換
    • OpenCVで画像処理
    • IplImage から UIImage型に変換して表示

    という流れになります。

    ここでは、UIImageとIplImageの相互変換のプログラムを紹介します。まずはUIImageをIplImageに変換するメソッド。

    - (UIImage *)resizedImageArbitrarily:(UIImage *)img size:(CGSize)size
    IplImage* createIplImageFromUIImage(UIImage* image)
    {
    	// CGImageをUIImageから取得
    	CGImageRef imageRef = image.CGImage;
    	
    	CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    	// 一時的なIplImageを作成
    	IplImage *iplimage = cvCreateImage(cvSize(image.size.width,image.size.height), IPL_DEPTH_8U, 4 );
    	
    	// CGContextを一時的なIplImageから作成
    	CGContextRef contextRef = CGBitmapContextCreate(
    													iplimage->imageData, iplimage->width, iplimage->height,
    													iplimage->depth, iplimage->widthStep,
    													colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault);
    	// CGImageをCGContextに描画
    	CGContextDrawImage(
    					   contextRef,
    					   CGRectMake(0, 0, image.size.width, image.size.height),
    					   imageRef);
    	
    	CGContextRelease(contextRef);
    	CGColorSpaceRelease(colorSpace);
    	
    	// 最終的なIplImageを作成
    	IplImage *ret = cvCreateImage(cvGetSize(iplimage), IPL_DEPTH_8U, 3);
    	cvCvtColor(iplimage, ret, CV_RGBA2BGR);
    	cvReleaseImage(&iplimage);
    	
    	return ret;
    }
    

    こちらは逆にOpenCVのIplImageからUIImageに変換するメソッド。

    UIImage* createUIImageFromIplImage(IplImage *image)
    {
    	CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    	// CGImageのためのバッファを確保
    	NSData *data =
        [NSData dataWithBytes:image->imageData length:image->imageSize];
    	CGDataProviderRef provider =
        CGDataProviderCreateWithCFData((CFDataRef)data);
    	// IplImageのデータからCGImageを作成
    	CGImageRef imageRef = CGImageCreate(
    										image->width, image->height,
    										image->depth, image->depth * image->nChannels, image->widthStep,
    										colorSpace, kCGImageAlphaNone|kCGBitmapByteOrderDefault,
    										provider, NULL, false, kCGRenderingIntentDefault
    										);
    	// UIImageをCGImageから取得
    	UIImage *ret = [UIImage imageWithCGImage:imageRef];
    	CGImageRelease(imageRef);
    	CGDataProviderRelease(provider);
    	CGColorSpaceRelease(colorSpace);
    	return ret;
    }
    

    [参考]

  • yoshimasa niwa iPhoneでOpenCVを使う方法
  •  

    TwitPicへ投稿するiPhoneアプリが出来るまで

    木曜日, 12月 23rd, 2010
    このエントリーを含むはてなブックマークはてなブックマーク - TwitPicへ投稿するiPhoneアプリが出来るまで

    twitpic1

    Twitterは2010年の8月末でBasic認証を廃止したため、それ以降はログインのために、OAuth(またはその簡易版のxAuth)を使わなければならなくなりました。

    このxAuthですが、得られるメリットはたくさんあるのですが、如何せん実装がめんどくさい&難しいわけです。そこで、今回はxAuthを使ってTwitPicへ投稿するアプリをつくってみたいと思います。

    [Step 1] TwitterにxAuthの使用を申請する
     
    まずは、Twitterの「アプリケーション登録申請」の画面からアプリケーションの登録を行います。この際、アプリケーションの種類は「クライアントアプリケーション」を、標準のアクセスタイプは「Read & Write」を選択しておいて下さい。

    登録後に表示される Consumer key と Consumer secret はアプリ作成の際に必要なので、メモっておいてください。登録情報は後ほどTwitterアプリケーションからも見ることができます。

    この登録ではOAuthの申請しかできないため、xAuthを使うためにはTwitterな人にメールで申請する必要が必要です。僕は次の次のようなメールをapi@twitter.comに送りました。

    Dear Brian

    My account is @apphokuson.

    I would like to use xAuth on my application named “色影”. My application ‘色影’ is a image processing software for iPhone. I would like to upload text and image from my application. Here is a web site of my app (in Japanese)

    http://iphone.moo.jp/colorshadow.html

    I also attached screen shot of my app.

    Best regards
    Kazuma

    Twitterの人からのメールによると、アプリの機能、使用目的、スクリーンショットは書いておく必要があるそうです。2・3日でTwitterな人から「xAuthに対応したよ」という返信があれば、準備完了です。

    twitpic2

    [Step 2] TwitPicからAPI keyを取得する
     
    こちらの「Register an Application」のページからアプリの登録を行い、API keyを取得します。この情報も後ほど、アプリを作成するのに必要ですので、控えておいてください。

    [Step 3] XAuthTwitterEngineを取得する
     
    xAuthの認証をライブラリ化したものが、すでに存在するのでそれを利用します。今回は、XAuthTwitterEngineを使用しました。まずは、こちらからサンプルプロジェクトをダウンロードして下さい。

    まずは、サンプルプロジェクトをそのまま実行してみましょう。そのためには、まずXAuthTwitterEngineDemoViewController.hのkOAuthConsumerKeyとkOAuthConsumerSecretに、それぞれStep 1で取得したonsumer key と Consumer secret をセットします。

    この作業後コンパイル&実行すれば、アプリが起動するので、accountとpasswordを設定し、「Get xAuth Access Token」ボタンをタップ後、「Send test tweet」ボタンをタップします。全てが上手く行けば、入力したアカウントにテストメッセージが投稿されます。

    twitpic3

    ここで注意することは、

    Twitterは二重投稿を禁止している

    ということです。はい、はまりました。投稿直後にもう一度「Send test tweet」ボタンをタップすると、エラーコード403で投稿が失敗します。対策としては、投稿コメントが直前のコメントと異なれば二重投稿とはみなされないため、投稿メッセージに現在時刻などを追加するなどのトリックが必要です。

    現在時刻の文字列はこんな感じで作れます

    NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
    [formatter setDateFormat:@"YYYY/MM/dd HH:mm:ss"]; 
    NSString *now = [formatter stringFromDate:[NSDate date];
    

    ここまでで、Twitterへの投稿準備は整いました。次からのステップで、TwitPicへの画像投稿のプログラムを作成していきます。

    [Step 4] 非同期通信の準備を行う
     
    TwitPicへの写真投稿は非同期通信を用いて行います。そのため、非同期通信用ライブラリのASIHTTPRequestをこちらからダウンロードして、そのなかのASIフォルダをStep 3で使用したプロジェクトにフォルダごと追加してください。(xmlフォルダは今回は使用しません)

    次に、フレームワーク関連の追加を行ないます。Xcode左カラムのFrameworksフォルダを右クリック →「追加」→「既存のフレームワーク」の順に選択し、下記のフレームワーク&ダイナミックライブラリ

  • CFNetwork.framework
  • MobileCoreServices.framework
  • SystemConfiguration.framework,
  • libxml2.dylib,
  • libz.1.2.3.dylib

    を追加します。

    twitpic2

    [Step 5] TwitPic投稿用のプログラムを作成する
     
    さて、いよいよ最後に投稿用のメソッドを作成します。下記に載せたのが追加する2つのメソッドになります。まずは、ASIFormDataRequest.hをimportしてから、uploadToTwitterByTwitPic:image中のsetPostValueの引数にStep 2で用意したTwitPicのAPI keyをセットしてください。

    - (ASIFormDataRequest*)createOAuthEchoRequest:(NSString*)url format:(NSString*)format 
    {
    	NSString *authorizeUrl = [NSString stringWithFormat:@"https://api.twitter.com/1/account/verify_credentials.%@", format];
    	OAMutableURLRequest *oauthRequest = [[[OAMutableURLRequest alloc] initWithURL:[NSURL URLWithString:authorizeUrl]
    																		 consumer:self.twitterEngine.consumer
    																			token:self.twitterEngine.accessToken   
    																			realm:@"http://api.twitter.com/"
    																signatureProvider:nil] autorelease];
    	
    	NSString *oauthHeader = [oauthRequest valueForHTTPHeaderField:@"Authorization"];
    	if (!oauthHeader) {
    		[oauthRequest prepare];
    		oauthHeader = [oauthRequest valueForHTTPHeaderField:@"Authorization"];
    	}
    	
    	NSLog(@"OAuth header : %@\n\n", oauthHeader);
    	
    	ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:url]];
    	request.requestMethod = @"POST";
    	request.shouldAttemptPersistentConnection = NO;	
    	
    	[request addRequestHeader:@"X-Auth-Service-Provider" value:authorizeUrl]; 
    	[request addRequestHeader:@"X-Verify-Credentials-Authorization" value:oauthHeader];
    	
    	return request;
    }
    
    - (void)uploadToTwitterByTwitPic:(NSString*)tweet image:(UIImage*)image {
    	NSString *url = @"http://api.twitpic.com/2/upload.json";
    	ASIFormDataRequest *request = [self createOAuthEchoRequest:url format:@"json"];
    	
    	NSData *imageRepresentation = UIImageJPEGRepresentation(image, 1.0);
    	[request setData:imageRepresentation forKey:@"media"];
    	[request setPostValue:tweet  forKey:@"message"];
    	[request setPostValue:@"" forKey:@"key"];
    	
    	[request setDelegate:self];
    	[request setDidFinishSelector:@selector(twitPicRequestFinished:)];
    	[request setDidFailSelector:@selector(requestFailed:)];	
    	[request startAsynchronous];
    }
    

    createOAuthEchoRequestメソッドでは、TwitPicへ投稿するためのリクエストを作成しています。また、uploadToTwitterByTwitPic:imageメソッドの中で、実際にTwitPicへの投稿を行っています。

    そこで、あとはsendTestTweetButtonTouchUpInsideメソッドなどの中で、uploadToTwitterByTwitPic:imageをコールすると、ボタンがタップされた時に、引数で渡した画像をTwitPicに投稿できるようになります。下に、ここまでのサンプルプロジェクトを置いておきます。是非参考にしてみてください

    TwitPic投稿テストプロジェクト
     
    twitpic4
     
    [Reference]
     
    今回の記事を書くにあたって、下記のサイトを参考にさせていただきました。この場を借りて御礼申し上げます

  • TwitPicのOAuthEcho対応
  • TwitterにポストするiPhoneアプリをBasic認証からxAuthに変更してみました