l'essentiel est invisible pour les yeux

Friday, February 22, 2008

2008年習得する言語は

有言実行の意を込めて、D言語。(Digital Marsの方)

まだ若い言語だが、Better C++としてコミュニティでの議論も踏まえて設計されたため、かなり実用的な機能が盛り込まれている。中規模以上の開発で特に力を発揮しそう。2008年は、英語と実用的なD言語と頭の体操にArcかScalaを一つ勉強する。D言語もArcもScalaも若い言語なため、最近の流行が取り入れられていたり、過去の言語で開発者を悩ませてきた問題をエレガントな方法で対応しているという楽しみがある。

皆さんは、今年何語を勉強しますか?

Thursday, February 21, 2008

スティーブジョブスの目

スティーブジョブスの目が好きだ。

スティーブジョブス 偉大なるクリエイティブディレクターの軌跡

ぎらつく眼光。みなぎる自信。自分が見る未来を信じて、決して疑わない驚くべき強さ。
そして、面白いと感じる物を見て取るや自分の考えなどあっさりと捨ててしまうしとやかさ。
アーティストとしての感性。

この本は、人間の目は、時間を経てこれほどまで変わる物なのか?と衝撃を与えてくれた一冊である。

Apple関連の本は、たくさん読んだが、この一冊はスティーブジョブスの写真集という意味で非常に価値のある一冊だ。Apple Iを送り出した頃の、眼光が鋭い、自信に満ちあふれたスティーブジョブス(と、少しやせているウォズ)の写真から、膵臓がんと診断され余命宣告を出され、不死鳥のごとくよみがえり「Appleは電話を再発明した」と話す2007年のMacExpoの写真までが掲載されている。あと、「昨日の事でクヨクヨするのではなく、一緒に明日を作っていこう」とゲイツと話す、D5公開インタビューの写真もだ。

本では、1985年の写真の次は、1995年まで写真が無い。
2枚の写真を比べると、この時期にジョブスの一気に禿げたのがよくわかる。年齢にして、30歳〜40歳。禿げるには少し早すぎる。Next Stepの経営難、資金難は、当時公表されていた情報よりもよほど大変だった事だろう。「誰がこの業界で毛が抜けるほど頑張ったのか?」とジョブスも言ったのだろうか?「自分の存在や自分が作った製品をどのように魅せるのか?」プロモーションは、とても大事な事だ。出すべき情報、魅せるべきブランドを徹底的にコントロールした、ジョブスのこだわりは素晴らしい。

ジョブスのファンで、ジョブスのようになりたい。
って思う人がいるかどうかわからないが、ジョブスを真似してもジョブスのモノマネにしかならない。ジョブスという存在がユニークだからこそ、価値がある。自分の存在をユニークな物にできた時に、それが自分のブランドになる。

PCから始まり、デジタルライフ構想、iPod, iPhoneへと今なお最先端を走り続ける男の半生を写真に収めたこの本には、エネルギーが詰まっている。

Sunday, February 17, 2008

as3filters: 画像処理用フィルターライブラリの公開とPhoto BoothをAS3で作った

第二回目のActionScript記事だ。前回は、AS3の練習にとas3zerobugを作ったが、ActionScript -> Firebugプロキシは既出だったようだ。ま、誰でも考えるアイデアだ。

as3filters



あなたのPCにカメラがついているならば、そいつは、いつもあなたを撮影する機会をうかがっている。Skypeのビデオチャットにしか使わないなんてもったいない。彼らをもっと面白く使ってやろう。リアルな世界がデジタルな世界に瞬時に取り込まれる面白さは、取り込んだリアルな情報を加工した時に現れると思う。例えば、あなたの顔をリアルタイムでとても美人に映し出すなんてどうだろうか?複合現実が当たり前になり、現実と仮想の区別がつかなくなった数世紀後には、人の顔なんて今の原型をなしていないかもしれない。

ブサイクだろうが、相手に見えている顔は現実の世界にオーバーレイされた仮想のあなたの顔だからだ。

