最近一直在网上找关于图片上传、旋转处理、压缩处理等相关的资料,发现也不是很多。首先图片处理还是挺复杂的,完全靠自己写代码实现,笔者感觉自己不具备这个实力,所以还是在网上找一些好的插件,然后综合下,节省时间。
记得在上一篇博文就介绍了图片上传的方案,今天就来说说图片旋转和压缩处理。因为这两点还是挺重要的,之所以会处理旋转这个问题,是由于ios拍照存在这个bug,导致上传的图片方向逆时针旋转了90。那么,怎么解决呢?其实,上篇博文所使用的两个前端插件都解决了旋转的问题,所以这个就不用担心了,虽然在后台也可以处理,但是还是比较麻烦的,大家可以去研究下。压缩的话,由于图片太大了,不压缩使用,会导致加载图片太慢。那么是在后台处理,还是前端处理呢?这一点我也不太清楚,需要结合性能和兼容性去选择。由于thumbnailator这个后台插件封装了对图片相关的处理,所以笔者就选用这个插件了,比较方便,下面笔者就来进行介绍。
一、maven依赖
<!-- 图片处理插件 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<!-- 图片EXIF信息 -->
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
<version>2.6.2</version>
</dependency>
压缩处理
笔者把代码封装到了一个工具类中,如下:
package com.qiyongkang.sys.util;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifIFD0Directory;
import net.coobird.thumbnailator.Thumbnails;
/**
*
* ClassName: ImageUtil <br/>
* Function: 图片处理. <br/>
* date: 2017年2月6日 下午1:49:15 <br/>
*
* @author qiyongkang
* @version
* @since JDK 1.6
*/
public class ImageUtil {
private static Logger logger = LogManager.getLogger(ImageUtil.class);
//宽
public static int IMAGE_WIDTH = 1;
//高
public static int IMAGE_HEIGHT = 2;
//方向
public static int ORIENTATION_ONE = 1; //正常
public static int ORIENTATION_THREE = 3; //180
public static int ORIENTATION_SIX = 6; //顺时针90
public static int ORIENTATION_EIGHT = 8; //逆时针90,顺时针270
/**
*
* getImageSize: 获取图片大小. <br/>
*
* @author qiyongkang
* @return
* @since JDK 1.6
*/
public static int getImageSize(File file, int flag) {
int size = 0;
if (file == null || !file.exists())
return size;
try {
if (IMAGE_WIDTH == flag) {
size = ImageIO.read(file).getWidth();
} else if (IMAGE_HEIGHT == flag) {
size = ImageIO.read(file).getHeight();
}
} catch (IOException e) {
logger.error("获取图片的大小异常", e);
e.printStackTrace();
}
return size;
}
/**
*
* getImageOrientation: 获取图片的方向 <br/>
*
* @author qiyongkang
* @param file
* @return
* @since JDK 1.6
*/
public static int getImageOrientation(File file) {
int orientation = ORIENTATION_ONE;
try {
Metadata metadata = ImageMetadataReader.readMetadata(file);
Directory dr = metadata.getDirectory(ExifIFD0Directory.class);
if (dr == null) {
logger.info("没有方向信息");
return orientation;
}
orientation = dr.getInt(ExifIFD0Directory.TAG_ORIENTATION);
logger.info("orientation:" + orientation);
} catch (Exception e) {
logger.error("获取图片的方向异常", e);
e.printStackTrace();
}
return orientation;
}
/**
*
* rotateImage: 旋转图片到正常的方向. <br/>
*
* @author qiyongkang
* @since JDK 1.6
*/
public static void rotateImage(File file) {
//计算方向
int orientation = getImageOrientation(file);
double angle = 0d;
if (orientation > ORIENTATION_ONE) {
//进行图片处理
switch (orientation) {
case 3:
//需要旋转180度
angle = 180d;
break;
case 6:
//需要旋转270度
angle = 270d;
break;
case 8:
//需要旋转90度
angle = 90d;
break;
}
}
try {
Thumbnails.of(file).scale(1).rotate(angle).toFile(file);;
} catch (IOException e) {
logger.error("旋转图片异常", e);
e.printStackTrace();
}
}
/**
*
* impressImage: 压缩图片. <br/>
*
* @author qiyongkang
* @param file
* @param width
* @param height
* @since JDK 1.6
*/
public static void impressImage(File file, int width, int height) {
try {
Thumbnails.of(file).size(width, height).toFile(file);
} catch (IOException e) {
e.printStackTrace();
logger.error("压缩图片异常:" + e);
}
}
public static void main(String[] args) {
File file = new File("C:\\Users\\qiyongkang\\Desktop\\测试图片\\17251486371832020.jpg");
// rotateImage(file);
System.out.println("图片的方向:" + getImageOrientation(file));
}
}
使用例子
在上一篇博文已经贴出了上传的代码,这里就是加了点压缩处理的代码,如下:
/**
* Project Name:qyk_testSpringMVC
* File Name:FileController.java
* Package Name:com.qiyongkang.sys.controller
* Date:2016年11月6日下午3:12:05
* Copyright (c) 2016, Thinkive(http://www.thinkive.com/) All Rights Reserved.
*
*/
package com.qiyongkang.sys.controller;
import java.io.File;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.qiyongkang.sys.dto.ExtJsObject;
import com.qiyongkang.sys.util.ImageUtil;
/**
* ClassName:FileController <br/>
* Function: TODO ADD FUNCTION. <br/>
* Reason: TODO ADD REASON. <br/>
* Date: 2016年11月6日 下午3:12:05 <br/>
*
* @author qiyongkang
* @version
* @since JDK 1.6
* @see
*/
@Controller
@RequestMapping
public class FileController {
/**
* 日志类
*/
private static Logger log = LogManager.getLogger(FileController.class);
private String tempPath = "/uploadImageTemp";// 临时存储目录
private String savePath = "/userImage";// 存储目录
private String fileName = ""; // 文件名
private static int PICTURE_WIDTH = 100; //压缩成的宽度
@RequestMapping
@ResponseBody
public ExtJsObject uploadImage(HttpServletRequest request) {
ExtJsObject extJsObject = new ExtJsObject();
try {
// 获取临时目录
String tempPathDir = request.getSession().getServletContext().getRealPath(this.tempPath);
File tempPathDirFile = new File(tempPathDir);
if (!tempPathDirFile.exists()) {
tempPathDirFile.mkdirs();
}
// 存储目录
String realDir = request.getSession().getServletContext().getRealPath(this.savePath);
File realDirFile = new File(realDir);
if (!realDirFile.exists()) {
realDirFile.mkdirs();
}
// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
// Set factory constraints
factory.setSizeThreshold(4096); // 设置缓冲区大小,这里是4kb
factory.setRepository(tempPathDirFile);// 设置缓冲区目录
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Set overall request size constraint
upload.setSizeMax(4194304); // 设置最大文件尺寸,这里是4MB
List<FileItem> items = upload.parseRequest(request);// 得到所有的文件
Iterator<FileItem> i = items.iterator();
while (i.hasNext()) {
FileItem fi = (FileItem) i.next();
String fileName = fi.getName();
if (fileName != null) {
// 这里加一个限制,如果不是图片格式,则提示错误. (gif,jpg,jpeg,bmp,png)
String suffixName = FilenameUtils.getExtension(fileName);
if ("gif".equalsIgnoreCase(suffixName) || "jpg".equalsIgnoreCase(suffixName)
|| "jpeg".equalsIgnoreCase(suffixName) || "bmp".equalsIgnoreCase(suffixName)
|| "png".equalsIgnoreCase(suffixName)) {
// 文件名
this.fileName = new Date().getTime() + "." + FilenameUtils.getExtension(fileName);
File savedFile = new File(realDir, this.fileName);
fi.write(savedFile);
// 小图片
File savedSmallFile = new File(realDir + "/small/", this.fileName);
FileUtils.copyFile(savedFile, savedSmallFile);
//压缩一把
ImageUtil.impressImage(savedSmallFile, PICTURE_WIDTH, PICTURE_WIDTH);
} else {
extJsObject.setSuccess(false);
extJsObject.setMsg("非图片格式,请重新上传!");
}
}
}
extJsObject.setSuccess(true);
extJsObject.setMsg("上传成功!");
extJsObject.setResult(this.fileName);
} catch (Exception e) {
extJsObject.setSuccess(false);
extJsObject.setMsg("上传失败!");
log.error("图片上传失败", e);
}
return extJsObject;
}
}
好了,就介绍到这了,用起来还是比较简单的,大家可以去试试,同时也欢迎分享更好的方式!