web-dev-qa-db-ja.com

Android上の大きなビットマップファイルのサイズを変更した出力ファイルに変更します

ファイルに大きなビットマップ(3888x2592など)があります。次に、そのビットマップのサイズを800x533に変更し、別のファイルに保存します。通常、Bitmap.createBitmapメソッドを呼び出してビットマップをスケーリングしますが、最初の引数としてソースビットマップが必要です。元の画像をBitmapオブジェクトに読み込むと、もちろんメモリを超えるため、提供できません(- ここ 、たとえば)。

また、正確な幅と高さにサイズを変更するため、BitmapFactory.Options.inSampleSizeを提供するBitmapFactory.decodeFile(file, options)などでビットマップを読み取ることもできません。 inSampleSizeを使用すると、ビットマップのサイズが972x648(inSampleSize=4を使用する場合)または778x518(inSampleSize=5を使用する場合、2の累乗ではない)にサイズ変更されます。

また、たとえば、最初のステップで972x648を使用してinSampleSizeを使用してイメージを読み取ってから、2番目のステップで正確に800x533にサイズ変更することは避けたいと思います。

私の質問をまとめると、10MP以上の大きな画像ファイルを読み取り、特定の新しい幅と高さにサイズ変更した新しい画像ファイルに保存する方法はありますか?

BitmapFactory.decodeFile(file, options)も試して、Options.outHeightとOptions.outWidthの値を手動で800と533に設定しましたが、それはうまくいきません。

209
Manuel

番号。誰かが私を直すことを望みますが、妥協点として試みたロード/サイズ変更アプローチを受け入れました。

閲覧している人のための手順は次のとおりです。

  1. ターゲットよりも大きいイメージを生成する可能性のある最大のinSampleSizeを計算します。
  2. オプションとしてinSampleSizeを渡して、BitmapFactory.decodeFile(file, options)を使用して画像をロードします。
  3. Bitmap.createScaledBitmap()を使用して目的のサイズにサイズ変更します。
141
Justin

Justin answerがコードに翻訳されました(私にとっては完璧です)。

private Bitmap getBitmap(String path) {

Uri uri = getImageUri(path);
InputStream in = null;
try {
    final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
    in = mContentResolver.openInputStream(uri);

    // Decode image size
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(in, null, options);
    in.close();



    int scale = 1;
    while ((options.outWidth * options.outHeight) * (1 / Math.pow(scale, 2)) > 
          IMAGE_MAX_SIZE) {
       scale++;
    }
    Log.d(TAG, "scale = " + scale + ", orig-width: " + options.outWidth + ", 
       orig-height: " + options.outHeight);

    Bitmap resultBitmap = null;
    in = mContentResolver.openInputStream(uri);
    if (scale > 1) {
        scale--;
        // scale to max possible inSampleSize that still yields an image
        // larger than target
        options = new BitmapFactory.Options();
        options.inSampleSize = scale;
        resultBitmap = BitmapFactory.decodeStream(in, null, options);

        // resize to desired dimensions
        int height = resultBitmap.getHeight();
        int width = resultBitmap.getWidth();
        Log.d(TAG, "1th scale operation dimenions - width: " + width + ",
           height: " + height);

        double y = Math.sqrt(IMAGE_MAX_SIZE
                / (((double) width) / height));
        double x = (y / height) * width;

        Bitmap scaledBitmap = Bitmap.createScaledBitmap(resultBitmap, (int) x, 
           (int) y, true);
        resultBitmap.recycle();
        resultBitmap = scaledBitmap;

        System.gc();
    } else {
        resultBitmap = BitmapFactory.decodeStream(in);
    }
    in.close();

    Log.d(TAG, "bitmap size - width: " +resultBitmap.getWidth() + ", height: " + 
       resultBitmap.getHeight());
    return resultBitmap;
} catch (IOException e) {
    Log.e(TAG, e.getMessage(),e);
    return null;
}
93
Ofir

これは「Mojo Risin」と「Ofir」のソリューションを「組み合わせた」ものです。これにより、最大幅と最大高さの境界を持つ比例サイズ変更された画像が得られます。

  1. 元のサイズを取得するためにメタデータを読み取るだけです(options.inJustDecodeBounds)。
  2. それはメモリを節約するために大まかなサイズ変更を使用します(itmap.createScaledBitmap)
  3. それは以前に作成されたラフなBitampに基づいて正確にサイズ変更されたイメージを使います。

私にとっては、5メガピクセル以下の画像で問題なく動作しています。

try
{
    int inWidth = 0;
    int inHeight = 0;

    InputStream in = new FileInputStream(pathOfInputImage);

    // decode image size (decode metadata only, not the whole image)
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(in, null, options);
    in.close();
    in = null;

    // save width and height
    inWidth = options.outWidth;
    inHeight = options.outHeight;

    // decode full image pre-resized
    in = new FileInputStream(pathOfInputImage);
    options = new BitmapFactory.Options();
    // calc rought re-size (this is no exact resize)
    options.inSampleSize = Math.max(inWidth/dstWidth, inHeight/dstHeight);
    // decode full image
    Bitmap roughBitmap = BitmapFactory.decodeStream(in, null, options);

    // calc exact destination size
    Matrix m = new Matrix();
    RectF inRect = new RectF(0, 0, roughBitmap.getWidth(), roughBitmap.getHeight());
    RectF outRect = new RectF(0, 0, dstWidth, dstHeight);
    m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER);
    float[] values = new float[9];
    m.getValues(values);

    // resize bitmap
    Bitmap resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) (roughBitmap.getWidth() * values[0]), (int) (roughBitmap.getHeight() * values[4]), true);

    // save image
    try
    {
        FileOutputStream out = new FileOutputStream(pathOfOutputImage);
        resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
    }
    catch (Exception e)
    {
        Log.e("Image", e.getMessage(), e);
    }
}
catch (IOException e)
{
    Log.e("Image", e.getMessage(), e);
}
43
blubl