さて、今回は画像処理用のフィルターを集めたライブラリを作ってみた。
残念ながら、(今の所)貴方の顔をかっこよく映し出したり、かわいく見せたりするフィルタではない。顔を回転させたり、つぶしたり、部分的に拡大したりと、Photoshopのフィルタ群でよくみられるフィルタだ。ま、ほとんとの場合ブサイクになるだろう。

CPUは消費するが、カメラで取り込んだ映像にリアルタイムでフィルターをかける事は、AS3では十分に可能だ。ハードウェアの進歩に感謝する。ブサイクフィルタだけでなくて、もっとおもしろいアイデアを持っている人を募集している。是非、as3filtersプロジェクトに参加してほしい。

Mac OSXユーザの皆様は、Photo Boothというアプリケーションを知っていると思う。このアプリケーションは、カメラで撮影と撮影した画像に面白いエフェクトをかけることのできる、シンプルなアプリケーションである。このアプリケーションをFlashで作った。

as3filters: Photo Booth Demo


このデモを実行するには、カメラが必要なのでカメラを持っていないユーザは、下記のプロジェクトページからスナップショットが見てください。さすがに、8つのフィルタを同時に処理するとCPU負荷が高いが、一つなら問題ない。

as3filters



as3filtersは、これらのエフェクトをActionScriptで簡単に当てる事のできるフィルターライブラリだ。

インストール方法
チェックアウトして、コンパイル時にリンクする。

% svn checkout http://as3filters.googlecode.com/svn/trunk/ as3filters
% cp as3filters/bin/as3filters.swc /path/to/your-project
% mxmlc -compiler.include-libraries as3filters.swc


Flex-configファイルを使用してもOK。

<?xml version="1.0"?>
<flex-config>
<compiler>
<library-path append="true">
<path-element>../bin/as3filters.swc</path-element>
</library-path>
</compiler>
</flex-config>



使い方
Filterクラスのスタティックメソッドで、フィルタを作成して、BitmapData#applyFilterメソッドでフィルタを適用する。第一引数は、フィルタ適用対象のBitmapDataオブジェクトを渡す。regionはフィルタを適用する領域となる。


var bmd:BitmapData = new BitmapData(width, height, true);
var region:Rectangle = new Rectangle(30, 30, 90, 90)
var twirlFilter:DisplacementMapFilter = Filter.twirlFilter(bmd, region);
bmd.draw(video);
bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), twirlFilter);



詳しくは、以下のPhoto Booth Demoアプリケーションのソースをご覧あれ。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
color="#000"
themeColor="#FFFFFF"
styleName="plain"
creationComplete="init();">

