GAEの画像APIのりサイズの画質がクソなのでクライアント側でいろいろやる

やりたいこと:GAEでサムネイル用の画像を作りたかった
問題:GAEに用意されたAPI使ってサイズを縮小すると、荒くなってとても汚くなった
解決:クライアント側で処理してアップロード

処理の流れ:
1:GAEで普通にアップロード
blobstoreに元画像が保存される
2:クライアント側(Javascript)で元画像を読み込んで、リサイズ処理をしてサムネ画像を生成&アップロード
3:サムネ画像をblobstoreに保持

  • -

2については、最初にこのページにたどり着いたが、アルゴリズムが悪いらしく、非常に処理に時間がかかって問題となった。
http://stackoverflow.com/questions/2303690/resizing-an-image-in-an-html5-canvas

その後、優れたライブラリにたどり着いた。
https://github.com/grantgalitz/JS-Image-Resizer
これで、2の処理はうまくいった。

最後に、どうやってcanvasの画像をblobstoreに保存するのかという問題が残った。
まず、js側の処理は下のを参考。
http://29a.ch/2011/9/11/uploading-from-html5-canvas-to-imgur-data-uri

app engine側は、こういう感じ。

FileService fileService = FileServiceFactory.getFileService();
AppEngineFile file = fileService.createNewBlobFile("image/jpeg");
boolean lock = true;
FileWriteChannel writeChannel = fileService.openWriteChannel(file, lock);
// This time we write to the channel using standard Java
writeChannel.write(ByteBuffer.wrap(Base64.decode(画像データの文字列)));
// Now finalize
writeChannel.closeFinally();
BlobKey key = fileService.getBlobKey(file);

  • -

追記:
2の処理についてIEではそのまま行かない。
imgタグのonloadでやると、参照の渡され方が他のブラウザと違うのでうまくいかんかったっぽい。
解決方法は、

var source = new Image();
source.onload = function(){
var elementHandle = document.createElement("canvas");
var contextHandle = elementHandle.getContext("2d");

}
source.src = "url_to_img";

みたいにnew Image();ベースでやれば無問題。