Android之图片压缩几种方式

大概可以分为以下几类:更换图片格式,质量压缩,采样率压缩,缩放压缩,调用jpeg压缩等

1.设置图片格式

Android目前常用的图片格式有png,jpeg和webp,
png无损压缩图片格式 ,支持Alpha通道,Android切图素材多采用此格式
jpeg:有损压缩图片格式 ,不支持背景透明,适用于照片等色彩丰富的大图压缩,不适合logo
webp :是一种同时提供了有损压缩和无损压缩的图片格式 ,派生自视频编码格式VP8,从谷歌官网来看,无损webp平均比png小26%,有损的webp平均比jpeg小25%~34%,无损webp支持Alpha通道,有损webp在一定的条件下同样支持,有损webp在Android4.0(API 14)之后支持,无损和透明在Android4.3(API18)之后支持
采用webp能够在保持图片清晰度的情况下,可以有效减小图片所占有的磁盘空间大小

2.质量压缩

质量压缩并不会改变图片在内存中的大小,仅仅会减小图片所占用的磁盘空间的大小,因为质量压缩不会改变图片的分辨率,而图片在内存中的大小是根据widthheight一个像素的所占用的字节数计算的,宽高没变,在内存中占用的大小自然不会变,**质量压缩的原理是通过改变图片的位深和透明度来减小图片占用的磁盘空间大小,所以不适合作为缩略图,可以用于想保持图片质量的同时减小图片所占用的磁盘空间大小。**另外,由于png是无损压缩,所以设置quality无效,以下是实现方式:

java 复制代码
    /**
     * 质量压缩
     *
     * @param format  图片格式 jpeg,png,webp
     * @param quality 图片的质量,0-100,数值越小质量越差
     */
    public static void compress(Bitmap.CompressFormat format, int quality) {
        File sdFile = Environment.getExternalStorageDirectory();
        File originFile = new File(sdFile, "originImg.jpg");
        Bitmap originBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath());
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        originBitmap.compress(format, quality, bos);
        try {
            FileOutputStream fos = new FileOutputStream(new File(sdFile, "child.jpg"));
            fos.write(bos.toByteArray());
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

3.采样率压缩

采样率压缩是通过设置BitmapFactory.Options.inSampleSize,来减小图片的分辨率,进而减小图片所占用的磁盘空间和内存大小。

设置的inSampleSize会导致压缩的图片的宽高都为1/inSampleSize,整体大小变为原始图片的inSampleSize平方分之一,当然,这些有些注意点:

1、inSampleSize小于等于1会按照1处理

2、inSampleSize只能设置为2的平方,不是2的平方则最终会减小到最近的2的平方数,如设置7会按4进行压缩,设置15会按8进行压缩。

具体的代码实现方式如下:

java 复制代码
    /**
     * @param inSampleSize 可以根据需求计算出合理的inSampleSize
     */
    public static void compress(int inSampleSize) {
        File sdFile = Environment.getExternalStorageDirectory();
        File originFile = new File(sdFile, "originImg.jpg");
        BitmapFactory.Options options = new BitmapFactory.Options();
        //设置此参数是仅仅读取图片的宽高到options中,不会将整张图片读到内存中,防止oom
        options.inJustDecodeBounds = true;
        Bitmap emptyBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath(), options);

        options.inJustDecodeBounds = false;
        options.inSampleSize = inSampleSize;
        Bitmap resultBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath(), options);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
        try {
            FileOutputStream fos = new FileOutputStream(new File(sdFile, "resultImg.jpg"));
            fos.write(bos.toByteArray());
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4.缩放压缩

通过减少图片的像素来降低图片的磁盘空间大小和内存大小,可以用于缓存缩略图

实现方式如下:

java 复制代码
    public void compress(View v) {
        File sdFile = Environment.getExternalStorageDirectory();
        File originFile = new File(sdFile, "originImg.jpg");
        Bitmap bitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath());
        //设置缩放比
        int radio = 8;
        Bitmap result = Bitmap.createBitmap(bitmap.getWidth() / radio, bitmap.getHeight() / radio, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(result);
        RectF rectF = new RectF(0, 0, bitmap.getWidth() / radio, bitmap.getHeight() / radio);
        //将原图画在缩放之后的矩形上
        canvas.drawBitmap(bitmap, null, rectF, null);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        result.compress(Bitmap.CompressFormat.JPEG, 100, bos);
        try {
            FileOutputStream fos = new FileOutputStream(new File(sdFile, "sizeCompress.jpg"));
            fos.write(bos.toByteArray());
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

5.其他

在缩放压缩的时候,可通过Bitmap.createBitmap(bitmap.getWidth() / radio, bitmap.getHeight() / radio, Bitmap.Config.ARGB_8888),如果不需要图片的透明度,可以将ARGB_8888改成RGB_565,这样之前每个像素占用4个字节,现在只需要2个字节,节省了一半的大小。

总结

1、使用webp格式的图片可以在保持清晰度的情况下减小图片的磁盘大小,是一种比较优秀的,google推荐的图片格式

2、质量压缩可以减小图片占用的磁盘空间,不会减小在内存中的大小

3、采样率压缩可以通过改变分辨率来减小图片所占用的磁盘空间和内存空间大小,但是采样率只能设置2的n次方,可能图片的最优比例在中间

4、尺寸压缩同样也是通过改变分辨率来减小图片所占用的磁盘空间和内存空间大小,缩放的尺寸没有限制

相关推荐
拭心4 小时前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
带电的小王7 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡7 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道7 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库8 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道9 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe9 小时前
Android Hook - 动态加载so库
android
居居飒10 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
Henry_He12 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗13 小时前
Android笔试面试题AI答之Android基础(1)
android