久々にandoidアプリを作成したので、利用したテクニックを残しておきます。
テクニックは2014年8月時点のもので、
android:minSdkVersion=”14”
android:targetSdkVersion=”19”
対応のアプリで利用しました。
画像処理 out of memory対策
androidの開発をしていると必ず頭を悩ますのが、Bitmapオブジェクトの扱いです。
1.6の頃と比べるとだいぶ扱いやすくなりましたが、まだまだ「out of memoryは終わらないぜ!」といった感じですね。
UriオブジェクトからBitmapオブジェクトを読み込む
BitmapFactory.Options options = new BitmapFactory.Options();
// Bitmapがをメモリに展開しないで、情報だけ取得
options.inJustDecodeBounds = true;
InputStream in = null;
try {
in = content.getContentResolver().openInputStream(uri);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
BitmapFactory.decodeStream(in, null, options);
try {
in.close();
} catch (IOException e) {}
android端末内のギャラリーやSDカードから画像を読み込む場合、Uriオブジェクトを受け取ります。
この時、UriからBitmapオブジェクトを作成するには、BitmapFactory.decodeStreamを利用します。
このとき重要なのが
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
の部分です。
inJustDecodeBoundsを使用することで、画像データをメモリに展開しないで情報だけを取得することができます。
画像サイズの調整
取得する画像サイズが大きい場合は、out of memoryを防ぐために縮小する必要があります。
よく使うパターンのコードを以下に記載します。
float scaleX = options.outWidth / width;
float scaleY = options.outHeight / height;
// サイズを計算
options.inSampleSize = (int) Math.floor(Float.valueOf(Math.max(scaleX, scaleY)).doubleValue());
inSampleSize = options.inSampleSize;
// サイズを2のべき上にする
for (int i = 2; i <= inSampleSize; i *= 2) {
options.inSampleSize = i;
}
// inSampleSizeをセットしてデコード
options.inJustDecodeBounds = false;
// システムメモリ上に再利用性の無いオブジェクトがある場合に勝手に解放する
options.inPurgeable = true;
// 画像の質を落とす
options.inPreferredConfig = Bitmap.Config.RGB_565;
上記のコードのwidthとheightは、画像の最大値を設定しています。
BitmapFactory.OptionsのinSampleSizeでサイズの調整をします。
options.inSampleSize = 2
ならサイズは1/2となります。
この時気を付けないといけないことは、2のべき上を設定しないと効果がないことです。なので、inSampleSizeが適切な値になるように処理を追加しています。
inPurgeableはシステムメモリ上に再利用性の無いオブジェクトがある場合に勝手に解放してくれます。デフォルトがfalseなので、trueにしておいたほうがなにかと良いと思います。
inPreferredConfigは画像の質を設定できます。
余程画質にこだわりがないアプリでない限り、Bitmap.Config.RGB_565を設定しておけば十分です。
あとはBitmapFactory.decodeStream(in, null, options);
を使えば省メモリでBitmapオブジェクトを取得することが可能です。
カメラ等の画像を扱う場合はMatrixやExifInterfaceを使うのですが、それはまた別の話なのでまたの機会に記載します。
以上。
0 件のコメント:
コメントを投稿