大きな画像を読み込む段階で小さくして読む

前回に続き OpenCvに直接関わらない話題だが、大きな画像を読み込んで画面に表示したり サムネールとして複数の画像を一緒に表示する際、無駄なメモリを使わないように 読み込む段階で 小さくして読むクラスを作成しました。

hoge256さんの AndroidでBitmapFactoryを使ってサイズの大きな画像を読み込むサンプルを参考にさせて いただきました。ありがとうございます。

作ったクラス

package jp.ne.dazoo.nobotta;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class ResizeLoad {
    public Bitmap bmpLoad(String path,int width,int height){
        Bitmap bmp = null;
        //読み込み用のオプションオブジェクトを生成
        BitmapFactory.Options opt = new BitmapFactory.Options();
        
        //この値をtrueにすると実際には画像を読み込まず、
        //画像のサイズ情報だけを取得することができます。
        opt.inJustDecodeBounds = true;

        //画像ファイル読み込み
        //ここでは上記のオプションがtrueのため実際には画像は読み込まれません。
        BitmapFactory.decodeFile(path, opt);

        //読み込んだサイズはoptions.outWidthとoptions.outHeightに
        //格納されるので、その値から読み込む際の縮尺を計算します。
        int scaleW = opt.outWidth / width + 1;
        int scaleH = opt.outHeight / height + 1;

        //縮尺は整数値で、2なら画像の縦横のピクセル数を1/2にしたサイズ。
        //3なら1/3にしたサイズで読み込まれます。
        int scale = Math.max(scaleW, scaleH);

        //今度は画像を読み込みたいのでfalseを指定
        opt.inJustDecodeBounds = false;

        //先程計算した縮尺値を指定
        opt.inSampleSize = scale;

        //これで指定した縮尺で画像を読み込めます。
        bmp = BitmapFactory.decodeFile(path, opt);

        return bmp;
    }
}

メイン側

public class OpenCVnyumonActivity extends Activity {
    ImageView imgv;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        String path=Environment.getExternalStorageDirectory()+"/DCIM/100ANDRO/dsc002.jpg"; <---これが大きい
        // 画面サイズを取得する
        Matrix matrix = new Matrix();
        DisplayMetrics metrics = new DisplayMetrics();
        this.getWindowManager().getDefaultDisplay().getMetrics(metrics);
        int screenWidth = metrics.widthPixels;
        int screenHeight = metrics.heightPixels;

        ResizeLoad rsl = new ResizeLoad();
        Bitmap src = (rsl.bmpLoad(path, screenWidth, screenHeight)).copy(Bitmap.Config.ARGB_8888, true);

        Mat mat = android.BitmapToMat(src);
        src.recycle();

        Bitmap dsc= Bitmap.createBitmap(mat.width(), mat.height(), Bitmap.Config.ARGB_8888);
        android.MatToBitmap(mat, dsc);
        
        imgv = (ImageView)findViewById(R.id.imageView1);
        imgv.setImageBitmap(dsc);
    }
}

この例では 画面全体のサイズを最大サイズに指定しています。しかし読む込むサイズは 元サイズの1/n のため 画面ぴったりにはなりません。ぴったりにするには 読み込んだ後 Resizeする必要があります。

お断り この処理では 特にMatを経由させる必要は、ありません。(笑い)

スポンサーリンク
Rectangle大広告
Rectangle大広告

シェアする

  • このエントリーをはてなブックマークに追加

フォローする