<mx:Script> <![CDATA[
import flash.display.*;
import flash.filters.*;
import flash.media.Camera;
import as3.Filter;
import mx.controls.*;
import mx.core.*;

private var camera:Camera;
private var fps:int = 18;
private const VIDEO_WIDTH:int = 150,
VIDEO_HEIGHT:int = 150;

private function setupVideo():void
{
bulge_video.width = dent_video.width = twirl_video.width = VIDEO_WIDTH;
squeeze_video.width = video.width = mirror_video.width = VIDEO_WIDTH;
tunnel_video.width = fisheye_video.width = strech_video.width = VIDEO_WIDTH;
bulge_video.height = dent_video.height = twirl_video.height = VIDEO_HEIGHT;
squeeze_video.height = video.height = mirror_video.height = VIDEO_HEIGHT;
tunnel_video.height = fisheye_video.height = strech_video.height = VIDEO_HEIGHT;
}

public function init():void
{
// setup camera
if(connectCamera()) {
// Setup video
setupVideo();
video.attachCamera(camera);

setInterval((function():Function {
// setup filters
var width:int = video.width;
var height:int = video.height;
var bmd:BitmapData = new BitmapData(width, height, true);
var region:Rectangle = new Rectangle(30, 30, 90, 90);
var bulgeFilter:DisplacementMapFilter = Filter.bulgeFilter(bmd, region);
var twirlFilter:DisplacementMapFilter = Filter.twirlFilter(bmd, region);
var squeezeFilter:DisplacementMapFilter = Filter.squeezeFilter(bmd);
var pinchFilter:DisplacementMapFilter = Filter.pinchFilter(bmd, region);
var tunnelFilter:DisplacementMapFilter = Filter.photicTunnelFilter(bmd, region);
var fisheyeFilter:DisplacementMapFilter = Filter.fisheyeFilter(bmd);
var strechFilter:DisplacementMapFilter = Filter.strechFilter(bmd);

// TODO: Dent filter is not supported yet.
var dentFilter:DisplacementMapFilter = Filter.squeezeFilter(bmd, region, 0.3);

return function():void {
// original
bmd.draw(video);

// bulge effect
var bulgeBmd:BitmapData = new BitmapData(width, height, false);
bulgeBmd.applyFilter(bmd, bmd.rect, new Point(0, 0), bulgeFilter);
bulge_video.addChild(new Bitmap(bulgeBmd));

// twirl effect
var twirlBmd:BitmapData = new BitmapData(width, height, false);
twirlBmd.applyFilter(bmd, bmd.rect, new Point(0, 0), twirlFilter);
twirl_video.addChild(new Bitmap(twirlBmd));

// squeeze effect
var squeezeBmd:BitmapData = new BitmapData(width, height, false);
squeezeBmd.applyFilter(bmd, bmd.rect, new Point(0, 0), squeezeFilter);
squeeze_video.addChild(new Bitmap(squeezeBmd));

// pinch effect
var tunnelBmd:BitmapData = new BitmapData(width, height, false);
tunnelBmd.applyFilter(bmd, bmd.rect, new Point(0, 0), tunnelFilter);
tunnel_video.addChild(new Bitmap(tunnelBmd));

// mirror effect
// NOTE: A little tricky because return BitmapData object directly.
mirror_video.addChild(new Bitmap(Filter.mirror(bmd)));

// fisheye effect
var fisheyeBmd:BitmapData = new BitmapData(width, height, false);
fisheyeBmd.applyFilter(bmd, bmd.rect, new Point(0, 0), fisheyeFilter);
fisheye_video.addChild(new Bitmap(fisheyeBmd));

// strech effect
var strechBmd:BitmapData = new BitmapData(width, height, false);
strechBmd.applyFilter(bmd, bmd.rect, new Point(0, 0), strechFilter);
strech_video.addChild(new Bitmap(strechBmd));

// dent effect
// TODO: Dent effect is not supported yet
var dentBmd:BitmapData = new BitmapData(width, height, false);
dentBmd.applyFilter(bmd, bmd.rect, new Point(0, 0), dentFilter);
dent_video.addChild(new Bitmap(dentBmd));
};
})(), 1000 / fps);
}
}
// {{{
private function rotate(source:BitmapData):BitmapData
{
var width:int = source.width;
var height:int = source.height;
var matrix:Matrix = new Matrix();
var rotation:Number = Math.PI / 2;
var dx:int = Math.floor(width / 2);
var dy:int = Math.floor(height / 2);
matrix.rotate(rotation);
matrix.translate(width, 0);
var bmd:BitmapData = new BitmapData(width, height, false);
bmd.draw(source, matrix);

return bmd;
}
// }}}

private function connectCamera():Boolean
{
camera = Camera.getCamera();
if(camera) {
camera.setMode(VIDEO_WIDTH, VIDEO_HEIGHT, fps);
return true;
} else {
return false;
}
}
]]></mx:Script>
<mx:VBox>
<mx:Label text="AS3 Photo Booth." fontSize="16"/>
<mx:HBox>
<mx:VideoDisplay id="bulge_video"/>
<mx:VideoDisplay id="dent_video"/>
<mx:VideoDisplay id="twirl_video"/>
</mx:HBox>
<mx:HBox>
<mx:VideoDisplay id="squeeze_video"/>
<mx:VideoDisplay id="video"/>
<mx:VideoDisplay id="mirror_video"/>
</mx:HBox>
<mx:HBox>
<mx:VideoDisplay id="tunnel_video"/>
<mx:VideoDisplay id="fisheye_video"/>
<mx:VideoDisplay id="strech_video"/>
</mx:HBox>
</mx:VBox>
</mx:Application>



Filter.asのソース

