【问题标题】:Load big Images in Android在 Android 中加载大图像
【发布时间】:2014-04-10 12:07:33
【问题描述】:

众所周知,Android 在 RAM 内存中存储位图数据时存在问题。我需要在视图上加载图像(来自 13Mpx 相机的照片),然后我需要能够放大和缩小图像。图像应该是可变的。现在是这样实现的:

BitmapFactory.Options options =  new BitmapFactory.Options();
options.inMutable = true;
_bitmap = BitmapFactory.decodeFile(_path, options);

当我拍摄一张大照片(13 或 8 Mpx)时,程序因“内存不足”错误而崩溃。我需要一些解决方案来解决这个问题。我需要一些可以加载和操作(缩放)大图像的类。它需要等于或小于 API-8。

我尝试了 Universall Image Loader,但它没有缩放选项。有人知道如何解决这个问题吗?

【问题讨论】:

标签: java android image


【解决方案1】:

位图每个像素占用 4 个字节 ==> 13MP 等于 52MB 内存。 您应该首先使用 BitmapFactory.Options 来获取大小。通过使用inJustDecodeBounds,您可以获得包含所有元数据的位图对象,但没有实际图像。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;

然后计算你的屏幕需要的比例尺寸:

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

并使用它来加载您的位图的缩放版本:

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

这在Developer Guide中都有解释

【讨论】:

    【解决方案2】:

    我建议使用 Square 的 Picasso 库。和PhotoView 用于图像缩放。

    【讨论】:

      【解决方案3】:

      试试这个来缩放位图

      final BitmapFactory.Options options = new BitmapFactory.Options();
                                  options.inJustDecodeBounds = true;
      
                                  /*
                                   * If set to a value > 1, requests the decoder to
                                   * subsample the original image, returning a smaller
                                   * image to save memory. The sample size is the
                                   * number of pixels in either dimension that
                                   * correspond to a single pixel in the decoded
                                   * bitmap. For example, inSampleSize == 4 returns an
                                   * image that is 1/4 the width/height of the
                                   * original, and 1/16 the number of pixels. Any
                                   * value <= 1 is treated the same as 1. Note: the
                                   * decoder uses a final value based on powers of 2,
                                   * any other value will be rounded down to the
                                   * nearest power of 2.
                                   */
                                  options.inSampleSize = 2;
      
                                  // Decode bitmap with inSampleSize set
                                  options.inJustDecodeBounds = false;
      
                                  bitmap = BitmapFactory.decodeFile(path, options);
      

      【讨论】:

        【解决方案4】:
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
        int imageHeight = options.outHeight;
        int imageWidth = options.outWidth;
        String imageType = options.outMimeType;
        

        为避免java.lang.OutOfMemory 异常,请在解码之前检查位图的尺寸,除非您绝对相信来源会为您提供大小可预测的图像数据,这些数据可以轻松容纳在可用内存中。 Reference

        【讨论】:

          【解决方案5】:

          非常感谢大家的回答。

          我认为我应该使用 inJustDecodeBounds 选项并加载调整大小的位图,但需要更有经验的人对这个问题有新的看法。

          我还考虑过使用 Universal Image Loader 来加载和缓存大图像,并使用 ScaleImageView 来缩放它。

          something可以解决我的问题。部分加载位图。

          【讨论】:

            猜你喜欢
            • 2017-04-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-11-26
            • 2016-04-23
            • 2012-07-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多