1 分类
Android图片压缩结合多种压缩方式,常用的有尺寸压缩、质量压缩、采样率压缩以及通过JNI调用libjpeg库来进行压缩。
参考此方法:Android-BitherCompress

备注:对于资源图片直接使用:tiny压缩

2 质量压缩
(1)原理:保持像素的前提下改变图片的位深及透明度,(即:通过算法抠掉(同化)了图片中的一些某个些点附近相近的像素),达到降低质量压缩文件大小的目的。

注意:它其实只能实现对file的影响,对加载这个图片出来的bitmap内存是无法节省的,还是那么大。因为bitmap在内存中的大小是按照像素计算的,也就是width*height,对于质量压缩,并不会改变图片的真实的像素(像素大小不会变)。

(2)使用场景:将图片压缩后将图片上传到服务器,或者保存到本地。根据实际需求来。

(3)源码示例
---------------------
作者:陈李冠
来源:CSDN
原文:https://blog.csdn.net/chenliguan/article/details/54409442
版权声明:本文为博主原创文章,转载请附上博文链接!

/**
* 3.质量压缩
* 设置bitmap options属性,降低图片的质量,像素不会减少
* 第一个参数为需要压缩的bitmap图片对象,第二个参数为压缩后图片保存的位置
* 设置options 属性0-100,来实现压缩
*
* @param bmp
* @param file
*/
public static void qualityCompress(Bitmap bmp, File file) {
// 0-100 100为不压缩
int quality = ;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 把压缩后的数据存放到baos中
bmp.compress(Bitmap.CompressFormat.JPEG, quality, baos);
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}

3 尺寸压缩

(1)原理:通过减少单位尺寸的像素值,正真意义上的降低像素。1020*8880–

(2)使用场景:缓存缩略图的时候(头像处理)

(3)源码示例

/**
* 4.尺寸压缩(通过缩放图片像素来减少图片占用内存大小)
*
* @param bmp
* @param file
*/ public static void sizeCompress(Bitmap bmp, File file) {
// 尺寸压缩倍数,值越大,图片尺寸越小
int ratio = ;
// 压缩Bitmap到对应尺寸
Bitmap result = Bitmap.createBitmap(bmp.getWidth() / ratio, bmp.getHeight() / ratio, Config.ARGB_8888);
Canvas canvas = new Canvas(result);
Rect rect = new Rect(, , bmp.getWidth() / ratio, bmp.getHeight() / ratio);
canvas.drawBitmap(bmp, null, rect, null); ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 把压缩后的数据存放到baos中
result.compress(Bitmap.CompressFormat.JPEG, , baos);
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}

4 采样率压缩
(1)原理:设置图片的采样率,降低图片像素

(2) 好处:是不会先将大图片读入内存,大大减少了内存的使用,也不必考虑将大图片读入内存后的释放事宜。

(3)问题:因为采样率是整数,所以不能很好的保证图片的质量。如我们需要的是在2和3采样率之间,用2的话图片就大了一点,但是用3的话图片质量就会有很明显的下降,这样也无法完全满足我的需要。

(4)源码示例