package as3 {
import flash.display.*;
import flash.geom.*;
import flash.filters.*;

/**
* as.Filter
*
* as3.Filter class includes methods generate variety of filters for image processing.
*/
public class Filter
{
/**
* Generate the DisplacementMapFilter for twirling effect.
*
* You can apply the filter is as follows:
*
* var bmd:BitmapData = new BitmapData(width, height, false);
* var filter:DisplacementMapFilter = Filter.twirlFilter(bmd);
* bmd.draw(video);
* bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), filter);
*
* You can also apply the filter specified region:
*
* var region:Rectangle = new Rectangle(100, 100, 100, 100);
* var filter:DisplacementMapFilter = Filter.twirlFilter(bmd, rect);
*
* @params source BitmapData The input bitmap data to apply the twirling effect.
* @params region Rectangle The region to apply the twirling effect.
* @params rotation Number The max amount to rotate, in radius.
* Default is Math.PI / 2.
*
* @return DisplacementMapFilter Filter to apply twirl effect
*/
static public function twirlFilter(source:BitmapData, region:Rectangle=null,
rotation:Number=0):DisplacementMapFilter
{
var width:int = source.width;
var height:int = source.height;
region ||= new Rectangle(0, 0, width, height);
rotation ||= Math.PI / 2;
var dbmd:BitmapData = new BitmapData(width, height, false, 0x8080);
var radius:Number = Math.min(region.width, region.height) / 2;
var centerX:int = region.x + region.width / 2;
var centerY:int = region.y + region.height / 2;
for(var y:int=0;y<height;++y) {
var ycoord:int = y - centerY;
for(var x:int=0;x<width;++x) {
var xcoord:int = x - centerX;
var dr:Number = radius - Math.sqrt(xcoord * xcoord + ycoord * ycoord);
if(dr > 0) {
var angle:Number = dr / radius * rotation;
var dx:Number = xcoord * Math.cos(angle) - ycoord * Math.sin(angle) - xcoord;
var dy:Number = xcoord * Math.sin(angle) + ycoord * Math.cos(angle) - ycoord;
var blue:int = 0x80 + Math.round(dx / width * 0xff);
var green:int = 0x80 + Math.round(dy / height * 0xff);
dbmd.setPixel(x, y, green << 8 | blue);
}
}
}
return new DisplacementMapFilter(dbmd,
new Point(0, 0),
BitmapDataChannel.BLUE,
BitmapDataChannel.GREEN,
width,
height,
DisplacementMapFilterMode.IGNORE);
}

/**
* Generate the BitmapData which applied mirror effect.
*
* You can create the mirrored BitmapData is as follows:
*
* var bmd = new BitmapData(video.width, video.height, false);
* bmd.draw(video);
* var mirroredBmd = Effect.mirror(bmd);
*
* @params source BitmapData The input bitmap data to apply the mirror effect.
* @params region Rectangle The region to apply the twirling effect. Default is entire region.
* @return BitmapData BitmapData which applied the mirror effect
*/
static public function mirror(source:BitmapData):BitmapData
{
var bmd:BitmapData = new BitmapData(source.width, source.height, false);
var halfWidth:int = Math.round(source.width / 2);
source.lock();
bmd.copyPixels(source, new Rectangle(0, 0, halfWidth, source.height), new Point(0,0));
for(var i:int=0;i<source.height;++i) {
for(var j:int=0;j<halfWidth;++j) {
bmd.setPixel32(halfWidth + j, i, source.getPixel32(halfWidth - j, i));
}
}
source.unlock();
return bmd;
}

/**
* Generate the DisplacementMapFilterMode for pinch effect.
*
* You can apply the filter is as follows:
*
* var bmd:BitmapData = new BitmapData(width, height, false);
* var filter:DisplacementMapFilter = Effect.pinchFilter(bmd);
* bmd.draw(video);
* bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), filter);
*
* You can also apply the filter specified region:
*
* var region:Rectangle = new Rectangle(100, 100, 100, 100);
* var amount:Number = 0.5;
* var filter:DisplacementMapFilter = Effect.pinchFilter(bmd, rect, amount);
*
* @params source BitmapData The input bitmap data to apply the twirling effect.
* @params region Rectangle The region to apply the twirling effect.
* @params amount Number Amount of pinch. (-1 <= x <= 1)
* Default is 0.35.
*/
static public function pinchFilter(source:BitmapData, region:Rectangle=null,
amount:Number=0.35):DisplacementMapFilter
{
var width:int = source.width;
var height:int = source.height;
region ||= new Rectangle(0, 0, width, height);
var radius:Number = Math.min(region.width, region.height) / 2;
var centerX:int = region.x + region.width / 2;
var centerY:int = region.y + region.height / 2;
var dbmd:BitmapData = new BitmapData(width, height, false, 0x8080);
for(var y:int=0;y<height;++y) {
var ycoord:int = y - centerY;
for(var x:int=0;x<width;++x) {
var xcoord:int = x - centerX;
var d:Number = Math.sqrt(xcoord * xcoord + ycoord * ycoord);
if(d < radius) {
var t:Number = d == 0 ? 0 : Math.pow(Math.sin(Math.PI / 2 * d / radius), -amount);
var dx:Number = xcoord * (t - 1) / width;
var dy:Number = ycoord * (t - 1) / height;
var blue:int = 0x80 + dx * 0xff;
var green:int = 0x80 + dy * 0xff;
dbmd.setPixel(x, y, green << 8 | blue);
}
}
}
return new DisplacementMapFilter(dbmd,
new Point(0, 0),
BitmapDataChannel.BLUE,
BitmapDataChannel.GREEN,
width,
height,
DisplacementMapFilterMode.CLAMP);
}

/**
* Generate the DisplacementMapFilter for photic tunnel effect.
* Photic tunnel effect is as same as effect of Photo Booth application in Mac OS.
*
* You can apply the filter is as follows:
*
* var bmd:BitmapData = new BitmapData(width, height, false);
* var filter:DisplacementMapFilter = Effect.pinchFilter(bmd);
* bmd.draw(video);
* bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), filter);
*
* @params source BitmapData The input bitmap data to apply the twirling effect.
* @params region Rectangle The region to apply the twirling effect.
* @return DisplacementMapFilter Filter to apply photic tunnel effect.
*/
static public function photicTunnelFilter(source:BitmapData, region:Rectangle=null):DisplacementMapFilter
{
var width:int = source.width;
var height:int = source.height;
region ||= new Rectangle(0, 0, width, height);
var centerX:int = region.x + region.width / 2;
var centerY:int = region.y + region.height / 2;
var dbmd:BitmapData = new BitmapData(width, height, false, 0x8080);
var radius:Number = Math.min(region.width, region.height) / 2;
for(var y:int=0;y<height;++y) {
var ycoord:int = y - centerY;
for(var x:int=0;x<width;++x) {
var xcoord:int = x - centerX;
var d:Number = Math.sqrt(xcoord * xcoord + ycoord * ycoord);
if(radius < d) {
var angle:Number = Math.atan2(Math.abs(ycoord), Math.abs(xcoord));
var dx:Number = (xcoord > 0? -1 : 1) * (d - radius) * Math.cos(angle) / width;
var dy:Number = (ycoord > 0? -1 : 1) * (d - radius) * Math.sin(angle) / height;
var blue:int = 0x80 + dx * 0xff;
var green:int = 0x80 + dy * 0xff;
dbmd.setPixel(x, y, green << 8 | blue);
}
}
}
return new DisplacementMapFilter(dbmd,
new Point(0, 0),
BitmapDataChannel.BLUE,
BitmapDataChannel.GREEN,
width,
height,
DisplacementMapFilterMode.CLAMP);
}

/**
* Generate the DisplacementMapFilter for bulge effect.
* Bulge effect is wrapper of pinchFilter method.
*
* @params source BitmapData The input bitmap data to apply the effect.
* @params region Rectangle The region to apply the bulge effect.
* @params amount Number Amount of bulge. (0 <= x <= 1)
* @return DisplacementMapFilter The filter to apply bulge effect.
*/
static public function bulgeFilter(source:BitmapData, region:Rectangle=null,
amount:Number=0.5):DisplacementMapFilter
{
// wrapper method of pinchFilter
return pinchFilter(source, region, Math.min(-amount, -1));
}
/**
* Generate the DisplacementMapFilter for squeeze effect.
* Dent effect is wrapper of pinchFilter method.
*
* @params source BitmapData The input bitmap data to apply the effect.
* @params region Rectangle The region to apply the bulge effect
* @params amount Number Amount of squeeze. (0 <= x <= 1)
*/
static public function squeezeFilter(source:BitmapData, region:Rectangle=null,
amount:Number=0.5):DisplacementMapFilter
{
// wrapper method of bulge filter
return pinchFilter(source, region, amount);
}

/**
* Generate the DisplacementMapFilter for fisheye effect.
*
* @params source BitmapData The input bitmap data to apply the twirling effect.
* @params amount Number Amount of fisheye (0 <= x <= 1)
* @return DisplacementMapFilter The filter to apply the fisheye effect.
*/
static public function fisheyeFilter(source:BitmapData, amount:Number=0.8):DisplacementMapFilter
{
var width:int = source.width;
var height:int = source.height;
var dbmd:BitmapData = new BitmapData(width, height, false, 0x8080);
var centerX:int = width / 2;
var centerY:int = height / 2;
var radius:Number = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
for(var y:int=0;y<height;++y) {
var ycoord:int = y - centerY;
for(var x:int=0;x<width;++x) {
var xcoord:int = x - centerX;
var d:Number = Math.sqrt(xcoord * xcoord + ycoord * ycoord);
if(d < radius) {
var t:Number = d == 0 ? 0 : Math.pow(Math.sin(Math.PI / 2 * d / radius), amount);
var dx:Number = xcoord * (t - 1) / width;
var dy:Number = ycoord * (t - 1) / height;
var blue:int = 0x80 + dx * 0xff;
var green:int = 0x80 + dy * 0xff;
dbmd.setPixel(x, y, green << 8 | blue);
}
}
}
return new DisplacementMapFilter(dbmd,
new Point(0, 0),
BitmapDataChannel.BLUE,
BitmapDataChannel.GREEN,
width,
height,
DisplacementMapFilterMode.CLAMP);
}

/**
* Generate the DisplacementMapFilter for strech effect.
*
* @params source BitmapData The input bitmap data to apply the twirling effect.
* @params amount Number Amount of strech (0 <= x <= 1), default is 0.6;
* @return DisplacementMapFilter The filter to apply the strech effect.
*/
static public function strechFilter(source:BitmapData, amount:Number=0.6):DisplacementMapFilter
{
var width:int = source.width;
var height:int = source.height;
var dbmd:BitmapData = new BitmapData(width, height, false, 0x8080);
var centerX:int = width / 2;
var centerY:int = height / 2;
var vregion:Rectangle = new Rectangle(0, 0 , width / 3, height);
var hregion:Rectangle = new Rectangle(0, 0, width, height / 3);
var blue:int;
var green:int;
for(var y:int=0;y<height;++y) {
var ycoord:int = y - centerY;
for(var x:int=0;x<width;++x) {
var xcoord:int = x - centerX;
var dx:int = (Math.abs(xcoord) < vregion.width)?
xcoord * (Math.pow(Math.abs(xcoord) / vregion.width, amount) - 1) : 0x0;
var dy:int = (Math.abs(ycoord) < hregion.height)?
ycoord * (Math.pow(Math.abs(ycoord) / hregion.height, amount) - 1) : 0x0;
blue = 0x80 + 0xff * dx / width;
green = 0x80 + 0xff * dy / height;
dbmd.setPixel(x, y, green << 8 | blue);
}
}
return new DisplacementMapFilter(dbmd,
new Point(0, 0),
BitmapDataChannel.BLUE,
BitmapDataChannel.GREEN,
width,
height,
DisplacementMapFilterMode.CLAMP);
}
}
}



