【问题标题】:Out of Memory Error during image compression图像压缩期间内存不足错误
【发布时间】:2015-10-29 10:42:22
【问题描述】:

我目前正在按照this site 的教程来压缩我的图像。它在一些手机上运行良好,例如 LG G3、Moto G 和一些三星型号。但是,对于小米4等部分手机,会导致该行出现Out-of-Memory错误。

options.inTempStorage = new byte[16 * 1024];

整个代码如下-

public Bitmap compressImage(String imageLocation) {
    Bitmap scaledBitmap = null;

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    Bitmap bmp = BitmapFactory.decodeFile(imageLocation, options);

    int actualHeight = options.outHeight;
    int actualWidth = options.outWidth;
    float maxHeight = 700.0f;//816.0f;
    float maxWidth = 500.0f; //612.0f;
    float imgRatio = actualWidth / actualHeight;
    float maxRatio = maxWidth / maxHeight;

    if (actualHeight > maxHeight || actualWidth > maxWidth) {
        if (imgRatio < maxRatio) {
            imgRatio = maxHeight / actualHeight;
            actualWidth = (int) (imgRatio * actualWidth);
            actualHeight = (int) maxHeight;
        } else if (imgRatio > maxRatio) {
            imgRatio = maxWidth / actualWidth;
            actualHeight = (int) (imgRatio * actualHeight);
            actualWidth = (int) maxWidth;
        } else {
            actualHeight = (int) maxHeight;
            actualWidth = (int) maxWidth;
        }
    }
    //options.inSampleSize = utils.calculateInSampleSize(options, actualWidth, actualHeight);
    options.inJustDecodeBounds = false;
    options.inDither = false;
    options.inPurgeable = true;
    options.inInputShareable = true;
    options.inTempStorage = new byte[16 * 1024];
    try {
        bmp = BitmapFactory.decodeFile(imageLocation, options);
    } catch (OutOfMemoryError exception) {
        exception.printStackTrace();
    }
    try {
        scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
    } catch (OutOfMemoryError exception) {
        exception.printStackTrace();
    }

    float ratioX = actualWidth / (float) options.outWidth;
    float ratioY = actualHeight / (float) options.outHeight;
    float middleX = actualWidth / 2.0f;
    float middleY = actualHeight / 2.0f;

    Matrix scaleMatrix = new Matrix();
    scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);

    Canvas canvas = new Canvas(scaledBitmap);
    canvas.setMatrix(scaleMatrix);
    canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));


    ExifInterface exif;
    try {
        exif = new ExifInterface(imageLocation);

        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
        Log.d("EXIF", "Exif: " + orientation);
        Matrix matrix = new Matrix();
        if (orientation == 6) {
            matrix.postRotate(90);
            Log.d("EXIF", "Exif: " + orientation);
        } else if (orientation == 3) {
            matrix.postRotate(180);
            Log.d("EXIF", "Exif: " + orientation);
        } else if (orientation == 8) {
            matrix.postRotate(270);
            Log.d("EXIF", "Exif: " + orientation);
        }
        scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
    } catch (IOException e) {
        e.printStackTrace();
    }

    return scaledBitmap;
}

有人可以帮我/就如何改进此代码以减少内存提供建议。

【问题讨论】:

  • 你可以降低质量
  • 尝试设置 options.inSampleSize = 16

标签: android bitmap compression out-of-memory


【解决方案1】:

您正在处理大型位图并在运行时加载所有位图 时间。您必须通过加载非常小心地处理大型位图 您不需要一次整个位图然后执行的大小 缩放。

请查看以下链接

  1. Is it possible to catch out of memory exception in java?

【讨论】:

  • 我在该活动中只加载一个位图。
  • @VarunAgarwal 好的。减小图像大小
  • 此代码用于减小图像大小。我从相机拍摄图像(2-4mb 取决于相机)并将其缩小到 700kb 左右。但它不适用于小米 m4 和其他一些。如果我使用异步任务会有所不同吗?
  • @VarunAgarwal 你可以试试async task。但主要问题是大尺寸。我想这就是为什么有问题
  • 是的,但现在 xiomi 图片是这样大小的。所以我必须处理和压缩它们,因为如果我按原样上传图像,它会花费太长时间,而且根本不会有效率。
【解决方案2】:

您应该根据所需的大小设置样本大小。尝试设置 options.inSampleSize 动态。即

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

//方法

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 = 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;
            }
        }

        return inSampleSize;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多