位图大小调整会导致内存不足

时间:2015-08-28 11:04:45

标签: java android bitmap out-of-memory

我有一个简单的类来根据我的要求调整位图图像的大小。有一个简单的方法负责如下:

public static Bitmap ResizeRichImages(Bitmap bitmap, Context mContext){
        try {
        float originalBitmapWidth = bitmap.getWidth();
        float originalBitmapHeight = bitmap.getHeight();
        float originalAspectRatio = originalBitmapWidth/originalBitmapHeight;
        double width_percentage = (0.05*screenWidthPixels(mContext));
        float newWidth = (float)((int)screenWidthPixels(mContext)-width_percentage);
        float newBitmapWidth = newWidth;
        float newBitmapHeight = newBitmapWidth/originalAspectRatio;
        bitmap = Bitmap.createScaledBitmap(bitmap, (int) newWidth, (int)newBitmapHeight, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;

    }

这就是我称之为这种方法的方式:

String URL = "https://maps.googleapis.com/maps/api/staticmap?center=-33.86527274921529,151.2050531328867&zoom=15&size=640x360&sensor=false&markers=color:blue%7Clabel:!%7C-33.86527274921529,151.2050531328867";

try {
bmp = Picasso.with(ViewStory.this).load(URL)
                                                            .get();
bmp = ImageController.ResizeRichImages(bmp, ViewStory.this);
                                                } catch (Exception e) {
                                                    e.printStackTrace();
                                                }

但是,几乎每次我在调用ResizeRichImages方法时都会出现内存不足异常。我哪里错了?

4 个答案:

答案 0 :(得分:0)

  • 相反,在清单中使用largeHeap选项应始终是最后一个选项,您可以尝试压缩,如下面的代码段。

*

byteArrImage = null;

ByteArrayOutputStream baos = new ByteArrayOutputStream();
if(data != null) thumbnail = (Bitmap) data.getExtras().get("data");
if(thumbnail != null) {
    //thumbnail.compress(Bitmap.CompressFormat.PNG, 85, baos);
    thumbnail.compress(Bitmap.CompressFormat.JPEG, 85, baos);
    byteArrImage = baos.toByteArray();
    uploadImageToServer();
}

答案 1 :(得分:0)

之前我遇到了同样的错误,但经过一些搜索我发现了另一种调整大型Bitmap图像的方法。将Bitmap与大图像一起使用时,必须使用BitmapFactory.Options.inSampleSize缩放图像。样本大小是任一维度中对应于解码位图中的单个像素的像素数。当您使用inSampleSize = 4时,它返回的图像是原始图像的宽度/高度的1/4。您还可以在Android开发者网站中看到更多细节。

使用此方法调整大小

private Bitmap decodeFileWithSmallSize(String sdcard_path) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
Bitmap myBitmap = BitmapFactory.decodeFile(sdcard_path, options);
return myBitmap;
}

在活动中使用

try {
    Bitmap bitmap = null;
    if (bitmap != null) {
        bitmap.recycle();
        bitmap = null;
    }
    bitmap = decodeFileWithSmallSize("path");
} 
catch (OutOfMemoryError e)
{
    Log.e("TAG",
            "OutOfMemoryError Exception" + e.getMessage());
}

答案 2 :(得分:0)

通常在处理位图时,我们需要根据所需的宽度和高度减少位图的样本量来减小内存大小。

如果你想传递位图,这个函数需要位图文件路径根据你的要求改变它。但这是正确加载图像的正确方法。

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

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

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

// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, 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 = 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;
}

有关详细信息,请参阅此链接:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

在您的情况下,如果您将最低级别定位为19,那么请使用api级别19上提供的重新配置功能 visit developers site

答案 3 :(得分:-1)

您还没有告诉我们您的位图有多大。也许它只是耗尽了你所有的可用内存,特别是如果你有其他大的位图(或其他东西)占用了大部分内存。

我会尝试在小位图上运行该过程,并将newBitmapWidth和newBitmapHeight减少到现在的十分之一。如果这样可以消除异常,那么在您处理完整尺寸之前,您确定需要优化内存使用。