2010/01/25〜2010/01/31の週次Appダウンロードレポート。
続きを読む
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など)に置き換える
- “©”や”™”や”®”を取り除く
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を実装してみたいと思うはず。
coverflowの実現方法は、以前からエリカ様の書籍にて公開されていましたが、undocumentedなAPIを使っているため、おそらくあの方法では申請したところでAppleに蹴られて終わりでしょう。最近はundocumented API検出ツールのようなものをAppleが使って審査してるという話もあるので、審査の目は前よりも厳しくなってる気がします。
となると、自力で実装していくしかないのですが、ちょうどよいライブラリがあったので、早速試してみる。
続きを読む
2009/11/09〜2009/11/15の週次Appダウンロードレポート。
続きを読む
2009/11/02〜2009/11/08の週次Appダウンロードレポート。
続きを読む
2009/10/26〜2009/11/01の週次Appダウンロードレポート。
続きを読む
2009/10/19〜2009/10/25の週次Appダウンロードレポート。
続きを読む
久しぶりに開発のエントリを。
これまで画像処理系のプログラムを書いたことがなかったので調べてみた。
カメラアプリ系の画像処理を行うには
- UIImageのピクセルデータへアクセスする方法を知る
- 画像処理アルゴリズムを知る
UIImageのピクセルデータへアクセスする
以下のサイトがとても参考になった。sonson@Picture&Software – [iPhone SDK] UIImageでピクセルを扱う
WWDC2009_Kazuki_Endo
UIImageからCGImageを取得してごにょごにょするとピクセルデータにアクセスできる様子。
上のサイトでは画像をグレーにするサンプルコードを公開してくれていたので、それを丸ごと拝借してみる。
いちいち変換クラスを用意するのは面倒なので、カテゴリを使ってUIImageを拡張してみる。
UIImageAddtion.h
#import <UIKit/UIKit.h> @interface UIImage (Effect) @end |
UIImageAddtion.m
#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やらでタッチやムーブ時にグレーにする処理を書いてみると
- (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
#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回実行してみた。






これはいろんなアルゴリズムを試してみるとおもしろそう。
2009/09/21〜2009/09/27の週次Appダウンロードレポート。
続きを読む
2009/09/14〜2009/09/20の週次Appダウンロードレポート。
続きを読む

