前言:
关于图片压缩需要考虑如下因素:
b>图片的大小(M)限制
c>图片尺寸(宽高)限制
c>图片(大小、尺寸)不需要处理
e>图片清晰度与大小、尺寸的矛盾处理
f>Spring中MultipartFile与原生File的转化及byte字符流处理
1.压缩处理工具类如下:
package com.worm.util;
import com.ding.framwork.util.secure.MD5Tool;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.entity.ContentType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.util.UUID;
/**
* 图片处理工具类
* @author learnworm
* @version 2020-12-10 上午10:07:13
*/
public class ImageUtil {
//默认素材宽
private final static int DEFAULT_MATERIAL_IMG_WIDTH = 1280;
//默认素材高
private final static int DEFAULT_MATERIAL_IMG_HEIGHT = 1920;
//默认大小限制(1M)
private final static long DEFAULT_MATERIAL_IMG_SIZE = 1024*1024;
public static void main(String[] args) throws IOException{
String path1 = "D:\\tmp\\mu3.jpg";
File file = new File(path1);
MultipartFile multipartFile = filtToMuti(file);
String materialUrl = multipartFile.getOriginalFilename();
byte[] bytes = ImageUtil.imgCompress(multipartFile);
String digest = MD5Tool.getFileMD5(ImageUtil.byteToFile(bytes, ImageUtil.getSufix(materialUrl)));
writeFile(bytes, "D:\\tmp\\sub", materialUrl);
System.out.println("--------1----------^"+digest+"====="+materialUrl);
}
/**
* 文件Md5签名
* @param bytes
* @param originalUrl
* @return
*/
public static String digistMd5(byte[] bytes,String originalUrl){
try {
return MD5Tool.getFileMD5(ImageUtil.byteToFile(bytes, ImageUtil.getSufix(originalUrl)));
}catch (IOException ioe){
ioe.printStackTrace();
return null;
}
}
/**
* 图片压缩处理
* @param mutiFile
* @return
*/
public static byte[] imgCompress(MultipartFile mutiFile){
byte[] bytes = null;
//转File类型文件
File file = mutiToFile(mutiFile);
//图片后缀
String sufix = getSufix(mutiFile.getName());
//图片大小
long len = mutiFile.getSize();
//图片尺寸
boolean size = isResize(file,DEFAULT_MATERIAL_IMG_WIDTH,DEFAULT_MATERIAL_IMG_HEIGHT);
try {
File rfile = null;
bytes = mutiFile.getBytes();
if(size){//限制尺寸大小
BufferedImage bimg = imgCompressResize(file,DEFAULT_MATERIAL_IMG_WIDTH,DEFAULT_MATERIAL_IMG_HEIGHT);
String bName = UUID.randomUUID().toString();
File tmpDirFile = Files.createTempDirectory("tempFile").toFile();
rfile = File.createTempFile(bName, sufix, tmpDirFile);
ImageIO.write(bimg, getSufix(mutiFile.getName()), rfile);
bytes = getImgBytes(rfile);
//重新计算大小
mutiFile = byteToMuti(bytes);
len = mutiFile.getSize();
}
if(len>DEFAULT_MATERIAL_IMG_SIZE){//保持清晰度
bytes = imgCompressQuality(mutiFile.getBytes(),DEFAULT_MATERIAL_IMG_SIZE,sufix);
//重新计算大小
mutiFile = byteToMuti(bytes);
len = mutiFile.getSize();
}
if(len>DEFAULT_MATERIAL_IMG_SIZE){//严格限制到指定大小
bytes = imgCompressLen(mutiFile.getBytes(),DEFAULT_MATERIAL_IMG_SIZE,sufix);
}
if(rfile!=null && rfile.exists()){
rfile.delete();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bytes;
}
/**
* 图片压缩算法-清淅度
* @param input
* @param maxLen 最大
* @return
* @throws IOException
*/
public static byte[] imgCompressQuality(byte[] input,long maxLen,String sufix) throws IOException {
if(input.length < maxLen){
return input;
}
if (StringUtils.isEmpty(sufix)){//如果空则默认jpg
sufix = "jpg";
}
float quality = 1.0f;
float scale = 1.0f;
ByteArrayOutputStream os = new ByteArrayOutputStream();
InputStream is = new ByteArrayInputStream(input);
Thumbnails.of(is).scale(scale).outputQuality(quality).outputFormat(sufix).toOutputStream(os);
byte[] result = os.toByteArray();
while(result.length > maxLen && quality > 0.399){//保清晰度
is.close();
is = new ByteArrayInputStream(input);
os.close();
os = new ByteArrayOutputStream();
quality = quality - 0.05f;
Thumbnails.of(is).scale(scale).outputQuality(quality).outputFormat(sufix).toOutputStream(os);
result = os.toByteArray();
}
return result;
}
/**
* 图片压缩-大小M
* @param input
* @param maxLen 大小
* @return
* @throws IOException
*/
public static byte[] imgCompressLen(byte[] input,long maxLen,String sufix) throws IOException {
if(input.length < maxLen){
return input;
}
if (StringUtils.isEmpty(sufix)){//如果空则默认jpg
sufix = "jpg";
}
float quality = 1.0f;
float scale = 1.0f;
ByteArrayOutputStream os = new ByteArrayOutputStream();
InputStream is = new ByteArrayInputStream(input);
Thumbnails.of(is).scale(scale).outputQuality(quality).outputFormat(sufix).toOutputStream(os);
byte[] result = os.toByteArray();
while(result.length > maxLen){//限制大小
is.close();
is = new ByteArrayInputStream(input);
os.close();
os = new ByteArrayOutputStream();
quality = quality - 0.05f;
Thumbnails.of(is).scale(scale).outputQuality(quality).outputFormat(sufix).toOutputStream(os);
result = os.toByteArray();
byte[] tmpbyte = os.toByteArray();
}
return result;
}
/**
* @desc 图片缩放
* @param file 图片
* @param defWidth 宽度
* @param defHeight 高度
*/
public static BufferedImage imgCompressResize(File file, int defWidth, int defHeight) {
try {
double ratio = 1; // 缩放比例
BufferedImage bi = ImageIO.read(file);
Image itemp = bi.getScaledInstance(defWidth, defHeight,Image.SCALE_SMOOTH);
int imgWidth = bi.getWidth();
int imgHeight = bi.getHeight();
//宽高需要处理
if(imgWidth > defWidth && imgHeight > defHeight) {
double ratioW = (new Integer(defWidth)).doubleValue()/imgWidth;
double ratioH = (new Integer(defHeight)).doubleValue()/imgHeight;
if(ratioW < ratioH) {
ratio = ratioW;
}else {
ratio = ratioH;
}
AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
itemp = op.filter(bi, null);
}
return (BufferedImage) itemp;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* @desc 图片缩放
* @param file 图片
* @param defWidth 宽度
* @param defHeight 高度
* @return boolean
*/
public static boolean isResize(File file, int defWidth, int defHeight) {
try {
BufferedImage bi = ImageIO.read(file);
int imgWidth = bi.getWidth();
int imgHeight = bi.getHeight();
//宽高是否符合要求
if(imgWidth > defWidth && imgHeight > defHeight) {
return true;
}
return false;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
/**
* 图片补白
* @param file 图片
* @param defWidth 宽
* param defHeight 高
*/
public static BufferedImage imgFiller(File file, int defWidth, int defHeight) {
try {
BufferedImage bi = ImageIO.read(file);
Image itemp = bi.getScaledInstance(defWidth, defHeight,Image.SCALE_SMOOTH);
int imgWidth = bi.getWidth();
int imgHeight = bi.getHeight();
BufferedImage image = new BufferedImage(defWidth, defHeight,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, defWidth, defHeight);
if (defWidth == itemp.getWidth(null))
g.drawImage(itemp, 0, (defHeight - itemp.getHeight(null)) / 2,
itemp.getWidth(null), itemp.getHeight(null),
Color.white, null);
else
g.drawImage(itemp, (defWidth - itemp.getWidth(null)) / 2, 0,
itemp.getWidth(null), itemp.getHeight(null),
Color.white, null);
g.dispose();
itemp = image;
return (BufferedImage) itemp;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 得到文件字节流
* @param file
* @return
*/
public static byte[] getImgBytes(File file){
byte[] buffer = null;
try {
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
byte[] b = new byte[1000];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
fis.close();
bos.close();
buffer = bos.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return buffer;
}
/**
* @desc 字节流转文件
* @param bytes
* @param ext
* @return
* @throws IOException
*/
public static File byteToFile(byte[] bytes,String ext) throws IOException {
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
String fileName = UUID.randomUUID().toString();
File tmpDirFile = Files.createTempDirectory("tempFile").toFile();
File resultFile = File.createTempFile(fileName, '.' + ext, tmpDirFile);
resultFile.deleteOnExit();
org.apache.commons.io.FileUtils.copyInputStreamToFile(inputStream, resultFile);
return resultFile;
}
/**
* 生成文件
* @param bfile
* @param filePath
* @param fileName
*/
public static void writeFile(byte[] bfile, String filePath,String fileName) {
BufferedOutputStream bos = null;
FileOutputStream fos = null;
File file = null;
try {
File dir = new File(filePath);
if(!dir.exists()&&dir.isDirectory()){//判断文件目录是否存在
dir.mkdirs();
}
file = new File(filePath+"\\"+fileName);
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
bos.write(bfile);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
/**
* MultipartFile转化File
* @param mFile
* @return
*/
public static File mutiToFile(MultipartFile mFile) {
File file = new File(mFile.getOriginalFilename());
try {
org.apache.commons.io.FileUtils.copyInputStreamToFile(mFile.getInputStream(), file);
return file;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* File转化MultipartFile
* @param file
* @return MultipartFile
*/
public static MultipartFile filtToMuti(File file) {
FileInputStream input;
try {
input = new FileInputStream(file);
MultipartFile multipartFile;
multipartFile = new MockMultipartFile(file.getName(), file.getName(), "text/plain", IOUtils.toByteArray(input));
return multipartFile;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* byte转化MultipartFile
* @param bytes
* @return MultipartFile
*/
public static MultipartFile byteToMuti(byte[] bytes) {
InputStream input;
try {
byte[] fileByte = new byte[bytes.length];
input = new ByteArrayInputStream(fileByte);
MultipartFile multipartFile;
multipartFile = new MockMultipartFile(ContentType.APPLICATION_OCTET_STREAM.toString(), input);
return multipartFile;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* 获取文件后缀
* @param filename
* @return
*/
public static String getSufix(String filename) {
if ((filename != null) && (filename.length() > 0)) {
int dot = filename.lastIndexOf('.');
if ((dot >-1) && (dot < (filename.length() - 1))) {
return filename.substring(dot + 1);
}
}
return "";
}
}
2. 需要配置引入的包
<!-- 图片压缩 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-mock</artifactId>
<version>2.0.8</version>
</dependency>
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>