01/25〜01/31のAppダウンロード数

Posted by: daichi  /  Category: ダウンロード

2010/01/25〜2010/01/31の週次Appダウンロードレポート。

続きを読む

AppStoreリンクの小ネタ

Posted by: daichi  /  Category: 販売促進

AppStoreへの簡単なリンクの作り方が以下に載ってます。
Technical Q&A QA1633: Creating easy-to-read links to the App Store for your applications and company

  • アプリ名でリンク
  • http://itunes.com/apps/アプリ名
  • 会社名でリンク
  • http://itunes.com/apps/会社名
  • アプリ名と会社名でリンク
  • http://itunes.com/apps/会社名/アプリ名
リンクにする時は
  • 大文字は小文字に
  • スペースは取り除く
  • “&”は”and”に
  • “!¡”#$%’()*+,\-./:;<=>¿?@[\]^_`{|}~”は取り除く
  • アクセント文字(ü, åなど)は元の文字(u, aなど)に置き換える
  • “©”や”™”や”®”を取り除く
でOK。

iTaskTimer Liteを例にするなら
  • アプリ名リンク
  • http://itunes.com/apps/itasktimerlite
  • 会社名リンク
  • http://itunes.com/apps/daichicho
  • 会社名+アプリ名リンク
  • http://itunes.com/apps/daichicho/itasktimerlite
でいける。

こういう情報が流れてくる以下のRSSはとりあえずフィード登録して損なしです。
http://developer.apple.com/rss/iphonedevnews.rss

【iPhone】coverflowを簡単に実装できるライブラリ

Posted by: daichi  /  Category: 未分類

OpenFlowDemo

iPhoneアプリ開発者なら一度はCoverflowを実装してみたいと思うはず。

coverflowの実現方法は、以前からエリカ様の書籍にて公開されていましたが、undocumentedなAPIを使っているため、おそらくあの方法では申請したところでAppleに蹴られて終わりでしょう。最近はundocumented API検出ツールのようなものをAppleが使って審査してるという話もあるので、審査の目は前よりも厳しくなってる気がします。

となると、自力で実装していくしかないのですが、ちょうどよいライブラリがあったので、早速試してみる。

続きを読む

11/09〜11/15のAppダウンロード数

Posted by: daichi  /  Category: ダウンロード

2009/11/09〜2009/11/15の週次Appダウンロードレポート。

続きを読む

11/02〜11/08のAppダウンロード数

Posted by: daichi  /  Category: ダウンロード

2009/11/02〜2009/11/08の週次Appダウンロードレポート。

続きを読む

10/26〜11/01のAppダウンロード数

Posted by: daichi  /  Category: ダウンロード

2009/10/26〜2009/11/01の週次Appダウンロードレポート。

続きを読む

10/19〜10/25のAppダウンロード数

Posted by: daichi  /  Category: ダウンロード

2009/10/19〜2009/10/25の週次Appダウンロードレポート。

続きを読む

【iPhone】カメラアプリ系の画像処理をする

Posted by: daichi  /  Category: iphone開発

久しぶりに開発のエントリを。
これまで画像処理系のプログラムを書いたことがなかったので調べてみた。

カメラアプリ系の画像処理を行うには

  1. UIImageのピクセルデータへアクセスする方法を知る
  2. 画像処理アルゴリズムを知る
が必要。

UIImageのピクセルデータへアクセスする

以下のサイトがとても参考になった。
sonson@Picture&Software – [iPhone SDK] UIImageでピクセルを扱う
WWDC2009_Kazuki_Endo

UIImageからCGImageを取得してごにょごにょするとピクセルデータにアクセスできる様子。
上のサイトでは画像をグレーにするサンプルコードを公開してくれていたので、それを丸ごと拝借してみる。
いちいち変換クラスを用意するのは面倒なので、カテゴリを使ってUIImageを拡張してみる。

UIImageAddtion.h


?View Code OBJECTIVE-C
#import <UIKit/UIKit.h>
@interface UIImage (Effect)
@end

UIImageAddtion.m


?View Code OBJECTIVE-C
#import "UIImageAddtion.h"
 
@implementation UIImage (Effect)
-(UIImage*)grayImage {
	[self grayImage:CGRectMake(0, 0, 320, 480)];
}
 
