复制粘贴就能用!!!
需求:好几张图片合成一张分享海报.其中还有半透明照片的生成与合成.不复杂调整比例比较耗时间
package com.web.controller.online;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import org.apache.commons.codec.binary.Base64;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
public class muban2 {
// private Logger logger = LoggerFactory.getLogger(this.getClass());
public static void main(String[] args) {
byte[] bytes = compositePicture();
String base64String = Base64.encodeBase64String(bytes);
// logger.info("{} encodeBase64String编码后:{}",companyKey, base64String.getBytes().length ,base64String.getBytes().length / 1024);
System.out.println("data:image/png;base64,"+base64String);
}
//调用底图 有头像就使用头像粘贴
public static byte[] compositePicture( ) {
try {
//生成了一张底图后 再次进行后面拼接
BufferedImage ditu = ditu();
Graphics2D g = ditu.createGraphics();//另起一个设置
//如果有头像信息
//头像跟用户名背景区域 创建黑色遮罩层
BufferedImage touxiang = new BufferedImage(386, 122, BufferedImage.TYPE_INT_RGB);
Graphics2D gTouxiang = touxiang.createGraphics();
gTouxiang.setColor(Color.BLACK);//设置这个图片对象的颜色
gTouxiang.fillRect(0, 0, 386, 122);//设置这个图片对象的颜色范围
gTouxiang.dispose();
//开启透明度 透明度必须在单独的一个配置中开启 否则会与其他东西共用透明 导致其他导入的图片字体也会透明
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f));//设置本次导入的所有图片与字体透明
Rectangle rectangleTouxiang = new Rectangle(24, 24, 386, 122);
BufferedImage touxiangBeijing = setClip(touxiang, 122);//头像背景切圆角
g.drawImage(touxiangBeijing.getScaledInstance(rectangleTouxiang.width, rectangleTouxiang.height, Image.SCALE_SMOOTH), rectangleTouxiang.x, rectangleTouxiang.y, null);//把透明头像背景放到指定的位置
g.dispose();
Graphics2D bg = ditu.createGraphics();//另起一个设置
//头像的底部
BufferedImage touxiangD = new BufferedImage(100, 100 , BufferedImage.TYPE_INT_RGB);
Graphics2D gTouxiangD = touxiangD.createGraphics();
gTouxiangD.setColor(Color.WHITE);//设置这个图片对象的颜色
gTouxiangD.fillRect(0, 0, 100, 100);//设置这个图片对象的颜色范围
BufferedImage bufferedImageTouXiangD = roundImage(touxiangD, 100, 100);//头像背景变圆
Graphics2D yuanDi = bufferedImageTouXiangD.createGraphics();
//头像变圆
BufferedImage guanxiaotong = new BufferedImage(96, 96, BufferedImage.TYPE_INT_RGB);
guanxiaotong.getGraphics().drawImage(
ImageIO.read(new File("C:\\Users\\Administrator\\Desktop\\timg.jpg")).getScaledInstance(96, 96, Image.SCALE_SMOOTH), 0, 0, null);
// BufferedImage guanxiaotong = JqzImageUtils.resizeImage(96, 96, ImageIO.read(new Url("www.某一张图片地址.com")));//调用网上图片
BufferedImage bufferedImage = roundImage(guanxiaotong, 96, 96);//变圆 设置大小尺寸
Rectangle rectangleG = new Rectangle(2, 2, 96, 96);//设置头像尺寸与在白背景内与边框的距离
yuanDi.drawImage(bufferedImage.getScaledInstance(rectangleG.width, rectangleG.height, Image.SCALE_SMOOTH), rectangleG.x, rectangleG.y, null);//把圆头像放到白色底部后面
Rectangle rectangletouxiangD = new Rectangle(34, 34, 100, 100);
bg.drawImage(bufferedImageTouXiangD.getScaledInstance(rectangletouxiangD.width, rectangletouxiangD.height, Image.SCALE_SMOOTH), rectangletouxiangD.x, rectangletouxiangD.y, null);//把贴好白色背景的头像放到头像背景后面
// 金额
bg.setFont(new Font("Microsoft YaHei", Font.BOLD, 30));//设置字体大小
bg.setColor(Color.WHITE);//设置字体颜色
bg.drawString("关晓彤", 150, 75);//设置字体位置
bg.setFont(new Font("Microsoft YaHei", Font.BOLD, 20));//设置字体大小
bg.setColor(Color.WHITE);//设置字体颜色
bg.drawString("给您分享了一个商品", 150, 110);//设置字体位置
ByteArrayOutputStream output = new ByteArrayOutputStream();
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(output);
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(ditu);
param.setQuality(0.98f, true);
encoder.encode(ditu, param);
return output.toByteArray();
} catch (IOException e) {
System.out.println("合成图片失败"+e.getMessage());
return null;
}
}
//生成底图
public static BufferedImage ditu(){
try {
//TODO
// 透明底
BufferedImage bg = new BufferedImage(664, 988, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bg.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, 664, 988);// 填充整个屏幕
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); // 消除画图锯齿
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // 消除文字锯齿
// 写入商品图
BufferedImage bufferedImageG = ImageIO.read(new URL(backgroundUrl));
int widthG = bufferedImageG.getWidth();
int heightG = bufferedImageG.getHeight();
BufferedImage goodsIm = new BufferedImage(widthG, heightG, 1);
goodsIm .getGraphics().drawImage(bufferedImageG .getScaledInstance(widthG,widthG, 4), 0, 0, (ImageObserver)null);
BufferedImage back;
if (widthG >= heightG) {//图片宽比高大(宽图) 取高的值 截成一个正方形
int x = 0;
if ((widthG - heightG) >= 2) {//像素大于2 才调整截图值
x = (widthG - heightG) / 2;//调整Y的值 截取图片中间
}
back = goodsIm.getSubimage(x, 0, heightG, heightG);//截取图片重新调整
} else {//图片高比宽大(高图) 取宽的值 截成一个正方形
int y = 0;
if ((heightG - widthG) >= 2) {//像素大于2 才调整截图值
y = (heightG - widthG) / 2;//调整Y的值 截取图片中间
}
back = goodsIm.getSubimage(0, y, widthG, widthG);//截取图片重新调整
}
Rectangle rectangle = new Rectangle(50, 168, 566, 556);//有头像
g.drawImage(back.getScaledInstance(rectangle.width, rectangle.height, Image.SCALE_SMOOTH), rectangle.x, rectangle.y, null);
// 写入二维码
BufferedImage qrcode = null;
try {
Map<EncodeHintType, String> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
BitMatrix bitMatrix = new MultiFormatWriter().encode("www.baidu.com", BarcodeFormat.QR_CODE, 462, 462, hints);
qrcode = toBufferedImage(bitMatrix);
} catch (WriterException e) {
e.printStackTrace();
}
g.drawImage(qrcode, 438, 714, 198, 198, null);
//人民币图标
g.setFont(new Font("Microsoft YaHei", Font.PLAIN, 36));
g.setColor(Color.red);
g.drawString("¥" , 54, 852);
// 金额
g.setFont(new Font("Microsoft YaHei", Font.BOLD, 60));
g.setColor(Color.red);
g.drawString("100", 76, 852);
// 重量
g.setFont(new Font("Microsoft YaHei", Font.PLAIN, 25));
g.setColor(new Color(89, 89, 89));
g.drawString("500g" , 210, 852);
g.setFont(new Font("Microsoft YaHei", Font.PLAIN, 25));
g.setColor(Color.gray);
g.drawString("XXXXXXXXXXX", 50, 728);
g.setFont(new Font("Microsoft YaHei", Font.PLAIN, 25));
g.setColor(Color.gray);
g.drawString("XXXXX", 50, 775);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 消除画图锯齿
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // 消除文字锯齿
g.dispose();
return bg;
} catch (IOException e) {
System.out.println("合成图片失败"+e.getMessage());
return null;
}
}
//将二维码转换成图片
public static BufferedImage toBufferedImage(BitMatrix matrix){
int width = matrix.getWidth();
int height = matrix.getHeight();
int BLACK = 0xFF000000;
int WHITE = 0xFFFFFFFF;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int i = 0;i < width; i++){
for (int j = 0;j < height; j++){
image.setRGB(i, j, matrix.get(i, j) ? BLACK : WHITE);
}
}
return image;
}
/***
* 做圆图片方法
* @param targetSize 文件的边长,单位:像素,最终得到的是一张正方形的图,所以要求targetSize<=源文件的最小边长 新构造的高度
* @param cornerRadius 圆角半径,单位:像素。如果=targetSize那么得到的是圆形图 圆角的宽度
* @return 文件的保存路径
* @throws IOException
*/
private static BufferedImage roundImage(BufferedImage image, int targetSize, int cornerRadius) {
BufferedImage outputImage = new BufferedImage(targetSize, targetSize, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = outputImage.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, targetSize, targetSize, cornerRadius, cornerRadius));
g2.setComposite(AlphaComposite.SrcAtop);
g2.drawImage(image, 0, 0, null);
g2.dispose();
return outputImage;
}
/**
* 图片设置圆角
* @param srcImage
* @return
* @throws IOException
*/
public static BufferedImage setRadius(BufferedImage srcImage) throws IOException{
int radius = (srcImage.getWidth() + srcImage.getHeight()) / 6;
return setRadius(srcImage, radius, 2, 5);
}
/**
* 图片设置圆角
* @param srcImage
* @param radius
* @param border
* @param padding
* @return
* @throws IOException
*/
public static BufferedImage setRadius(BufferedImage srcImage, int radius, int border, int padding) throws IOException{
int width = srcImage.getWidth();
int height = srcImage.getHeight();
int canvasWidth = width + padding * 2;
int canvasHeight = height + padding * 2;
BufferedImage image = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D gs = image.createGraphics();
gs.setComposite(AlphaComposite.Src);
gs.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
gs.setColor(Color.WHITE);
gs.fill(new RoundRectangle2D.Float(0, 0, canvasWidth, canvasHeight, radius, radius));
gs.setComposite(AlphaComposite.SrcAtop);
gs.drawImage(setClip(srcImage, radius), padding, padding, null);
if(border !=0){
gs.setColor(Color.GRAY);
gs.setStroke(new BasicStroke(border));
gs.drawRoundRect(padding, padding, canvasWidth - 2 * padding, canvasHeight - 2 * padding, radius, radius);
}
gs.dispose();
return image;
}
/**
* 图片切圆角 抗锯齿
* @param srcImage
* @param radius
* @return
*/
public static BufferedImage setClip(BufferedImage srcImage, int radius){
int width = srcImage.getWidth();
int height = srcImage.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = image.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillRoundRect(0, 0, width, height, radius, radius);
g2d.setComposite(AlphaComposite.SrcIn);//抗锯齿
g2d.drawImage(srcImage, 0, 0, width, height, null);
return image;
}
}