Android图像解码海量内存消耗

时间:2015-09-11 13:33:17

标签: android performance android-bitmap

我想在上传之前压缩/重新缩放图片。这是我用于压缩的代码。它适用于非常大的图像,但particular image使用了huge amount of RAM。我已经链接了必要的图像。这是我使用的代码。

我不得不强行调用System.gc()来释放过度使用的内存。

public static File compressImage(File image) throws IOException {

        // Decode just the boundaries
        final BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
        mBitmapOptions.inJustDecodeBounds = true;

        final FileInputStream fileInputStream = new FileInputStream(image);
        final Bitmap temporary = BitmapFactory.decodeStream(fileInputStream, null, mBitmapOptions);
        if (temporary != null)
            temporary.recycle();

        // Calculate inSampleSize
        // Raw height and width of image
        final int height = mBitmapOptions.outHeight;
        final int width = mBitmapOptions.outWidth;
        final int sideLength = 800;
        closeQuietly(fileInputStream);

        int reqHeight = height;
        int reqWidth = width;
        final int inDensity;
        final int inTargetDensity;

        if (height > width) {

            inDensity = height;
            inTargetDensity = reqHeight;
            if (height > sideLength) {

                reqHeight = sideLength;
                reqWidth = (width * sideLength) / height;
            }
        } else if (width > height) {

            inDensity = width;
            inTargetDensity = reqWidth;
            if (width > sideLength) {
                reqWidth = sideLength;
                reqHeight = (height * sideLength) / width;
            }
        } else {

            reqWidth = sideLength;
            reqHeight = sideLength;
            inDensity = height;
            inTargetDensity = reqHeight;
        }

        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth)
                inSampleSize *= 2;
        }

        //now go resize the image to the size you want
        mBitmapOptions.inSampleSize = inSampleSize;
        mBitmapOptions.inDither = true;
        mBitmapOptions.inPreferQualityOverSpeed = true;
        mBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;
        mBitmapOptions.inJustDecodeBounds = false;
        mBitmapOptions.inScaled = true;
        mBitmapOptions.inDensity = inDensity;
        mBitmapOptions.inTargetDensity = inTargetDensity * mBitmapOptions.inSampleSize;

        final File tempFile = File.createTempFile("compressed_profile_photo", null);
        final FileInputStream fInputStream = new FileInputStream(image);
        final FileOutputStream fileOutputStream = new FileOutputStream(tempFile);

        // will load & resize the image to be 1/inSampleSize dimensions
        final Bitmap bitmap = BitmapFactory.decodeStream(fInputStream, null, mBitmapOptions);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 85, fileOutputStream);
        fileOutputStream.flush();
        bitmap.recycle();
        closeQuietly(fInputStream, fileOutputStream);

        //noinspection ResultOfMethodCallIgnored
        image.delete();
        return tempFile;
    }

2 个答案:

答案 0 :(得分:0)

也许只需关注the tip of the Official Training

private void setPic() {
    // Get the dimensions of the View
    int targetW = mImageView.getWidth();
    int targetH = mImageView.getHeight();

    // Get the dimensions of the bitmap
    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(mCurrentPhotoPath, 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(mCurrentPhotoPath, bmOptions);
    mImageView.setImageBitmap(bitmap);
}

答案 1 :(得分:0)

这部分有一个愚蠢的错误:

if (height > width) {

            inDensity = height;
            inTargetDensity = reqHeight;
            if (height > sideLength) {

                reqHeight = sideLength;
                reqWidth = (width * sideLength) / height;
            }
        } else if (width > height) {

            inDensity = width;
            inTargetDensity = reqWidth;
            if (width > sideLength) {
                reqWidth = sideLength;
                reqHeight = (height * sideLength) / width;
            }
        }

它应该是这样的:

if (height > width) {

            if (height > sideLength) {

                reqHeight = sideLength;
                reqWidth = (width * sideLength) / height;
            }
            inDensity = height;
            inTargetDensity = reqHeight;

        } else if (width > height) {

            if (width > sideLength) {
                reqWidth = sideLength;
                reqHeight = (height * sideLength) / width;
            }
            inDensity = width;
            inTargetDensity = reqWidth;

        }

因为调整大小甚至没有发生!