goo blog サービス終了のお知らせ 

タブレット用プログラムの書き止め

android OS & iPadOS の記録。

基礎。サムネイル画像を求める手法。BitmapFactory.Options と options.inSampleSize

2021-12-17 23:38:17 | Android studio 日記

RecyclerViewのアダプタ内でサムネイル画像を設定している。
自前で縮小サイズを算出してbitmapを縮小加工。setImageBitmap()で終了。
元サイズを読み出し、縮小加工、設定。メモリでのやり取りが多い。

デベロッパーの説明でサムネイルのサイズに近いところまで、2のべき乗で割って数値を求める。
BitmapFactory.Options.inSampleSizeに数値をセットしてデコード、システムが縮小出力してくれる。
近いサイズになっているので、そのままセットしてscaleTypeでフィット表示してもらう。
recyclerViewの表示が速くなった…。


RecyclerView用アダプタ内のプログラム

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

        if ( imagePaths == null ) return ;// 画像ファイルパス配列の要素の有無

        Bitmap bitmap = loadImage( position );

        if (bitmap != null)
            holder.imageView.setImageBitmap( bitmap );
        else
            holder.imageView.setImageBitmap(  // デコードできないとき用意されてるリソースをセット
                  BitmapFactory.decodeResource( myContext.getResources(), R.drawable.not_find) );

        holder.textView.setText( imagePaths.get(position) );
        bitmap = null;
    }

    private Bitmap loadImage( int position ) {

        if ( position < 0 || position >= imagePaths.size() ) return null;

        String fName = imagePaths.get(position);
        if ( fName == null ) return null;

        File file = new File( fName );
        if ( !file.exists() || !file.isFile() ) return null;

        Bitmap scaleBitmap = null;
        try {
            BitmapFactory.Options op = new BitmapFactory.Options();
            op.inJustDecodeBounds = true; // 実データは読み込まない

            InputStream istream = new FileInputStream( file );
            BitmapFactory.decodeStream( istream, null, op );
            istream.close();

            // favoriteSizeは、サムネイルサイズ @dimen で宣言されているものを展開

            op.inSampleSize = calculateInSampleSize( op, favoriteSize, favoriteSize ); // 縮小サイズ
            op.inJustDecodeBounds = false; // 実データを読み込む

            istream = new FileInputStream( file );
            scaleBitmap = BitmapFactory.decodeStream( istream, null, op );
            istream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return scaleBitmap;
    }

    public int calculateInSampleSize( BitmapFactory.Options op, int reqWidth, int reqHeight ) {
        int height = op.outHeight;
        int width = op.outWidth;
        int inSamplSize = 1;

        if ( height > reqHeight || width > reqWidth ) {
            int halfHeight = height / 2;
            int halfWidth = width / 2;

            while ( ( halfHeight / inSamplSize ) >= reqHeight && ( halfWidth / inSamplSize ) >= reqWidth ) {
                inSamplSize *= 2; // 分母が2のべき乗
            }
        }
        return inSamplSize;
    }


デベロッパーは隅まで読むべし。理解できなくても(笑)