写真を美人化するブックマークレット
お手軽な美人フィルタ
私の勤める会社で今度ちょっとした発表をするのですが、久々にHTMLを題材にすることにしました。
昔から美人フィルタとかそういったものがありましたが、これをサーバや専用ソフトなしでHTML5のcanvasとJavaScriptを使って実現しようという話。さらにカンタンに誰でも使えるようにブックマークレットにしてしまいます。お手軽ですね!
画像はモデルピースさんで配布されているフリー素材です。藤浦真菜さんという方の写真をトリミング、サイズ縮小させていただいています。
そして本題のブックマークレット
ブックマークレットは以下の通りです。なお、FirefoxとChromeとSafari(全てWindowsで最新版)では動くのを確認しました。AndroidでもOK(マウスでなぞるのはできませんが。)。
javascript:(function(){var%20FACTOR=0.8;function%20filter(org_img){var%20canvas=document.createElement('canvas');var%20context=canvas.getContext('2d');var%20_canvasW=org_img.naturalWidth;var%20_canvasH=org_img.naturalHeight;canvas.width=_canvasW;canvas.height=_canvasH;var%20imgObj=new%20Image(_canvasW,_canvasH);imgObj.src=org_img.src;context.drawImage(imgObj,0,0);var%20newImage=new%20Array(_canvasW*_canvasH*3);for(var%20y=0;y%20<%20_canvasH-1;y++){for(var%20x=0;x%20<%20_canvasW-1;x++){var%20pixelData1=getPixel(canvas,x,y,_canvasW,_canvasH);var%20pixelData2=getPixel(canvas,x+1,y,_canvasW,_canvasH);var%20pixelData3=getPixel(canvas,x,y+1,_canvasW,_canvasH);%20R=Math.abs(pixelData1.R%20-%20pixelData2.R)%20+%20Math.abs(pixelData1.R%20-%20pixelData3.R);var%20G=Math.abs(pixelData1.G%20-%20pixelData2.G)%20+%20Math.abs(pixelData1.G%20-%20pixelData3.G);var%20B=Math.abs(pixelData1.B%20-%20pixelData2.B)%20+%20Math.abs(pixelData1.B%20-%20pixelData3.B);setPixel(canvas,x,y,pixelData1.R-FACTOR*R,pixelData1.G-FACTOR*G,pixelData1.B-FACTOR*B,255,_canvasW,_canvasH);}}if(org_img.parentNode){org_img.parentNode.replaceChild(canvas,org_img);}else{org_img.appendChild(canvas);alert('not_replace');}}function%20getPixel(srcCanvas,x,y,canvasW,canvasH){var%20imagePixelData=srcCanvas.getContext('2d').getImageData(x,y,1,1).data;var%20R=imagePixelData[0];var%20G=imagePixelData[1];var%20B=imagePixelData[2];return%20{R:R,G:G,B:B};}function%20setPixel(srcCanvas,x,y,R,G,B,A,canvasW,canvasH){var%20context=srcCanvas.getContext('2d');var%20pixelImage=context.createImageData(1,1);pixelImage.data[0]=R;pixelImage.data[1]=G;pixelImage.data[2]=B;pixelImage.data[3]=A;context.putImageData(pixelImage,x,y);}var%20imgs=document.getElementsByTagName('img');for(var%20i%20in%20imgs){if(imgs[i].src==null){continue;}imgs[i].addEventListener('mouseover',function(ev){filter(ev.target)},false);}})();
長いですね。読む気にならないので解説もなしにしましょう。
使い方
使い方は、外部サイト http://atzy.info/bookmarklet.htmlにも書いておきましたが、簡単です。
ブックマークレットを保存したら、変換したい画像のあるページに行ってブックマークレットを選択します。
そして「えい!」と声をかけながら魔法をかける要領で画像をなぞります*1。そして数秒(画像サイズやPCのパワーによります)待ちますと画像が美人化します。
ただ、たとえばはてなのように、画像とページが同じドメインにない場合にはこの魔法がうまくかかりません。大人の言葉でいうとセキュリティに引っかかってしまいます。
しかし、その場合は、画像を右クリックで選択して、画像のみを表示したうえでブックマークレットを実行すればよいのです。
その他
- 変換後画像は保存も可能
- 画像が小さすぎると、けばけばしくなります
- 画像が大きすぎると、あまり変わり映えしません
- さて、こんなのが発表内容でいいのだろうか?
*1:ほんとはマウスなしで自動でやってもいいんですが、このマウスの「えい!」が少し気持ちいいのです。
そろそろPerl4に関して一言いっとくか(クラシカルPerl入門)
仕事でPerlを使うことになり、先週から久々に(本格的に)使ってみました。大体プログラミング言語なんてものは特殊なやつを除けばどれも根本は同じなので、それ自体で詰まるということはありません。
が、10数年ぶりのPerlを使いながら、懐かしいことを思い出してみました。思えば遠くへ来たものだ。
my!our!
Perl4では、my*1だとかありませんし、our*2ももちろんありません。
当然ながら、localを使います。
myはまさにレキシカルスコープ、ourはパッケージローカルな変数となります。で、Perl4に存在した(というか、今も存在しますが)localというのは、特殊なグローバル変数。その時点でグローバル変数の値を置き換えてしまい、ブロックを出た後でグローバル変数の値を戻します。つまり、以下では、test2()の中で$aが10ではなく1なのですね。myによる宣言とは意味が異なります。
$a = 10; sub test { local $a = 1; test2(); } sub test2 { print $a; # 10 or 1? }
なお、localを使う意味はほぼ既にありません。
型グロブ
Perlにはグロブというものが二種類あり、一つがファイル名グロブ*3で、もう一つが型グロブです。
型グロブというのは、普通に生きている我々は使わないのですが、特殊な用途で利用します。Perlで使う変数やサブルーチンなどは総称して「シンボル」と呼ばれますが、この「シンボル」を統合して使うのが型グロブです。
何を言っているのかわからないかもしれませんが、簡単に言えば、$a、@a、%a、&aといったものを統合して*aとして指す機能が型グロブです。
それで何ができるのかといえば大したことができるわけではないのですが、Perl4ではたまに用途がありました。その一つが「ファイルハンドルの変数化」です。
ファイルハンドルは、何も考えずに使うとグローバルとなります。
open(FILE, "file.txt"); # このFILEはプログラム全体で参照可能。
これが非常にうざいわけです。例えばローカル化したり、サブルーチンの引数に渡したりしたいわけです。
しかし、このFILEは変数ではありません。
しかし、型グロブ*FILEを使うと、このFILEというファイルハンドルを変数のように使うことができます。
local *FILE; # FILEを局所化 open(FILE, "file.txt"); sub test{ local(*FILE) = shift; # 変数のように使える。 while(<FILE>){ print; } }
なお、仮に$FILEとか@FILEといったものが別個に存在した場合、*FILEによって巻き添えにされますのでご注意。
今なら、ファイルハンドルはモジュール経由で扱うことができます。
フォーマット文
Perl4でどうのという話ではありませんが、昨今のPerlであまり見かけない機能。確か昔は「はじめてのPerl」でも紹介されていた機能です。
$name = "Yamada"; $age = 30; write REPORT; format REPORT |@<<<<<<<<< | @>>| $name, $age .
これによって、上で言えば$nameと$ageの内容を|Yamada | 30| のように整形して出力することができます。
なぜ使われないかといえば、formatで参照される変数は、グローバルである必要があるため。(ourやらlocalならば可ですが、myだとダメですね。)なお、formlineって機能がありますが、これも使われているのを見たことないですね。
dbmopen
最近は、ファイルDB(BarkleyDBなど)を直接に扱うことも少ないのかもしれません。が、tie*4を使って、DBとハッシュを結びつけるという手法があります。
ですが、Perl4ではdbmopen()を使います。はじめてのPerlでも使ってましたね。
dbmopen(%MYDB,'dir/dbfile',0666);
こうやって、DBに結びつけたハッシュを使います。ちなみに、閉じるときはdbmclose()があります。
今では使う意味がありません。
シンボリックリファレンス
リファレンスを使うのはPerl5では当然。しかしPerl4にはそのようなしゃれたものはありませんでした。
しかし、こんなことはできます。
$a = "abc"; $abc = "xyz"; print ${$a}; # これが print $abc; として働く
これがシンボリックリファレンス、あるいはソフトリファレンスです。皆様がPerl5で使っているものがハードリファレンス。
既に、使う意味は全くないといえるでしょう。use strict;すると使えませんし。
ハードリファレンスがないということは、矢印演算子もありません。
chop
chomp() によって、行末改行文字を切り取るのはよく使う機能の一つですが、これもPerl5から。Perl4ではchop()を使って、行末の1文字を切り取ります。
map
Perl4にはmap関数もありませんでした…。ですので、配列の置き換えはforeachなどを使っていました。
モジュール
そもそもモジュール自体ありませんでした。ですので、useすることもありません。requireによって他のコードを取り込むことはできました。
CPANからモジュールを引っ張ってきて簡単に機能が増やせるようになったのもPerl5のおかげ。
論理演算子
「かつ」や「または」といったものに、and/or/notを使えるのもPerl5から。Perl4では&&と||と!です。
とはいえ、Perl5でPerl4風の書き方が使われなくなったわけではありません。andと&&は結合の強さが違うので注意(他も同様)。
repcachedのmemcached 1.4対応
mdounin(Maxim Dounin)さんが開発しているmemcached、あるいはrepcachedのforkがあるのですが、そこではrepcachedがmemcached 1.4.5に対応しています。
https://github.com/mdounin/memcached/tree/repcached
KLabで開発されていたrepcached(2.2まであります)は、memcached 1.2.8までの対応ですので、モダンなmemcached 1.4系を使うことができなかったわけですが、このmdounin版を使えばレプリ機能を使いつつ、memcached 1.4を使うことができるわけです。(ただ、おそらくマルチスレッドは無効化される。)
mdounin版の最新のものはrepcached 2.3と称していますが、あくまでブランチコードと思われます。なお、この最新版は、repcachedの問題であるところの「CPU使用率100%問題」の修正も入っています。
https://github.com/mdounin/memcached/commit/90ae0dfb122d4a13e3350eb6efd315f431e96772
これを見ると、一時的なネットワーク問題が起きた際の挙動が怪しいのを修正したとか何とか。
テストコードを見ると、以下のようなことをやっています。
- ノードBのみ一時停止(suspend)
- ノードAに大量更新
- ノードAを一時停止・ノードBを再開
- ノードBに大量更新
- ノードAを再開
- 1秒sleep
- ノードAからget、ノードBからget
ちょっと試した感じでは、レプリ先プロセスを止めて(ポートは開いたまま)大量の更新を走らせると、CPU使用率が100%になるような…。これが起きなくなるようです。
mixi API for PC
眠れなかったので、mixiアプリの作り方を読んでみた。
実際、そんなに難しくないですね。
儲けるのは難しそうですが、ちょっとしたものを作るくらいなら敷居は低そう。
プログラムはほとんどJavaScriptで書けばいいのかな。通信するサーバを作るならば、そこは好きな言語で書けばいいけど、それをするとサーバ管理も面倒だな。データ永続化機能もあるようだから、そっちに全部入れてJavaScriptだけで突っ走るのもありだね。
「ATOKダイレクト プラグイン開発グループ」ができてる
お、はてなにこんなのができている。
ATOKダイレクト プラグイン開発グループ
最近、あまり使ってなかったけど、またやってみようかな。