1.把需要合成的两个(多个)图片转成BufferedImage
BufferedImage bgImgBuf = ImageIO.read("背景图");
BufferedImage qrImgBuf = ImageIO.read("二维码图");
2.合成
BufferedImage genBufImg = overlyingImage(bgImgBuf,qrImgBuf, his.getQrWH(),his.getQrX(),his.getQrY(), Float.parseFloat(his.getQrA()));/**
* @param bgImgBuf 源文件(BufferedImage)
* @param qrImgBuf 二维码文件(BufferedImage)
* @param qrWH 二维码的宽高
* @param x 距离右下角的X偏移量
* @param y 距离右下角的Y偏移量
* @param qrA 透明度, 选择值从0.01.0: 完全透明完全不透明
* @return BufferedImage * @Title: 构造合并图片
*/
public static BufferedImage overlyingImage(BufferedImage bgImgBuf, BufferedImage qrImgBuf, int qrWH, int x, int y, float qrA) {int bgImgW = bgImgBuf.getWidth(); int bgImgH = bgImgBuf.getHeight(); //创建Graphics2D对象,用在底图对象上绘图Graphics2D g2d = bgImgBuf.createGraphics(); //g2d.setBackground(Color.WHITE); //在图形和图像中实现混合和透明效果g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, qrA));
//绘制 g2d.drawImage(qrImgBuf, bgImgW - qrWH - x, bgImgH - qrWH - y, qrWH, qrWH, null); g2d.dispose(); return bgImgBuf;
}
3.注意事项
合并只是得到一个BufferedImage的文件,前端是不能直接展示出来这个图片的,需要做转换处理,把BufferedImage 转成MultipartFile(或者File)。
注意事项:BufferedImage不能直接转成MultipartFile,转出来的MultipartFile是由问题的(至于有什么问题,可以Debug就能看到问题了)。
流程如下:
3.1 把BufferedImage转成File
String ext = FileUtil.extName(his.getBgImg());
String fileName = his.getNo().concat(".").concat(ext);
String path = ClassLoader.getSystemResource("").getPath().concat("temp_file");
logger.info("临时文件存储路径:{}", path);
//把合成的海报先临时保存到项目的resources/temp_file下
String filePath = path.concat("/").concat(fileName);
File file = new File(filePath);
ImageIO.write(genBufImg, ext, file);
logger.info("图片保存:{}", file.exists());
3.2 把File存到项目目录下(或者磁盘)
String ext = FileUtil.extName(his.getBgImg());
String fileName = his.getNo().concat(".").concat(ext);
String path = ClassLoader.getSystemResource("").getPath().concat("temp_file");
logger.info("临时文件存储路径:{}", path);
//把合成的海报先临时保存到项目的resources/temp_file下
String filePath = path.concat("/").concat(fileName);
File file = new File(filePath);
ImageIO.write(genBufImg, ext, file);
logger.info("图片保存:{}", file.exists());
3.3 从项目目录(或磁盘)把File读取出来(一般这步直接使用上面3.2的File即可
File file = new File(filePath);
3.4 把读取到的File转成MultipartFile
public static MultipartFile file2MultipartFile(File file) {return new CommonsMultipartFile(createFileItem(file));
}private static FileItem createFileItem(File file){DiskFileItemFactory factory = new DiskFileItemFactory(16, null); FileItem fileItem = factory.createItem("testField", "text/plain", true, file.getName()); int byteRead = 0; byte[] buffer = new byte[8192];try (FileInputStream fis = new FileInputStream(file); OutputStream os = fileItem.getOutputStream()) { while ((byteRead = fis.read(buffer, 0, 8192)) != -1) {os.write(buffer, 0, byteRead); } os.close(); fis.close(); } catch (IOException e) {e.printStackTrace(); } return fileItem;
}
3.6 MultipartFile上传到七牛云(或者服务器)得到可展示的URL(这步如果不需要,可以不写)
//如有需求
3.7 删除项目目录(磁盘)的源文件(如有必要)
file.delete();
其实,3.1、3.2、3.3、3.4这几步都是解决BufferedImage不能直接转成MultipartFile这个问题。
如果合成的图片由遮罩(阴影),那么一定是这个原因,在把合成得到的BufferedImage转成File存到时,有这么一个方法ImageIO.write(genBufImg, ext, file)
,第二个参数是图片的后缀,必须使用图片的原后缀,不能修改,比如,原来图片的后缀是png,这里你写死成jpg,就会出现这个问题;
4.需要引入的包
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.5</version>
</dependency>