Android三种常见的图片压缩方式
作者:唠嗑008 发布时间:2022-12-21 06:03:59
下面就为大家带来3种比较常见的压缩方式
先给出一组数据
原图:width:2976; height:2976
原图实际:--->byte:2299820 Mb:2.19328
质量压缩 size--->:byte:1599831 kb:1562.33496
按比例压缩 size--->:byte:191707 kb:187.21387
鲁班压缩 size--->:byte:143792 kb:140.42188
压缩效果:鲁班压缩 > 按比例压缩 > 质量压缩
1、质量压缩
public void getBitmap(String imgPath, String outPath) {
BitmapFactory.Options newOpts = new BitmapFactory.Options();
newOpts.inJustDecodeBounds = false;
newOpts.inPurgeable = true;
newOpts.inInputShareable = true;
// Do not compress
newOpts.inSampleSize = 1;
newOpts.inPreferredConfig = Config.RGB_565;
storeImage(bitmap, outPath); //保存图片
}
注意
质量压缩不会减少图片的像素,它是在保持像素的前提下改变图片的位深及透明度等,来达到压缩图片的目的,这也是为什么该方法叫质量压缩方法。所以这种方法,很可能不会减少图片的大小
如果是bit.compress(CompressFormat.PNG, quality, baos);这样的png格式,quality就没有作用了,bytes.length不会变化,因为png图片是无损的,不能进行压缩
保存图片
/**
* 把bitmap转化成图片存储在本地
*
* @param bitmap
* @param outPath 本地的存储路径
* @throws FileNotFoundException
*/
public static boolean storeImage(Bitmap bitmap, String outPath) throws FileNotFoundException {
FileOutputStream os = new FileOutputStream(outPath);
boolean compressResult = bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
return compressResult;
}
2、按比例压缩(尺寸压缩、采样率压缩)
/**
* 按比例压缩
*
* @param path 原图片路径
* @param targetW 压缩后宽度
* @param targetH 压缩后高度
* @return 压缩后的图片的保存路径
*/
public static String compressScale(String path,, String outPath, int targetW, int targetH) throws FileNotFoundException {
// 获取option
BitmapFactory.Options options = new BitmapFactory.Options();
// inJustDecodeBounds设置为true,这样使用该option decode出来的Bitmap是null,
// 只是把长宽存放到option中
options.inJustDecodeBounds = true;
// 此时bitmap为null
Bitmap bitmap = BitmapFactory.decodeFile(path, options);
int inSampleSize = 1; // 1是不缩放
// 计算宽高缩放比例
int inSampleSizeW = options.outWidth / targetW;
int inSampleSizeH = options.outHeight / targetH;
// 最终取大的那个为缩放比例,这样才能适配,例如宽缩放3倍才能适配屏幕,而
// 高不缩放就可以,那样的话如果按高缩放,宽在屏幕内就显示不下了
if (inSampleSizeW > inSampleSizeH) {
inSampleSize = inSampleSizeW;
} else {
inSampleSize = inSampleSizeH;
}
// 一定要记得将inJustDecodeBounds设为false,否则Bitmap为null
options.inJustDecodeBounds = false;
// 设置缩放比例(采样率)
options.inSampleSize = inSampleSize;
bitmap = BitmapFactory.decodeFile(path, options);
boolean isSuccess = storeImage(bitmap, outPath);
if (isSuccess) {
return outPath;
}
return "";
}
这种方法是设置图片的采样率,降低图片像素,通过缩放图片像素来减少图片大小。
那么我又是如何来获取图片压缩前后的大小的呢?
注意:这里的图片的大小是指图片的实际大小,不是bitmap在内存中所占的大小,看压缩效果,就得看图片在文件中所占的大小。
/**
* 获取本地文件大小
*
* @param imgPath 图片的路径
* @return 图片实际的大小,单位byte
*/
public static int getFileSize(String imgPath) {
int size = 0;
try {
FileInputStream fis = new FileInputStream(new File(imgPath));
size = fis.available();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return size;
}
3、鲁班压缩(推荐)
鲁班压缩是根据一种算法得出来的,压缩效果基本上和微信一致,差不多在200k以内,图片不失真。
鲁班压缩:
https://github.com/Curzibn/Luban
build.gradle添加依赖
compile 'top.zibin:Luban:1.1.3'
private void lunBanPress(String path) {
String pressPath = Environment.getExternalStorageDirectory().getPath();
Luban.with(this)
.load(path) // 传人要压缩的图片列表
.ignoreBy(100) // 忽略不压缩图片的大小
.setTargetDir(pressPath) // 设置压缩后文件存储位置
.setCompressListener(new OnCompressListener() { //设置回调
@Override
public void onStart() {
// TODO 压缩开始前调用,可以在方法内启动 loading UI
Log.i(TAG, "onStart:开始鲁班压缩 ");
}
@Override
public void onSuccess(File file) {
// TODO 压缩成功后调用,返回压缩后的图片文件
Glide.with(activity).load(file).into(iv2);
Log.i(TAG, "onSuccess: 鲁班压缩成功 :");
try {
int size = new FileInputStream(file).available();
Log.i("tag", "鲁班压缩 size--->:" + "byte:" + size + " kb:"
+ (float) size / 1024);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onError(Throwable e) {
// TODO 当压缩过程出现问题时调用
Log.i(TAG, "onError: 鲁班压缩出错");
}
}).launch(); //启动压缩
}
源码地址:
https://github.com/zhouxu88/ImgCompress
到这里就结束啦~
来源:https://mp.weixin.qq.com/s/2ELx5c5EqZ27EUjwViPrXQ
猜你喜欢
- 闲话不多说,直接上图。给大家讲讲我的编程思想吧。第一部分:沉浸式状态栏(API-Level 19, Android4.4 KitKat 之后
- 现假设某个公司采用公用电话来传递数据,数据是四位的整数,在传递过程中是加密的。加密规则是每位数字都加上5,然后再用除以10的余数代替该数字,
- 代码背景一个班级,有两类学生,A类:不学习,玩,但是玩的东西不一样,有的是做游戏,有的是看电视B类:放哨的学生,专门看老师的动向,如果老师进
- 本文介绍了AndroidStudio3.0开发调试安卓NDK的C++代码,分享给大家,具有如下:一、新建项目新建项目,没有发现Include
- 问题描述最近IDEA抽风了,不管是新建SpringBoot工程,还是导入项目。IDEA代码里面都会飘红~Build项目时,会提示错误:错误:
- 代码分2块,server端:class Program {  
- 需求: 给定一个URL地址, 例如: http://www.cncounter.com/tools/shorturl.php, 解析对应的I
- 线程池类图我们最常使用的Executors实现创建线程池使用线程主要是用上述类图中提供的类。在上边的类图中,包含了一个Executor框架,
- 本文实例为大家分享了C#超市收银系统设计的具体代码,供大家参考,具体内容如下1.登录界面代码如下:using System;using Sy
- 最近研究了一下Contacts源码,仿照上面自己写了一个TabHostTest程序,现整理如下:main.xml布局文件:<?xml
- 以下内容归纳了通过Java程序打印PDF文档时的3种情形。即:1 静默打印2 显示打印对话框打印3 打印PDF时自定义纸张大小使用工具:Sp
- 使用开源框架是,可以直接复制源代码到自己的项目(本人在Android Studio中操作报R程序包不存在),也可以使用jar包,下面记录一下
- 1)在我们的项目中添加引用文件:TaskSchedulerEngine.dll(dll定义了一个ITask接口,定义了两个方法Initial
- 我们先来看本地如何生成图片验证码的,再来写输出到网页的验证码如何实现。先来看最简单的—实现的功能是,将一个字符串变成图片写入到文件中实现代码
- springboot-dubbo cannot be cast to使用spring boot 集成dubbo的时候遇到问题:2018-05
- 问题: 在win10系统中,使用IDEA 查看源码的时候,经常跳转代码,这样会让使用者感觉和方便,但是当你想要返回上次跳转的位置时,却不知道
- 简介功能需求如图所示,点击下一个按钮,所有卡片向右滚动,其中最后一张需要变更为最前面的一张,点击上一个按钮,所有卡片向左滚动,最前面的一张需
- SpringBoot starter用了springboot 那么久了居然都还没自定义过starter,想想都觉得羞愧,所以今天来玩一下。S
- 最近根据项目需要,整理了一个相对比较全面的 WheelView 使用控件,借用之前看到的一句话来说,就是站在巨人肩膀上,进行了一些小调整。
- 前言关于mybatis-plus的简介以及基本使用,我在《SpringBoot整合mybatis-plus–入门超详细》一文中已做介绍,此处