当前位置: 代码网 > it编程>App开发>Android > Android---性能优化之图片压缩

Android---性能优化之图片压缩

2024年08月06日 Android 我要评论
质量压缩会用到 Bitmap.compress()。这个方法有三个参数:Bitmap.CompressFormat format:图像的压缩格式(jpeg ,png, webp);,0--100。0 压缩率为 100%,100 意味着不压缩;OutputStream stream:写入压缩数据的数据流。返回值:如果成功把压缩数据写入写入输出流,则返回 true;

质量压缩

质量压缩会用到 bitmap.compress()。

public boolean compress(bitmap.compressformat format, int quality, outputstream stream);

这个方法有三个参数:

\bullet bitmap.compressformat format:图像的压缩格式(jpeg ,png, webp); 

\bullet int quality:图像压缩率,0--100。0 压缩率为 100%,100 意味着不压缩;

\bullet outputstream stream:写入压缩数据的数据流。

返回值:

\bullet 如果成功把压缩数据写入写入输出流,则返回 true;

代码:

    /**
     * todo 图片质量压缩
     * @param image 要压缩的图片
     * @param maximagesize 最大质量(单位:kb)
     * @return
     */
    private bitmap compressimagequality(bitmap image, int maximagesize) {

        bytearrayoutputstream baos = new bytearrayoutputstream();
        // todo 将 bitmap 写入到 baos 这个输出流中(bytearrayoutputstream)
        image.compress(bitmap.compressformat.jpeg, 100, baos);

        int options = 100;
        do {

            options -= 10;
            baos.reset();
            image.compress(bitmap.compressformat.jpeg, options, baos);

        }while (baos.tobytearray().length / 1024 > maximagesize && options > 0);

        bytearrayinputstream bais = new bytearrayinputstream(baos.tobytearray());
        bitmap compressedimage = bitmapfactory.decodestream(bais, null, null);
        // 把压缩后的图片保存到相册
        saveimagetogallery(this, compressedimage, "compress_image.png");
        //
        return compressedimage;
    }

尺寸压缩

options

\bullet 属性 injustdecodebounds,如果该值为 true,那么将不返回实际的 bitmap,也不给其分配内存空间这样就避免内存溢出了。但允许我们查询图片的信息,这其中就包括图片大小信息,options.outheight(图片原始高度)和 option.outwidth(图片原始宽度)

\bullet 属性 insamplesize,我们可以使用它实现缩放,如果被设置为一个值,在图片解码时,将图片按照指定的比例进行缩小,从而降低图片的尺寸。例如,insamplesize=2,则取出的缩略图的宽和高都是原始图片的 1/2,图片大小就为原始大小的 1/4。

两次 decode,传入不同的 options 配置:

 第一次 injustdecodebounds = false,获取 outheight/outwidth 原始宽高,不加载图片到内存里。再获取合适的 insamplesize 后,然后再设置  injustdecodebounds = true,把合适的图像正真加载到内存里面来。

代码:

/**
     * 对图片进行尺寸压缩
     */
    private bitmap compressimagesize(string imagepath, int reqwidth, int reqheight){
        bitmapfactory.options options = new bitmapfactory.options();
        options.injustdecodebounds = true;
        // 参数1:要解码的文件的完整文件路径
        bitmapfactory.decodefile(imagepath, options);
        
        // 图片的原始宽高
        int height = options.outheight;
        int width = options.outwidth;
        int insamplesize = 1; // 刚开始的缩放比例为1

        // 计算图片缩放比例
        if (height > reqheight || width > reqwidth) {
            int halfheight = height / 2;
            int halfwidth = width / 2;
            while ((halfheight / insamplesize) >= reqheight
                    && (halfwidth / insamplesize) >= reqwidth) {
                insamplesize *= 2; // 扩大缩放比例,为 2^n
            }

        }

        // 使用计算出的缩放比例解码图片
        options.insamplesize = insamplesize;
        options.injustdecodebounds = false;
        bitmap compressimagesize = bitmapfactory.decodefile(imagepath, options);
        // 保存图片到相册
        saveimagetogallery(this, compressimagesize, "compress_size.png");
        return compressimagesize;
    }

 这个方法接收三个参数:图片路径、期望的宽度和期望的高度。

图片的路径:iamgepath 该怎么传。我这里是以打开相册选取一张图片,然后在 onactivityresult 回调中,回去到一个 uri。

//todo 获取选择的图片
uri uri = data.getdata();
// todo 获取图片路径
mimagepath = getrealpathfromuri(uri);

然后再调用 getrealpathfromuri() 函数来获取到选择图片的真实路径。

 /**
     * 根据 uri 获取图片的真实路径
     * todo 在 onactivityresult() 回调中获取到图片的 uri, 然后通过‘contentresolver' 获取到图片的时间路径
     */
    private string getrealpathfromuri(uri contenturi){
        string[] projection = {mediastore.images.media.data};
        cursor cursor = getcontentresolver().query(contenturi, projection, null, null, null);
        if (cursor == null) {
            return contenturi.getpath();
        }else {
            cursor.movetofirst();
            int index = cursor.getcolumnindexorthrow(mediastore.images.media.data);
            string path = cursor.getstring(index);
            cursor.close();
            return path;
        }
    }

 首先,我们使用 bitmapfactory.options 的 injustdecodebounds 属性解码图片,这个属性设置为 true 表示只读取图片的原始宽度和高度不会真正加载图片到内存中。接着,我们根据图片的原始宽度和高度,计算出一个合适的 insamplesize, 最后使用这个 insamplesize 解码图片,得到一个缩小了尺寸的 bitmap 对象。

值得注意的是,使用 insamplesize 进行图片压缩时,可能会导致图片的质量变差。这是因为 insamplesize 实际上是将图片缩小了,相当于降低了图片的分辨率。因此,使用这种方式进行图片压缩时,需要根据实际情况选择合适的 insamplesize 值,以平衡图片的尺寸和质量。

native 压缩

libjpeg 是一个完全用 c 语言编写的库,包含了被广泛使用的 jpeg 解码、jpeg 编码和其他的 jpeg 功能的实现。

libjpeg-turbo 图像编解码器,使用了 simd 指令来加速 x86、x86-64、arm 和 power pc 系统上的 jpeg 压缩和解压缩,libjpeg-turbo 的速度通常是 libjepg 的 2-6 倍

使用 libjpeg 对图像数据压缩的流程:

完整 demo

提供上面质量/尺寸压缩的完整代码:包括打开相册的操作、把压缩的图片保存到相册(查看压缩前后图片质量/尺寸的变化)和 xml 等。

链接:https://pan.baidu.com/s/18wzw1l2mza8xtvmwo3wkjg 
提取码:7j4r

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com