-(UIImage*)grayImage:(CGRect)rect {
	// CGImageを取得する
	CGImageRef cgImage;
	cgImage = self.CGImage;
 
	// 画像情報を取得する
	size_t width;
	size_t height;
	size_t bitsPerComponent;
	size_t bitsPerPixel;
	size_t bytesPerRow;
	CGColorSpaceRef colorSpace;
	CGBitmapInfo bitmapInfo;
	bool shouldInterpolate;
	CGColorRenderingIntent intent;
	width = CGImageGetWidth(cgImage);
	height = CGImageGetHeight(cgImage);
	bitsPerComponent = CGImageGetBitsPerComponent(cgImage);
	bitsPerPixel = CGImageGetBitsPerPixel(cgImage);
	bytesPerRow = CGImageGetBytesPerRow(cgImage);
	colorSpace = CGImageGetColorSpace(cgImage);
	bitmapInfo = CGImageGetBitmapInfo(cgImage);
	shouldInterpolate = CGImageGetShouldInterpolate(cgImage);
	intent = CGImageGetRenderingIntent(cgImage);
 
	// データプロバイダを取得する
	CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImage);
 
	if (rect.size.width + rect.origin.x  > width) {
		rect.size.width = width - rect.origin.x;
	}
	if (rect.size.height + rect.origin.y > height) {
		rect.size.height = height - rect.origin.y;
	}
 
 
	// ビットマップデータを取得する
	CFDataRef data = CGDataProviderCopyData(dataProvider);
	UInt8* buffer = (UInt8*)CFDataGetBytePtr(data);
 
	// ビットマップに効果を与える
 
	NSUInteger i, j;
	for (j = rect.origin.y ; j < rect.origin.y + rect.size.height; j++)
	{
		for (i = rect.origin.x; i < rect.origin.x + rect.size.width; i++) 
		{
			// ピクセルのポインタを取得する
			UInt8* tmp = buffer + j * bytesPerRow + i * 4;
 
			// RGBの値を取得する
			UInt8 r, g, b;
			r = *(tmp + 3);
			g = *(tmp + 2);
			b = *(tmp + 1);
 
			// 輝度値を計算する
			UInt8 y = (77 * r + 28 * g + 151 * b) / 256;
 
			// 輝度の値をRGB値として設定する
			*(tmp + 1) = y;//b
			*(tmp + 2) = y;//g
			*(tmp + 3) = y;//r
		}
        }
 
	// 効果を与えたデータを作成する
	CFDataRef effectedData;
	effectedData = CFDataCreate(NULL, buffer, CFDataGetLength(data));
 
	// 効果を与えたデータプロバイダを作成する
	CGDataProviderRef effectedDataProvider;
	effectedDataProvider = CGDataProviderCreateWithCFData(effectedData);
 
	// 画像を作成する
	CGImageRef effectedCgImage = CGImageCreate(
		 width, height, 
		 bitsPerComponent, bitsPerPixel, bytesPerRow, 
		 colorSpace, bitmapInfo, effectedDataProvider, 
		 NULL, shouldInterpolate, intent);
 
        UIImage* effectedImage = [[[UIImage alloc] initWithCGImage:effectedCgImage] autorelease];
 
	// 作成したデータを解放する
	CGImageRelease(effectedCgImage);
	CFRelease(effectedDataProvider);
	CFRelease(effectedData);
	CFRelease(data);	
 
	return effectedImage;
}

上の二重ループの中でiが画像の横方向、jが画像の縦方向のピクセルに対応していて、1ピクセルずつ処理してる。

これで[image grayImage]のような形でグレー画像を生成できるようになる。
実行結果はこんな感じ。

加工前加工後

さらにCGRectでグレーにする部分を選べるようにしたので、UIImageViewやらでタッチやムーブ時にグレーにする処理を書いてみると

?View Code OBJECTIVE-C
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
	[self process:touches withEvent:event];
}
 
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
	[self process:touches withEvent:event];
}
 
- (void) process:(NSSet *)touches withEvent:(UIEvent *)event {
	CGPoint pt = [[touches anyObject] locationInView:self];
	int margin = 10;
	self.image = [self.image grayImage:CGRectMake(pt.x - margin/2, pt.y - margin/2, margin, margin)];	
}

こんな感じでオイルキャンバスチックな画像ができた。

タッチ

ん。これはおもしろい。

画像処理アルゴリズムを調べてみる

調べてみるといろいろ参考になるサイトが見つかった。
プログラミング – [物理のかぎしっぽ]
画像処理におけるアルゴリズム
TEOライブラリによる画像処理プログラミングガイド