TODO
Dent Filter(Photoshopのフィルタ -> 球面でマイナス指定と同じ)が正しくないのに気づかれたかもしれません。屈折率や曲座標の式などを使えばできると思うのですが、数式モデルがまだわかっていません。as3filtersにコミッタとして参加してもらえるか、数式を教えてください。

Saturday, February 16, 2008

Mobile on Railsのレポジトリ移行とコミッタの募集

ちょうど一年程前に作成したMobile on Railsですが、レポジトリをRuby Forgeに移行しました。
コメント欄にてフィードバックを頂いていたのですがBloggerの通知機能が機能しておらず、気づきませんでした。
申し訳ないです。

現状携帯開発から離れていて、メンテナンスができていない状態なのでバグや不具合などが存在しており、使用されている皆様の手元でパッチをあてるなりして使用されている事と思います。これらのノウハウを共有しないのは、携帯サイトの開発をする開発者の開発効率を下げる事になります。

Ruby Forgeに移したので、コミッタとして参加お願いします。
Ruby Forgeにてアカウントを作成し、rakuto at gmailまでアカウント名をお伝えください。

http://rubyforge.org/projects/mor/
http://mor.rubyforge.org/svn/trunk/

絵文字変換を全てRubyで書いているのでパフォーマンスが気になっています。キャリア毎のテンプレートキャッシュの仕組みをコミットしてくれる方がいたら嬉しいな。

