複数の写真をまとめて縮小&アップロードするプログラムを作った
2016年12月11日
●写真のアップロードが大変
ブログに写真を載せるときに毎回思うのが、写真のアップロードがとても大変なこと。
1.MobableTypeのファイルアップロード画面を開く
2.写真を選択して「アップロード」ボタンをクリック
3.「HTMLを表示」「この画像のサムネイルを作る」をチェックして、縮小用の最大幅を入力して、「埋め込み」ボタンをクリック
この手順を写真の数だけ繰り返す必要がある。
たまにエラーで上手く行かなかったりするともうイライラするよね。
●そんなわけで
複数の写真をまとめて縮小してアップロードしてくれるプログラムをRuby&Javaで作った。
が、結構苦戦した。
その過程を書くけど、長いので興味ない人はすっ飛ばして下さい。
●Rubyオンリーでやりたかった
理想の手順はこう。
1.ブラウザで専用ページを開いて、複数の写真を選択して、「アップロード」ボタンをクリック
2.全ての写真をアップロードして、サーバー側で写真を縮小してサムネイルも生成してくれて、ブログ貼り付け用のタグを出力する。
ここで問題だったのが、写真(画像)の縮小。
Rubyの画像処理をやらせなきゃいけないわけだけど、これがなかなか難しかった。
●RMagickを使いたかった
Rubyで画像縮小するには、RMagickっていうgemを使えば良いらしいことが分かった。
早速ローカル環境にインストールしようとすると、エラー。
ImageMagickっていう画像編集ソフトがインストールされていないといけないらしい。
このサイト(RMagick を Windows にインストールする方法)とかを参照しながら、色々やったら何とかインストールは出来た。
そして、ruby側でRMagickを読み込んで(requireして)早速使おうと思ったら、「Broken pipe」なる謎のエラーでそもそも読み込みが出来ない。
これはWindows環境の問題かも知れないから、サーバー側なら起きないかも。
というわけで、サーバー側にRMagickをインストールすることに。
そしたら、RMagickのインストールで「/usr/local/lib/ruby/2.2.0/mkmf.rb:456:in `try_do': The compiler failed to generate an executable file. (RuntimeError)」とかいう謎のエラー。
調べてみると、ImageMagickのバージョンが違うとダメとか、入れ直すと上手く行くとか書いてあったりするけど、そもそも権限の問題でXREAサーバーに入ってるImageMagickの入れ直しが多分出来ない。
なので、RMagickは諦めた。
●RMagickがダメならMiniMagickを使えば良いじゃない
RMagickより軽量なMiniMagickって言うのがあるらしい。
早速入れてみた。
Windows環境も、サーバー環境もどっちにもインストールできた。
これは期待できそうだ。
例によってMiniMagickをrequireしてrubyプログラムを書いてみたところ、またもやエラー。
ImageMagickは既にインストールしてるのに、ImageMagickがインストールされていません的なエラーが出るんですけど!
しょうがないから、Windows環境は諦めてサーバー環境で動作確認。
そしたら、「Internal Server Error」。
例外補足も出来ずに原因不明なサーバーエラーで終了。
XREAはサーバー側のエラーログが取得出来ないから、本当に原因不明。
諦めよう…。
●こうなったらWindows環境で縮小したものをサーバーにアップする
もう、サーバーで画像を縮小するのは諦めた。
ローカルで縮小してからアップロードしよう。
ちょうど、画像を縮小するgemを探してた時に、Javaで画像を縮小するImageResizeっていうgemを発見した。
(参考:gemだけで画像をリサイズできるImageResizeを作った)
Java必須だからサーバーでは動かないけど、ローカルならこれ使えばいけるかも?
(一応XREAにJREのインストールを試みたけど、パーミッションエラーで弾かれた。残念)
早速ImageResizeをインストールして、rubyプログラムで呼び出して使ってみた。
すると、縮小できた!
できた!
できた…けど、なんか汚い。
非常に汚い。
Java標準APIで縮小してるらしいんだけど、これが綺麗にリサイズ出来ない原因っぽい。
いやー惜しい。
●Javaならもっと頑張れるはず
ローカル環境でJavaで画像処理してるんだから、そこの部分だけ違うアルゴリズムに書き換えれば良い。
そんなわけで、Javaで綺麗に画像縮小出来るアルゴリズムを探した。
最初に、このサイト(Javaでサムネイル作成:#侍ズム)で紹介されてる「Graphics2D」を使ったリサイズに挑戦。
うん。
前よりは少し綺麗になった。
でも、MobableTypeで縮小した画像よりはまだまだ汚い。
没。
次に、このサイト(Javaで画像縮小:クノっちの日記)で紹介されてる中で一番綺麗って書かれてる、「java-image-scaling」ってのを試してみた。
と、思ったらこれはJava標準じゃなくて外部のJarがいるらしい。
ググったらあったので落としてきた。
さらに中で参照してるFilter的なJarもその後ググって落としてきた。(Antで自分でビルドした)
一応、ライセンス的にも問題なし。
そして、早速使ってみた。
うん。
「Graphics2D」より大分良くなった。
ただ、なんかやたらとシャープネスがかかってる気がする。
と思ってソースをよく見ると…
public static BufferedImage reSize3(BufferedImage img, int width, int height) {
ResampleOp resampleOp = new ResampleOp(width, height);
resampleOp.setFilter(ResampleFilters.getLanczos3Filter());
resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.VerySharp);
BufferedImage rescaled = resampleOp.filter(img, null);
return rescaled;
}
VerySharpってなんじゃい。
そんなもの求めてないよ!
ここ変えて、シャープネス処理は軽減された。
さらに、その上の行の「getLanczos3Filter()」ってのがリサイズアルゴリズムを示していて、いろんなのが用意されてた。
折角なので色々試してみた。
縮小画像の綺麗さで言うと、バイキュービック法(BiCubic)とランチョス法(Lanczos3)が優秀なことが分かった。
かなり誤差だけど、アルゴリズム的にはランチョス法の方が若干綺麗になりやすいっぽい。
ただし処理時間がかかるとか。
性能はあんまり求めてないので、ランチョス法を選択して、結局こうなった。
private BufferedImage resize3(BufferedImage img, int width, int height) {
ResampleOp resampleOp = new ResampleOp(width, height);
resampleOp.setFilter(ResampleFilters.getLanczos3Filter());
resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.None);
BufferedImage rescaled = resampleOp.filter(img, null);
return rescaled;
}
結局アンシャープマスクを切っただけって言うね…。
●プログラム完成
そんなわけで、プログラムが完成した。
4.アップロードした画像のサムネ(実際のサムネの1/5サイズ)と、ブログ貼り付け用のタグが表示される
こんな感じで、複数のファイルをまとめてアップロードしてくれてサムネも作ってくれる。
書き忘れたけど、ついでにEXIFも取ってくれるようにした。
●まとめ
色々苦労したけど、何とか目的のものが出来た。
昨日のブログ記事で早速使ってみたけど、55枚のファイルアップロードが非常に楽に出来てかなり快適。
とても良い。
サムネより小さいサイズの画像だとサムネサイズに拡大されるとか、EXIF取れないファイルの制御とか、まだまだ改善点はあるけど、普段の写真アップロード作業には普通に使えるレベルにはなった。
これで枚数気にせず現像出来るね。
疲れた。
old « 泉の森~横浜散策 | メイン | クロネコヤマトのミニカーが届いた » new