/* * @author Michael Feng * @date 2017年9月4日 */import java.awt.AlphaComposite;import java.awt.Color;import java.awt.Graphics2D;import java.awt.Rectangle;import java.awt.RenderingHints;import java.awt.geom.Ellipse2D;import java.awt.geom.RoundRectangle2D;import java.awt.image.BufferedImage;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.net.URL;import javax.imageio.ImageIO;import org.apache.commons.lang3.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class ImageUtils { private static final Logger logger = LoggerFactory.getLogger(ImageUtils.class); /** * * @Title: 构造图片 * @Description: 生成水印并返回java.awt.image.BufferedImage * @param file * 源文件(图片) * @param waterFile * 水印文件(图片) * @param x * 距离右下角的X偏移量 * @param y * 距离右下角的Y偏移量 * @param alpha * 透明度, 选择值从0.0~1.0: 完全透明~完全不透明 * @return BufferedImage * @throws IOException */ private static BufferedImage watermark(ImageParam param) throws IOException { // 获取原图 BufferedImage buffImg = null; if(isHttpFile(param.getSourceImagePath())){ InputStream sis = null; try{ URL sourceUrl = new URL(param.getSourceImagePath()); sis = sourceUrl.openConnection().getInputStream(); buffImg = ImageIO.read(sis); }catch(Exception e){ logger.error("读取源文件异常,{}",e); }finally{ if(sis != null){ sis.close(); } } }else{ File file = null; try{ file = new File(param.getSourceImagePath()); buffImg = ImageIO.read(file); }catch(Exception e){ logger.error("读取源文件异常,{}",e); } } // 获取二维码 BufferedImage waterImg = null; if(isHttpFile(param.getQrCodeImagePath())){ InputStream sis = null; try{ URL sourceUrl = new URL(param.getQrCodeImagePath()); sis = sourceUrl.openConnection().getInputStream(); waterImg = ImageIO.read(sis); }catch(Exception e){ logger.error("读取二维码异常,{}",e); }finally{ if(sis != null){ sis.close(); } } }else{ File file = null; try{ file = new File(param.getQrCodeImagePath()); waterImg = ImageIO.read(file); }catch(Exception e){ logger.error("读取二维码异常,{}",e); } } //按照要求缩放二维码 if(param.getQrWidth() > 0 && param.getQrHeight() > 0){ BufferedImage tag = new BufferedImage(param.getQrWidth(), param.getQrHeight(), BufferedImage.TYPE_INT_RGB); tag.getGraphics().drawImage(waterImg, 0, 0,param.getQrWidth(), param.getQrHeight(), null); waterImg = tag; } //合成图片 try{ int buffWidth = buffImg.getWidth(); int bufHeight = buffImg.getHeight(); // 创建Graphics2D对象,用在底图对象上绘图 Graphics2D g2d = buffImg.createGraphics(); int waterImgWidth = waterImg.getWidth();// 获取层图的宽度 int waterImgHeight = waterImg.getHeight();// 获取层图的高度 // 在图形和图像中实现混合和透明效果 g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, param.getAlpha())); // 绘制 int start = buffWidth- param.getX() - waterImgWidth; int end = bufHeight- param.getY() - waterImgHeight; if(start < 0){ logger.error("X 设置过大"); start = 0; } if(end < 0){ logger.error("Y 设置过大"); } g2d.drawImage(waterImg, start, end , waterImgWidth, waterImgHeight, null); g2d.dispose();// 释放图形上下文使用的系统资源 }catch(Exception e){ logger.error("合成图片字节流异常,{}",e); } return buffImg; } /** * 输出水印图片 * * @param buffImg * 图像加水印之后的BufferedImage对象 * @param savePath * 图像加水印之后的保存路径 */ private static boolean generateWaterFile(BufferedImage buffImg, String savePath) { if(buffImg == null || StringUtils.isEmpty(savePath)){ return false; } boolean rs = false; int temp = savePath.lastIndexOf(".") + 1; try { rs = ImageIO.write(buffImg, savePath.substring(temp), new File(savePath)); } catch (IOException e) { logger.error("合成图片错误", e); return false; } return rs; } /** * 参数校验 * @param param * @return */ private static boolean checkParam(ImageParam param ){ if(param == null || StringUtils.isEmpty(param.getSourceImagePath()) || StringUtils.isEmpty(param.getQrCodeImagePath()) || StringUtils.isEmpty(param.getDestinyImagePath())){ return false; } return true; } /** * 判断path是否是web请求 * @param path * @return */ private static boolean isHttpFile(String path){ if(!StringUtils.isEmpty(path) && path.toLowerCase().startsWith("http")){ return true; } return false; } //合成图片 public static boolean mergeImage(ImageParam param){ if(!checkParam(param)){ logger.error("参数不合法!{}",param.toString()); return false; } long start = System.currentTimeMillis(); try{ BufferedImage buffImg = watermark(param); generateWaterFile(buffImg, param.getDestinyImagePath()); // 输出水印图片 }catch(IOException e){ logger.error("合成图片异常,{}",e); return false; } long end = System.currentTimeMillis(); logger.info("合成图片耗时:{},合成地址:",(end - start),param.getDestinyImagePath()); return true; } /** * 画圆形图片,sourcePath是原图片路径,radius是圆形图片的半径 * @param sourcePath 原图片地址,不能为空 * @param destinyPath 目的图片地址,不能为空 * @param radius,不能为负数,为0或者null表示用图片的宽、高最小值做直径 * @return */ public static boolean getCircleImage(CircleImageParam param){ if(StringUtils.isEmpty(param.getSourcePath()) || StringUtils.isEmpty(param.getDestinyPath())){ return false; } long start = System.currentTimeMillis(); // 获取原图片 BufferedImage waterImg = null; try{ if(isHttpFile(param.getSourcePath())){ InputStream sis = null; try{ URL sourceUrl = new URL(param.getSourcePath()); sis = sourceUrl.openConnection().getInputStream(); waterImg = ImageIO.read(sis); }catch(Exception e){ logger.error("读取原图片异常,{}",e); }finally{ if(sis != null){ sis.close(); } } }else{ File file = null; try{ file = new File(param.getSourcePath()); waterImg = ImageIO.read(file); }catch(Exception e){ logger.error("读取原图片异常,{}",e); } } }catch(Exception e){ logger.error("图片转换成圆形失败", e); return false; } //半径有设置时,以设置的半径为主 int width = waterImg.getWidth(); int height = waterImg.getHeight(); int getDiameter = (width < height)?width:height; if(param.getDiameter() != null && param.getDiameter() > 0){ getDiameter = param.getDiameter(); } //按照要求缩放图片 BufferedImage tag = new BufferedImage(getDiameter, getDiameter, BufferedImage.TYPE_INT_RGB); tag.getGraphics().drawImage(waterImg, 0, 0,getDiameter, getDiameter, null); waterImg = tag; //生成最终的图片 boolean rs = false; Graphics2D g2 = null; try { tag = new BufferedImage(getDiameter, getDiameter, BufferedImage.TYPE_INT_ARGB); g2 = tag.createGraphics(); g2.setComposite(AlphaComposite.Src); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(Color.WHITE); g2.fill(new RoundRectangle2D.Float(0, 0, getDiameter, getDiameter, getDiameter,getDiameter)); g2.setComposite(AlphaComposite.SrcAtop); g2.drawImage(waterImg, 0, 0, null); int temp = param.getDestinyPath().lastIndexOf(".") + 1; rs = ImageIO.write(tag,param.getDestinyPath().substring(temp), new File(param.getDestinyPath())); } catch (IOException e) { logger.error("合成图片错误", e); return false; }finally{ if(g2 != null){ g2.dispose(); } } long end = System.currentTimeMillis(); logger.info("生成圆角图片耗时:{},图片地址:",(end - start),param.getDestinyPath()); return rs; } /** * * @param args * @throws IOException * IO异常直接抛出了 * @author bls */ public static void main(String[] args) throws IOException {// String sourceFilePath = "https://z0.muscache.com/im/pictures/ec501732-e7bf-47d3-bdbb-cb2e9e5ddd6f.jpg"; String waterFilePath = "https://gss0.bdstatic.com/94o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike80%2C5%2C5%2C80%2C26/sign=fa9140accd95d143ce7bec711299e967/2934349b033b5bb571dc8c5133d3d539b600bc12.jpg"; String sourceFilePath = "C://image1.jpg";// String waterFilePath = "C://image2.jpg"; String saveFilePath = "C://new.png"; // ImageParam param = new ImageParam();// param.setSourceImagePath(sourceFilePath);//底层原图片地址 必传// param.setQrCodeImagePath(waterFilePath);//二维码图片 必传// param.setDestinyImagePath(saveFilePath);//目标保存图片路径 必传// param.setX(10); // 相对底层图片右下角的横轴 像素点 默认为0// param.setY(100);// 相对底层图片右下角的纵轴 像素点 默认为0 param.setAlpha(0.5f);//二维码图片的透明度,默认为1// param.setQrWidth(100);//二维码宽度// param.setQrHeight(50);//二维码高度// // boolean rs = ImageUtils.mergeImage(param);// System.out.println("rs:" + rs); CircleImageParam circleParam = new CircleImageParam(); circleParam.setSourcePath(sourceFilePath);//可以是网络图片,可是是本地图片 circleParam.setDestinyPath(saveFilePath);//必须是本地图片,且图片格式必须是png circleParam.setDiameter(300);//图片直径,不指定,则是原图片宽高的最小值 boolean r = ImageUtils.getCircleImage(circleParam); System.out.println("r:" + r); }}