前回、Bitmapの読み込みの画像解像度と端末解像度による違いでの軋轢(?)的な部分を紹介しました。
では、今回はその部分を最適化して利用をしてみたいと思います。
画像の部分に関しては解像度の低い端末だと画像が大きすぎる可能性があり、また、撮影した写真も解像度が大きすぎてそのまま読み込みをしようとすると、メモリエラーが発生する可能性があります。
その際にbitmapのサイズを変更すればいいので
Bitmap _bm = BitmapFactory.decodeResource(resources, id, options); Matrix matrix = new Matrix(); matrix.postScale(scale, scale); Bitmap bmp = Bitmap.createBitmap(_bm, 0, 0, _bm.getWidth(), _bm.getHeight(), matrix, true); _bm.recycle(); _bm = null;
ように画像のサイズを小さく変更する必要があります。(scale倍のBitmapになって、元のBitmapは消します)
また、Bitmap化の段階で、サイズが分かっていれば
options.inSampleSize = 2;
で2分の1のサイズで小さく読み込む事ができるので負荷は少なくなります。
で下記のような関数を作成してみました。
public Bitmap makeBitmap(int wDpi,Resources resources,int id,int MaxWidth,int MaxHeight){ BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(resources, id, options); int _oDpi = options.inDensity; float scale = (float)_oDpi/wDpi; options.inJustDecodeBounds = false; float max = Math.max((float)options.outWidth*scale/MaxWidth, (float)options.outHeight*scale/MaxHeight); max = (float) Math.floor(max); if(max > 1){ options.inSampleSize = (int)max; Log.e("size", Float.toString(max)); }else if(max < 1){ Log.e("makeBitmap", "low Size"); } options.inPurgeable=true; Bitmap _bm = BitmapFactory.decodeResource(resources, id, options); Matrix matrix = new Matrix(); matrix.postScale(scale*scale, scale*scale); Bitmap bmp = Bitmap.createBitmap(_bm, 0, 0, _bm.getWidth(), _bm.getHeight(), matrix, true); _bm.recycle(); _bm = null; return bmp; }
でポイントとしては、利用したいサイズ(最大値)を決めておくとそのサイズに応じた読み込みをしてくれます。利用方法は下記のような形です。
DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); int _wDpi = (int)metrics.densityDpi; Bitmap _bm = makeBitmap(_wDpi,getResources(),R.drawable.tip2,800,800);
上記で引数は
第一:端末のdensityDpi 第二:リソース 第三:画像のID 第四:横幅 第五:縦幅
です、サイズの値に関しては800*800の矩形に収まる時に最適なbitmapが取得できるという意味で、800*800のサイズで画像が取得できるわけではないのでお気をつけください。サイズの変更等はご自身で調整お願いします。
以前
BitmapFactory.Optionsを使ってメモリ節約
で紹介していた方法も使いつつ、サイズの調整も含めたものができたと思います。
画像の容量を落とす
options.inPreferredConfig = Bitmap.Config.ARGB_4444;
もいれてもいいかもしれません。