2

そうです、特定の URL から画像を表示する必要がある Android アプリケーションを作成しています。残念ながら、画像が大きすぎるため、デコードせずにドローアブルに渡すと、メモリ不足の例外が発生します。

このため、最初に BitmapFactory.decodeStream を使用して画像をデコードしようとしました。

ここにいくつかのコードがあります:

まず、画像をデコードするために使用する方法:

public static Bitmap decodeSampledBitmapFromResource(Resources res, String src,
            int reqWidth, int reqHeight) {

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();

        InputStream input = null;
        InputStream input2 = null;

        Rect paddingRect = new Rect(-1, -1, -1, -1);

        try {
            URL url = new URL(src);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            input = connection.getInputStream();
            //input2 = connection.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(input, paddingRect, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

       try {
        input.reset();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;

        return BitmapFactory.decodeStream(input, paddingRect, options);
    }

public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 40;

    if (height > reqHeight || width > reqWidth) {
        if (width > height) {
            inSampleSize = Math.round((float)height / (float)reqHeight);
        } else {
            inSampleSize = Math.round((float)width / (float)reqWidth);
        }
    }
    return inSampleSize;
}

そして、アクティビティの OnCreate でそのメソッドを呼び出す場所:

imageFrame1.setImageBitmap(
                decodeSampledBitmapFromResource(getResources(), src, 100, 100));

コードが現在のように、最初にデコードした後に入力ストリームをリセットしようとすると、IOException がキャッチされ、LogCat メッセージが表示されます: SKImageDecoder::Factory Returned Null.

input.reset(); を削除すると コードから、同じ LogCat メッセージが表示されますが、IOException はありません。

ここの誰かが何か提案をしてくれることを期待して、この時点でちょっと困惑しましたか?

4

2 に答える 2

1

基になるロジックがストリームを (十分に) キャッシュしていないため、HTTP 接続からストリームをリセットすることはできません。

画像をローカル ストレージ (ディスクまたはメモリ) に書き込み、それを分析するアプローチを作成します。必要に応じて、両方を同時に実行します (より手間がかかります)。

于 2012-12-07T13:51:49.100 に答える
0

inputStreamはリセットをサポートしていない可能性があることに注意してください。さらに、最初にmark()を呼び出す必要があります。ポイントをマークするには、inputStreamをにリセットする必要があります。マーク/リセットがサポートされているかどうかを確認するには、InputStream.markSupported()を呼び出します。

マーク/リセットなしで、画像をローカルファイルにダウンロードできます。OutOfMemoryは発生せず、Webから(サブサンプリングを使用して)実行しようとしたのと同じ方法でFileInputStreamから画像をデコードできます。

于 2012-12-07T14:01:34.483 に答える