/**
* 5.采样率压缩(设置图片的采样率,降低图片像素)
*
* @param filePath
* @param file
*/
public static void samplingRateCompress(String filePath, File file) {
// 数值越高,图片像素越低
int inSampleSize = ;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
// options.inJustDecodeBounds = true;//为true的时候不会真正加载图片,而是得到图片的宽高信息。
//采样率
options.inSampleSize = inSampleSize;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 把压缩后的数据存放到baos中
bitmap.compress(Bitmap.CompressFormat.JPEG, , baos);
try {
if (file.exists()) {
file.delete();
} else {
file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}

5 JNI终极压缩
5.1 Android图像处理引擎的缺漏
为什么IOS拍照1M的图片要比安卓拍照排出来的5M的图片还要清晰。都是在同一个环境下,保存的都是JPEG?

(1)历程
95年 JPEG处理引擎,用于最初的在PC上面处理图片的引擎。
05年 skia开源的引擎, 开发了一套基于JPEG处理引擎的第二次开发。便于浏览器的使用。
07年安卓用的skia引擎(阉割版),谷歌拿了skia,去掉一个编码算法—哈夫曼算法。采用定长编码算法。但是解码还是保留了哈夫曼算法,导致了图片处理后文件变大了。
(2)原因
当时由于CPU和内存在手机上都非常吃紧 性能差,由于哈夫曼算法非常吃CPU,被迫用了其他的算法。
(3)优化方案
绕过安卓Bitmap API层,来自己编码实现—-修复使用哈夫曼算法。

5.2 哈夫曼算法
哈夫曼树详解点击—数据结构与算法之二叉树+遍历+哈夫曼树

(1)ARGB:一个像素点包涵四个信息:alpha,red,green,blue
(2)如何得到每一个字母出现的权重?需要去扫描整个信息(图片信息–每一个像素包括ARGB),要大量计算,很耗CPU,1280*800像素*4。
(2)

5.3 JNI开发步骤(大概步骤,具体实现未定)
(1)准备工作

()http://www.ijg.org/下载JPEG引擎使用的库---libjpeg库,
基于该引擎来做一定的开发----自己实现编码,JNI开发。
()导入库文件libjpegbither.so
()导入头文件
()写mk文件——Android.mk、Applicatoin.mk
()写代码——C++:XX.cpp、C:XX.c

(2)开发过程

()将android的bitmap解码,并转换成RGB数据
一个图片信息---像素点(argb),alpha去掉
()JPEG对象分配空间以及初始化
()指定压缩数据源
()获取文件信息
()为压缩设置参数,比如图像大小、类型、颜色空间
boolean arith_code;
/* TRUE=arithmetic coding, FALSE=Huffman */
()开始压缩——jpeg_start_compress()
()压缩结束——jpeg_finish_compress()
()释放资源

5.4 源码示例

/**
* 1.JNI终极压缩(通过JNI图片压缩把Bitmap保存到指定目录)
*
* @param image bitmap对象
* @param filePath 要保存的指定目录
* @Description: 通过JNI图片压缩把Bitmap保存到指定目录
*/
public static void jniUltimateCompress(Bitmap image, String filePath) {
// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int quality = ;
// JNI调用保存图片到SD卡 这个关键
NativeUtil.saveBitmap(image, quality, filePath, true);
} /**
* 1.JNI基本压缩(不保存Bitmap)
*
* @param bit bitmap对象
* @param fileName 指定保存目录名
* @param optimize 是否采用哈弗曼表数据计算 品质相差5-10倍
* @Description: JNI基本压缩
*/
public static void jniBasicCompress(Bitmap bit, String fileName, boolean optimize) {
saveBitmap(bit, DEFAULT_QUALITY, fileName, optimize);
} /**
* 调用native方法
*
* @param bit
* @param quality
* @param fileName
* @param optimize
* @Description:函数描述
*/
private static void saveBitmap(Bitmap bit, int quality, String fileName, boolean optimize) {
compressBitmap(bit, bit.getWidth(), bit.getHeight(), quality, fileName.getBytes(), optimize);
} /**
* 调用底层 bitherlibjni.c中的方法
*
* @param bit
* @param w
* @param h
* @param quality
* @param fileNameBytes
* @param optimize
* @return
* @Description:函数描述
*/
private static native String compressBitmap(Bitmap bit, int w, int h, int quality, byte[] fileNameBytes,
boolean optimize); /**
* 加载lib下两个so文件
*/
static {
System.loadLibrary("jpegbither");
System.loadLibrary("bitherjni");
}

6 混合终极方法

(1)原理:三种方式结合使用实现指定图片内存大小,清晰度达到最优。

(2)使用场景:大图压缩,同时对图片质量要求较高。

(3)源码示例

/**
* 2.混合终极方法(尺寸、质量、JNI压缩)
*
* @param image bitmap对象
* @param filePath 要保存的指定目录
* @Description: 通过JNI图片压缩把Bitmap保存到指定目录
*/
public static void mixCompress(Bitmap image, String filePath) {
// 最大图片大小 1000KB
int maxSize = ;
// 获取尺寸压缩倍数
int ratio = NativeUtil.getRatioSize(image.getWidth(), image.getHeight());
// 压缩Bitmap到对应尺寸
Bitmap result = Bitmap.createBitmap(image.getWidth() / ratio, image.getHeight() / ratio, Config.ARGB_8888);
Canvas canvas = new Canvas(result);
Rect rect = new Rect(, , image.getWidth() / ratio, image.getHeight() / ratio);
canvas.drawBitmap(image, null, rect, null); ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int quality = ;
result.compress(Bitmap.CompressFormat.JPEG, quality, baos);
// 循环判断如果压缩后图片是否大于最大值,大于继续压缩
while (baos.toByteArray().length / > maxSize) {
// 重置baos即清空baos
baos.reset();
// 每次都减少10
quality -= ;
// 这里压缩options%,把压缩后的数据存放到baos中
result.compress(Bitmap.CompressFormat.JPEG, quality, baos);
}
// JNI调用保存图片到SD卡 这个关键
NativeUtil.saveBitmap(result, quality, filePath, true);
// 释放Bitmap
if (result != null && !result.isRecycled()) {
result.recycle();
result = null;
}
} /**
* 计算缩放比
*
* @param bitWidth 当前图片宽度
* @param bitHeight 当前图片高度
* @return
* @Description:函数描述
*/
public static int getRatioSize(int bitWidth, int bitHeight) {
// 图片最大分辨率
int imageHeight = ;
int imageWidth = ;
// 缩放比
int ratio = ;
// 缩放比,由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
if (bitWidth > bitHeight && bitWidth > imageHeight) {
// 如果图片宽度比高度大,以宽度为基准
ratio = bitWidth / imageHeight;
} else if (bitWidth < bitHeight && bitHeight > imageHeight) {
// 如果图片高度比宽度大,以高度为基准
ratio = bitHeight / imageHeight;
}
// 最小比率为1
if (ratio <= )
ratio = ;
return ratio;
}

7 多种方法对比
7.1 当图片内存大于1MB
(1)原图内存是3.22MB
(2)截图如下:

(3)效果:
尺寸压缩后图片太模糊;
混合终极方法压缩效果更佳,与jni终极方法压缩内存区别不大;
质量压缩后图片与jni终极方法压缩后图片效果接近,略显模糊;
(4)总结:可以考虑使用混合终极方法。

7.2 当图片内存小于1MB
(1)原图内存是109.94KB
(2)截图如下:

(3)效果:

尺寸压缩后图片太模糊;
混合终极方法压缩后内存反而增加了一半;
质量压缩后图片和jni终极方法压缩后图片效果接近,但是内存更大;
jni终极方法压缩后图片效果与原图相差不大,内存也不大。

(4)总结:可以考虑使用jni终极方法。

8 参考链接

Android图片压缩(质量压缩和尺寸压缩)&Bitmap转成字符串上传

Android性能优化之图片压缩优化的更多相关文章

  1. Android 性能优化——之图片的优化

    Android 性能优化——之图片的优化 在Android性能优化中,我们会发现占内存最大的和对性能影响最大的往往是图片资源,其次是控件资源.相对来说,其他的资源的影响会小一点.这里我就先对图片资源的 ...

  2. Android 图片内存优化与图片压缩

    1. 对图片本身进行操作 尽量不要使用 setImageBitmap.setImageResource. BitmapFactory.decodeResource 来设置一张大图,因为这些方法在完成 ...

  3. 【Android - 进阶】之图片压缩

    很多时候,如果APP需要下载和加载很多图片(尤其是大图片)的时候,就往往会报如下图所示的错误: 如上图所示,OOM(OutOfMemoryError)表示内存溢出,这是因为网络或内存中的图片被加载成B ...

  4. android内存优化之图片压缩和缓存

    由于手机内存的限制和网络流量的费用现在,我们在加载图片的时候,必须要做好图片的压缩和缓存. 图片缓存机制一般有2种,软引用和内存缓存技术. 1.压缩图片:压缩图片要既不能模糊,也不能拉伸图片. 图片操 ...

  5. 图片压缩优化kraken

    https://kraken.io/web-interface 测试过,可以节省10%左右的大小,图片清晰度不受影响.

  6. png图片压缩优化

    1.2 软件环境 软件名称:Opting下载地址: http://optipng.sourceforge.net/ 安装版本:0.7.5安装位置:/apps/svr/opting 安装可能遇到的问题: ...

  7. android bitmap compress(图片压缩)

    android bitmap compress android的照相功能随着手机硬件的发展,变得越来越强大,能够找出很高分辨率的图片. 有些场景中,需要照相并且上传到服务,但是由于图片的大小太大,那么 ...

  8. [Android算法] bitmap 将图片压缩到指定的大小

    Bitmap压缩到指定大小: private void imageZoom() {//图片允许最大空间 单位:KBdouble maxSize =400.00;//将bitmap放至数组中,意在bit ...

  9. 前端构建工具之gulp(一)「图片压缩」

    前端构建工具之gulp(一)「图片压缩」 已经很久没有写过博客了,现下终于事情少了,开始写博吧 今天网站要做一些优化:图片压缩,资源合并等 以前一直使用百度的FIS工具,但是FIS还没有提供图片压缩的 ...

随机推荐

  1. C# Math.Round实现中国式四舍五入

    decimal sum = 11111.334; sum = , MidpointRounding.AwayFromZero);  sum:11111.33decimal sum = 11111.34 ...

  2. spring注解第02课 包扫描@ComponentScan、@ComponentScans

    1.配置文件形式: <context:component-scan base-package="com.atguigu" /> spring会扫描此包下的@Servic ...

  3. spring boot2 整合(一)Mybatis (特别完整!)

    大概介绍下流程: 借助idea实现mybatis逆向工程 用xml配置实现整合 用cmd命令行实现mybatis逆向工程 用mapping.xml配置实现数据交互 用注解的方式实现数据交互 首先我的开 ...

  4. 求f(n)=[n/1]+[n/2]+---+[n/n]的值 简单杂题

    这种小题首先根据 n/1+n/2+n/3+--+n/n=nlogn+欧拉常数r 可以知道 1e12的范围也不会爆longlong,不需要写高精度(到现在都不会写) 再根据数据范围可知O(n)级别的暴力 ...

  5. Coursera Deep Learning 2 Improving Deep Neural Networks: Hyperparameter tuning, Regularization and Optimization - week1, Assignment(Gradient Checking)

    声明:所有内容来自coursera,作为个人学习笔记记录在这里. Gradient Checking Welcome to the final assignment for this week! In ...

  6. HMM拓扑与转移模型

        <Topology> <TopologyEntry> <ForPhones> 1 2 3 4 5 6 7 8 </ForPhones> < ...

  7. Tomcat清理日志文件无法立即释放磁盘空间

    1 自己删除了Tomcat的日志文件,但是依然显示磁盘百分百占用 进入Tomcat目录显示日志已经删除 查询磁盘空间依旧百分百占用 2 自己杀死Tomcat进程然后重启,成功释放空间 3 原因,通过网 ...

  8. 代码管理工具Git的安装及使用

    一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 二:SVN与Git的最主要的区别? SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以 ...

  9. 5-4日 socket套接字

    1,socket定义 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面 ...

  10. Service Mesh

    概念 A service mesh is a dedicated infrastructure layer for handling service-to-service communication. ...