なぜAPIを使わないのですか?

int h = 48; // height in pixels
int w = 48; // width in pixels    
Bitmap scaled = Bitmap.createScaledBitmap(largeBitmap, w, h, true);
23
Bostone

これまでのところ他の優れた答えを認めて、私がこれのために今までに見た最もよいコードは写真撮影ツールのためのドキュメンテーションにあります。

「拡大縮小画像のデコード」というタイトルのセクションを参照してください。

http://developer.Android.com/training/camera/photobasics.html

それが提案する解決策は、ここで他の人たちのようにサイズを変更して拡大縮小する解決策です、しかし、それはかなりきれいです。

便宜上、すぐに使える機能として以下のコードをコピーしました。

private void setPic(String imagePath, ImageView destination) {
    int targetW = destination.getWidth();
    int targetH = destination.getHeight();
    // Get the dimensions of the bitmap
    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(imagePath, bmOptions);
    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;

    // Determine how much to scale down the image
    int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

    // Decode the image file into a Bitmap sized to fill the View
    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

    Bitmap bitmap = BitmapFactory.decodeFile(imagePath, bmOptions);
    destination.setImageBitmap(bitmap);
}
20
Alex

これらの答えを読んだ後、 Androidのドキュメント これは、メモリに読み込まずにビットマップのサイズを変更するためのコードです。

public Bitmap getResizedBitmap(int targetW, int targetH,  String imagePath) {

    // Get the dimensions of the bitmap
    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    //inJustDecodeBounds = true <-- will not load the bitmap into memory
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(imagePath, bmOptions);
    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;

    // Determine how much to scale down the image
    int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

    // Decode the image file into a Bitmap sized to fill the View
    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

    Bitmap bitmap = BitmapFactory.decodeFile(imagePath, bmOptions);
    return(bitmap);
}
18
penduDev

大きなビットマップを持っていてサイズを変えてデコードしたいときは、次のようにします。

BitmapFactory.Options options = new BitmapFactory.Options();
InputStream is = null;
is = new FileInputStream(path_to_file);
BitmapFactory.decodeStream(is,null,options);
is.close();
is = new FileInputStream(path_to_file);
// here w and h are the desired width and height
options.inSampleSize = Math.max(options.outWidth/w, options.outHeight/h);
// bitmap is the resized bitmap
Bitmap bitmap = BitmapFactory.decodeStream(is,null,options);
5
Mojo Risin