参考
http://d.hatena.ne.jp/hardcore100/20080212#c

Friday, February 15, 2008

as3filters: Variety of filters for image processing

I think DisplacementMapFilter is pretty cool, but this is a little difficult. So I have created pack of DisplacementMapFilter for variety of effects. We'd like to use DisplacementMapFilter easily to apply interesting effects to the image. If you have interesting idea or skill, please e-mail to rakuto@gmail.com.

as3filters



I have created Demo application for as3filters. If you are Mac OSX user then you know Photo Booth application, don't you? Photo Booth is simple application to take picture and apply some effects. This one is pretty simple, but intrestin. So I created application with Flash like Photo Booth.

as3filters - Photo Booth Demo




You need to enable the web camera to run the demo. If you don't have web camera then see snapshot.
Snapshot of Photo Booth DEMO

Install
Please see as3filters for details.

% svn checkout http://as3filters.googlecode.com/svn/trunk/ as3filters
% cp as3filters/bin/as3filters.swc /path/to/your-project
% mxmlc -compiler.include-libraries as3filters.swc


How to apply the filters

var bmd:BitmapData = new BitmapData(width, height, true);
var region:Rectangle = new Rectangle(30, 30, 90, 90)
var twirlFilter:DisplacementMapFilter = Filter.twirlFilter(bmd, region);
bmd.draw(video);
bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), twirlFilter);


