BitmapFactory.Options常用的几个参数

项目中用到了加载图片的地方,总结了一下简单的对图片加载处理:

BitmapFactory提供了一些decode(解码)获取Bitmap实例的方法,例如decodeByteArray(), decodeFile(), decodeResource()等等,我们可以使用这些方法直接读取文件,读取Resourse,读取文件流等多种形式从而获取Bitmap资源, 然而在构造相对应位图时会尝试分配物理内存,就可能存在OOM了…

**对于这个问题的解决我们可以在解码时传入BitmapFactory.Options标识来声明解码规则:**
BimapFactory.Options options = new BitmapFatory.Options();
options.inJustDecodeBounds = true;
1.设置inJustDecodeBounds属性,不必加载全部资源到内存中,而是仅仅获取资源的边界参数,它会返回一个值为null的Bitamp引用,从而获取原资源的宽,高,类型等属性值;
Google API : If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.
BitmapFactory.decodeFile("filepath",options)
int height = options.outHeight;
int width = options.outWidth;
String mimetype = options.outMimeType;

在获取到边界参数后再做相应的逻辑来实现控制逻辑 …

 2. 实现加载可缩放的图片资源

上面我们获取了源文件的具体尺寸,接下来就要处理数据了,如果我们原图是1080*1980像素的图片,想要显示在300*200像素的View里面,那么我就要在解码时来约束解码的过程,我们需要压缩资源,这是需要设置inSampleSize的值:

options.inSampleSize = 1;

对于inSamplesize的说明Goole API阐述:

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.

大概意思是:如果设置为值> 1,要求解码器以子采样原始图像,返回一个较小的图像以节省内存。样本大小是对应于位图的解码的单个像素中任一维的像素数。例如,inSampleSize == 4返回一个图像是1/4原来的宽度/高度,和1/16的像素数。任何值<= 1同等对待。注意:所述解码器使用基于2的幂的最终值,任何其它值将被向下舍入为最接近2的幂。

然后我们通过已知的View的尺寸和源文件的尺寸来动态修改inSamplesize的值,来自定义解码时的采样尺寸;

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

这样我们就可以根据我们需要定义的条件来控制inSamplesize的动态值,如实际需求不服主要修改while(条件)即可,正确设置采样比例后就可以知己使用控制值了:

BimapFactory.Options options = new BitmapFatory.Options();
options.inJustDecodeBounds = true;
options.inSampleSize = calculateInSampleSize(options,200,300);
options.inJustDecodeBounds = false;
Bitmap bitmap = BitamapFactory.decodeFile("filepath",options);
imageView.setIamgeBitmap(bitmap);

这样就实现了一个主动控制图片缩放的设置了,不会因为解码过大的图片而大量申请内存了;
NOTE: 在真正要解码前一定要设置inJustDecodeBounds = false标识值;

3.设置解码时图片压缩的色彩质量参数;

在解码时可以设置引用Bitmap.Config的参数,用来保存解码后的色彩值:

options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Google API 原文: If this is non-null, the decoder will try to decode into this internal configuration. If it is null, or the request cannot be met, the decoder will try to pick the best matching config based on the system's screen depth, and characteristics of the original image such as if it has per-pixel alpha (requiring a config that also does). Image are loaded with the ARGB_8888 config by default.
大致意思:如果是这种非空,解码器将尝试解码成这个内部配置。如果为空,或者该请求不能被满足,则解码器将尝试挑选基于所述系统的屏幕深度的最佳匹配的配置,以及诸如如果它具有每像素的α的原始图像的特征(要求一个配置也一样)。图片加载与默认ARGB_8888配置。

Android 中通常设置四种常用色彩质量参数来控制渲染的色彩的质量,在源码中定义了四个枚举值:

 public enum Config {
        // these native values must match up with the enum in SkBitmap.h
        /**
         * Each pixel is stored as a single translucency (alpha) channel.
         * This is very useful to efficiently store masks for instance.
         * No color information is stored.
         * With this configuration, each pixel requires 1 byte of memory.
         * 每个像素都会作为透明的信息存储,一个像素占1个字节;
         */
        ALPHA_8     (1),

        /**
         * Each pixel is stored on 2 bytes and only the RGB channels are
         * encoded: red is stored with 5 bits of precision (32 possible
         * values), green is stored with 6 bits of precision (64 possible
         * values) and blue is stored with 5 bits of precision.
         *
         * This configuration can produce slight visual artifacts depending
         * on the configuration of the source. For instance, without
         * dithering, the result might show a greenish tint. To get better
         * results dithering should be applied.
         *
         * This configuration may be useful when using opaque bitmaps
         * that do not require high color fidelity.
         * 每个像素占用2字节,使用不需要高色彩保真度不透明位图时,这个配置会更好一些;
         */
        RGB_565     (3),

        /**
         * Each pixel is stored on 2 bytes. The three RGB color channels
         * and the alpha channel (translucency) are stored with a 4 bits
         * precision (16 possible values.)
         *
         * This configuration is mostly useful if the application needs
         * to store translucency information but also needs to save
         * memory.
         *
         * It is recommended to use {@link #ARGB_8888} instead of this
         * configuration.
         *
         * Note: as of {@link android.os.Build.VERSION_CODES#KITKAT},
         * any bitmap created with this configuration will be created
         * using {@link #ARGB_8888} instead.
         *
         * @deprecated Because of the poor quality of this configuration,
         *             it is advised to use {@link #ARGB_8888} instead.
         * 每个像素占2字节,应该尽可能地使用ARGB_8888配置来替换它;
         */
        ARGB_4444   (4),

        /**
         * Each pixel is stored on 4 bytes. Each channel (RGB and alpha
         * for translucency) is stored with 8 bits of precision (256
         * possible values.)
         *
         * This configuration is very flexible and offers the best
         * quality. It should be used whenever possible.
         * 每个像素占4个字节...它会提供最好的图片质量,应尽可能地使用这个参数;
         */
        ARGB_8888   (5);
    }

根据我们要呈现的效果来选择不同的配置。

更多信息请参考;Google API 文档

你可能感兴趣的:(android)