Android 中解决图片加载OOM 之 bitmap 压缩显示,压缩上传

java.lang.OutOfMemoryError

OOM就是内存溢出,即Out Of Memory。也就是说内存占有量超过了VM所分配的最大。

现在的手机照相功能强大图片的大小往往达到好几兆,并且android中处理图片的基础类是Bitmap,顾名思义,就是位图。占用内存的算法如:图片的width*height*Config。 如果Config设置为ARGB_8888,那么上面的Config就是4。一张480*320的图片占用的内存就是480*320*4  byte。 在默认情况下android进程的内存占用量为16M,所以导致了内存溢出,

在手机应用中 如果单独将一张图片加载显示,比如说微信发送图片时可以预览图片,这种情况下直接加载图片也就是用BItMap

 BitmapFactory.decodeFile(pathName);不进行压缩一般不会出现内存溢出,但是在多张图片展示时,会出现oom导致程序崩溃这时我们要进行图片压缩,这部分代码大家都应该很熟悉了,

 public Bitmap revitionImageSize(String path) throws IOException {
        BufferedInputStream in = null;
        try {
<span style="white-space:pre">		</span>//根据地址转换为 文件输入流对象 也可以把File转换成输入对象 
            in = new BufferedInputStream(new FileInputStream(path));
            BitmapFactory.Options options = new BitmapFactory.Options();
           //<span style="font-family: 'Microsoft YaHei', Verdana, sans-serif, 宋体;">Options 设置图片属性</span>
            options.inJustDecodeBounds = true;//这个属性是重点这样设置之后
            BitmapFactory.decodeStream(in, null, options);// 调用这个方法可以不把图片加载到内存中,但可以获取图片的宽高大小
            in.close();
            in = null;
            int i = 0;
            Bitmap bitmap = null;
            while (true) {
                if ((options.outWidth >> i <= 256)
                        && (options.outHeight >> i <= 256)) {
                    in = new BufferedInputStream(new FileInputStream(new File(
                            path)));
                   //调整图片大小
                    options.inSampleSize = calculateInSampleSize(options,
                            CommonUtil.dip2px(this, 80),
                            CommonUtil.dip2px(this, 80));
                    options.inJustDecodeBounds = false;//设置加载到内存中
                    bitmap = BitmapFactory.decodeStream(in, null, options); //创建图片
                    break;
                }
                i += 1;
            }
            return bitmap;
        } catch (Exception e) {
            Log.e("System.out", e.getMessage());
            return null;
        } finally {
            if (null != in) {//关闭流
                in.close();
                in = null;
            }
        }
    }

    // 按照宽高中 短的压缩 
    public 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) {//判断实际大小是不是不要求大小 大
            if (width > height) { //如果 宽度笔高地长的话 安短的一边 计算压缩比
                inSampleSize = Math.round((float) height / (float) reqHeight);
            } else {
                inSampleSize = Math.round((float) width / (float) reqWidth);
            }
        }
        return inSampleSize;
    }
这样返回压缩好的图片,这样只是单纯的压缩了一张图片 显示一张图片,做图片相册类的activity时还涉及到遍历手机sd卡里的所有图片这里就不到说了,

压缩图片上传


图片压缩的部分跟
上面也是差不多的

private void setUpImageFile() {
        FileInputStream is = null;

        File f = null, imageFile; //f压缩后的图片 压缩前的图片文件
        Bitmap image = null;
        try {
            imageFile = new File(path);
            if (imageFile.length() <= 800 * 1024) { // 判端文件大小 800k以内直接上传
                this.upPath = path;
                return;
            }
            is = new FileInputStream(imageFile);
            // 定义一个file,为压缩后的图片
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:sss");
           //创建个文件
            f = new File(Environment.getExternalStorageDirectory() + “/image”, simpleDateFormat.format(new Date()) + "上传.jpeg");
            if (!f.getParentFile().exists())//创建目录
                f.getParentFile().mkdirs();
            int size = (int) (imageFile.length() / (1024 * 1024) * 10);// 计算目标文件的大小 大于1024K压缩到1024k以内 
            size = (int) Math.rint(size / 10);
            Options options = new Options();
            options.inSampleSize = size;
            // 将图片缩小为原来的 1/size ,上传
            image = BitmapFactory.decodeStream(is, null, options);
            is.close();
        } catch (Exception e1) {
            e1.printStackTrace();
            return;
        }
       // 把bitmap创建处理 再次压缩
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 这里100表示不压缩,将不压缩的数据存放到baos中
        int per = 100;
        while (baos.toByteArray().length / 1024 > 1024) { // 循环判断如果压缩后图片是否大于1024kb,大于继续压缩
            baos.reset();// 重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, per, baos);// 将图片压缩为原来的(100-per)%,把压缩后的数据存放到baos中
            per -= 5;// 每次都减少10

        }
        // 回收图片,清理内存
        if (image != null && !image.isRecycled()) {
            image.recycle();
            image = null;
            System.gc();
        }
//把内存中的 image 写到文件中
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
        try {
            baos.close();
            FileOutputStream os;
            os = new FileOutputStream(f);
            // 将输入流复制到输出流中
            CopyStream(isBm, os);
            isBm.close();
            os.close();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        this.upPath = f.getAbsolutePath();
    }

    private void CopyStream(ByteArrayInputStream isBm, FileOutputStream os) {
        byte[] buff = new byte[1024];
        int length = 0;
        try {
            while ((length = isBm.read(buff)) != -1) {
                os.write(buff, 0, length);
            }
        } catch (IOException e) { 
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
这样在sd的/image目录下创建了等待上传的压缩后的文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值