(相关资料图)
前言:让我们手撸一个图片压缩库,对压缩工具鲁班进行升级改造。
在平常开发当中,我们一般是使用第三方的工具,不仅快,而且上手简单,基本不用我们动脑子,压缩我们用鲁班压缩,加载图片我们用Glide,这两大工具我想在座的基本上都用吧,不过我们要想提升自己,就要搞清楚深一点的东西,这里我将会带着大家做一款压缩工具,功能媲美鲁班压缩,而且还带有鲁班没有的功能,如输出指定格式等,在这个过程中我们要学会如何获取bitmap,第一篇已经罗列了多种从项目中取图片转bitmap,这里就不多说了。当我们拿到bitmap我们要知道的事情还有很多,比如图片的色彩模式,一个像素点大小,什么是色深,位深等。绝对让你有收获,干货满满,冲呀。目录1、图片相关概念 1.1 ARGB介绍 1.2 Bitmap概念 1.3 色彩模式 1.4 色深和位深 1.5 内存中Bitmap的大小 1.6 系统一般分配的大小2、图片压缩方式3、压缩的常见方式 3.1、质量压缩 3.2、采样压缩 3.2.1 临近采样(临近点插值算法) 3.2.2 双线性采样(双线性内插值算法) 3.2.3 双线性采样对比邻近采样的优势在于:4、微信和鲁班压缩对比
注意:1 byte(字节) = 8bit(位)1 KB = 1024 byte(字节)
// 获取应用程序最大可用内存(以字节为单位,/1024/1024=M 华为p20 pro是384M)int maxMemory = (int) Runtime.getRuntime().maxMemory();int cacheSize = maxMemory / 8; // 设置图片缓存大小为程序最大可用内存的1/8mMemoryCache = new LruCache(cacheSize) {@Overrideprotected int sizeOf(String key, Bitmap bitmap) {return bitmap.getByteCount();}----------------------其他获取方式--------------------ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);//最大分配内存,单位Mint memoryClass = activityManager.getMemoryClass();Log.e("memoryclass=",String.valueOf(memoryClass));//最大分配内存获取方法2float maxMemory = (float) (Runtime.getRuntime().maxMemory() * 1.0/ (1024 * 1024));//当前分配的总内存float totalMemory = (float) (Runtime.getRuntime().totalMemory() * 1.0/ (1024 * 1024));//剩余内存float freeMemory = (float) (Runtime.getRuntime().freeMemory() * 1.0/ (1024 * 1024));Log.e("memoryclass=maxMemory",String.valueOf(maxMemory));Log.e("memoryclass=totalMemory",String.valueOf(totalMemory));Log.e("memoryclass=freeMemory",String.valueOf(freeMemory));
Android目前常用的图片格式有png,jpeg和webp,
png:无损压缩图片格式,支持Alpha通道,Android切图素材多采用此格式jpeg:有损压缩图片格式,不支持背景透明,适用于照片等色彩丰富的大图压缩,不适合logowebp:是一种同时提供了有损压缩和无损压缩的图片格式,派生自视频编码格式VP8,从谷歌官网来看,无损webp平均比png小26%,有损的webp平均比jpeg小25%~34%,无损webp支持Alpha通道,有损webp在一定的条件下同样支持,有损webp在Android4.0(API 14)之后支持,无损和透明在Android4.3(API18)之后支持采用webp能够在保持图片清晰度的情况下,可以有效减小图片所占有的磁盘空间大小
Android中Bitmap所占内存大小计算方式:图片长度 x 图片宽度 x 一个像素点占用的字节数
质量压缩:主要是通过编解码来达到缩小体积。采样压缩:主要是通过采样率,像素点个数等来达到缩小体积
Bitmap.compress(Bitmap.CompressFormat.JPEG,quality,outputStream)其中Bitmap.CompressFormat.JPEGBitmap.CompressFormat.PNG 无损,无法再质量压缩?Bitmap.CompressFormat.WEBP 可优化30%,比JPEG更加省空间quality:0-100,1最小体积,100 最高质量,体积也是最大outputStream: ByteArrayOutputStream 一个输出流,压缩后的流,如果要保存成图片文件,就保存此流
使用了BitmapFactory.options 下的inSampleSize:采样压缩系数 如果是2,直接缩放宽高为原先 二分之一 (1/2)该方式比较粗暴,2个像素取一个。宽高都减少了,自然内存也降低了。------------------------------------------------------------------------------ public static void ljCom(InputStream open){ BitmapFactory.Options options = new BitmapFactory.Options();//或者 inDensity 搭配 inTargetDensity 使用,算法和 inSampleSize 一样 options.inSampleSize = 2; //设置图片的缩放比例(宽和高) , google推荐用2的倍数:// Bitmap bitmap = BitmapFactory.decodeFile("app/src/main/assets/wx.png");// Bitmap compress = BitmapFactory.decodeFile("app/src/main/assets/wx.png", options); Bitmap mbitmap = BitmapFactory.decodeStream(open, null, options); Log.e("双线性采样","----压缩后----》" +"\n内存大小》"+mbitmap.getByteCount() +"\n宽度》"+mbitmap.getWidth() +"\n高度》"+mbitmap.getHeight()); }
Bitmap bitmap = BitmapFactory.decodeFile("xxx.png");Bitmap compress = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth()/2, bitmap.getHeight()/2, true);或者直接使用 matrix 进行缩放Bitmap bitmap = BitmapFactory.decodeFile("xxx.png");Matrix matrix = new Matrix();matrix.setScale(0.5f, 0.5f);bm = Bitmap.createBitmap(bitmap, 0, 0, bit.getWidth(), bit.getHeight(), matrix, true);
看源码可以知道createScaledBitmap函数最终也是使用第二种方式的matrix进行缩放,双线性采样使用的是双线性內插值算法,这个算法不像邻近点插值算法一样,直接粗暴的选择一个像素,而是参考了源像素相应位置周围2x2个点的值,根据相对位置取对应的权重,经过计算之后得到目标图像。双线性内插值算法在图像的缩放处理中具有抗锯齿功能, 是最简单和常见的图像缩放算法,当对相邻2x2个像素点采用双线性內插值算法时,所得表面在邻域处是吻合的,但斜率不吻合,并且双线性内插值算法的平滑作用可能使得图像的细节产生退化,这种现象在上采样时尤其明显。filter:当进行的不只是平移变换时,filter参数为true可以进行滤波处理,有助于改善新图像质量;flase时,计算机不做过滤处理。使用方式
/** * 双线性采样 * */public static void sxxCon(Bitmap bitmap){ Log.e("双线性采样","----压缩前----》" +"\n内存大小》"+bitmap.getByteCount() +"\n原图宽度》"+bitmap.getWidth() +"\n原图高度》"+bitmap.getHeight()); //等比例缩放压缩 Bitmap mbitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth()/2, bitmap.getHeight()/2, true); Log.e("双线性采样","----压缩后----》" +"\n内存大小》"+mbitmap.getByteCount() +"\n宽度》"+mbitmap.getWidth() +"\n高度》"+mbitmap.getHeight());}/** * 双线性采样 * */public static void sxxCon2(Context context,Bitmap bitmap){ Log.e("双线性采样","----压缩前----》" +"\n内存大小》"+bitmap.getByteCount() +"\n宽度》"+bitmap.getWidth() +"\n高度》"+bitmap.getHeight()); Matrix matrix = new Matrix(); matrix.setScale(0.6f, 0.6f); Bitmap mbitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); Log.e("双线性采样","----压缩后----》\n" +"\n内存大小》"+mbitmap.getByteCount() +"\n宽度》"+mbitmap.getWidth() +"\n高度》"+mbitmap.getHeight()); saveBitmapAsPng2(context,mbitmap,"aaq");}
微信 | LuBan | |
1 | 采样率压缩 | |
2 | 进行宽高的等比压缩(微信对原图和缩略图限制了最大长宽或者最小长宽) | 进行宽高的等比压缩 |
3 | 对图片的质量进行压缩(一般75或者70)应该说的是quality=75 | 对图片的质量进行压缩 |
4 | 采用webP的格式 |
标签:
Copyright © 2015-2022 南非消费网版权所有 备案号:沪ICP备2022005074号-13 联系邮箱:58 55 97 3@qq.com