What kinds of filter can I apply?
Currently, there are few filters. We'd like to contribute the as3filters project.
  • Twirl
  • Pinch
  • Fisheye
  • Mirror
  • Photic tunnel
  • Bulge
  • Squeeze
  • Strech


TOOD
Maybe you found dent filter is invalid. I don't know SphereFilter alogorithm. Someone tell me SphereFilter algorithm please.

Thursday, February 07, 2008

OpendID 2.0 でのdelegateの指定

OpenID 2.xでは、delegationの指定方法が変更されています。

OpenID Authentication 2.0 - Final

A LINK element MUST be included with attributes "rel" set to "openid2.provider" and "href" set to an OP Endpoint URL

A LINK element MAY be included with attributes "rel" set to "openid2.local_id" and "href" set to the end user's OP-Local Identifier



<link rel="openid2.provider" href="http://www.myopenid.com/server"/>
<link rel="openid2.local_id" href="http://rakuto.myopenid.com/"/>


それぞれ、OpenID 1.xのopenid.serverにopenid2.providerが対応、opeid.delegateにopenid2.local_idに対応しています。こちらを指定しない際は、OpenID1.xが使用される事になります。後方互換性があるはずなのですが、ruby-openid2.0.3では、上記のように指定しないと、ログインは成功するが、nickname, emailといったフィールドが返されませんでした。ruby-openidでログインできない際は、試してみて下さい。

restful_open_id_authenticationは、OpenID1.xの対応から開発が止まっているので、2.x対応版はこちらからインストールできます。
s21g::Hello, world! - restful_open_id_authentication_redux

Friday, February 01, 2008

[DEMO 08] 脳にアクセスする近未来のハイテクおしゃぶり

DEMO 08 Panel: Research and Technology in Life, on the Web



DEMO 08のレポートを読んでいると、初日に開催された二つのセッションのレポートがあったのだが、その一つThe University of KansasのDr. Steven M. Barlow, Professorによる研究発表のセッションが非常に興味深い。