これは他の誰かがこの質問を見るのに役立つかもしれません。私はJustinのコードを書き換えて、メソッドが必要なターゲットサイズオブジェクトを受け取ることができるようにしました。 Canvasを使用している場合、これはとてもうまくいきます。すべての功績は彼のすばらしい初期コードのためにJUSTINに行くべきです。

    private Bitmap getBitmap(int path, Canvas canvas) {

        Resources resource = null;
        try {
            final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
            resource = getResources();

            // Decode image size
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeResource(resource, path, options);

            int scale = 1;
            while ((options.outWidth * options.outHeight) * (1 / Math.pow(scale, 2)) > 
                  IMAGE_MAX_SIZE) {
               scale++;
            }
            Log.d("TAG", "scale = " + scale + ", orig-width: " + options.outWidth + ", orig-height: " + options.outHeight);

            Bitmap pic = null;
            if (scale > 1) {
                scale--;
                // scale to max possible inSampleSize that still yields an image
                // larger than target
                options = new BitmapFactory.Options();
                options.inSampleSize = scale;
                pic = BitmapFactory.decodeResource(resource, path, options);

                // resize to desired dimensions
                int height = canvas.getHeight();
                int width = canvas.getWidth();
                Log.d("TAG", "1th scale operation dimenions - width: " + width + ", height: " + height);

                double y = Math.sqrt(IMAGE_MAX_SIZE
                        / (((double) width) / height));
                double x = (y / height) * width;

                Bitmap scaledBitmap = Bitmap.createScaledBitmap(pic, (int) x, (int) y, true);
                pic.recycle();
                pic = scaledBitmap;

                System.gc();
            } else {
                pic = BitmapFactory.decodeResource(resource, path);
            }

            Log.d("TAG", "bitmap size - width: " +pic.getWidth() + ", height: " + pic.getHeight());
            return pic;
        } catch (Exception e) {
            Log.e("TAG", e.getMessage(),e);
            return null;
        }
    }

ジャスティンのコードは、大きなビットマップを扱うオーバーヘッドを減らすのに非常に効果的です。

5
Music Monkey

私の解決策がベストプラクティスであるかどうかはわかりませんが、inDensityおよびinTargetDensityオプションを使用して、希望のスケーリングでビットマップをロードすることができました。描画可能リソースをロードしていない場合、inDensityは最初は0なので、このアプローチは非リソースイメージをロードするためのものです。

変数imageUrimaxImageSideLength、およびcontextは、私のメソッドのパラメータです。わかりやすくするために、AsyncTaskをラップせずにメソッド実装のみを掲載しました。

            ContentResolver resolver = context.getContentResolver();
            InputStream is;
            try {
                is = resolver.openInputStream(imageUri);
            } catch (FileNotFoundException e) {
                Log.e(TAG, "Image not found.", e);
                return null;
            }
            Options opts = new Options();
            opts.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(is, null, opts);

            // scale the image
            float maxSideLength = maxImageSideLength;
            float scaleFactor = Math.min(maxSideLength / opts.outWidth, maxSideLength / opts.outHeight);
            // do not upscale!
            if (scaleFactor < 1) {
                opts.inDensity = 10000;
                opts.inTargetDensity = (int) ((float) opts.inDensity * scaleFactor);
            }
            opts.inJustDecodeBounds = false;

            try {
                is.close();
            } catch (IOException e) {
                // ignore
            }
            try {
                is = resolver.openInputStream(imageUri);
            } catch (FileNotFoundException e) {
                Log.e(TAG, "Image not found.", e);
                return null;
            }
            Bitmap bitmap = BitmapFactory.decodeStream(is, null, opts);
            try {
                is.close();
            } catch (IOException e) {
                // ignore
            }

            return bitmap;
4
cybergen

