輪郭線ウェブ (2)
もうすでにこのままじゃ使えねえと気づいてしまったが、やっておきたいことがあるので続ける。
大まかな構想
- 画像をアップロード
- パラメータとサムネが表示される
- パラメータを変えるとサムネがリアルタイムで変わる
- サムネをクリックすると元サイズを同じ大きさの画像が表示される
- ダウンロードクリックするとダウンロードされる (これは微妙)
アップロードはajax(YUI)で行い、サーバはアップロードの結果として画像サイズとMD5値を返す。サーバではアップロード時点で設定可能なすべてのパラメータ分の画像を作る(5つ+5つ分のサムネ)。ページでユーザがパラメータが変えるとパラメータに対応するサムネを表示するように書き換える。サムネは5つ分のサムネを1列に結合した画像にして、パラメータ変更によるサーバへの問い合わせを行わないようにする(CSSを変えるだけにする)。画像がクリックされたときはパラメータに対応する画像を表示するようにimgタグを作成する。このとき、先にファイルがあるかをXHRで確認する。ファイルがなかった場合は再度アップロードしてから表示する。サーバ側では作成されて一定時間を超えた画像を削除するため、このチェック処理が必要になる。
今のところこんな感じ。
今日やったこと(夕方〜)
int weg_main(const char *filename, const char *dirname);
というCの関数を作った。400行くらい。filenameに画像を指定すると、dirnameディレクトリにすべてのパラメータに対応する画像とサムネを作成する。これをXSでラップして、CGIから呼び出す。普通サイズだと0.3秒くらい、超巨大サイズだと12秒くらいかかる。超巨大サイズはハジクようにする。
やったこととハマったこと
OpenCVで1ビットグレースケールのPNGが作成できないから作った
入出力で8bitに変換されていた。
作成する画像数が多いので、せめて画像のサイズをおさえたい。輪郭線画像は、白と黒の2色しかないので、1bit grayscale(black & white) PNGにするとファイルサイズが小さくなる。
しかたがないので、libpngを使って、OpenCVのIplImage型を1bit grayscale PNGで保存する関数を書いた。
PNGの圧縮モードに迷ったけどデフォルトにした
libpngはzlibを使っていて、Z_BEST_COMPRESSIONなどの圧縮モードが指定できる。画像サイズを小さくしたいので、Z_BEST_COMPRESSIONにしていたが、これがZ_DEFAULT_COMPRESSIONの2倍くらい遅くて、ファイルサイズはそんなに変わらないようだったので、Z_DEFAULT_COMPRESSIONにした。
並列化並列化
- 一度に6枚の画像を作る
- C2D
- 並列化!
という安直な考えのもと並列化。まずgcc 4.2をホームディレクトリに入れてOpenMPを使おうと思ったけど、挫折*1。pthreadを使って自分で書く。各画像をワーカースレッドで作ることで複数のCPUを使えることを期待する程度の処理を入れる。
pthreadとallocaの組み合わせでスタックオーバーフロー
大き目の画像を変換すると落ちた。もとはスレッドにすることを考えていなかったので、PNGを作成するときのバッファ確保にallocaを使っていて、pthreadのデフォルトのスタックサイズが1MBしかないので*2、1MB/sizeof(png_byte)以上の大きさの画像を出力しようとするとスタックオーバーフローしていた。
pthread_attrでスタックサイズを変えるか、allocaをmallocに変えるか迷ったけど、そもそもfreeするのがメンドイという理由だけでallocaだったので、同じようにpthread_attr_initとかpthread_attr_setstacksizeとかメンドイという理由で、mallocに変えた。なんてテキトウなんだ。
さくらインターネットのFreeBSDはSMPカーネルじゃない
% sysctl hw.model hw.model: Intel(R) Core(TM)2 CPU T7200 @ 2.00GHz % sysctl kern.smp kern.smp.cpus: 1 kern.smp.disabled: 0 kern.smp.active: 0 kern.smp.maxcpus: 1
/(^o^)\ナンテコッタ
CPUが1つしか見えていないので、計算は並列になんか動かないことが発覚。
ファイルIOとかはそんなに時間かかってないし、画像の変換とPNGデータの作成が遅いので、もうどうしようもない。
いまここ
秋田寝る。
*1:サーバとコーディングというかすべてはさくらインターネット(レンサバスタンダード)で行っている
*2:環境による