乳児は、欲求を伝えるために「泣く」事しかできない。何をしても泣き止まないため、子供の口を押さえつけたり、時には鬱病になり心中まで考える母親もいると聞く。おなかがすいたから、病気で苦しいからか、もしくはキングコング西野さんのライブがつまらないから泣いているのか、人間は知る術を持たない。

カンザス大学のSpeech-Language-Hearing研究室から発表されたのは、おしゃぶり型のデバイスを通して乳児の脳に働きかける事ができるものだ。このデバイスの可能性として、未熟児で生まれてきた乳児の脳の発達障害や、呼吸する/ミルクを飲み込むといった生きる上で必要な脳の発達を改善する助けをしてくれる。

The Actifier: "high-tech silicon pacifier"として紹介されているおしゃぶり型デバイス


ビデオ中で実験に参加した女性は、自然で快適で、ふつうのおしゃぶりと同じ感覚だったと語っているが、どうみても普通のおしゃぶりのサイズではない。とても違和感がある。実は、このおしゃぶりは乳児の口内の状態をリアルタイムで解析する高性能なコンピュータへと接続されている。

The instrument consists of a pacifier attached to a frame about the size of an infant's shoebox. The wiring in the frame connects to a high-speed computer that gives real-time analysis of the baby's oral motor skills.


このおしゃぶりは、乳児の靴箱程の大きさのフレームからなる。フレームは、ハイスピードなコンピューターに接続され、リアルタイムで乳児の口腔運動を解析する。



一番肝心な所だが、どうしてこのおしゃぶりを通して乳児の脳の状態を知れるのだろうか?

"Those muscles have direct connections to the brain stem, which has connections to higher structures, like the cerebral hemisphere,"

乳児の口角筋は脳幹への直接のコネクションを持つ。と博士は語る。

The Actifier(ハイテクシリコンおしゃぶり)の先に接続された、乳児の脳の状態をリアルタイムで解析するコンピューターがおそらくNTrainer Systemである。


When a pre-term infant is born, most of you know that it needs a lot of support in an incubator in order to finish developing outside the womb. As the machines used to support the pre-term infant do a good amount of the work for that infant, certain stimuli is lacking in the pre-term infant’s brain that would otherwise trigger development for necessities like learning how to suck (a feeding basic for infants). Technology working directly with the brain.


未熟児が生まれた際には、よく知られている通り、子宮の外で発達するために多くの支援が必要となる。このデバイスを使用する事で、乳児のために必要になる多くの仕事を支援する事ができるようになる。未熟児は、どのように(おっぱいを)吸えばよいかといった生きていく上で必要となる、特定の刺激が欠落している。テクノロジーは直接私達の脳に働きかけている。

ニューラルインタフェースの話は、人類に希望をもたらすだろう。この例では未熟児や乳児を持つ母親にとって明るいニュースであると思うし、目の見えない人、耳が聞こえない人に、インプラント型でバイスで電気信号を送る事で、"見えていると脳に思わせる"実験も成功している。ただし、人間は欠如している物を補うためではなく、自分の能力を増大させるためにテクノロジーに依存したいという欲求に打ち勝つ事ができなくなるだろう。ステロイド等と同様に能力増大のためにテクノロジーを利用する事は、法律で禁止されるだろうが、どこまでが欠如を補う物で、どこからが能力増強かと判断を下す事はとても難しい。

ニューラルインタフェースは、脳に電気信号を送る事で見えない物を見えているように感じたり、聞こえないものを聞こえているように感じる事ができるが、複合現実感(Mixed Reality, MR)も同様の問題を抱えていると思う。ニューラルインタフェースと同様に、MRも最初は多くの人間が抵抗を示すだろうが、ブレイクスルーを超えれば、普及は加速度的に進む。なぜなら、MRの世界にいない自分だけが、周囲の人間にくらべて損をするからだ。こうなると、MRの世界にいない事は、疎外感を生む。恐ろしいのは、現実と仮想の世界の区別がつかなくなる事である。仮想の世界では、自分の思うように生きる事ができ、自分のやりたいように振る舞う事ができる。そうなった時、脳は現実感を失ってしまうだろう。

これらのテクノロジーが多くの人に希望をもたらす事も事実。

参考