あなたが正確なサイズにリサイズしたいと思い、必要とされるだけ多くの品質を保ちたいということを考慮して、私はあなたがこれを試みるべきであると思います。

  1. BitmapFactory.decodeFileを呼び出してcheckSizeOptions.inJustDecodeBoundsを呼び出し、サイズ変更された画像のサイズを調べます。
  2. あなたがメモリを超えないようにあなたのデバイス上で使用できる最大可能なinSampleSizeを計算します。 bitmapSizeInBytes = 2 *幅*高さ。一般的にあなたの写真にはinSampleSize = 2が良いでしょう。メモリに足を載せる必要があるのは2 * 1944 x 1296)=4.8Mbбだけだからです。
  3. ビットマップをロードするには、inSampleSizeと共にBitmapFactory.decodeFileを使用します。
  4. ビットマップを正確なサイズに調整します。

動機づけ:マルチステップスケーリングはあなたに高品質の写真を与えるかもしれません、しかし、それが高いinSampleSizeを使うことよりよく働くという保証はありません。実際には、inSampleSizeを5のように(2のべき乗ではなく)使用して、1回の操作で直接スケーリングすることもできます。または4を使用するだけで、その画像をUIで使用できます。あなたがそれをサーバーに送るなら - あなたはあなたが高度なスケーリング技術を使うことを可能にするサーバー側で正確なサイズにスケーリングすることができるよりも。

注:step-3で読み込まれたビットマップが少なくとも4倍大きい場合(つまり4 * targetWidth <width)、品質を向上させるためにいくつかのサイズ変更を使用することができます。少なくともそれは一般的なJavaで動作します、Androidではスケーリングに使用される補間を指定するオプションはありません http://today.Java.net/pub/a/today/2007/04/03/ perils-of-image-getscaledinstance.html

2
Andrey Chorniy

上記のコードは少しきれいになりました。 InputStreamは、同様に閉じられるように、最後に閉じています。

*注意
入力:InputStreamは、int w、int hです。
出力:ビットマップ

    try
    {

        final int inWidth;
        final int inHeight;

        final File tempFile = new File(temp, System.currentTimeMillis() + is.toString() + ".temp");

        {

            final FileOutputStream tempOut = new FileOutputStream(tempFile);

            StreamUtil.copyTo(is, tempOut);

            tempOut.close();

        }



        {

            final InputStream in = new FileInputStream(tempFile);
            final BitmapFactory.Options options = new BitmapFactory.Options();

            try {

                // decode image size (decode metadata only, not the whole image)
                options.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(in, null, options);

            }
            finally {
                in.close();
            }

            // save width and height
            inWidth = options.outWidth;
            inHeight = options.outHeight;

        }

        final Bitmap roughBitmap;

        {

            // decode full image pre-resized
            final InputStream in = new FileInputStream(tempFile);

            try {

                final BitmapFactory.Options options = new BitmapFactory.Options();
                // calc rought re-size (this is no exact resize)
                options.inSampleSize = Math.max(inWidth/w, inHeight/h);
                // decode full image
                roughBitmap = BitmapFactory.decodeStream(in, null, options);

            }
            finally {
                in.close();
            }

            tempFile.delete();

        }

        float[] values = new float[9];

        {

            // calc exact destination size
            Matrix m = new Matrix();
            RectF inRect = new RectF(0, 0, roughBitmap.getWidth(), roughBitmap.getHeight());
            RectF outRect = new RectF(0, 0, w, h);
            m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER);
            m.getValues(values);

        }

        // resize bitmap
        final Bitmap resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) (roughBitmap.getWidth() * values[0]), (int) (roughBitmap.getHeight() * values[4]), true);

        return resizedBitmap;

    }
    catch (IOException e) {

        logger.error("Error:" , e);
        throw new ResourceException("could not create bitmap");

    }
2
user1327738

私はこのようなコードを使用しました:

  String filePath=Environment.getExternalStorageDirectory()+"/test_image.jpg";
  BitmapFactory.Options options=new BitmapFactory.Options();
  InputStream is=new FileInputStream(filePath);
  BitmapFactory.decodeStream(is, null, options);
  is.close();
  is=new FileInputStream(filePath);
  // here w and h are the desired width and height
  options.inSampleSize=Math.max(options.outWidth/460, options.outHeight/288); //Max 460 x 288 is my desired...
  // bmp is the resized bitmap
  Bitmap bmp=BitmapFactory.decodeStream(is, null, options);
  is.close();
  Log.d(Constants.TAG, "Scaled bitmap bytes, "+bmp.getRowBytes()+", width:"+bmp.getWidth()+", height:"+bmp.getHeight());

