スケルトン・エピ

letsspeakのブログです。

javascriptのcanvasで画像を自由にトリミングしてアップロードする機能を作ってみた

今回はjavascriptで画像をアップロードする際にトリミングするコードをcanvasを使って書いてみました。


趣味でゲームのスクリーンショットをアップロードしてみんなで見せ合うようなWebアプリケーションを作っていたのですが、元の画像サイズやファイル形式って人によってまちまちだったりします。


ゲームということもあり、デジカメのような大きすぎる画像サイズになることはないのですが、どうしてもプライベートなチャット内容が入ってしまうのは嫌です。できれば自分の見せたい範囲だけをアップロードしたいものです。


また無圧縮のpngやbmpなんかでアップロードされた場合、数MBの画像をやりとりする分けにはいきません。そこですこし劣化したjpeg等の圧縮された画像形式に変換することになりますが、これをサーバー側で行うと、プレビュー画像をユーザーに見せるタイミングがサーバーで処理を行った後になってしまい、ユーザーの時間とサーバーリソースが無駄に消費されてしまいます。


そんな訳ですべてjsのcanvasでやってしまおう!という感じで実験しつつ作ってみました!

trimming_upload.js
https://github.com/letsspeak/trimming_upload.js


行っていることは、

1.ファイルが選択されたら画像を読み込む
2.この際、画面表示用のlayer1には設定された最大サイズで比率を維持して読み込む
3.また裏のbaseに元画像のサイズのまま読み込んでおく
4.画面表示部分がクリックされた際にlayer2にトリミング用の矩形を描画する
5.画面には常にlayer1とlayer2を合成して表示する
6.トリミング確定後、アップロードボタンが押されたら元サイズのbaseボタンからトリミングサイズに基づいた比率で切り抜いてデータを送信する。

という感じです。

f:id:letsspeak:20131122020607p:plain


こんな感じで設定した最大さいずでプレビューしつつ、トリミングは元画像の比率で行うようになっています。

今回のハマりポイント
context.drawImage() の際の第一引数になるcanvasサイズが width, height ともに 0 の場合に例外が発生するようです。これに気づかず20分程はまってしまいました...。


書いていて気がつきましたが、元のトリミングサイズのままアップロードしたい場合の処理がありませんねwこの辺を次の課題としつつ今回はこの辺で終わりとさせていただきます。

ではよいお年を。