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

android OS & iPadOS の記録。

基礎。サムネイル画像キャッシュ処理草案

2022-01-24 22:01:51 | Android studio 日記

相関をデータベースで管理するのもあると思う。が…。
直感的で楽なのでキャッシュフォルダに実際の画像ファイルのディレクトリ階層を再現して、サムネイル画像ファイルを配置するでいいか。

キャッシュフォルダパス + 画像ファイル絶対パス
パス合成は、こんな感じのイメージ。


・画像ファイルの絶対パス取得。
・キャッシュフォルダパスと画像ファイルの絶対パスを合成。
・キャッシュフォルダに合成パスのファイルが存在するか調べる。
・存在しなければ、サムネイルを作成。
・作成データを所定の場所に保存する。

今回はテスト用の内容で実際の組み込みは変更する。

 

現実的なのは、Web掲載記事で説明があったメインスレッドと別スレッドで分けるもの。

メインUIスレッドではキャッシュを確認して、有無で利用か作成か。アダプター内で処理?。
別スレッドでは、あるトリガーでディレクトリ内のサムネイル画像を作成する。

トリガーの説明は見てないから、キャッシュ内になかった時に別スレッドをスタートさせるでいいのかな。

キャッシュフォルダで絶対パスを文字列で作って、new File() でFileデータを取ろうとしたけど、上手くいかないので、new File( dir, child ); を繰り返して階層を掘り下げた。一般のデータフォルダと違うという事かな?


<かなり省略>


    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

 

// 画像ファイル取得

        File f = getExternalStoragePublicDirectory(DIRECTORY_PICTURES); // 画像ファイルがあるディレクトリパス
        File f1 = new File(f.getAbsolutePath() + "/image1/182.jpg"); // 画像のフルパス


// キャッシュ情報取得&作成

        File cacheDir = getCacheDir();

        List<String> list = disassemblyPath( f1 ); // フルパスをディレクトリ名、ファイル名に分解
        List<String> dirList = list.subList( 1,list.size()-1 ); // 画像ファイル名を除く

        makeCacheDirectory( dirList ); // キャッシュフォルダにサムネイル画像ファイルを保存するディレクトリを作成

        Bitmap bitmap;

        File cDir = assemblyCachePath( dirList ); // キャッシュフォルダにディレクトリ階層を再現
        File cf = new File( cDir, f1.getName() ); // サムネイル画像ファイル存在チェック用

// キャッシュフォルダにサムネイル画像の有無。無ければ作って保存

        if ( !cf.exists() ) { // サムネイル画像ファイルが存在していない

            bitmap = thumbnaileImage(f1.getAbsolutePath());

            if ( bitmap != null ) {
                try {
                    File ff = new File(cDir, f1.getName());

                    FileOutputStream fos = new FileOutputStream( ff );
                    Bitmap.CompressFormat bcf = getCompressFormat( f1.getName() ); // 
                    if ( bcf != null )
                        bitmap.compress( bcf, 100, fos ); // bitmap を圧縮して出力

                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

        list.clear();
        list = null;
    }

    public Bitmap.CompressFormat getCompressFormat( String name ) {
        String t = name.toLowerCase();
        if ( t.endsWith( ".jpg" ) ) return Bitmap.CompressFormat.JPEG;
        if ( t.endsWith( ".png" ) ) return Bitmap.CompressFormat.PNG;
        return null;
    }

    public void makeCacheDirectory( List< String> list ) {
        int len;
        if ( list == null || ( len = list.size() ) == 0 ) return;
        File cacheDir = getCacheDir();
        do {
            cacheDir = new File( cacheDir, list.get(--len) );
            if (!cacheDir.exists() && !cacheDir.mkdirs())
                break;
        } while ( len > 0 );
    }

    public List< String> disassemblyPath( File f ) {
        List< String> list = new ArrayList<String>();
        File path = f;
        do {
            list.add(path.getName());
            path = path.getParentFile();
        } while ( path != null && !path.getName().equals(""));

        return list;
    }

    public boolean existsCacheDirectory( List< String> list ) {
        int len;
        if ( list == null || ( len = list.size() ) == 0 ) return false;

        File cacheDir = getCacheDir();
        String t;

        for ( len-=1; len >= 0; len-- ) {
            t = list.get(len);
            cacheDir = new File( cacheDir, t );
        }

        return cacheDir.exists();
    }

    public File assemblyCachePath( List< String> list ) {
        int len;
        if ( list == null || ( len = list.size() ) == 0 ) return null;

        File cacheDir = getCacheDir();
        String t;

        for ( len-=1; len >= 0; len-- ) {
            t = list.get(len);
            cacheDir = new File( cacheDir, t );
        }

        return cacheDir;
    }


    public Bitmap thumbnaileImage(String fName ) {
        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 );

            op.inSampleSize = calculateInSampleSize( op, 144, 144 );
            op.inJustDecodeBounds = false;
            istream.close();
            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;
            }
        }

        return inSamplSize;
    }