欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 图片压缩(防止OOM、尺寸压缩、质量压缩)

程序员文章站 2022-06-02 22:27:05
android开发中,图片的处理基本有有所接触,对于图片的压缩也有很多的博客提到,我也是查看了许多的博客后,自己总结了一下,写了一个测试的demo,我测试的图片是6720*4480 12.9m的图片...

android开发中,图片的处理基本有有所接触,对于图片的压缩也有很多的博客提到,我也是查看了许多的博客后,自己总结了一下,写了一个测试的demo,我测试的图片是6720*4480 12.9m的图片,压缩到91.24kb,下面是全部的代码,有需要改进的地方请在评论区提出,android新人还请各位大牛多多指教 !

首先在加载图片的时候要防止oom

    /**
     * 将本地路径转化为bitmap
     *
     * @param path 本地路径
     * @return 返回本地资源的bitmap
     */
    private bitmap loadfile(string path) {
        file mfile = new file(path);
        bitmap mbitmap = null;
        //判读文件是否存在
        if (mfile.exists()) {
            bitmapfactory.options moptions = new bitmapfactory.options();
            //设置只加载尺寸资源
            moptions.injustdecodebounds = true;
            //设置资源
            bitmapfactory.decodefile(path, moptions);
            //图片加载缩方处理
            coundscale(moptions);
            //设置加载资源模式
            moptions.injustdecodebounds = false;
            //设置资源
            mbitmap = bitmapfactory.decodefile(path, moptions);
        }
        return mbitmap;
    }


    /**
     * 计算缩放比例,防止oom
     *
     * @param opeions bitmapfactory.options
     */
    private void coundscale(bitmapfactory.options opeions) {
        if (opeions != null) {
            //原图的尺寸
            int orginalwidht = opeions.outwidth;
            int orginalhieght = opeions.outheight;
            //如果图片尺寸大于一定尺寸的时候进行缩放
            if (orginalwidht > 1080 || orginalhieght > 1920) {
                //缩小倍数
                int scale = 1;

                if (orginalwidht > orginalhieght) {
                    //长图片的时候(以宽度为基准缩小)
                    scale = orginalwidht / 1080;
                } else if (orginalwidht < orginalhieght) {
                    //高图的时候(以高度为基准缩小)
                    scale = orginalhieght / 1920;
                } else {
                    //正方形图的时候(以宽度为基准缩小)
                    scale = orginalwidht / 1080;
                }
                log.i(tag, "coundscale: " + scale);
                opeions.insamplesize = scale;
            }
        }
    }

统一图片的尺寸

    /**
     * 进行图片尺寸裁剪
     *
     * @param loadbitmap 本地图片资源
     * @return 尺寸处理后的资源
     */
    private bitmap cutfile(bitmap loadbitmap) {
        bitmap mcutbitmap = null;
        if (loadbitmap != null) {
            //获取经过第一次处理后图片的尺寸;
            int mloadbitmapwidth = loadbitmap.getwidth();
            int mloadbitmapheight = loadbitmap.getheight();
            float scalex = 0;
            float scaley = 0;
            //图片的宽高比例
            float picscale = (float) mloadbitmapwidth / mloadbitmapheight;
            //计算压缩尺寸比(无论图片大小,直接规定尺寸)
            if (mloadbitmapwidth > mloadbitmapheight) {
                //长图片的时候(宽度缩放到1080,高度安装原图的宽高比缩放尺寸)
                scalex = 1080.0f / mloadbitmapwidth;
                scaley = 1080.0f / picscale / mloadbitmapheight;
            } else if (mloadbitmapwidth < mloadbitmapheight) {
                //高图的时候
                scalex = 1080.0f / mloadbitmapwidth;
                scaley = 1920.0f / mloadbitmapheight;
            } else {
                //正方形图的时候(按照宽度为基准缩放)
                scalex = 1080.0f / mloadbitmapwidth;
                scaley = scalex;
            }
            //创建一个矩阵
            matrix mmatrix = new matrix();
            //设置缩放比例
            mmatrix.postscale(scalex, scaley);
            //生成新的bitmap
            mcutbitmap = bitmap.createbitmap(loadbitmap, 0, 0, mloadbitmapwidth, mloadbitmapheight, mmatrix, false);
        }
        return mcutbitmap;
    }

降低图片的质量

    /**
     * 质量压缩
     *
     * @param mbitmap 处理尺寸后的资源
     * @return 压缩结束后的文件
     */
    private file qualtiy(bitmap mbitmap) {
        file mfile = null;
        if (mbitmap != null) {
            //设置压缩后图片不超过100kb
            int maxkb = 100;
            //创建一个缓存区
            bytearrayoutputstream mbytearrayoutputstream = new bytearrayoutputstream();
            //默认压缩质量(不压缩)
            int options = 100;
            //压缩后的大小
            int endkb = 0;
            do {
                //清空缓存区
                mbytearrayoutputstream.reset();
                //将数据写入缓存区
                mbitmap.compress(bitmap.compressformat.jpeg, options, mbytearrayoutputstream);
                //降低质量
                options -= 5;
                //重新计算缓存区数据大小
                endkb = mbytearrayoutputstream.tobytearray().length;
                //如果压缩系数小于0的时候直接跳出循环
                if (options <= 0) {
                    break;
                }
                //判断当前资源大小是否大于期望大小
            } while (endkb / 1024 > maxkb);
            //创建一个输入流
            fileoutputstream mfileoutputstream = null;
            bufferedoutputstream mbufferedoutputstream = null;
            //创建一个空文件
            mfile = new file(environment.getexternalstoragedirectory().getabsolutepath() + "/manageend.jpg");
            try {
                mfileoutputstream = new fileoutputstream(mfile);
                mbufferedoutputstream = new bufferedoutputstream(mfileoutputstream);
                //将压缩后的数据写入都空文件中
                mbufferedoutputstream.write(mbytearrayoutputstream.tobytearray());
            } catch (filenotfoundexception e) {
                e.printstacktrace();
            } catch (ioexception e) {
                e.printstacktrace();
            } finally {
                try {
                    if (mbytearrayoutputstream != null && mbufferedoutputstream != null && mfileoutputstream != null) {
                        //关闭流
                        mbytearrayoutputstream.flush();
                        mbufferedoutputstream.flush();
                        mfileoutputstream.close();
                        mbufferedoutputstream.close();
                        mbytearrayoutputstream.close();
                    }
                } catch (ioexception e) {
                    e.printstacktrace();
                }
            }
        }
        return mfile;
    }