私はオリジナルの画像が1230 x 1230であることを試してみました、そして得られたビットマップは330 x 330であると言いました。
そして2590 x 3849を試してみると、OutOfMemoryErrorが出ます。

私はそれをトレースしました、それでもまだ元のビットマップが大きすぎるならば、それはライン "BitmapFactory.decodeStream(is、null、options);"にOutOfMemoryErrorを投げます...

2
RRTW

これはサイズ変更に別のアプローチをとる記事です。プロセスで使用可能なメモリに基づいて、可能な限り大きいビットマップをメモリにロードしてから、変換を実行します。

http://bricolsoftconsulting.com/2012/12/07/handling-large-images-on-Android/

1
Theo

ピクセルをスキップせずに画像を「正しい」方法で拡大縮小するには、画像デコーダにフックして、行ごとにダウンサンプリングを実行する必要があります。 Android(およびその基盤となるSkiaライブラリ)はそのようなフックを提供していないため、自分でロールバックする必要があります。あなたがJPEG画像を話していると仮定すると、あなたの最善の策はC言語でlibjpegを直接使うことでしょう。

複雑な複雑さを考えると、2段階のサブサンプル - その後 - スケール変更を使用することは、おそらくイメージプレビュータイプのアプリケーションに最適です。

1
D0SBoots

もしあなたがどうしても一段階のサイズ変更をしたいのなら、おそらくAndroid:largeHeap = trueならビットマップ全体をロードすることができますが、ご覧のとおりこれはお勧めできません。

ドキュメントから:Android:largeHeapアプリケーションのプロセスを大きなDalvikヒープで作成するかどうか。これは、アプリケーション用に作成されたすべてのプロセスに適用されます。プロセスにロードされた最初のアプリケーションにのみ適用されます。複数のアプリケーションがプロセスを使用できるようにするために共有ユーザーIDを使用している場合は、それらすべてがこのオプションを一貫して使用する必要があります。そうしないと、予期しない結果が生じます。ほとんどのアプリはこれを必要とせず、代わりにパフォーマンスを向上させるために全体的なメモリ使用量を減らすことに集中するべきです。これを有効にしても、利用可能なメモリの一定の増加を保証するわけではありません。デバイスによっては、利用可能なメモリの総容量によって制約を受けるためです。

1
PSIXO

これは私のために働きました。この関数は、SDカード上のファイルへのパスを取得し、表示可能な最大サイズでビットマップを返します。このコードはOfirのもので、sd上の画像ファイルのような変更がいくつかあります。代わりにRessourceを使用し、幅と高さはDisplay Objectから取得します。

private Bitmap makeBitmap(String path) {

    try {
        final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
        //resource = getResources();

        // Decode image size
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);

        int scale = 1;
        while ((options.outWidth * options.outHeight) * (1 / Math.pow(scale, 2)) >
                IMAGE_MAX_SIZE) {
            scale++;
        }
        Log.d("TAG", "scale = " + scale + ", orig-width: " + options.outWidth + ", orig-height: " + options.outHeight);

        Bitmap pic = null;
        if (scale > 1) {
            scale--;
            // scale to max possible inSampleSize that still yields an image
            // larger than target
            options = new BitmapFactory.Options();
            options.inSampleSize = scale;
            pic = BitmapFactory.decodeFile(path, options);

            // resize to desired dimensions

            Display display = getWindowManager().getDefaultDisplay();
            Point size = new Point();
            display.getSize(size);
            int width = size.y;
            int height = size.x;

            //int height = imageView.getHeight();
            //int width = imageView.getWidth();
            Log.d("TAG", "1th scale operation dimenions - width: " + width + ", height: " + height);

            double y = Math.sqrt(IMAGE_MAX_SIZE
                    / (((double) width) / height));
            double x = (y / height) * width;

            Bitmap scaledBitmap = Bitmap.createScaledBitmap(pic, (int) x, (int) y, true);
            pic.recycle();
            pic = scaledBitmap;

            System.gc();
        } else {
            pic = BitmapFactory.decodeFile(path);
        }

        Log.d("TAG", "bitmap size - width: " +pic.getWidth() + ", height: " + pic.getHeight());
        return pic;

    } catch (Exception e) {
        Log.e("TAG", e.getMessage(),e);
        return null;
    }

}
0
Penta

