需求:项目需要把生成的小程序二维码中心的logo换成用户自己的头像
解决方案:
1、先获取到小程序生成的二维码
//小程序路径
String page = "";
//传入小程序appId和小程序secret
JSONObject json = WxMaUtil.getAccessToken(appId, secret);
// 设置请求参数
JSONObject paramJson = new JSONObject();
paramJson.put("scene",XXX); // 你要放的参数
paramJson.put("page", page);//页面地址
paramJson.put("width", 430); // 宽度
paramJson.put("auto_color", true);
InputStream inputStream = WxMaUtil.getAppletEWMInputStream(json.getString("access_token"), paramJson);
2、合并图片需要使用 BufferedImage 类型,因此需要把InputStream 转换成 BufferedImage
//inputStream 转 BufferedInputStream
JPEGImageDecoder decoderFile = JPEGCodec.createJPEGDecoder(inputStream);
BufferedImage bis = decoderFile.decodeAsBufferedImage();
3、获取用户的头像
4、把用户头像缩放到logo大小
// 图片缩放 -----------stat
BufferedImage buffImg1 = ImageIO.read(new URL(url));
// 图片宽度
double width = buffImg1.getWidth();
// 图片高度
double height = buffImg1.getHeight();
//设置大小
if (width > 188 && height > 188) {
width = 188/(double)buffImg1.getWidth()*(double)buffImg1.getWidth();
height = 188/(double)buffImg1.getHeight()*(double)buffImg1.getHeight();
}
// ------------end
//缩放图片并转换成 BufferedImage
BufferedImage tag = toBufferedImage(buffImg1.getScaledInstance((int)width, (int)height, Image.SCALE_DEFAULT));
转换BufferedImage使用的工具类
// image 转换成 BufferedImage
public static BufferedImage toBufferedImage(Image image) {
if (image instanceof BufferedImage) {
return (BufferedImage)image;
}
image = new ImageIcon(image).getImage();
BufferedImage bimage = null;
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
try {
int transparency = Transparency.OPAQUE;
// Create the buffered image
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
bimage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), transparency);
} catch (HeadlessException e) {
}
if (bimage == null) {
int type = BufferedImage.TYPE_INT_RGB;
bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
}
Graphics g = bimage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return bimage;
}
5、把用户头像改成圆形
BufferedImage resultImg = null;
try {
if (StringUtils.isBlank(url)) {
return null;
}
// 图片转圆形 --------stat
resultImg = new BufferedImage(tag.getWidth(), tag.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = resultImg.createGraphics();
Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, tag.getWidth(), tag.getHeight());
// 使用 setRenderingHint 设置抗锯齿
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
resultImg = g.getDeviceConfiguration().createCompatibleImage(tag.getWidth(),tag.getHeight(),Transparency.TRANSLUCENT);
g = resultImg.createGraphics();
// 使用 setRenderingHint 设置抗锯齿
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setClip(shape);
g.drawImage(tag, 0, 0, null);
g.dispose();
} catch (MalformedURLException e) {
log.error("URL格式异常" + e.getMessage(), e);
} catch (IOException e) {
log.error("读取图片异常" + e.getMessage(), e);
}
return resultImg;
6、设置一张空白图片覆盖到之前logo位置(因为不确定用户头像是否存在透明背景图片或头像过小无法完全覆盖原有logo,为了美观设置一张空白图片)
7、先合并logo和空白图片,再合并头像
//设置 空白图片覆盖之前logo
BufferedImage c = tt.loadImageLocal("E:/blankImg.png");
//合并图片
BufferedImage bufferedImage1 = tt.addImage(bis, c,118,120);
//合并图片并输出
inputStream = tt.bufferedImageToInputStream(tt.addImage(bufferedImage1, bufferedImage, 120, 120));
合并图片工具类
//两个图片合成一个图片 b 二维码 d 头像
public BufferedImage addImage(BufferedImage b, BufferedImage d,int width,int height) {
try {
int w = d.getWidth();
int h = d.getHeight();
Graphics2D g = null;
g = b.createGraphics();
g.drawImage(d, width, height, w, h, null);
g.dispose();
} catch (Exception e) {
e.printStackTrace();
}
return b;
}
BufferedImage 转 InputStream工具类
//BufferedImage 转 InputStream
public InputStream bufferedImageToInputStream(BufferedImage image){
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ImageIO.write(image, "png", os);
InputStream input = new ByteArrayInputStream(os.toByteArray());
return input;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
8、往指定位置添加文字并输出
//添加文字
ArrayList<ImageDTO> list = new ArrayList<>();
list.add(createImageDTO(quotation.getQuotationName(),new Color(255,59,48),new java.awt.Font("宋体", Font.PLAIN, 20), 10, 420));
inputStream = tt.bufferedImageToInputStream(WaterMarkUtils.writeImage2(bufferedImage2, list));
public static BufferedImage writeImage2(BufferedImage srcImg, List<ImageDTO> list) {
BufferedImage bufImg = null;
try {
//读取原图片信息
int srcImgWidth = srcImg.getWidth(null);//获取图片的宽
int srcImgHeight = srcImg.getHeight(null);//获取图片的高
//添加文字:
bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufImg.createGraphics();
g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
for (ImageDTO imgDTO : list) {
g.setColor(imgDTO.getColor()); //根据图片的背景设置水印颜色
g.setFont(imgDTO.getFont()); //设置字体
g.drawString(imgDTO.getText(), imgDTO.getX(), imgDTO.getY()); //画出水印
}
g.dispose();
} catch (Exception e) {
log.error("==== 系统异常::{} ====", e);
}
return bufImg;
}
原始效果: 替换后效果:
借鉴了:
https://blog.csdn.net/servermanage/article/details/103470214