Ktouth Brand. on Web

け〜くんこと K.Ktouth のだらだらした日常と突発的に作るプログラムや読み物とかの雑多サイト



[2007年04月06日]

画像処理ライブラリ

2007年04月07日 09:49更新 筆者:K.Ktouth

相変わらず風邪気味。調子悪い。
つーか、仕事中ずっと両膝が痛くて力が入れにくかった。これって風邪の初期症状よね……長引きそうだったので明日あるらしい会社の花見の席は断ってみたかなし
こういうときに……俺ってタイミング悪い orz

で、現在写真投稿まわりの実装を進めているわけですが、ImageScienceというRubyライブラリが最近話題になっていたので、サムネイル作成にこれを使ってみようとインストールをしてみました。
ローカルでは特に問題なく動作したのですが……問題はさくらサーバの方。

まず、前提ライブラリである「FreeImage」ですが、root権限でのインストールしか考慮してないため、コンパイル成功後のインストールに失敗します。
まぁ、必要ファイル自体は多くないので、手作業でホームディレクトリ以下の各ディレクトリ($HOME/lib $HOME/include)にコピーして完了。

もう一つの前提ライブラリ「RubyInline」と「ImageScience」はgem形式なので素直に「gem install -r image_science」と入力すればOK。
もちろん、事前にrubygemのセットアップと、ホームフォルダ以下へのインストールはすんでるし、GEM_HOME環境変数も設定済み。

で、これで使用可能になるか……と思ったら失敗多数。
telnetで「ruby -rubygems 'require "image_science"; p :OK!'」が成功しない。
ここからが結構時間かかりました。

ImageScienceのバグ

現時点でのImageScience(1.1.1)にはちょっとしたバグがあって、環境によってはそのためコンパイルが通りません。

これがエラーメッセージ
# ここ以下の$HOME $GEM_HOMEなどは適時読み替えてください

%ruby -rubygems -I$HOME/include -e 'require "image_science"; p :OK!'
$GEM_HOME/gems/image_science-1.1.1/lib/image_science.rb: In function `resize':
$GEM_HOME/gems/image_science-1.1.1/lib/image_science.rb:189: syntax error before `*'
$GEM_HOME/gems/image_science-1.1.1/lib/image_science.rb:190: `image' undeclared (first use in this function)
$GEM_HOME/gems/image_science-1.1.1/lib/image_science.rb:190: (Each undeclared identifier is reported only once
$GEM_HOME/gems/image_science-1.1.1/lib/image_science.rb:190: for each function it appears in.)
$GEM_HOME/gems/image_science-1.1.1/lib/image_science.rb: In function `save':
$GEM_HOME/gems/image_science-1.1.1/lib/image_science.rb:200: syntax error before `int'
$GEM_HOME/gems/image_science-1.1.1/lib/image_science.rb:201: `flags' undeclared (first use in this function)
$GEM_HOME/gems/RubyInline-3.6.2/./inline.rb:408:in `build': error executing cc -shared -O -pipe -D_THREAD_SAFE -fPIC -I /usr/local/lib/ruby/1.8/i386-freebsd4 -o "$HOME/.ruby_inline/Inline_ImageScience_aa58.so" "$HOME/.ruby_inline/Inline_ImageScience_aa58.c" -lfreeimage -lstdc++: 256 (CompilationError)
Renamed $HOME/.ruby_inline/Inline_ImageScience_aa58.c to $HOME/.ruby_inline/Inline_ImageScience_aa58.c.bad from $GEM_HOME/gems/RubyInline-3.6.2/./inline.rb:628:in `inline'
   from $GEM_HOME/gems/image_science-1.1.1/lib/image_science.rb:84
   from $HOME/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:33:in `gem_original_require'
   from $HOME/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:33:in `require'
   from -e:1

まず気になったのが、キャッシュをチェックして必要ならコンパイルするというRubyInlineの仕様。ということは、CGI動作する際にもコンパイラ用のパラメータを渡す必要があるわけです。
もちろん今回のバグの修正もしなくてはなりません。

ということで、image_science.rbの修正を。
ヘッダとライブラリに関しては単純にパスを追加したらいいわけですから……

inline do |builder|
 if test ?d, "/opt/local" then
  builder.add_compile_flags "-I/opt/local/include"
  builder.add_link_flags "-L/opt/local/lib"
 end
 builder.add_compile_flags "-I$HOME/include"
 builder.add_link_flags "-L$HOME/lib"
 builder.add_link_flags "-lfreeimage"
 builder.add_link_flags "-lstdc++" # only needed on PPC for some reason. lame
 builder.include '"FreeImage.h"'

……と、オプション追加。
コンパイルエラーも、よくよくチェックしてみれば単純。

 VALUE resize(int w, int h) {
  FIBITMAP *image;
  GET_BITMAP(bitmap);
  image = FreeImage_Rescale(bitmap, w, h, FILTER_CATMULLROM);
 VALUE save(char * output) {
  FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(output);
  if (fif == FIF_UNKNOWN) fif = FIX2INT(rb_iv_get(self, "@file_type"));
  if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsWriting(fif)) {
   int flags;
   GET_BITMAP(bitmap);
   flags = fif == FIF_JPEG ? JPEG_QUALITYSUPERB : 0;

……つまり、C言語なのに変数宣言がブロック先頭になってなかったというだけでした。単純な文法ミスなのですぐにでも修正されるでしょう。
これでコンパイルが通り、利用が可能になるはずです。

CGIで利用する

これで使用準備は整ったと言うことで、CGIの方での使い方。
スクリプトはいきなりrubyコードを書くのではなく、ファイルの先頭で環境変数をきちんと設定する必要があります。
具体的にはこんな感じです

#!/bin/sh
HOME=/home/xxxxxx # ホームディレクトリを指定する
VER=1.8
ARCH=i386-freebsd4 # ここら辺はさくらサーバの設定

XLIB=$HOME/lib/ruby # rubyライブラリのベースディレクトリ
XSLIB=$XLIB/site_ruby # rubyライブラリのsiteディレクトリ

# 以下の4つが動作に必要な環境変数
export RUBYLIB=$XSLIB/$VER:$XSLIB/$VER/$ARCH:$XSLIB:$XLIB/$VER:$XLIB/$VER/$ARCH
export LD_LIBRARY_PATH=$HOME/lib:/usr/local/lib:/usr/lib:/lib
export GEM_HOME=$HOME/rubygems
export INLINEDIR=$HOME

exec ruby -S -Ku -x $0 "$@" # ここで改めてrubyスクリプトを呼び出す。-xオプションで、次の行まで読み飛ばし
#!/usr/local/bin/ruby

これで正しくライブラリをロードすることができることを確認しました。

とまぁ、ここまで書きましたが。

適当に画像ファイルを読み込もうとすると「Unknown File Format」エラーが出て例外終了してしまいました。
……どーやら、肝心のFreeImageライブラリが正しく動作してない模様げー
こっちはコードが多くて、解析するより別の方法を探ったほうが早そうな予感……わーん

……って、ここまでの処理が無駄!?(ぉ
# まぁ、動く人はこれで動くでしょ、って事で^^;

本日のリンク元
アンテナ
その他のリンク元
検索