私はInteger.numberOfLeadingZerosを使って最良のサンプルサイズ、より良いパフォーマンスを計算します。

Kotlinのフルコード:

@Throws(IOException::class)
fun File.decodeBitmap(options: BitmapFactory.Options): Bitmap? {
    return inputStream().use {
        BitmapFactory.decodeStream(it, null, options)
    }
}

@Throws(IOException::class)
fun File.decodeBitmapAtLeast(
        @androidx.annotation.IntRange(from = 1) width: Int,
        @androidx.annotation.IntRange(from = 1) height: Int
): Bitmap? {
    val options = BitmapFactory.Options()

    options.inJustDecodeBounds = true
    decodeBitmap(options)

    val ow = options.outWidth
    val oh = options.outHeight

    if (ow == -1 || oh == -1) return null

    val w = ow / width
    val h = oh / height

    if (w > 1 && h > 1) {
        val p = 31 - maxOf(Integer.numberOfLeadingZeros(w), Integer.numberOfLeadingZeros(h))
        options.inSampleSize = 1 shl maxOf(0, p)
    }
    options.inJustDecodeBounds = false
    return decodeBitmap(options)
}
0
lymoge

これは私が使っているコードで、Android上でメモリ内の大きな画像をデコードするのに問題はありません。私の入力パラメータがおよそ1024x1024である限り、私は20MBより大きい画像をデコードすることができました。返されたビットマップを別のファイルに保存することができます。この方法の下に、画像を新しいビットマップに拡大縮小するためにも使用する別の方法があります。このコードを自由に使用してください。

/*****************************************************************************
 * public decode - decode the image into a Bitmap
 * 
 * @param xyDimension
 *            - The max XY Dimension before the image is scaled down - XY =
 *            1080x1080 and Image = 2000x2000 image will be scaled down to a
 *            value equal or less then set value.
 * @param bitmapConfig
 *            - Bitmap.Config Valid values = ( Bitmap.Config.ARGB_4444,
 *            Bitmap.Config.RGB_565, Bitmap.Config.ARGB_8888 )
 * 
 * @return Bitmap - Image - a value of "null" if there is an issue decoding
 *         image dimension
 * 
 * @throws FileNotFoundException
 *             - If the image has been removed while this operation is
 *             taking place
 */
public Bitmap decode( int xyDimension, Bitmap.Config bitmapConfig ) throws FileNotFoundException
{
    // The Bitmap to return given a Uri to a file
    Bitmap bitmap = null;
    File file = null;
    FileInputStream fis = null;
    InputStream in = null;

    // Try to decode the Uri
    try
    {
        // Initialize scale to no real scaling factor
        double scale = 1;

        // Get FileInputStream to get a FileDescriptor
        file = new File( this.imageUri.getPath() );

        fis = new FileInputStream( file );
        FileDescriptor fd = fis.getFD();

        // Get a BitmapFactory Options object
        BitmapFactory.Options o = new BitmapFactory.Options();

        // Decode only the image size
        o.inJustDecodeBounds = true;
        o.inPreferredConfig = bitmapConfig;

        // Decode to get Width & Height of image only
        BitmapFactory.decodeFileDescriptor( fd, null, o );
        BitmapFactory.decodeStream( null );

        if( o.outHeight > xyDimension || o.outWidth > xyDimension )
        {
            // Change the scale if the image is larger then desired image
            // max size
            scale = Math.pow( 2, (int) Math.round( Math.log( xyDimension / (double) Math.max( o.outHeight, o.outWidth ) ) / Math.log( 0.5 ) ) );
        }

        // Decode with inSampleSize scale will either be 1 or calculated value
        o.inJustDecodeBounds = false;
        o.inSampleSize = (int) scale;

        // Decode the Uri for real with the inSampleSize
        in = new BufferedInputStream( fis );
        bitmap = BitmapFactory.decodeStream( in, null, o );
    }
    catch( OutOfMemoryError e )
    {
        Log.e( DEBUG_TAG, "decode : OutOfMemoryError" );
        e.printStackTrace();
    }
    catch( NullPointerException e )
    {
        Log.e( DEBUG_TAG, "decode : NullPointerException" );
        e.printStackTrace();
    }
    catch( RuntimeException e )
    {
        Log.e( DEBUG_TAG, "decode : RuntimeException" );
        e.printStackTrace();
    }
    catch( FileNotFoundException e )
    {
        Log.e( DEBUG_TAG, "decode : FileNotFoundException" );
        e.printStackTrace();
    }
    catch( IOException e )
    {
        Log.e( DEBUG_TAG, "decode : IOException" );
        e.printStackTrace();
    }

    // Save memory
    file = null;
    fis = null;
    in = null;

    return bitmap;

} // decode

