图片压缩CompressUtil解析
- CompressUtil 流程图:
CompressUtil 类 详解
public class CompressUtil {
/*** 最终封装的压缩方法* @param imgPath* @return*/
public static Bitmap process(String imgPath){int degree = readPictureDegree(imgPath); //获取旋转角度Bitmap bmp =getBmpByMaxSize(imgPath, 480); //获取当前路径图片的位图,最大尺寸180*1024if (degree != 0) {bmp = rotaingImageView(degree, bmp); //有旋转角度的旋转角度}return bmp;
}
/*** 读取图片属性:旋转的角度* @param path 图片绝对路径* @return degree旋转的角度*/
@SuppressLint("NewApi")
public static int readPictureDegree(String path){int degree = 0; //设置默认图片角度为0度try {/*** Exif: 图像信息* Exif是一种图像文件格式,它的数据存储与JPEG格式是完全相同的。* 实际上Exif格式就是在JPEG格式头部插入了数码照片的信息,包括* 拍摄时的光圈、快门、白平衡、ISO、焦距、日期时间等各种和拍摄* 条件以及相机品牌、型号、色彩编码、拍摄时录制的声音以及GPS全* 球定位系统数据、缩略图等。你可以利用任何可以查看JPEG文件的* 看图软件浏览Exif格式的照片,但并不是所有的图形程序都能处理* Exif信息。** ExifInterface: 图像信息接口类*//*** ExifInterface构造函数 ExifInterface(String filename)* 从指定的JPEG文件中读取EXIF标签。*///获取指定图片的图片处理对象ExifInterface exifInterface = new ExifInterface(path);/*** int <- getAttributeInt(String tag, int defaultValue)* 返回指定标记的整数值** Attribute : 属性** tag : 指标 (一共21个)* ExifInterface.TAG_APERTURE => 光圈指标* ExifInterface.TAG_DATETIME => 日期时间指标* ExifInterface.TAG_EXPOSURE_TIME => 发布时间指标* ExifInterface.TAG_FLASH => 闪光灯* ExifInterface.TAG_FOCAL_LENGTH => 焦距指标* ExifInterface.TAG_GPS_ALTITUDE => GPS海拔高度指标* ExifInterface.TAG_GPS_ALTITUDE_REF => GPS海拔参考点指标* ExifInterface.TAG_GPS_DATESTAMP => GPS日期戳指标* ExifInterface.TAG_GPS_LATITUDE => GPS纬度指标* ExifInterface.TAG_GPS_LATITUDE_REF => GPS纬度参考点指标* ExifInterface.TAG_GPS_LONGITUDE => GPS经度指标* ExifInterface.TAG_GPS_LONGITUDE_REF => GPS经度参考点指标* ExifInterface.TAG_GPS_PROCESSING_METHOD => GPS加工指标* ExifInterface.TAG_GPS_TIMESTAMP => GPS时间戳指标* ExifInterface.TAG_IMAGE_LENGTH => 图像长度指标* ExifInterface.TAG_IMAGE_WIDTH => 图像宽度指标* ExifInterface.TAG_ISO => 标签* ExifInterface.TAG_MAKE => 制作* ExifInterface.TAG_MODEL => 模型* ExifInterface.TAG_ORIENTATION => 定位指标* ExifInterface.TAG_WHITE_BALANCE => 白平衡指标** defaultValue : 默认值 (一共11个)** ExifInterface.ORIENTATION_FLIP_HORIZONTAL => 水平翻转* ExifInterface.ORIENTATION_FLIP_VERTICAL => 垂直翻转* ExifInterface.ORIENTATION_NORMAL => 正常* ExifInterface.ORIENTATION_ROTATE_180 => 旋转180度* ExifInterface.ORIENTATION_ROTATE_270 => 旋转270度* ExifInterface.ORIENTATION_ROTATE_90 => 旋转90度* ExifInterface.ORIENTATION_TRANSPOSE => 取向的转置* ExifInterface.ORIENTATION_TRANSVERSE => 方位横向* ExifInterface.ORIENTATION_UNDEFINED => 方向未定义* ExifInterface.WHITEBALANCE_AUTO => 白平衡自动* ExifInterface.WHITEBALANCE_MANUAL => 手动白平衡*/// 获取该图片的方向参数int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_ROTATE_90);switch (orientation) {case ExifInterface.ORIENTATION_ROTATE_90:degree = 90;break;case ExifInterface.ORIENTATION_ROTATE_180:degree = 180;break;case ExifInterface.ORIENTATION_ROTATE_270:degree = 270;break;}} catch (IOException e) {e.printStackTrace();}return degree;
}/*** 旋转图片* @param angle* @param bitmap* @return Bitmap** Bitmap : 位图* Bitmap是Android系统中的图像处理的最重要类之一。* 用它可以获取图像文件信息,进行图像剪切、旋转、缩* 放等操作,并可以指定格式保存图像文件。** Bitmap实现在android.graphics包中。但是Bitmap* 类的构造函数是私有的,外面并不能实例化,只能是通* 过JNI实例化。这必然是 某个辅助类提供了创建Bitmap* 的接口,而这个类的实现通过JNI接口来实例化Bitmap的,* 这个类就是BitmapFactory。** decode : 解码** BitmapFactory.decodeFile(String pathName)* BitmapFactory.decodeFile(String pathName,Options opts)* BitmapFactory.decodeResource(Resource res,int id)* BitmapFactory.decodeResource(Resource res,int id,Options opts)** 利用BitmapFactory可以从一个指定文件中,利用decodeFile()解出Bitmap;* 也可以定义的图片资源中,利用decodeResource()解出Bitmap** 其中Options是decode时的选项* 在使用方法decodeFile()/decodeResource()时,都可以指定一个BitmapFacotry.Options。** 利用Options的下列属性,可以指定decode的选项* inPreferredConfig => decode到内存中,手机中所采用的编码,可选值定义在Bitmap.Config中。缺省值是ARGB_8888* inJustDecodeBounds => 如果设置为true,并不会把图像的数据完全解码,亦即decodeXyz()返回值为null,但是Options的outAbc中解出了图像的基本信息* inSampleSize => 设置decode时的缩放比例**/
public static Bitmap rotaingImageView(int angle , Bitmap bitmap) {// Bitmap可以和Matrix结合实现图像的剪切、旋转、缩放等操作//获取Matrix对象Matrix matrix = new Matrix();//设置旋转角度matrix.postRotate(angle);// 创建新的图片Bitmap resizedBitmap=bitmap;/*** 用原Bitmap通过变换生成新的Bitmap的方法:** public static Bitmap createBitmap(Bitmap source,int x,int y,int width,int height,Matrix m,boolean filter)* 这种方法是最终的实现,后两种只是对这种方法的封装** public static Bitmap createBitmap(Bitmap source,int x,int y,int width,int height)* 这种方法可以从源Bitmap中指定区域(x,y, width, height)中挖出一块来实现剪切** public static Bitmap createScaledBitmap(Bitmap src,int dstWidth,int dstHeight,boolean filter)* 这种方法可以把源Bitmap缩放为dstWidth x dstHeight的Bitmap** filter => 设为true => 对Bitmap进行滤波处理,会有抗锯齿的效果*/try {resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);/*** Bitmap的recycle问题* recycle : 回收* 虽然Android有自己的垃圾回收机制,对于是不是要我们自己调用recycle,还的看情况而定。* 如果只是使用少量的几张图片,回收与否关系不大。可是若有大量bitmap需要垃圾回收处理,* 那必然垃圾回收需要做的次数就更多也发生地更频繁,会对系统资源造成负荷。所以,这个时* 候还是自己试用recycle来释放的比较好。** 注意 => 只有当你确认你不会在使用这个bitmap的时候,就可以选择调用recycle()方法释放它。**/bitmap.recycle();//进行垃圾回收System.gc();}catch (OutOfMemoryError e){e.printStackTrace();}return resizedBitmap;
}/*** 减少图片质量压缩* @param bmp* @param maxSize* @param fileSize* @return*/
public static Bitmap compressBmp(Bitmap bmp, int maxSize, long fileSize) {Bitmap newBmp=bmp;//ByteArrayOutputStream => 捕获内存缓冲区的数据,转换成字节数组。ByteArrayOutputStream baos=null;//ByteArrayInputStream => 将字节数组转化为输入流ByteArrayInputStream bais=null;int quality = 100;if(fileSize>4*1024*1024){quality=40;}else if(fileSize>2*1024*1024){quality=50;}else if(fileSize>800*1024){quality=60;}try {/*** ByteArrayOutputStream类是在创建它的实例时,程序内部创建一个byte型别数组的缓冲区,* 然后利用ByteArrayOutputStream和ByteArrayInputStream的实例向数组中写入或读出* byte型数据。在网络传输中我们往往要传输很多变量,我们可以利用ByteArrayOutputStream* 把所有的变量收集到一起,然后一次性把数据发送出去。*/baos = new ByteArrayOutputStream();System.out.print("开始压缩: " + quality);/*** 图片压缩* Bitmap.compress(CompressFormat format, int quality, OutputStream stream)* 方法的参数format可设置JPEG或PNG格式;quality可选择压缩质量;fOut是输出流(OutputStream)*/bmp.compress(Bitmap.CompressFormat.JPEG, quality, baos);float maxByte = maxSize * 1024;baos.flush();float scale = 1;while (baos.size() > maxByte) {System.out.print("压缩大小:" + baos.size() / 1024);System.out.print("压缩大小2:" + baos.toByteArray().length / 1024);scale = Math.round((float) baos.size() / maxByte);if (scale < 1) scale = 1;quality -= scale * 2;baos.reset(); //重置流,使流计数=0。重置该流丢弃所有当前累积输出。bmp.compress(Bitmap.CompressFormat.JPEG, quality, baos);baos.flush();}
// File file=new File(FileUtil.getAudioPath()+File.separator+System.currentTimeMillis()+”.jpg”);
// BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(file));
// bos.write(baos.toByteArray());
// bos.flush();
// bos.close();
System.out.print("压缩后大小:" + baos.size() / 1024);bais = new ByteArrayInputStream(baos.toByteArray());baos.flush();newBmp = BitmapFactory.decodeStream(bais);bmp.recycle();System.gc();}catch (OutOfMemoryError e){e.printStackTrace();//内存溢出则压缩更多if(!bmp.isRecycled()) {try {quality=quality/2;baos = new ByteArrayOutputStream();bmp.compress(Bitmap.CompressFormat.JPEG, quality, baos);bais = new ByteArrayInputStream(baos.toByteArray());baos.flush();newBmp = BitmapFactory.decodeStream(bais);}catch (Exception ex){}}}catch (Exception e){e.printStackTrace();}finally{try {if (bais != null) {bais.close();}if (baos != null) {baos.close();}}catch (Exception e){}}return newBmp;
}public static Bitmap getBmpByMaxSize(String path, int maxSize){/*** Android使用BitmapFactory.Options解决加载大图片内存溢出问题** 由于Android对图片使用内存有限制,若是加载几兆的大图片便内存溢出。* Bitmap会将图片的所有像素(即长x宽)加载到内存中,如果图片分辨率* 过大,会直接导致内存溢出(java.lang.OutOfMemoryError),只有* 在BitmapFactory加载图片时使用BitmapFactory.Options对相关参* 数进行配置来减少加载的像素。** BitmapFactory.Options这个类,有一个字段叫做 inJustDecodeBounds 。* 如果我们把它设为true,那么BitmapFactory.decodeFile(String path,* Options opt)并不会真的返回一个Bitmap给你,它仅仅会把它的宽,高取回* 来给你,这样就不会占用太多的内存,也就不会那么频繁的发生OOM(Out Of* Memory)了。**/BitmapFactory.Options options=new BitmapFactory.Options();//使图片最小边框缩小到800像素options.inJustDecodeBounds=true;//这里返回的bitmap=null,但可以通过options.outWidth 和 options.outHeight就是我们想要的宽和高了BitmapFactory.decodeFile(path, options);//最短的永远都是宽度double width=options.outWidth<options.outHeight? options.outWidth: options.outHeight;//实际宽度/理想宽度 => 上传图片缩放比例int sampleSize=(int)Math.round(width/480);System.out.print("上传图片缩放比例:" + sampleSize);if(sampleSize<1) sampleSize=1;/*** inSampleSize表示缩略图大小为原始图片大小的几分之一,* 即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。*/options.inSampleSize = sampleSize;options.inJustDecodeBounds=false;options.inDither=false; /*不进行图片抖动处理*/options.inPreferredConfig=null; /*设置让解码器以最佳方式解码*//*** 下面两个字段需要组合使用 节约内存*/options.inPurgeable = true; // 允许可清除options.inInputShareable = true;long length=new File(path).length();if(length>(1.5*1024*1024)){ //大于1.5M时options.inSampleSize+=(int)(length/1024/1024)*0.5; //当大于2M时为避免内存溢出缩小}Bitmap bitmap=null;try {bitmap = BitmapFactory.decodeFile(path, options);}catch (OutOfMemoryError e){e.printStackTrace();//内存溢出则将图片缩小一半if(options.inSampleSize<1) options.inSampleSize=1;options.inSampleSize=options.inSampleSize*2;bitmap=BitmapFactory.decodeFile(path, options);}if(length>(800*1024)) { //大于20K字节压缩bitmap = compressBmp(bitmap, maxSize, length);}return bitmap;
}
}
图片压缩CompressUtil解析相关推荐
- png图片压缩原理解析
什么是PNG PNG的全称叫便携式网络图型(Portable Network Graphics)是目前最流行的网络传输和展示的图片格式,原因有如下几点: 无损压缩:PNG图片采取了基于LZ77派生算法 ...
- PNG 图片压缩原理解析
原文地址见文末,感谢原作者. Table of Contents 背景 什么是PNG PNG类型 PNG图片数据结构 PNG的压缩 压缩(Compression) 结语 背景 今天凌晨一点,突然有个人 ...
- PNG图片压缩原理解析--屌丝的眼泪
今天看到一篇文章,本以为是技术硬核,却发现是杯情感鸡汤~,转一下. 链接: https://segmentfault.com/a/1190000018557449 背景 今天凌晨一点,突然有个人加我的 ...
- 可能是最详细的Android图片压缩原理分析(二)—— 鲁班压缩算法解析
本篇文章已授权微信公众号guolin_blog(郭霖)独家发布 稀土掘金链接 前言 通过上一篇,我们了解了一些关于图片压缩的基础知识,这篇文章我们主要讲解一下鲁班压缩的算法逻辑,很多博客都是从Gith ...
- 【Android 内存优化】Android 原生 API 图片压缩原理 ( Bitmap_compress 方法解析 | Skia 二维图形库 | libjpeg 函数库 | libpng 函数库 )
文章目录 一. 图片质量压缩方法 二. Skia 二维图形库 三. libjpeg.libpng 函数库引入 在博客 [Android 内存优化]图片文件压缩 ( Android 原生 API 提供的 ...
- 【Android 内存优化】Android 原生 API 图片压缩原理 ( 哈夫曼编码开关 | 哈夫曼编码原理 | libjpeg-turbo 函数库 )
文章目录 一. 哈夫曼编码开关 二. 哈夫曼编码原理 三. libjpeg-turbo 函数库 四. libjpeg-turbo 函数库下载 [Android 内存优化]图片文件压缩 ( Androi ...
- 【Android 内存优化】图片文件压缩 ( Android 原生 API 提供的图片压缩功能能 | 图片质量压缩 | 图片尺寸压缩 )
文章目录 一. 图片压缩 二. 图片文件压缩类型 三. Android 原生 API 提供的质量压缩 四. Android 原生 API 提供的尺寸压缩 一. 图片压缩 图片压缩 : ① 文件压缩 : ...
- glide 压缩图拍呢_用Glide-图片的压缩-图片压缩原理
前言: 这一节里面我们将介绍Glide如何对图片进行压缩,这一点在加载图片较多或者加载的图片像素很高的程序里面至关重要 Glide 系列目录 1.Glide-入门教程 2.Glide-占位图以及加载动 ...
- java图片压缩不失真_软件分享 | Lit图片压缩
软件分享 01 软件名称 Lit图片压缩 02 软件版本 V1.2.0.016 03 软件简介 Lit图片压缩app是一款免费简单好用的图片压缩工具,让图片在不失真的情况下,进行压缩和裁剪,轻松就能压 ...
最新文章
- css聊天布局,CSS实现聊天布局
- 【企业管理】围绕价值创造开展人力资源管理
- nodejs——URL 基础API
- Okhttp 插入缓存拦截器 解析
- SOA技术相关介绍(RPC, Web Service, REST,SOAP,JMI)
- 为什么越来越多的人喜欢旅游?
- java基础 6 基本类型与运算
- ubuntu里面的任务管理器
- 微信 for Mac 3.1.0 测试版发布,支持发朋友圈啦!
- Mnesia动态添加节点杂记
- 【论文译文】BigGAN
- 2020-12-24
- solidworks装配教程:快速给装配体添加新零件
- 事后诸葛亮项目总结会议
- Google网页加速器的工作原理
- 背诵英语单词(你没看错)
- 微信小程序——生命周期
- VUE xls文件的上传以及下载
- C语言——冒泡排序(分析详解)
- 白盒测试与黑盒测试的定义与区别