2011/07/27


Emacsはインライン画像も表示出来て、ブラウザにもなって、vimでは到底真似出来ない芸当が出来るの事は、vimmerであれば皆知ってる事だとは思うんだけど...
昨日こんな動画があることを教えて貰った。
GVimでとある科学の超電磁砲OP「only my railgun」‐ニコニコ動画(9)

たくさんプログラミングしてった。ちょっと疲れた。ちなみに、これはリアルタイムのレンダリングではない。私自分のパソコンには2fpsぐらいです。64色でお楽しみ。感想はこちら(中国語だが):http://www.fancymouse.net/blog/2009/12/20/gvim_railgun_op/

http://www.nicovideo.jp/watch/sm9143016
「えっ?どうやってるの?」って思われた方もいるかもしれない。
実はコラでもなんでもない。Vimで出来る(正しくはGVim)。Vimは画像を表示する事は出来ないが、シンタックスハイライトにかけては他のエディタと比べ物にならないくらい優秀だ。XPM画像ファイル(X Pixmap)はASCIIだけで書かれたC言語のヘッダファイルなのだが、先頭に色定義、後続にその定義を使ったデータ部となっている為、VimではXPM画像ファイルを開くとさも画像ファイルであるかの様に見える。もちろんフォントの大きさが1ドットになるので若干縦長にはなる。
gvim-xpm
この仕組みを使えば、Vimで動画が再生出来る。もちろん↑の動画作者も言ってる通り、リアルタイムじゃないのであしからず。なおこの手順は↑の動画を見てmattnが勝手に推測した方法なので若干手法が違うかもしれない。

まず、動画を再生しそれを連番画像ファイルとして出力する。ここではmplayerを使うと楽。
# mplayer /home/mattn/動画/仮面ライダーディケイド変身.avi -vo jpeg
放っておくとどこまでもjpeg画像を出力しまくるので適度に止める。
次にこのjpegファイル群をxpm画像ファイルへ変換する。こんな場合はシェルスクリプトにお任せ。
mkdir out
/bin/ls *.jpg |\
while read -r line; do
    FNAME=`basename $line .jpg`
    convert $line -resize 150x100 out/$FNAME.xpm ;
done
convertはImageMagickに付属されている。
さて、outディレクトリにxpmファイル群が出力されたので、一枚適当に開いて最下行までを表示した時に全てのドットが収まる様に、フォントとウィンドウ幅を調整する。フォントが小さすぎてウィンドウ幅が分からないのであれば、「:new」して無名バッファを作り、挿入モードで「<c-r>=&columns . " " . &lines . " " . &guifont」と入力してどこかに保存してしまえばいい。
表示しきったらこれをGVimの枠付きでキャプチャを取る訳だが、数十枚ある画像を手作業ではやってられない。ここも自動化する。
以下のvimスクリプトを書いた。
set guifont=Symbol\ 1
set columns=300
set lines=90
unlet! images
let images = split(globpath(".", "*.xpm"), "\n")
for image in images
  exe "e ".image
  normal! G
  redraw
  silent! exec "!scrot -u"
  bw!
endfor
なるべく正方形に近いフォントを選んだつもり。scrotはスクリーンキャプチャで、何時も愛用している物。デスクトップ全体とかエコじゃない事はしたくないので「-u」オプションを付けて、フォーカスのあるウィンドウだけキャプチャを取った。
これを実行すれば、現在のフォルダからxpmファイル群を一つずつ開き、最下行に移動し、画面更新後にキャプチャを取得、バッファを終了、という動きになる。ちなみに今回の例だと、1画像を表示仕切るのに4秒程度かかったので、合計すると数十分掛かった。

さて、これでscrotが生成したキャプチャが出来上がるので、合成する。こんな場合はmencoderが役に立つ。
mencoder mf://*scrot.png -mf w=320:h=335:fps=5:type=png -ovc copy -o output.avi
一瞬にしてoutput.aviが生成された。
fpsは適度に調整が必要。

それでは出来上がった物を...

続きを読む...

Posted at by



2011/07/20


なんだか楽しそう。
Amon2::Liteでmarkdownその他のリアルタイムプレビュー - すぎゃーんメモ

Amon2::Liteでmarkdownその他のリアルタイムプレビュー Perl Amon2::Lite というモジュールを Amon2 に添付してみました。 - TokuLog 改メ tokuhir...

http://d.hatena.ne.jp/sugyan/20110720/1311146296
こういうの皆で共有したいよねと思ったので最近話題のPaaS、fluxflexにデプロイしてみた。
fluxflex

Easy One-Click Install for Web Applications You can install various OSS in a second just with one-cl...

http://www.fluxflex.com
http://text-converter.fluxflex.com
ちょっとハマった点が、fluxflexにはcpanm等による自動インストール機能が無い事。自前でextlibみたいなのに放り込めばいいんだけど、これがなかなか面倒くさい。適当なcgiを書いてどのモジュールの読み込みで失敗しているか調べた結果でいろいろ添付してます。
正直、要らない物もあがってるかもしれません。
とりあえず動いたので、負荷かけない程度に遊んで下さい。

一応CGIのコード貼っておきます。
#!/usr/bin/perl
use strict;
use warnings;

use lib qw( ../lib );
use Amon2::Lite;
use Encode 'encode_utf8';
use Text::Markdown 'markdown';
use Text::Xatena;
use Pod::Simple::XHTML;
use Plack::Handler::CGI;

$ENV{REQUEST_METHOD} ||= 'GET';
$ENV{SCRIPT_NAME} ||= $0;
$ENV{PATH_INFO} ||= '/';

my $converters = {
    markdown => sub {
        my $text = shift;
        return markdown($text);
    },
    xatena => sub {
        my $text = shift;
        return Text::Xatena->new->format($text);
    },
    pod => sub {
        my $text = shift;
        my $parser = Pod::Simple::XHTML->new;
        $parser->html_header('');
        $parser->html_footer('');
        $parser->output_string(\my $html);
        $parser->parse_string_document($text);
        return $html;
    },
};

get '/' => sub {
    my ($c) = @_;
    return $c->render('index.tt');
};

post '/preview' => sub {
    my ($c) = @_;
    my $converter = $converters->{$c->req->param('format')};
    my $html = $converter ? $converter->($c->req->param('text')) : '';
    return $c->create_response(200, ['Content-Type' => 'text/plain'], [encode_utf8($html)]);
};

Plack::Handler::CGI->new->run(__PACKAGE__->to_app);
あと、頭の方でやってるENVの初期値設定は、これが無いとエラーで動かなかった為。この辺は後でフィードバックしておきます。
dotcloudの時もそうでしたが、__DATA_トークンにあったテンプレートはtmpl/index.ttに配置して動作させています。

おまけで、Text::Xatenaの出力を少し変えて(codeというclass属性をprettyprintに変更)、google code prettifyによる色付け機能を足してあります。
#ちょさん!変更出来る様にして下さい!

SuprePre記法で遊んで下さい!
Posted at by



2011/07/19


なんか呼ばれたけど、勉強しとかなくちゃ答えるにも答えれないだろうなと思ったので、ちょっとくらいは勉強しておこうとAmon2でgyazoを書いてdotcloudにpushしてみた。
まず # amon2-setup.pl --flavor=Lite Gyazo
として雛形を作る。
POSTハンドラを書く。
post '/' => sub {
    my $c = shift;
    my $imagedata = $c->req->param('imagedata');
    $imagedata = read_file($c->req->uploads->{imagedata}->pathbinmode => ':raw'unless $imagedata;
    my $filename = "image/" . md5_hex($imagedata) . ".png";
    write_file($filename, {binmode => ':raw'}, $imagedata);
    my $url = $c->req->base() . $filename;
    return $c->create_response(200, ['Content-Type' => 'text/plain'], [$url]);
};
セッション使わないのでプラグイン読み込み処理をカットして、Plack::Middleware::Staticでimageディレクトリを見える様にした。あとdotcloudで動かす為に__DATA__トークンに書かれているindex.ttをtmpl/index.ttに移した。
app.psgiの全体コードはこんな感じ。
use strict;
use warnings;
use File::Spec;
use File::Basename;
use File::Slurp;
use Digest::MD5 qw( md5_hex );
use lib File::Spec->catdir(dirname(__FILE__), 'extlib''lib''perl5');
use lib File::Spec->catdir(dirname(__FILE__), 'lib');
use Plack::Builder;
use Amon2::Lite;

# put your configuration here
sub config {
    +{
    }
}

get '/' => sub {
    my $c = shift;
    return $c->render('index.tt');
};

post '/' => sub {
    my $c = shift;
    my $imagedata = $c->req->param('imagedata');
    $imagedata = read_file($c->req->uploads->{imagedata}->pathbinmode => ':raw'unless $imagedata;
    my $filename = "image/" . md5_hex($imagedata) . ".png";
    write_file($filename, {binmode => ':raw'}, $imagedata);
    my $url = $c->req->base() . $filename;
    return $c->create_response(200, ['Content-Type' => 'text/plain'], [$url]);
};

# for your security
__PACKAGE__->add_trigger(
    AFTER_DISPATCH => sub {
        my ( $c$res ) = @_;
        $res->header'X-Content-Type-Options' => 'nosniff' );
    },
);

builder {
    enable 'Plack::Middleware::Static',
        path => qr{^(?:/static/|/robot\.txt$|/favicon.ico$|/image/)},
        root => File::Spec->catdir(dirname(__FILE__));
    enable 'Plack::Middleware::ReverseProxy';

    __PACKAGE__->to_app();
};
最後にdotcloud.ymlに www:
    type: perl
    requirements:
        File::Slurp
        Digest::MD5
        Amon2
を書いてgitでcommitした後に # dotcloud push mattn すれば、あとはdotcloudが自動で依存物をワンサカワンサカ入れてくれて、動くようになる。(mattnというのはdotcloud createで作った際のapplication。上記wwwはservice)
できあがったサーバはこれ

なんか知らない間にhttp://gyazo.mattn.dotcloud.comみたいなURLで公開出来なくなっちゃったので、ひとまず我慢します。

最後に一言

それAmon2じゃなくてもおk
Posted at by