注:createScaledBitmapが上記のdecodeメソッドを呼び出す以外は、メソッドは互いに関係ありません。メモの幅と高さは元の画像とは異なる場合があります。

/*****************************************************************************
 * public createScaledBitmap - Creates a new bitmap, scaled from an existing
 * bitmap.
 * 
 * @param dstWidth
 *            - Scale the width to this dimension
 * @param dstHeight
 *            - Scale the height to this dimension
 * @param xyDimension
 *            - The max XY Dimension before the original image is scaled
 *            down - XY = 1080x1080 and Image = 2000x2000 image will be
 *            scaled down to a value equal or less then set value.
 * @param bitmapConfig
 *            - Bitmap.Config Valid values = ( Bitmap.Config.ARGB_4444,
 *            Bitmap.Config.RGB_565, Bitmap.Config.ARGB_8888 )
 * 
 * @return Bitmap - Image scaled - a value of "null" if there is an issue
 * 
 */
public Bitmap createScaledBitmap( int dstWidth, int dstHeight, int xyDimension, Bitmap.Config bitmapConfig )
{
    Bitmap scaledBitmap = null;

    try
    {
        Bitmap bitmap = this.decode( xyDimension, bitmapConfig );

        // Create an empty Bitmap which will contain the new scaled bitmap
        // This scaled bitmap should be the size we want to scale the
        // original bitmap too
        scaledBitmap = Bitmap.createBitmap( dstWidth, dstHeight, bitmapConfig );

        float ratioX = dstWidth / (float) bitmap.getWidth();
        float ratioY = dstHeight / (float) bitmap.getHeight();
        float middleX = dstWidth / 2.0f;
        float middleY = dstHeight / 2.0f;

        // Used to for scaling the image
        Matrix scaleMatrix = new Matrix();
        scaleMatrix.setScale( ratioX, ratioY, middleX, middleY );

        // Used to do the work of scaling
        Canvas canvas = new Canvas( scaledBitmap );
        canvas.setMatrix( scaleMatrix );
        canvas.drawBitmap( bitmap, middleX - bitmap.getWidth() / 2, middleY - bitmap.getHeight() / 2, new Paint( Paint.FILTER_BITMAP_FLAG ) );
    }
    catch( IllegalArgumentException e )
    {
        Log.e( DEBUG_TAG, "createScaledBitmap : IllegalArgumentException" );
        e.printStackTrace();
    }
    catch( NullPointerException e )
    {
        Log.e( DEBUG_TAG, "createScaledBitmap : NullPointerException" );
        e.printStackTrace();
    }
    catch( FileNotFoundException e )
    {
        Log.e( DEBUG_TAG, "createScaledBitmap : FileNotFoundException" );
        e.printStackTrace();
    }

    return scaledBitmap;
} // End createScaledBitmap
0
user560663
 Bitmap yourBitmap;
 Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true);

または

 resized = Bitmap.createScaledBitmap(yourBitmap,(int)(yourBitmap.getWidth()*0.8), (int)(yourBitmap.getHeight()*0.8), true);
0

この正確な問題に関する素晴らしい記事がAndroid開発者Webサイトにあります。 大きなビットマップを効率的にロードする

0
Muzikant