この中でも簡単そうな平均化フィルタを実装してみる。
平均化フィルタを作る – [物理のかぎしっぽ]

平均化フィルタは対象ピクセルの周辺の値の平均値を求めて、対象ピクセルの値を決める方法。これで単純な「ぼかし」が実現できる。

例によってカテゴリに追加。

UIImageAddtion.m


?View Code OBJECTIVE-C
#include <math.h>
 
- (UIImage*)averageFilter{
    [self averageFilter:1];
}
 
- (UIImage*)averageFilter:(NSInteger)pixel{
	// CGImageを取得する
	CGImageRef cgImage;
	cgImage = self.CGImage;
 
	// 画像情報を取得する
	size_t width = CGImageGetWidth(cgImage);
	size_t height = CGImageGetHeight(cgImage);
	size_t bitsPerComponent = CGImageGetBitsPerComponent(cgImage);
	size_t bitsPerPixel = CGImageGetBitsPerPixel(cgImage);
	size_t bytesPerRow = CGImageGetBytesPerRow(cgImage);
	CGColorSpaceRef colorSpace = CGImageGetColorSpace(cgImage);
	CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(cgImage);
	bool shouldInterpolate = CGImageGetShouldInterpolate(cgImage);
	CGColorRenderingIntent intent = CGImageGetRenderingIntent(cgImage);
 
	// データプロバイダを取得する
	CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImage);
 
	// ビットマップデータを取得する
	CFDataRef data = CGDataProviderCopyData(dataProvider);
	UInt8* buffer = (UInt8*)CFDataGetBytePtr(data);
 
	// ビットマップに効果を与える
	NSUInteger i, j;
 
	for (j = pixel ; j < height -pixel; j++)
	{
		for (i = pixel ; i < width -pixel; i++) 
		{
			// ピクセルのポインタを取得する
			UInt8* tmp = buffer + j * bytesPerRow + i * 4;
 
			// RGBの値を取得する
			UInt8 r, g, b;
			r = *(tmp + 3);//b
			g = *(tmp + 2);//g
			b = *(tmp + 1);//r
 
			Float32 sumr, sumg, sumb;
			sumr = 0;
			sumg = 0;
			sumb = 0;
			for (int k=-pixel;k<=pixel;k++){
				for (int l=-pixel;l<=pixel;l++){
					UInt8* t = buffer + (j+k) * bytesPerRow + (i+l) * 4;
					sumr += *(t + 3);
					sumg += *(t + 2);
					sumb += *(t + 1);
				}
			}
 
			*(tmp + 1) = sumb/pow((1+(2*pixel)),2);//b
			*(tmp + 2) = sumg/pow((1+(2*pixel)),2);//g
			*(tmp + 3) = sumr/pow((1+(2*pixel)),2);//r
		}
        }
 
	// 効果を与えたデータを作成する
	CFDataRef effectedData = CFDataCreate(NULL, buffer, CFDataGetLength(data));
 
	// 効果を与えたデータプロバイダを作成する
	CGDataProviderRef effectedDataProvider = CGDataProviderCreateWithCFData(effectedData);
 
	// 画像を作成する
	CGImageRef effectedCgImage = CGImageCreate(
		width, height, 
		bitsPerComponent, bitsPerPixel, bytesPerRow, 
		colorSpace, bitmapInfo, effectedDataProvider, 
		NULL, shouldInterpolate, intent);
 
    UIImage* effectedImage = [[[UIImage alloc] initWithCGImage:effectedCgImage] autorelease];
 
	// 作成したデータを解放する
	CGImageRelease(effectedCgImage);
	CFRelease(effectedDataProvider);
	CFRelease(effectedData);
	CFRelease(data);
 
	return effectedImage;	
}

これで[image averageFilter]を呼ぶとぼかしがかかる。
5回実行してみた。

加工前ぼかし1ぼかし2ぼかし3ぼかし4ぼかし5

これはいろんなアルゴリズムを試してみるとおもしろそう。

09/21〜09/27のAppダウンロード数

Posted by: daichi  /  Category: ダウンロード

2009/09/21〜2009/09/27の週次Appダウンロードレポート。

続きを読む

09/14〜09/20のAppダウンロード数

Posted by: daichi  /  Category: ダウンロード

2009/09/14〜2009/09/20の週次Appダウンロードレポート。

続きを読む

Get Adobe Flash playerPlugin by wpburn.com wordpress themes