import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
public class ImageUtil {
/**
* 按指定宽度 等比例缩放图片
*
* @param bufferedImage 图片
* @throws IOException
*/
public static BufferedImagethumbnail(BufferedImage bufferedImage, String suffix)throws IOException {
Integer originalWidth = bufferedImage.getWidth();
Integer originalHeight = bufferedImage.getHeight();
int wscale = Math.round((originalWidth /500) *100) /100;
int hscale = Math.round((originalHeight /500) *100) /100;
int scale = Math.max(wscale, hscale);
if (scale <2) {
scale =2;
}
int newWidth = originalWidth / scale;
int newHeight = originalHeight / scale;
if (suffix !=null &&(suffix.trim().toLowerCase().endsWith("png")
||suffix.trim().toLowerCase().endsWith("gif"))) {
bufferedImage =dealPngAndGif(bufferedImage, newWidth, newHeight);
}else {
bufferedImage =dealCommon(bufferedImage, newWidth, newHeight);
}
if (newWidth > newHeight) {
//长方形宽大于高,截掉部分宽
int i =new BigDecimal(newWidth).subtract(new BigDecimal(newHeight)).intValue();
bufferedImage = bufferedImage.getSubimage(i /2, 0, newHeight, newHeight);
}else if (newWidth < newHeight) {
//长方形高大于宽,截掉部分高
int i =new BigDecimal(newHeight).subtract(new BigDecimal(newWidth)).intValue();
bufferedImage = bufferedImage.getSubimage(0, i /2, newWidth, newWidth);
}
return bufferedImage;
}
/**
* 生成高质量图片
*
* @param bufferedImage 图片
* @throws IOException
*/
public static BufferedImagehighDefinition(BufferedImage bufferedImage, String suffix)
throws IOException {
Integer originalWidth = bufferedImage.getWidth();
Integer originalHeight = bufferedImage.getHeight();
if (originalWidth <3000) {
return bufferedImage;
}
int newWidth =new BigDecimal(originalWidth).divide(
new BigDecimal(1.6), 2, BigDecimal.ROUND_HALF_DOWN).intValue();
int newHeight =new BigDecimal(originalHeight).divide(
new BigDecimal(1.6), 2, BigDecimal.ROUND_HALF_DOWN).intValue();
if (suffix !=null &&(suffix.trim().toLowerCase().endsWith("png") || suffix.trim().toLowerCase().endsWith("gif"))) {
return dealPngAndGif(bufferedImage, newWidth, newHeight);
}else {
return dealCommon(bufferedImage, newWidth, newHeight);
}
}
/**
* 处理gif图片
*
* @param bufferedImage 图片流
* @param width 宽度
* @param height 高度
* @return
*/
private static BufferedImagedealPngAndGif(BufferedImage bufferedImage, int width, int height) {
// 处理 png 背景变黑的问题
BufferedImage newImage =new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = newImage.createGraphics();
newImage =graphics2D.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
graphics2D.dispose();
graphics2D = newImage.createGraphics();
graphics2D.drawImage(bufferedImage.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING), 0, 0, null);
graphics2D.dispose();
return newImage;
}
/**
* 普通图片处理
*
* @param bufferedImage 图片流
* @param width 宽度
* @param height 高度
* @return
*/
private static BufferedImagedealCommon(BufferedImage bufferedImage, int width, int height) {
BufferedImage newImage =new BufferedImage(width, height, bufferedImage.getType());
Graphics graphics = newImage.getGraphics();
graphics.drawImage(bufferedImage, 0, 0, width, height, null);
graphics.dispose();
return newImage;
}
/**
* 翻转类
*
* @param src
* @param imagePro
* @param ro
* @return
*/
public static BufferedImageconvert(BufferedImage src, Map imagePro, int ro) {
int angle =90 * ro;
int type = src.getColorModel().getTransparency();
int wid = imagePro.get("width");
int hei = imagePro.get("height");
if (ro %2 !=0) {
int temp = imagePro.get("width");
imagePro.put("width", imagePro.get("height"));
imagePro.put("height", temp);
}
Rectangle re =new Rectangle(new Dimension(imagePro.get("width"), imagePro.get("height")));
BufferedImage BfImg =null;
BfImg =new BufferedImage(re.width, re.height, type);
Graphics2D g2 = BfImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.rotate(Math.toRadians(angle), re.width /2, re.height /2);
g2.drawImage(src, (re.width - wid) /2, (re.height - hei) /2, null);
g2.dispose();
return BfImg;
}
/**
* 是否需要翻转
*
* @param map
* @return
*/
public static int getAngle(Map map) {
int ro =0;
if (map.get("Orientation") !=null) {
String ori = map.get("Orientation").toString();
if (ori.indexOf("90") >=0) {
ro =1;
}else if (ori.indexOf("180") >=0) {
ro =2;
}else if (ori.indexOf("270") >=0) {
ro =3;
}
}
return ro;
}
/**
* 获取图片exif信息
*
* @param inputStream
* @return
* @throws ImageProcessingException
* @throws IOException
*/
public static MapgetExif(InputStream inputStream)throws ImageProcessingException, IOException {
Metadata metadata = ImageMetadataReader.readMetadata(inputStream);
return printExif(metadata);
}
/**
* 将旋转角度信息拿到
*/
private static MapprintExif(Metadata metadata) {
Map map =new HashMap();
String tagName =null;
String desc =null;
for (Directory directory : metadata.getDirectories()) {
for (Tag tag : directory.getTags()) {
tagName = tag.getTagName();
desc = tag.getDescription();
if (tagName.equals("Orientation")) {
map.put("Orientation", desc);
}
}
}
return map;
}
}
-------------------------------------------------------分割线--------------------------------------------------
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
/**
* 图片拼接类.
*/
public class ImageMerge {
/**
* 图片拼接类
*
* @param inputStreams 图片流
* @param text1 底部文字1
* @param text2 底部文字2
* @param isCodeImage 是否有2维码
* @return
* @throws Exception
*/
public static BufferedImagedoMerge(InputStream[] inputStreams, String text1, String text2, Boolean isCodeImage)throws Exception {
if (isCodeImage) {
BufferedImage[] bufferedImages =new BufferedImage[inputStreams.length];
int width =1600;
for (int i =0; i < inputStreams.length -1; i++) {
bufferedImages[i] = ImageIO.read(inputStreams[i]);
}
bufferedImages[inputStreams.length -1] =generateImg(inputStreams[inputStreams.length -1], width, text1, text2);
return dealImage(bufferedImages, width);
}else {
BufferedImage[] bufferedImages =new BufferedImage[inputStreams.length +1];
int width =1600;
for (int i =0; i < inputStreams.length; i++) {
bufferedImages[i] = ImageIO.read(inputStreams[i]);
}
if (text1 !=null || text2 !=null) {
bufferedImages[inputStreams.length] =generateImg(null, width, text1, text2);
}
return dealImage(bufferedImages, width);
}
}
/**
* 图片等宽处理
*
* @param bufferedImages 图片缓存
* @param width 宽度
* @return
*/
private static BufferedImagedealImage(BufferedImage[] bufferedImages, int width) {
BufferedImage[] bufferedImagesNew =new BufferedImage[bufferedImages.length];
for (int i =0; i < bufferedImages.length; i++) {
BufferedImage originImage = bufferedImages[i];
int originWidth = originImage.getWidth();
int originHeight = originImage.getHeight();
BigDecimal scale =new BigDecimal(originWidth).divide(new BigDecimal(width), 10, BigDecimal.ROUND_HALF_DOWN);
int height =new BigDecimal(originHeight).divide(scale, 10, BigDecimal.ROUND_HALF_DOWN).intValue();
BufferedImage newImage =new BufferedImage(width, height, originImage.getType());
Graphics graphics = newImage.getGraphics();
graphics.drawImage(originImage, 0, 0, width, height, null);
graphics.dispose();
bufferedImagesNew[i] = newImage;
}
return mergeImage(bufferedImagesNew, width);
}
/**
* 拼接图片
*
* @param images img1 ,img2
*/
public static BufferedImagemergeImage(BufferedImage[] images, int width) {
int len = images.length;
if (len <1) {
throw new RuntimeException("图片数量小于1");
}
int height =0;
for (int i =0; i < len; i++) {
height += images[i].getHeight();
}
int gap =3;
height += (len -1) * gap;
// 生成新图片
BufferedImage imageNew =new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//增加少许图片间隙
BufferedImage blank =new BufferedImage(width, gap, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = blank.createGraphics();
graphics2D.setBackground(Color.WHITE);
graphics2D.fillRect(0, 0, width, gap);
int[] blankArray = blank.getRGB(0, 0, width, gap, new int[width * gap], 0, width);
int startY =0;
for (int i =0; i < images.length; i++) {
int iWidth = images[i].getWidth();
int iHeight = images[i].getHeight();
// 逐行扫描图像中各个像素的RGB到数组中
int[] imageArray = images[i].getRGB(0, 0, iWidth, iHeight, new int[iWidth * iHeight], 0, iWidth);
imageNew.setRGB(0, startY, width, iHeight, imageArray, 0, width);
startY += iHeight;
if (i < (images.length -1)) {
imageNew.setRGB(0, startY, width, gap, blankArray, 0, width);
startY += gap;
}
}
return imageNew;
}
/**
* 生成拼接的二维码
*
* @param codeInputStream 二维码图片
* @param width 宽度
* @param text1 底部文字1
* @param text2 底部文字2
* @return
* @throws Exception
*/
public static BufferedImagegenerateImg(InputStream codeInputStream, int width, String text1, String text2)throws Exception {
int height =new BigDecimal(width).divide(new BigDecimal(4), 10,BigDecimal.ROUND_HALF_DOWN).intValue();
// 生成底部图片
BufferedImage imageLocal =new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 以原图片为模板
Graphics2D graphics2D = imageLocal.createGraphics();
graphics2D.setBackground(Color.WHITE);
graphics2D.fillRect(0, 0, width, height);
if (codeInputStream !=null) {
// 加载用户的二维码
BufferedImage imageCode = ImageIO.read(codeInputStream);
// 在模板上添加用户二维码(地址,左边距,上边距,图片宽度,图片高度,未知)
graphics2D.drawImage(imageCode, width - height + (height /4), height /4, height /2, height /2, null);
}
//设置文本样式
int fontSize =new BigDecimal(width).divide(new BigDecimal(30), 10, BigDecimal.ROUND_HALF_DOWN).intValue();
graphics2D.setFont(new Font("宋体", Font.BOLD, fontSize));
graphics2D.setColor(Color.black);
//计算文字长度,计算居中的x点坐标
graphics2D.drawString(text1, width /20, (height /4) + fontSize);
graphics2D.setFont(new Font("宋体", Font.PLAIN, fontSize *7 /10));
graphics2D.setColor(Color.darkGray);
graphics2D.drawString(text2, width /20, (height *3 /4) - (fontSize /2));
return imageLocal;
}
}
使用方式:
int ro = ImageUtil.getAngle(ImageUtil.getExif(file.getInputStream())); --判断图片是否旋转
BufferedImage afterImage = ImageUtil.convert(bufferedImage, imagePro, ro); --判断图片是否旋转
afterImage = ImageUtil.highDefinition(afterImage, extName); -- 生成高质量图片
BufferedImage thumbnail = ImageUtil.thumbnail(afterImage, extName); --生成缩略图
ImageMerge.doMerge(inputStreams, text1, text2, isCodeImage); --图片拼接