以前GridViewに画像をたくさん並べる方法
のときにサムネイル化するために
画像を縮小する必要があったのだけど、
あまり考えずに
Google App Engine で以下のようなServletを書いて
処理していた。
public class ResizeServlet extends HttpServlet {
private static final long serialVersionUID = -999999L;
/** デフォルトの高さ(ピクセル) */
public static final int HEIGHT = 50;
/** ロガー */
private static final Logger log =
Logger.getLogger(ResizeServlet.class.getName());
/**
* 生存確認
*/
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
PrintWriter pw = resp.getWriter();
pw.print("ResizeServlet is alive!");
pw.close();
}
/**
* 画像を高さ100spに変更して戻す
*/
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException{
DataInputStream dis = new DataInputStream(req.getInputStream());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int c;
while((c = dis.read())!=-1){
baos.write(c);
}
byte[] org = baos.toByteArray();
log.info("doPost: length=" + org.length);
Image image = ImagesServiceFactory.makeImage(org);
int height = image.getHeight();
int width = image.getWidth();
Transform resizer =
ImagesServiceFactory.makeResize(
(int)(((double)width*HEIGHT)/((double)height)), HEIGHT);
ImagesService service = ImagesServiceFactory.getImagesService();
byte[] result =
service.applyTransform(resizer, image).getImageData();
DataOutputStream dos = new DataOutputStream(resp.getOutputStream());
dos.write(result, 0, result.length);
dos.close();
dis.close();
}
}
App Engineの上記のServletサイトへPOSTで送った画像を
App Engineに用意されているGoogle APIで高さ100ptの画像に変換して
送信元へ返しているだけの単純なつくりだ。
実際にはパラメータで高さ指定できるものを利用しているが
サンプルコードは決め打ちにしてある。
ちなみに、Android側はURLConnectionを使ってbyte[]でもらってくればいい。
private byte[] resizeImage(String url, byte[] org) throws IOException{
URLConnection conn = new URL(url).openConnection();
Log.d(TAG, "getImage: url =" + url);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/octet-stream");
conn.setRequestProperty("User-Agent", "androidSample");
conn.setRequestProperty("Content-Length",
new Integer(org.length).toString());
// 送信
OutputStream os = conn.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.write(org, 0, org.length);
// 受信
InputStream is = conn.getInputStream();
DataInputStream dis = new DataInputStream(is);
int b;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while((b = dis.read())!=-1){
baos.write(b);
}
dis.close();
is.close();
dos.close();
os.close();
byte[] result = baos.toByteArray();
Log.d(TAG, "resize: org_length=" + org.length + ", result_length=" +
result.length);
return result;
}
引数の変数urlは先のApp Engineの該当ServletのURLを
書けば良い。
カメラにせよ、S3上にせよ画像データをbyte[]で渡してやれば
戻り値として小さくなった画像を返してくれる。
これを非同期でGridLayoutを更新させるように実装すればいい。
#ボタンイベントなどに書くと、とたん固まってしまうから、やらないほうがいい
#とりあえず動けばいい人は書いてもいいが..
けれど、
昨日Androidの会のMLに以下のようないくつかの方法が
紹介されていた。
画像をきれいに縮小する方法
まだ試してはいないけれども
これだと通信事情が悪い場所でも
縮小できそうだ。
画像に関する知識が私にはまったくなかったので
ありもの(AppEngineのImageService)で何とかしようとしていたけど、
質問した人は画像処理について詳しい方のようで
もっといい方法を紹介してくれている。
勉強になった。
0 件のコメント:
コメントを投稿