android 图片压缩之 injustdecodebounds

转载自:博客园 博主 减掉一斤是一斤 

今天给大家分享的是解决解析图片的出现oom的问题,我们可以用BitmapFactory这里的各种Decode方法,如果图片很小的话,不会出现oom,但是当图片很大的时候
就要用BitmapFactory.Options这个东东了,Options里主要有两个参数比较重要.

options.inJustDecodeBounds = false/true;  
//图片压缩比例.  
options.inSampleSize = ssize;  
我们去解析一个图片,如果太大,就会OOM,我们可以设置压缩比例inSampleSize,但是这个压缩比例设置多少就是个问题,所以我们解析图片可以分为俩个步骤,

第一步就是获取图片的宽高

        这里要设置Options.inJustDecodeBounds=true,这时候decode的bitmap为null,只是把图片的宽高放在Options里,

然后第二步就是设置合适的压缩比例inSampleSize,这时候获得合适的Bitmap.这里我画了简单的流程图,如下:

主要是通过BitmapFactory.Options 来实现。

Options中有个属性inJustDecodeBounds。我们可以充分利用它,来避免大图片的溢出问题。他是什么原理呢?

API这样说:如果该 值设为true那么将不返回实际的bitmap,也不给其分配内存空间这样就避免内存溢出了。但是允许我们查询图片的信息这其中就包括图片大小信息(

options.outHeight (图片原始高度)和option.outWidth(图片原始宽度))。

Options中有个属性inSampleSize。我们可以充分利用它,实现缩放。

如果被设置为一个值> 1,要求解码器解码出原始图像的一个子样本,返回一个较小的bitmap,以节省存储空间。

例如,inSampleSize = = 2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。

对于任何值< = 1的同样处置为1。

那么相应的方法也就出来了,通过设置 inJustDecodeBounds为true,获取到outHeight(图片原始高度)和 outWidth(图片的原始宽度),然后计算一个inSampleSize(缩放值),

然后就可以取图片了,这里要注意的是,inSampleSize 可能小于0,必须做判断。

实现步骤:

第一步:BitmapFactory.Option

设置 inJustDecodeBounds为true

第二步:BitmapFactory.decodeFile(path,option)方法

解码图片路径为一个位图。如果指定的文件名是空的,或者不能解码到一个位图,函数将返回null[空值]。

获取到outHeight(图片原始高度)和 outWidth(图片的原始宽度)

第三步:计算缩放比例,也可以不计算,直接给它设定一个值。

options.inSampleSize = "你的缩放倍数";

如果是2就是高度和宽度都是原始的一半。

第四步:设置options.inJustDecodeBounds = false;

重新读出图片

bitmap = BitmapFactory.decodeFile(path, options);

具体实现:

package xiaosi.compress;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;

public class Compress extends Activity
{
    /** Called when the activity is first created. */
    private ImageView    image    = null;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        image = (ImageView) findViewById(R.id.image);
        image.setImageBitmap(decodeBitmap());
    }

    public Bitmap decodeBitmap()
    {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        // 通过这个bitmap获取图片的宽和高       
        Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/MTXX/3.jpg", options);
        if (bitmap == null)
        {
            System.out.println("bitmap为空");
        }
        float realWidth = options.outWidth;
        float realHeight = options.outHeight;
        System.out.println("真实图片高度:" + realHeight + "宽度:" + realWidth);
        // 计算缩放比       
        int scale = (int) ((realHeight > realWidth ? realHeight : realWidth) / 100);
        if (scale <= 0)
        {
            scale = 1;
        }
        options.inSampleSize = scale;
        options.inJustDecodeBounds = false;
        // 注意这次要把options.inJustDecodeBounds 设为 false,这次图片是要读取出来的。      
        bitmap = BitmapFactory.decodeFile("/sdcard/MTXX/3.jpg", options);
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        System.out.println("缩略图高度:" + h + "宽度:" + w);
        return bitmap;
    }
}
------------------------

补充:

保存bitmap 到文件

    /**
     * 保存bitmap到sd卡filePath文件中 如果有,则删除
     * @param bitmap
     * @param filePath :图片绝对路径
     * @return
     */
    public static boolean saveBitmap2file(Bitmap bitmap,String filePath){
        if (bitmap==null){
            return false;
        }
        //压缩格式
        CompressFormat format = CompressFormat.JPEG;
        int quality =100;
        OutputStream stream=null;
        File file=new File(filePath);
        File dir=file.getParentFile();
        if (!dir.exists()){
            dir.mkdirs();//创建父目录
        }
        if (file.exists()){
            file.delete();
        }

        try {
            stream = new FileOutputStream(filePath);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return  bitmap.compress(format,quality,stream);
    }
在由 bitmap 保存到 文件的过程中需要的还可以使用 Bitmap.compress  方法 对图片进行进一步的压缩

public boolean compress(CompressFormat format, int quality, OutputStream stream) {}
quality :0~100 表示压缩率,如:当quality=30,表示压缩率为70% ; 即quality 值越小图片越失真

网友观点:

Android的JPG保存方法降质比较厉害,保存大概3、4次后出现明显马赛克,保存PNG虽然能防止但速度太慢,所以我公司现在保存JPG都是调自己写的一套JPG库来保存

参考资料:多次compress 傲娇Android二三事之天不长地不久的Bitmap.compress

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 中进行图片压缩可以使用以下两种方式: 1. 使用 BitmapFactory 进行图片压缩 ```java public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // 首先将 inJustDecodeBounds 设置为 true,解析图片的宽高信息,不将图片的像素加载到内存中 final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // 根据计算出的 inSampleSize 来进行图片的压缩 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // 将 inJustDecodeBounds 设置为 false,重新解析图片,这次会将图片的像素加载到内存中 options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); } public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // 获取图片的原始宽高 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; // 计算 inSampleSize 的值,确保宽高都不会超过目标宽高 while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { inSampleSize *= 2; } } return inSampleSize; } ``` 调用该方法时,可以指定需要压缩到的目标宽高: ```java Bitmap compressedBitmap = decodeSampledBitmapFromResource(getResources(), R.drawable.image, 500, 500); ``` 2. 使用第三方库进行图片压缩Android 中有很多第三方库可以用来进行图片压缩,比如: - Luban:https://github.com/Curzibn/Luban - Compressor:https://github.com/zetbaitsu/Compressor 这些库通常都提供了简单易用的 API,可以很方便地进行图片压缩

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值