功能这么齐全的图片压缩类,还有谁?
2015-12-04 17:53
471 查看
效果图:
压缩日志
com.pengkv.moon I/--->: 原尺寸:1215*1080 com.pengkv.moon I/--->: 最终压缩比例:3倍/新尺寸:405*360
工具特点
* 可以解析单张图片 * 可以解析多张图片 * 处理了压缩过程中OOM * 处理了部分手机照片旋转问题 * 压缩后存储在缓存中,并可以清理 * 压缩后返回缓存路径,方便上传 * 可以从缓存路径读取出Bitmap,方便展示 * 封装在2个类里,方便调用
使用方法
ImageCompressUtil.compressImageList(this, photos, new ImageCompressUtil.ProcessImgListCallBack() { @Override public void compressSuccess(final List<String> imgList) { //imgList为压缩后图片的路径 } });
压缩工具类
import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Environment; import android.text.TextUtils; import android.util.Log; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import utils.ImageRotateUtil; /** * Created by pengkv on 15/12/2. * 图片压缩工具类 */ public class ImageCompressUtil { private static List<String> mImageList = new ArrayList<>();// 临时图片集合 private static String mImagePath = ""; // 单个临时图片 public static String cachePath = ""; public static int reqWidth = 320; public static int reqHeight = 480; //压缩单张图片方法 public static void compressImage(final Context ctx, final String filePath, final ProcessImgCallBack callBack) { mImagePath = "";//清空路径 new Thread(new Runnable() { @Override public void run() { //如果路径是图片,则进行压缩 if (isImage(filePath)) { mImagePath = compress(ctx, filePath); } callBack.compressSuccess(mImagePath); } }).start(); } //压缩图片集合方法 public static void compressImageList(final Context ctx, final List<String> fileList, final ProcessImgListCallBack callBack) { mImageList.clear();//清空集合 if (fileList == null || fileList.isEmpty()) { callBack.compressSuccess(mImageList); return; } new Thread(new Runnable() { @Override public void run() { String tempPath = ""; for (String imagePath : fileList) { if (isImage(imagePath)) { tempPath = compress(ctx, imagePath); mImageList.add(tempPath); } } callBack.compressSuccess(mImageList); } }).start(); } //图片压缩的方法 public static String compress(Context ctx, String filePath) { if (TextUtils.isEmpty(filePath)) return filePath; File file = new File(filePath); if (!file.exists())//判断路径是否存在 return filePath; if (file.length() < 1)//文件是否为空 return null; File tempFile = getDiskCacheDir(ctx); String outImagePath = tempFile.getAbsolutePath(); // 输出图片文件路径 int degree = ImageRotateUtil.getBitmapDegree(filePath); // 检查图片的旋转角度 //谷歌官网压缩图片 final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); // 旋转:这步处理主要是为了处理三星手机拍的照片 if (degree > 0) { bitmap = ImageRotateUtil.rotateBitmapByDegree(bitmap, degree); } // 写入文件 FileOutputStream fos; try { fos = new FileOutputStream(tempFile); bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos); fos.flush(); fos.close(); bitmap.recycle(); } catch (FileNotFoundException e) { e.printStackTrace(); return filePath; } catch (Exception e) { e.printStackTrace(); return filePath; } return outImagePath; } /** * 计算压缩比例值 * 按照2、3、4...倍压缩 * * @param options 解析图片的配置信息 * @param reqWidth 所需图片压缩尺寸最小宽度 * @param reqHeight 所需图片压缩尺寸最小高度 * @return */ public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int picheight = options.outHeight; final int picwidth = options.outWidth; Log.i("--->", "原尺寸:" + picwidth + "*" + picheight); int targetheight = picheight; int targetwidth = picwidth; int inSampleSize = 1; if (targetheight > reqHeight || targetwidth > reqWidth) { while (targetheight >= reqHeight && targetwidth >= reqWidth) { inSampleSize += 1; targetheight = picheight / inSampleSize; targetwidth = picwidth / inSampleSize; } } Log.i("--->", "最终压缩比例:" + inSampleSize + "倍/新尺寸:" + targetwidth + "*" + targetheight); return inSampleSize; } //图片集合压缩成功后的回调接口 public interface ProcessImgListCallBack { void compressSuccess(List<String> imgList); } //单张图片压缩成功后的回调接口 public interface ProcessImgCallBack { void compressSuccess(String imgPath); } /** * 获取文件后缀名 * * @param fileName * @return 文件后缀名 */ public static String getFileType(String fileName) { if (!TextUtils.isEmpty(fileName)) { int typeIndex = fileName.lastIndexOf("."); if (typeIndex != -1) { String fileType = fileName.substring(typeIndex + 1).toLowerCase(); return fileType; } } return ""; } /** * 判断是否是图片 * * @param fileName * @return 是否是图片类型 */ public static boolean isImage(String fileName) { String type = getFileType(fileName); if (!TextUtils.isEmpty(type) && (type.equals("jpg") || type.equals("gif") || type.equals("png") || type.equals("jpeg") || type.equals("bmp") || type.equals("wbmp") || type.equals("ico") || type.equals("jpe"))) { return true; } return false; } /** * 将压缩后的图片存储在缓存中 */ public static File getDiskCacheDir(Context ctx) { if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable()) { cachePath = ctx.getExternalCacheDir().getPath(); } else { cachePath = ctx.getCacheDir().getPath(); } String uniqueName = System.currentTimeMillis() + "_tmp.jpg"; return new File(cachePath + File.separator + uniqueName); } /** * 清理缓存文件夹 */ public static void clearCache(Context ctx) { File file = new File(cachePath); File[] childFile = file.listFiles(); if (childFile == null || childFile.length == 0) { return; } for (File f : childFile) { f.delete(); // 循环删除子文件 } } /** * 从图片路径读取出图片 * * @param imagePath * @return */ private Bitmap decodeFile(String imagePath) { Bitmap bitmap = null; try { File file = new File(imagePath); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = false; FileInputStream fis = new FileInputStream(file); bitmap = BitmapFactory.decodeStream(fis, null, options); fis.close(); } catch (IOException e) { e.printStackTrace(); } return bitmap; } }
图片旋转工具类
import android.graphics.Bitmap; import android.graphics.Matrix; import android.media.ExifInterface; import java.io.IOException; /** * Created by pengkv on 15/12/2. * 图片旋转工具类 */ public class ImageRotateUtil { /** * 读取图片的旋转的角度 * * @param path 图片绝对路径 * @return 图片的旋转角度 */ public static int getBitmapDegree(String path) { int degree = 0; try { // 从指定路径下读取图片,并获取其EXIF信息 ExifInterface exifInterface = new ExifInterface(path); // 获取图片的旋转信息 int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); 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 bm 需要旋转的图片 * @param degree 旋转角度 * @return 旋转后的图片 */ public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) { Bitmap returnBm = null; // 根据旋转角度,生成旋转矩阵 Matrix matrix = new Matrix(); matrix.postRotate(degree); try { // 将原始图片按照旋转矩阵进行旋转,并得到新的图片 returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true); } catch (OutOfMemoryError e) { e.printStackTrace(); //当内存溢出时,利用递归进行重新旋转 while (returnBm == null) { System.gc(); System.runFinalization(); returnBm = rotateBitmapByDegree(bm, degree); } } if (returnBm == null) { returnBm = bm; } if (bm != returnBm) { bm.recycle(); } return returnBm; } }
最后小结
可以更改类中的压缩参数,对图片压缩的质量进行调整相关文章推荐
- Unity 如何减少DrawCall
- printf 格式化输出符号详细说明
- LeetCode 179 Largest Number
- 云的成因和成分
- Linux 安装redis 详解
- 全能型开源远程终端:MobaXterm
- MyEclipse安装插件的三种方法和使用心得
- 深入理解C--Four 内存四区全局区剖析
- DOPE OPENCART 自适应主题模板 ABC-0701
- acm2056 神烦 超限 超限
- SharePoint Server 2016 update
- STM32时钟 分析
- next()和nextLine()方法的区别
- Wamserver 添加虚拟主机的方式
- C++终极复习篇(五)----STL标准模板库
- 黑马程序员——OC学习——@class的使用
- 关于幻读
- 从数据库中获取数据第二个文件结果集
- 7)查找[1]顺序表的查找
- Python中@的用法(Decorator:装饰器)