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

android OS & iPadOS の記録。

基礎。画像Fileパスから、BitmapDrawable作成。

2022-04-23 02:03:13 | Android studio 日記

消費メモリ見直しで一枚の画像を表示させるメソッドを確認。

タブレット横置き固定でスクリーンに大きさを合わせる。
ポートレート画像は左90度回転させる。
ランドスケープ画像はそのまま表示。


getContext()は、contextを取得するメソッド。自前で作る。
Bitmap.createBitmap()のmatrix の設定で元画像の大きさ、回転を一度で加工する。

    mBitmap = Bitmap.createBitmap( mBitmap, 0, 0, Width, Height, matrix, true );

myMessage(string) はダイアログで自前で用意。

 

    public BitmapDrawable setImage( File f ) { // jpg か png チェック済みであること。

        if ( f == null || !f.exists() || !f.isFile() )
            return null;

        Bitmap mBitmap;
        BitmapDrawable drawable = null;
        BitmapFactory.Options BFop = new BitmapFactory.Options();
        Matrix matrix = new Matrix();
        float mag;
        int w, h;

        try {

            BFop.inJustDecodeBounds = true; // 実態は読み込まない

            InputStream istream = new FileInputStream( f );
            mBitmap = BitmapFactory.decodeStream( istream, null, BFop );
            istream.close();
            mBitmap = null;

            if ( getImageShape( BFop.outWidth, BFop.outHeight ) == Configuration.ORIENTATION_PORTRAIT ) {
                // ポートレート画像
                w = BFop.outHeight; // 回転を踏まえ縦横サイズ入れ替え
                h = BFop.outWidth;
                matrix.postRotate(270.00f ); // 左90度回転設定
            } else {
                // ランドスケープ画像
                w = BFop.outWidth;
                h = BFop.outHeight;
            }

            // 元画像が極度に大きい場合はある程度縮小。消費メモリ削減。
            BFop.inSampleSize = calculateInSampleSize( BFop, w, h );

            mag = calcImageViewFit( BFop, w, h ); // スクリーンに填め込むため倍率を取得
            matrix.postScale( mag, mag );

            BFop.inJustDecodeBounds = false; // 実態を読み込む
            istream = new FileInputStream( f ); // ストリームリセット

/*
            mBitmap = BitmapFactory.decodeStream( istream, null, BFop );
            if ( mBitmap != null )
                mBitmap = Bitmap.createBitmap( mBitmap, 0, 0, BFop.outWidth, BFop.outHeight, matrix, true );
            エラーチェックを入れたい場合は分ける。catch で受け取るのでまとめた。
*/

            mBitmap = Bitmap.createBitmap(
                    BitmapFactory.decodeStream( istream, null, BFop ),
                    0, 0, BFop.outWidth, BFop.outHeight, matrix, true
            );

            istream.close();
            drawable = new BitmapDrawable( getContext().getResources(), mBitmap );

        } catch ( IOException ioe ) {
            myMessage( getContext().getResources().getString( R.string.error_io_exception ) );
            return null;
        } catch ( OutOfMemoryError ome ) {
            myMessage( getContext().getResources().getString( R.string.error_out_of_memory ) );
            return null;
        } catch ( Exception e ) {
            return null;
        }
        mBitmap = null;
        return drawable;
    }

    public float calcImageViewFit( BitmapFactory.Options BFop, int imageWidth, int imageHeight ) {

        int displayWidth = getScreenWidth(); // スクリーンサイズ取得は別途参照
        int displayHeight = getScreenHeight();
        float fX = (float) displayWidth / (float) ( imageWidth / BFop.inSampleSize );
        float fY = (float) displayHeight / (float) ( imageHeight / BFop.inSampleSize );
        float ret = 1f;

        if ( ( ( imageWidth >= displayWidth) && ( imageHeight >= displayHeight ) )
                || ( ( imageWidth <= displayWidth ) && ( imageHeight <= displayHeight ) ) ) {
            ret = Math.min(fX, fY);
        } else if ( imageWidth > displayWidth )
            ret = fX;
        else
            ret = fY;

        return ret;
    }

    private int calculateInSampleSize(BitmapFactory.Options op, int reqW, int reqH ) {
        int height = op.outHeight;
        int width = op.outWidth;
        int inSamplSize = 1;

        if ( height > reqH || width > reqW) {
            int halfHeight = height / 2;
            int halfWidth = width / 2;

            while ( ( halfHeight / inSamplSize ) >= reqH &&
                    ( halfWidth / inSamplSize ) >= reqW
            ) {
                inSamplSize *= 2;
            }
        }
        return inSamplSize;
    }

    public int getImageShape(int x, int y) {
        int ret = Configuration.ORIENTATION_PORTRAIT;
        if (x > y) ret = Configuration.ORIENTATION_LANDSCAPE;
        return ret;
    }