功能这么齐全的图片压缩类,还有谁?

2023-12-01 03:10
文章标签 功能 图片 压缩 齐全

本文主要是介绍功能这么齐全的图片压缩类,还有谁?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

效果图:

这里写图片描述

压缩日志

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;}
}

最后小结

可以更改类中的压缩参数,对图片压缩的质量进行调整

这篇关于功能这么齐全的图片压缩类,还有谁?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/439562

相关文章

最好用的WPF加载动画功能

《最好用的WPF加载动画功能》当开发应用程序时,提供良好的用户体验(UX)是至关重要的,加载动画作为一种有效的沟通工具,它不仅能告知用户系统正在工作,还能够通过视觉上的吸引力来增强整体用户体验,本文给... 目录前言需求分析高级用法综合案例总结最后前言当开发应用程序时,提供良好的用户体验(UX)是至关重要

python实现自动登录12306自动抢票功能

《python实现自动登录12306自动抢票功能》随着互联网技术的发展,越来越多的人选择通过网络平台购票,特别是在中国,12306作为官方火车票预订平台,承担了巨大的访问量,对于热门线路或者节假日出行... 目录一、遇到的问题?二、改进三、进阶–展望总结一、遇到的问题?1.url-正确的表头:就是首先ur

如何评价Ubuntu 24.04 LTS? Ubuntu 24.04 LTS新功能亮点和重要变化

《如何评价Ubuntu24.04LTS?Ubuntu24.04LTS新功能亮点和重要变化》Ubuntu24.04LTS即将发布,带来一系列提升用户体验的显著功能,本文深入探讨了该版本的亮... Ubuntu 24.04 LTS,代号 Noble NumBAT,正式发布下载!如果你在使用 Ubuntu 23.

TP-LINK/水星和hasivo交换机怎么选? 三款网管交换机系统功能对比

《TP-LINK/水星和hasivo交换机怎么选?三款网管交换机系统功能对比》今天选了三款都是”8+1″的2.5G网管交换机,分别是TP-LINK水星和hasivo交换机,该怎么选呢?这些交换机功... TP-LINK、水星和hasivo这三台交换机都是”8+1″的2.5G网管交换机,我手里的China编程has

Django中使用SMTP实现邮件发送功能

《Django中使用SMTP实现邮件发送功能》在Django中使用SMTP发送邮件是一个常见的需求,通常用于发送用户注册确认邮件、密码重置邮件等,下面我们来看看如何在Django中配置S... 目录1. 配置 Django 项目以使用 SMTP2. 创建 Django 应用3. 添加应用到项目设置4. 创建

使用 Python 和 LabelMe 实现图片验证码的自动标注功能

《使用Python和LabelMe实现图片验证码的自动标注功能》文章介绍了如何使用Python和LabelMe自动标注图片验证码,主要步骤包括图像预处理、OCR识别和生成标注文件,通过结合Pa... 目录使用 python 和 LabelMe 实现图片验证码的自动标注环境准备必备工具安装依赖实现自动标注核心

通过C#和RTSPClient实现简易音视频解码功能

《通过C#和RTSPClient实现简易音视频解码功能》在多媒体应用中,实时传输协议(RTSP)用于流媒体服务,特别是音视频监控系统,通过C#和RTSPClient库,可以轻松实现简易的音视... 目录前言正文关键特性解决方案实现步骤示例代码总结最后前言在多媒体应用中,实时传输协议(RTSP)用于流媒体服

Java操作xls替换文本或图片的功能实现

《Java操作xls替换文本或图片的功能实现》这篇文章主要给大家介绍了关于Java操作xls替换文本或图片功能实现的相关资料,文中通过示例代码讲解了文件上传、文件处理和Excel文件生成,需要的朋友可... 目录准备xls模板文件:template.xls准备需要替换的图片和数据功能实现包声明与导入类声明与

基于Qt实现系统主题感知功能

《基于Qt实现系统主题感知功能》在现代桌面应用程序开发中,系统主题感知是一项重要的功能,它使得应用程序能够根据用户的系统主题设置(如深色模式或浅色模式)自动调整其外观,Qt作为一个跨平台的C++图形用... 目录【正文开始】一、使用效果二、系统主题感知助手类(SystemThemeHelper)三、实现细节

Qt实现文件的压缩和解压缩操作

《Qt实现文件的压缩和解压缩操作》这篇文章主要为大家详细介绍了如何使用Qt库中的QZipReader和QZipWriter实现文件的压缩和解压缩功能,文中的示例代码简洁易懂,需要的可以参考一下... 目录一、实现方式二、具体步骤1、在.pro文件中添加模块gui-private2、通过QObject方式创建