本文主要是介绍功能这么齐全的图片压缩类,还有谁?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
效果图:
压缩日志
com.pengkv.moon I/--->: 原尺寸:1215*1080
com.pengkv.moon I/--->: 最终压缩比例:3倍/新尺寸:405*360
工具特点
* 可以解析单张图片* 可以解析多张图片* 处理了压缩过程中OOM* 处理了部分手机照片旋转问题* 压缩后存储在缓存中,并可以清理* 压缩后返回缓存路径,方便上传* 可以从缓存路径读取出Bitmap,方便展示* 封装在2个类里,方便调用
使用方法
ImageCompressUtil.compressImageList(this, photos, new ImageCompressUtil.ProcessImgListCallBack() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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;}
}
最后小结
可以更改类中的压缩参数,对图片压缩的质量进行调整
这篇关于功能这么齐全的图片压缩类,还有谁?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!