Commit 98091597 authored by shiyu's avatar shiyu

图片旋转处理

parent 5d33e647
......@@ -14,6 +14,7 @@ import com.wwdz.ch.admin.service.UploadService;
import com.wwdz.ch.admin.util.AuthSupport;
import com.wwdz.ch.core.storage.StorageService;
import com.wwdz.ch.core.type.Result;
import com.wwdz.ch.core.util.ImgUtil;
import com.wwdz.ch.core.util.MediaUtil;
import com.wwdz.ch.core.util.ResponseUtil;
import com.wwdz.ch.core.validator.Order;
......@@ -31,8 +32,11 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;
import javax.imageio.ImageIO;
import javax.validation.constraints.NotNull;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
......@@ -74,7 +78,21 @@ public class AdminStorageController {
String originalFilename = file.getOriginalFilename();
long nowTime = System.currentTimeMillis();
String name = new BASE64Encoder().encode(Long.toString(nowTime).getBytes()) + RandomUtil.randomInt(1000);
String url = storageService.store(file.getInputStream(), file.getSize(), file.getContentType(),
InputStream targetInput = null;
try (InputStream inputStream = file.getInputStream()) {
BufferedImage image = ImageIO.read(inputStream);
ImgUtil.ImageOrientationWithNameResult orientationResult = ImgUtil.getImageFileNameWithWithRepaintInfo(file, image, null);
name = orientationResult.getImageName();
if (orientationResult.getNeedRepaint()) {
logger.info("当前图片需要进行重绘,旋转角度:【{}】", orientationResult.getAngel());
targetInput = ImgUtil.repaintImage2InputStream(image, orientationResult.getAngel(), orientationResult.getType());
}
} catch (Exception e) {
logger.error("get image size failed : ", e);
}
String url = storageService.store(targetInput, file.getSize(), file.getContentType(),
name, MediaUtil.isRotation(file));
Map<String, Object> data = new HashMap<>();
data.put("url", url);
......
package com.wwdz.ch.core.util;
import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifIFD0Directory;
import com.wwdz.ch.core.consts.MediaTypeEnum;
import com.wwdz.mall.common.util.ImageUtil;
import com.wwdz.user.api.model.user.User;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
@Slf4j
public class ImgUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(ImgUtil.class);
/**
* 打开图片校准
*/
private static final String OPEN_EXIF_FLAG = "true";
public static String convertHeaderImageUrl(String imageUrl) {
if (StringUtils.isNotEmpty(imageUrl) && !imageUrl.contains("http")) {
imageUrl = ImageUtil.getUrl(imageUrl);
}
return imageUrl;
}
/**
* 根据图片扩展信息进行图片名称构建
*
* @param file
* @param width
* @param height
* @return
*/
private static String buildNameByImageExif(MultipartFile file, String prefix, int width, int height) {
String result = prefix + "_" + width + "x" + height;
try (InputStream inputStream = file.getInputStream()) {
Metadata metadata = ImageMetadataReader.readMetadata(inputStream);
ExifIFD0Directory exifIfDo = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
int orientation;
try {
if (null != exifIfDo) {
orientation = exifIfDo.getInt(ExifIFD0Directory.TAG_ORIENTATION);
} else {
return result;
}
} catch (Exception e) {
//图片没有设置TAG_ORIENTATION doNothing
return result;
}
switch (orientation) {
case 1:
//没有进行翻转不进行处理
break;
case 6:
case 8:
//翻转270度 互换一下宽高
//翻转90度,互换一下宽高
result = prefix + "_" + height + "x" + width;
break;
case 3:
//翻转180度不进行处理
break;
default:
break;
}
} catch (Exception e) {
LOGGER.error("进行图片信息加载处理失败,原因:", e);
}
return result;
}
/**
* 用户获取携带名称以及图片反转信息的结果
*
* @param file
* @param image
* @return
*/
public static ImageOrientationWithNameResult getImageFileNameWithWithRepaintInfo(MultipartFile file, BufferedImage image, User userDO) {
String userNamePrefix = "";
if (null != userDO) {
userNamePrefix = userDO.getUserId() + "_";
}
ImageOrientationWithNameResult result = null;
String nowTime = System.currentTimeMillis() + "";
String name = new BASE64Encoder().encode(nowTime.getBytes()) + RandomUtil.getRandomInt(1000);
if (null != image) {
result = buildImageNameWithRepaintByImageExif(file, name, image.getWidth(), image.getHeight());
}
String ext = MediaTypeEnum.IMAGE_JPG.getExt();
if (null == file.getContentType()) {
throw new IllegalArgumentException("需要上传的图片信息不完整,无法获取图片格式");
}
if (file.getContentType().toLowerCase().contains(MediaTypeEnum.IMAGE_PNG.getMime())) {
ext = MediaTypeEnum.IMAGE_PNG.getExt();
} else if (file.getContentType().toLowerCase().contains(MediaTypeEnum.IMAGE_GIF.getMime())) {
ext = MediaTypeEnum.IMAGE_GIF.getExt();
}
if (null == result) {
return new ImageOrientationWithNameResult(userNamePrefix + name + "." + ext, false, null, null);
}
//设置最终图片CDN名称及格式
result.setImageName(userNamePrefix + result.getImageName() + "." + ext);
result.setType(ext);
return result;
}
/**
* 根据图片扩展信息进行图片名称构建,并返回是否需要进行重绘标识
*
* @param file
* @param prefix
* @param width
* @param height
* @return
*/
private static ImageOrientationWithNameResult buildImageNameWithRepaintByImageExif(MultipartFile file, String prefix, int width, int height) {
if (null != file) {
try (InputStream inputStream = file.getInputStream()) {
return doBuildImageNameWithRepaintByImageExif(inputStream, prefix, width, height);
} catch (IOException e) {
log.error("获取图片流失败,原因:", e);
}
}
return null;
}
/**
* 根据图片扩展信息进行图片名称构建,并返回是否需要进行重绘标识
*
* @param inputStream
* @param prefix
* @param width
* @param height
* @return
*/
private static ImageOrientationWithNameResult doBuildImageNameWithRepaintByImageExif(InputStream inputStream, String prefix, int width, int height) {
String name = prefix + "_" + width + "x" + height;
ImageOrientationWithNameResult result = new ImageOrientationWithNameResult(name, false, null, null);
Metadata metadata = null;
try {
metadata = ImageMetadataReader.readMetadata(inputStream);
} catch (Exception e) {
log.warn("普通图片处理方式失败,用一下Base64的方式", e);
try (BufferedInputStream bis = new BufferedInputStream(inputStream)) {
metadata = ImageMetadataReader.readMetadata(bis);
} catch (Exception ioException) {
log.error("base64处理方式也失败", e);
}
}
try {
if (null == metadata) {
return result;
}
ExifIFD0Directory exifIfDo = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
int orientation;
try {
if (null != exifIfDo) {
orientation = exifIfDo.getInt(ExifIFD0Directory.TAG_ORIENTATION);
} else {
log.warn("未读取到图片的orientation信息...");
return result;
}
} catch (Exception e) {
//图片没有设置TAG_ORIENTATION doNothing
return result;
}
switch (orientation) {
case 1:
//没有进行翻转不进行处理
break;
case 6:
//翻转90度,互换一下宽高
result = new ImageOrientationWithNameResult(prefix + "_" + height + "x" + width, true, orientation, 90);
break;
case 3:
//翻转180度,宽高不用互换,但图片需要重绘制
result = new ImageOrientationWithNameResult(name, true, orientation, 180);
break;
case 8:
//翻转270度 互换一下宽高
result = new ImageOrientationWithNameResult(prefix + "_" + height + "x" + width, true, orientation, 270);
break;
default:
break;
}
} catch (Exception e) {
LOGGER.error("进行图片信息加载处理失败,原因:", e);
}
return result;
}
/**
* 重绘图片
*
* @param bufferedImage 原图
* @param angel 需要旋转角度
* @return
*/
public static BufferedImage repaintImage(BufferedImage bufferedImage, int angel) {
if (bufferedImage == null) {
return null;
}
BufferedImage result;
try {
if (angel < 0) {
// 将负数角度,纠正为正数角度
angel = angel + 360;
}
int imageWidth = bufferedImage.getWidth(null);
int imageHeight = bufferedImage.getHeight(null);
// 计算重新绘制图片的尺寸
Rectangle rectangle = calculatorRotatedSize(new Rectangle(new Dimension(imageWidth, imageHeight)), angel);
// 获取原始图片的透明度
int type = bufferedImage.getColorModel().getTransparency();
result = new BufferedImage(rectangle.width, rectangle.height, type);
Graphics2D graphics = result.createGraphics();
// 平移位置
graphics.translate((rectangle.width - imageWidth) / 2, (rectangle.height - imageHeight) / 2);
// 旋转角度
graphics.rotate(Math.toRadians(angel), (double) imageWidth / 2, (double) imageHeight / 2);
// 绘图
graphics.drawImage(bufferedImage, null, null);
} catch (Exception e) {
log.error("图片重绘失败,返回原图片,原因:", e);
return bufferedImage;
}
return result;
}
/**
* 重绘图片直接返回输入流
*
* @param bufferedImage 原图
* @param angel 角度
* @param type 图片类型
* @return
*/
public static InputStream repaintImage2InputStream(BufferedImage bufferedImage, int angel, String type) {
return bufferedImageToInputStream(repaintImage(bufferedImage, angel), type);
}
/**
* 计算旋转后的尺寸
*
* @param src
* @param angel
* @return
*/
private static Rectangle calculatorRotatedSize(Rectangle src, int angel) {
if (angel >= 90) {
if (angel / 90 % 2 == 1) {
int temp = src.height;
src.height = src.width;
src.width = temp;
}
angel = angel % 90;
}
double r = Math.sqrt((double) src.height * src.height + src.width * src.width) / 2;
double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
double angelAlpha = (Math.PI - Math.toRadians(angel)) / 2;
double angelWidth = Math.atan((double) src.height / src.width);
double angelHeight = Math.atan((double) src.width / src.height);
int len2Width = (int) (len * Math.cos(Math.PI - angelAlpha - angelWidth));
int len2Height = (int) (len * Math.cos(Math.PI - angelAlpha - angelHeight));
int targetWidth = src.width + len2Width * 2;
int targetHeight = src.height + len2Height * 2;
return new Rectangle(new Dimension(targetWidth, targetHeight));
}
/**
* 将BufferedImage转换为InputStream
*
* @param image 数据源
* @param type 图片格式
* @return
*/
private static InputStream bufferedImageToInputStream(BufferedImage image, String type) {
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
ImageIO.write(image, type, os);
return new ByteArrayInputStream(os.toByteArray());
} catch (IOException e) {
log.error("bufferedImageToInputStream 出错,原因:", e);
}
return null;
}
@Data
@Accessors(chain = true)
public static class ImageOrientationWithNameResult {
public ImageOrientationWithNameResult(String imageName, Boolean needRepaint, Integer orientation, Integer angel) {
this.imageName = imageName;
this.needRepaint = needRepaint;
this.orientation = orientation;
this.angel = angel;
}
public ImageOrientationWithNameResult(String imageName, Boolean needRepaint, Integer orientation, Integer angel, String type) {
this.imageName = imageName;
this.needRepaint = needRepaint;
this.orientation = orientation;
this.angel = angel;
this.type = type;
}
/**
* 图片名称
*/
private String imageName;
/**
* 是否需要进行图片重绘
*/
private Boolean needRepaint;
/**
* 重绘依赖的参数
*/
private Integer orientation;
/**
* 旋转度数
*/
private Integer angel;
/**
* 目标图片格式 jps,png 等...
*/
private String type;
}
public static void approvalFile(MultipartFile filecontent, String path, String name) {
OutputStream os = null;
InputStream inputStream = null;
try {
inputStream = filecontent.getInputStream();
} catch (IOException e) {
log.error("approvalFile0 error", e);
}
try {
// 2、保存到临时文件
// 1K的数据缓冲
byte[] bs = new byte[1024];
// 读取到的数据长度
int len;
// 输出的文件流保存到本地文件
File tempFile = new File(path);
if (!tempFile.exists()) {
tempFile.mkdirs();
}
os = new FileOutputStream(tempFile.getPath() + File.separator + name);
// 开始读取
assert inputStream != null;
while ((len = inputStream.read(bs)) != -1) {
os.write(bs, 0, len);
}
} catch (Exception e) {
log.error("approvalFile error : ", e);
} finally {
// 完毕,关闭所有链接
try {
if (os != null) {
os.close();
}
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
log.error("approvalFile error", e);
}
}
}
}
package com.wwdz.ch.core.util;
import java.security.SecureRandom;
public class RandomUtil {
private static final SecureRandom RANDOM = new SecureRandom();
/**
* 获取随机20长度字符串
*
* @return 随机字符串
*/
public static String getRandom20Str() {
return getRandomStr(20);
}
/**
* 获取随机字符串
*
* @param length 字符串长度
* @return 随机字符串
*/
public static String getRandomStr(int length) {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, length);
}
/**
* 获取随机int值
*
* @param broad 边界
* @return int随机值
*/
public static int getRandomInt(int broad){
return RANDOM.nextInt(broad);
}
public static int getRandomInt(){
return RANDOM.nextInt();
}
}
......@@ -10,6 +10,7 @@ import com.wwdz.ch.core.storage.StorageService;
import com.wwdz.ch.core.type.PageSearchResult;
import com.wwdz.ch.core.type.Result;
import com.wwdz.ch.core.util.CacheUtil;
import com.wwdz.ch.core.util.ImgUtil;
import com.wwdz.ch.core.util.MediaUtil;
import com.wwdz.ch.db.bean.EsPageInfo;
import com.wwdz.ch.db.bean.ItemOfEs;
......@@ -1116,9 +1117,20 @@ public class ItemServiceImpl implements ItemService {
InputStream imageStream = bufferedImageToInputStream(bufferedImage, lastKey.substring(1));
qiniuStorage.store(imageStream, file.getSize(), file.getContentType(), keyName);*/
InputStream targetInput = null;
try (InputStream inputStream = file.getInputStream()) {
BufferedImage image = ImageIO.read(inputStream);
ImgUtil.ImageOrientationWithNameResult orientationResult = ImgUtil.getImageFileNameWithWithRepaintInfo(file, image, null);
if (orientationResult.getNeedRepaint()) {
logger.info("当前图片需要进行重绘,旋转角度:【{}】", orientationResult.getAngel());
targetInput = ImgUtil.repaintImage2InputStream(image, orientationResult.getAngel(), orientationResult.getType());
}
} catch (Exception e) {
logger.error("get image size failed : ", e);
}
String originalFilename = file.getOriginalFilename();
String url = storageService.store(file.getInputStream(), file.getSize(), file.getContentType(), originalFilename, MediaUtil.isRotation(file));
String url = storageService.store(targetInput, file.getSize(), file.getContentType(), originalFilename, MediaUtil.isRotation(file));
Map<String, Object> map = new HashMap<>();
map.put("url", url);
return Result.success(map);
......
......@@ -3,6 +3,7 @@ package com.wwdz.ch.wx.web;
import com.alibaba.fastjson.JSONObject;
import com.wwdz.ch.core.storage.StorageService;
import com.wwdz.ch.core.util.CharUtil;
import com.wwdz.ch.core.util.ImgUtil;
import com.wwdz.ch.core.util.MediaUtil;
import com.wwdz.ch.core.util.ResponseUtil;
import com.wwdz.ch.db.dao.dts.DtsStorageDao;
......@@ -22,6 +23,8 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
......@@ -78,7 +81,21 @@ public class WxStorageController {
logger.info("【请求开始】上传文件,请求参数,file:{}", file.getOriginalFilename());
String originalFilename = file.getOriginalFilename();
String url = storageService.store(file.getInputStream(), file.getSize(), file.getContentType(),
InputStream targetInput = null;
try (InputStream inputStream = file.getInputStream()) {
BufferedImage image = ImageIO.read(inputStream);
ImgUtil.ImageOrientationWithNameResult orientationResult = ImgUtil.getImageFileNameWithWithRepaintInfo(file, image, null);
if (orientationResult.getNeedRepaint()) {
logger.info("当前图片需要进行重绘,旋转角度:【{}】", orientationResult.getAngel());
targetInput = ImgUtil.repaintImage2InputStream(image, orientationResult.getAngel(), orientationResult.getType());
}
} catch (Exception e) {
logger.error("get image size failed : ", e);
}
String url = storageService.store(targetInput, file.getSize(), file.getContentType(),
originalFilename, MediaUtil.isRotation(file));
Map<String, Object> data = new HashMap<>();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment