Android图片压缩(二次采样)

二次采样是为了避免图片加载时的OOM异常。

1.第一次采样

第一次采样我主要是想要获得图片的压缩比例,假如说我有一张图片是200*200,那么我想把这张图片的缩略图显示在一个50*50的ImageView上,那我的压缩比例应该为4,那么这个4应该怎么样来获得呢?这就是我们第一步的操作了,我先加载图片的边界到内存中,这个加载操作并不会耗费多少内存,加载到内存之后,我就可以获得这张图片的宽高参数,然后根据图片的宽高,再结合控件的宽高计算出缩放比例。

2.第二次采样

在第一次采样的基础上,我来进行二次采样。二次采样的时候,我把第一次采样后算出来的结果作为一个参数传递给第BitmapFactory,这样在加载图片的时候系统就不会将整张图片加载进来了,而是只会加载该图片的一张缩略图进来,这样不仅提高了加载速率,而且也极大的节省了内存,而且对于用户来说,他也不会有视觉上的差异。

package com.xiaoyehai.threadpool;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

/**
 * 对图片进行二次采样的工具类
 * Created by xiaoyehai on 2016/12/30.
 */
public class CompressImageUtil {

    /**
     * 对资源文件中的图片进行压缩
     *
     * @param context    上下文对象
     * @param imageId    压缩图片的id
     * @param destWidth  显示图片的控件宽度
     * @param destHeight 显示图片的控件高度
     * @return
     */
    public static Bitmap getBitmap(Context context, int imageId, int destWidth, int destHeight) {
        //创建一个可选项对象,该对象用于配置图片的处理参数
        BitmapFactory.Options options = new BitmapFactory.Options();

        //第一次采样,该属性设置为true只会加载图片的边框进来,并不会加载图片具体的像素点,也就是说不会把图片加载到内存中
        options.inJustDecodeBounds = true;

        //加载图片,该方法只是从图片文件中读取图片的宽和高信息,而没有真正的加载到内存中
        BitmapFactory.decodeResource(context.getResources(), imageId, options);

        //获取图片的宽和高
        int imageWidth = options.outWidth;
        int imageHeight = options.outHeight;

        //定义缩放比例
        int sampleSize = 1;
        while (imageWidth / sampleSize > destHeight || imageHeight / sampleSize > destWidth) {
            //如果宽高的任意一方的缩放比例没有达到要求,都继续增大缩放比例
            //sampleSize应该为2的n次幂,如果给sampleSize设置的数字不是2的n次幂,那么系统会就近取值
            sampleSize *= 2;
        }

        //第二次采样,使用缩放比例进行缩放加载图,加载器就会返回图片了
        options.inJustDecodeBounds = false;

        //设置压缩比
        options.inSampleSize = sampleSize;

        /**
         * inPreferredConfig设置图片的质量:
         * ARGB_8888:默认的图片质量,也是最好的质量,32位,4个字节
         * ARGB_4444:是ARGB_8888占用内存的一半,但质量比较低,不推荐使用
         * RGB_565:不带透明度,是ARGB_8888占用内存的一半,质量不错,推荐使用
         */
        //设置图片质量
        options.inPreferredConfig = Bitmap.Config.RGB_565;

        //返回压缩后的图片
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), imageId, options);

        //Log.i("info", "压缩后图片的大小:" + bitmap.getByteCount());
        return bitmap;
    }

    /**
     * 对内存卡中的图片进行压缩
     *
     * @param path       图片路径
     * @param destWidth  显示图片的控件宽度
     * @param destHeight 显示图片的控件高度
     * @return
     */
    public static Bitmap getBitmap(String path, int destWidth, int destHeight) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);
        int imageWidth = options.outWidth;
        int imageHeight = options.outHeight;
        int sampleSize = 1;
        while (imageWidth / sampleSize > destHeight || imageHeight / sampleSize > destWidth) {
            sampleSize *= 2;
        }

        options.inJustDecodeBounds = false;
        options.inSampleSize = sampleSize;
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        Bitmap bitmap = BitmapFactory.decodeFile(path, options);

        //Log.i("info", "压缩后图片的大小:" + bitmap.getByteCount());
        return bitmap;
    }

    /**
     * 通过网络请求返回的字节数据进行二次采样并返回bitmap
     *
     * @param bytes
     * @param destWidth  显示图片的控件宽度
     * @param destHeight 显示图片的控件高度
     * @return
     */
    public static Bitmap getBitmap(byte[] bytes, int destWidth, int destHeight) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
        int imageWidth = options.outWidth;
        int imageHeight = options.outHeight;
        int sampleSize = 1;
        while (imageWidth / sampleSize > destHeight || imageHeight / sampleSize > destWidth) {
            sampleSize *= 2;
        }

        options.inJustDecodeBounds = false;
        options.inSampleSize = sampleSize;
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);

        // Log.i("info", "压缩后图片的大小:" + bitmap.getByteCount());
        return bitmap;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_36699930/article/details/80406776