springboot 做图片添加水印(图片来源:网络或者本地 水印条数:多条)
和前面的几个随笔一样,都是在一个大型项目里面。今天要做的是证书生成下载。在图片上面添加水印,水印条数多条。直接代码 ——>
介绍:
1.我这里面是用的一个工具类,当然里面我自己又添加一些代码比如,我这里面的图片是自己先上传到文件服务器,然后服务器返回给我一个url ,这个url在浏览器里面就可以直接下载。
所以我这里获取图片的地方改动了一下。
2.原本这里面是只能添加一条水印的,然后我就对它进行了修改。直接说就是,你要添加几条水印,就是工具类参数那边的改动就是了。
3.添加完成的水印,原本是保存在本地的,然后我这边还是要上传到服务器,也就是说添加水印的过程是在服务器进行完成。这里我对工具类进行了修改,文件以流的方式上传而不经本地。
4.就是因为第三步,所以原本水印的文字是用的windows下面的自带字体,但是添加水印的过程是在服务器,而服务器并没下载字体。解决方法两个 一个是服务器下载需要的字体,第二种就是我这种把需要的字体放在项目根目录,然后读取字体文件。因为项目部署是打成jar包目录读取又不同,所以我这处理了一下。
字体放置位置:
service层接口:
/** * 证书需要的字段 * @return */ Map<String,Object> getAllStaffTrainWorker(JSONObject jsonParam);
serviceImpl实现类:
1 /** 2 * 获取证书需要的字段 3 * @return 4 */ 5 @Override 6 public Map<String,Object> getAllStaffTrainWorker(JSONObject jsonParam) { 7 String allStaffWorkerId = jsonParam.getString("allStaffWorkerIds"); 8 if (null == allStaffWorkerId){ 9 errLog("getAllStaffTrainWorker", ErrorCodeMsg.PARAM_ERROR.getMessage(), "员工id不存在"); 10 throw new AttemptException(ErrorCodeMsg.PARAM_ERROR,"员工id不存在"); 11 } 12 //员工表查询出员工的基本信息 13 Example example = new Example(AllStaffTrainWorker.class); 14 Example.Criteria criteria = example.createCriteria(); 15 criteria.andEqualTo("isDeleted", CmnConstants.IS_DELETED_NO); 16 criteria.andEqualTo("isEnabled", CmnConstants.IS_ENABLED_YES); 17 String [] allStaffWorkerArry = allStaffWorkerId.split(","); 18 List<Long> allStaffWorkerIds = new ArrayList<>(); 19 for (String allStaffWorkerIdss :allStaffWorkerArry){ 20 allStaffWorkerIds.add(Long.valueOf(allStaffWorkerIdss)); 21 } 22 criteria.andIn("allStaffWorkerId",allStaffWorkerIds); 23 List<AllStaffTrainWorker> allStaffTrainWorkerList = this.allStaffTrainWorkerMapper.selectByExample(example); 24 //姓名 25 String workerName = null; 26 //身份证号 27 String workerCardNum = null; 28 //组织名称 29 String allStaffOrgName = null; 30 //学员得分 31 BigDecimal studentScore = null; 32 //证书编号 33 String certNum = null; 34 //证书名称 35 String trainCredentialName = null; 36 //获取模板内容 37 String templateContent = null; 38 //获取背景图片路径 39 String imgUrl =null; 40 if (null != allStaffTrainWorkerList){ 41 for (AllStaffTrainWorker allStaffTrainWorker1 : allStaffTrainWorkerList){ 42 workerName= allStaffTrainWorker1.getWorkerName(); 43 workerCardNum = allStaffTrainWorker1.getWorkerCardNum(); 44 allStaffOrgName = allStaffTrainWorker1.getAllStaffOrgName(); 45 } 46 //考试表获取分数 47 Example example1 = new Example(AllStaffTrainWorkerExam.class); 48 Example.Criteria criteria1 = example1.createCriteria(); 49 criteria1.andEqualTo("isDeleted", CmnConstants.IS_DELETED_NO); 50 criteria1.andEqualTo("isEnabled", CmnConstants.IS_ENABLED_YES); 51 criteria1.andEqualTo("allStaffWorkerId",allStaffWorkerId); 52 List<AllStaffTrainWorkerExam> allStaffTrainWorkerExamList = this.allStaffTrainWorkerExamMapper.selectByExample(example1); 53 for (AllStaffTrainWorkerExam allStaffTrainWorkerExam : allStaffTrainWorkerExamList){ 54 studentScore = allStaffTrainWorkerExam.getStudentScore(); 55 } 56 //证书表得到证书编号 57 Example example2 = new Example(AllStaffTrainWorkerCert.class); 58 Example.Criteria criteria2 = example2.createCriteria(); 59 criteria2.andEqualTo("isDeleted", CmnConstants.IS_DELETED_NO); 60 criteria2.andEqualTo("isEnabled", CmnConstants.IS_ENABLED_YES); 61 criteria2.andEqualTo("allStaffWorkerId",allStaffWorkerId); 62 List<AllStaffTrainWorkerCert> allStaffTrainWorkerCertList = this.allStaffTrainWorkerCertMapper.selectByExample(example2); 63 Long allStaffTrainCertId = null; 64 for (AllStaffTrainWorkerCert allStaffTrainWorkerCert : allStaffTrainWorkerCertList){ 65 certNum = allStaffTrainWorkerCert.getCertNum(); 66 allStaffTrainCertId = allStaffTrainWorkerCert.getAllStaffTrainCertId(); 67 } 68 //配置证书表获取证书名称 69 Example example3= new Example(AllStaffTrainCert.class); 70 Example.Criteria criteria3 = example3.createCriteria(); 71 criteria3.andEqualTo("isDeleted", CmnConstants.IS_DELETED_NO); 72 criteria3.andEqualTo("isEnabled", CmnConstants.IS_ENABLED_YES); 73 criteria3.andEqualTo("allStaffTrainCertId",allStaffTrainCertId); 74 List<AllStaffTrainCert> allStaffTrainCertList = this.allStaffTrainCertMapper.selectByExample(example3); 75 //模板id 76 Long allStaffTrainTemplateId = null; 77 //图片id 78 Long allStaffTrainImgId = null; 79 for (AllStaffTrainCert allStaffTrainCert : allStaffTrainCertList){ 80 trainCredentialName = allStaffTrainCert.getTrainCredentialName(); 81 allStaffTrainTemplateId = allStaffTrainCert.getAllStaffTrainTemplateId(); 82 allStaffTrainImgId = allStaffTrainCert.getAllStaffTrainImgId(); 83 } 84 Example example4 = new Example(AllStaffTrainCertTemplate.class); 85 Example.Criteria criteria4 = example4.createCriteria(); 86 criteria4.andEqualTo("isDeleted", CmnConstants.IS_DELETED_NO); 87 criteria4.andEqualTo("isEnabled", CmnConstants.IS_ENABLED_YES); 88 criteria4.andEqualTo("allStaffTrainTemplateId",allStaffTrainTemplateId); 89 AllStaffTrainCertTemplate allStaffTrainCertTemplate = this.allStaffTrainCertTemplateMapper.selectOneByExample(example4); 90 //获取模板内容 91 templateContent = allStaffTrainCertTemplate.getTemplateContent(); 92 Example example5 = new Example(AllStaffTrainCertImg.class); 93 Example.Criteria criteria5 = example5.createCriteria(); 94 criteria5.andEqualTo("isDeleted", CmnConstants.IS_DELETED_NO); 95 criteria5.andEqualTo("isEnabled", CmnConstants.IS_ENABLED_YES); 96 criteria5.andEqualTo("allStaffTrainImgId",allStaffTrainImgId); 97 AllStaffTrainCertImg allStaffTrainCertImg = this.allStaffTrainCertImgMapper.selectOneByExample(example5); 98 //获取背景图片路径 99 imgUrl = allStaffTrainCertImg.getImgUrl(); 100 } 101 ClassPathResource classPathResource = new ClassPathResource("fonts/msyh.ttc"); 102 InputStream inputStream = null; 103 try { 104 inputStream = classPathResource.getInputStream(); 105 }catch (Exception e){ 106 e.getMessage(); 107 } 108 Font dynamicFont = null; 109 try { 110 dynamicFont = Font.createFont(Font.TRUETYPE_FONT, inputStream); 111 }catch (Exception e){ 112 e.printStackTrace(); 113 } 114 Font font = dynamicFont.deriveFont(Font.PLAIN, 28); //水印字体 方法3 115 //水印字体 116 /*Font font = new Font("微软雅黑", Font.PLAIN, 28);*/ 117 //源图片地址 118 String srcImgPath="http://"+imgUrl; 119 //待存储的地址 120 String tarImgPath = "F:/证书.jpeg"; 121 //格式化时间 122 SimpleDateFormat f=new SimpleDateFormat("yyyy MM dd"); 123 String format = f.format(new Date()); 124 //时间 125 String waterMarkContent=format; 126 //姓名 127 String workerNames = workerName; 128 //身份证号 129 String workerCardNums = workerCardNum; 130 //组织名称 131 String allStaffOrgNames = allStaffOrgName; 132 //学员得分 133 BigDecimal studentScores = studentScore; 134 //证书编号 135 String certNums =certNum; 136 //证书名称 137 String trainCredentialNames = trainCredentialName; 138 //获取模板内容 139 String templateContents = templateContent; 140 141 //水印图片色彩以及透明度 142 Color color=new Color(79 ,79 ,79); 143 BufferedImage bufferedImage = (BufferedImage) WaterMarkUtils.addWaterMark(srcImgPath, tarImgPath, waterMarkContent, workerNames, workerCardNums, allStaffOrgNames, studentScores, certNums, trainCredentialNames, templateContents, color, font); 144 String sessionToke =jsonParam.getString("sessionToke"); 145 String attname = "证书"+".jpeg"; 146 String url = null; 147 try { 148 byte[] jpegs = imageToBytes(bufferedImage, "jpeg"); 149 url = FastDFSUtils.getDoUpload(sessionToke,attname,jpegs); 150 }catch (Exception e){ 151 errLog("getDownloadAllStaffWorkers",ErrorCodeMsg.UNKNOWN_ERROR.getMessage(),e.getMessage()); 152 throw new AttemptException(ErrorCodeMsg.UNKNOWN_ERROR,e.getMessage()); 153 } 154 Map<String, Object> resultMap = getFastDFSFileInfoMap(url,attname); 155 return resultMap; 156 } 157 158 public byte[] imageToBytes(BufferedImage bImage, String format) { 159 ByteArrayOutputStream out = new ByteArrayOutputStream(); 160 try { 161 ImageIO.write(bImage, format, out); 162 } catch (IOException e) { 163 e.printStackTrace(); 164 } 165 return out.toByteArray(); 166 } 167 168 /** 169 * 返回给前端下载地址 170 * 171 * @param url 172 * @param attname 173 * @return 174 */ 175 private Map<String, Object> getFastDFSFileInfoMap(String url, String attname) { 176 String filePath = null; 177 if (StringUtils.isNotEmpty(url)) { 178 JSONObject jsonObject = JSONObject.parseObject(url); 179 String data = jsonObject.getString("data"); 180 JSONObject dataObject = JSONObject.parseObject(data); 181 filePath = dataObject.getString("filePath"); 182 if (StringUtils.isEmpty(filePath)) { 183 errLog("getFastDFSFileInfoMap", ErrorCodeMsg.UNKNOWN_ERROR.getMessage(), "获取文件服务下载地址为空"); 184 throw new AttemptException(ErrorCodeMsg.UNKNOWN_ERROR, "获取文件服务下载地址为空"); 185 } 186 } 187 Map<String, Object> map = new HashMap<>(32); 188 map.put("url",fileServer+"/"+filePath); 189 map.put("attname", attname); 190 return map; 191 }
controller层代码:
1 /** 2 * 证书需要的内容 3 * @return 4 */ 5 @PostMapping("/getAllStaffTrainWorker") 6 public ResponseStruct getAllStaffTrainWorker(@RequestBody JSONObject jsonParam){ 7 return ResponseStruct.success(this.allStaffTrainWorkerCertInterface.getAllStaffTrainWorker(jsonParam)); 8 }
图片处理工具类 WaterMarkUtils:
1 package com.guangl.allStaff.train.utils; 2 3 4 import javax.imageio.ImageIO; 5 import java.awt.*; 6 import java.awt.image.BufferedImage; 7 import java.io.*; 8 import java.math.BigDecimal; 9 import java.net.HttpURLConnection; 10 import java.net.URL; 11 12 public class WaterMarkUtils { 13 /** 14 * @param srcImgPath 源图片路径 15 * @param tarImgPath 保存的图片路径 16 * @param waterMarkContent 水印内容 17 * @param markContentColor 水印颜色 18 * @param font 水印字体 19 * @param workerNames 20 */ 21 public static Object addWaterMark(String srcImgPath, String tarImgPath, String waterMarkContent, String workerNames, 22 String workerCardNums, String allStaffOrgNames, BigDecimal studentScores, String certNums, String trainCredentialNames, 23 String templateContents, Color markContentColor, Font font) { 24 try { 25 //new一个url对象 26 URL url = new URL(srcImgPath); 27 //打开链接 28 HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 29 //设置请求方式 30 /*conn.setRequestMethod("GET");*/ 31 //超时相应时间为5秒 32 conn.setConnectTimeout(5*1000); 33 //通过输入流获取图片数据 34 InputStream inputStream = null; 35 try { 36 inputStream = conn.getInputStream(); 37 }catch (Exception e){ 38 e.printStackTrace(); 39 } 40 //文件转化为图片 41 Image srcImg = null; 42 try { 43 srcImg = ImageIO.read(inputStream); 44 }catch (Exception e){ 45 e.printStackTrace(); 46 } 47 //获取图片的宽 48 int srcImgWidth = srcImg.getWidth(null); 49 //获取图片的高 50 int srcImgHeight = srcImg.getHeight(null); 51 52 // 加水印 53 BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB); 54 Graphics2D g = bufImg.createGraphics(); 55 g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null); 56 //根据图片的背景设置水印颜色 57 g.setColor(markContentColor); 58 //设置字体 59 g.setFont(font); 60 //设置时间水印的坐标 61 int x = (int) (srcImgWidth - 1.64*getWatermarkLength(waterMarkContent, g)); 62 int y = (int) (srcImgHeight - 1.15*getWatermarkLength(waterMarkContent, g)); 63 int x2 = 0; 64 int y2 = 0; 65 //设置姓名水印坐标 66 if (workerNames.length() == 3){ 67 x2 = (int) (srcImgWidth - 7.4*getWatermarkLength(workerNames,g)); 68 y2 = (int) (srcImgHeight - 7.27*getWatermarkLength(workerNames,g)); 69 }else if (workerNames.length() == 2){ 70 x2 = (int) (srcImgWidth - 11*getWatermarkLength(workerNames,g)); 71 y2 = (int) (srcImgHeight - 10.9*getWatermarkLength(workerNames,g)); 72 }else if (workerNames.length() == 4){ 73 x2 = (int) (srcImgWidth - 5.9*getWatermarkLength(workerNames,g)); 74 y2 = (int) (srcImgHeight - 5.45*getWatermarkLength(workerNames,g)); 75 } 76 int x3 =0; 77 int y3 =0; 78 if (workerCardNums.length() == 18){ 79 //设置身份证号水印坐标 80 x3 = (int) (srcImgWidth - 1.6*getWatermarkLength(workerCardNums,g)); 81 y3 = (int) (srcImgHeight - 0.4*getWatermarkLength(workerCardNums,g)); 82 }else if (workerCardNums.length() == 17){ 83 x3 = (int) (srcImgWidth - 1.7*getWatermarkLength(workerCardNums,g)); 84 y3 = (int) (srcImgHeight - 0.42*getWatermarkLength(workerCardNums,g)); 85 }else if (workerCardNums.length() == 16){ 86 x3 = (int) (srcImgWidth - 1.8*getWatermarkLength(workerCardNums,g)); 87 y3 = (int) (srcImgHeight - 0.45*getWatermarkLength(workerCardNums,g)); 88 } 89 //设置组织名称水印坐标 90 int x4 = srcImgWidth - 2*getWatermarkLength(allStaffOrgNames,g); 91 int y4 = srcImgHeight - 3*getWatermarkLength(allStaffOrgNames,g); 92 int x5 = 0; 93 int y5 = 0; 94 if (studentScores.longValue() >= 100){ 95 //设置分数水印坐标 96 x5 = (int) (srcImgWidth - 11.8*getWatermarkLength(String.valueOf(studentScores),g)); 97 y5 = (int) (srcImgHeight - 9.7*getWatermarkLength(String.valueOf(studentScores),g)); 98 }else if (studentScores.longValue() <10 && studentScores.longValue()>= 0){ 99 //设置分数水印坐标 100 x5 = (int) (srcImgWidth - 35*getWatermarkLength(String.valueOf(studentScores),g)); 101 y5 = (int) (srcImgHeight - 28.99*getWatermarkLength(String.valueOf(studentScores),g)); 102 }else if (studentScores.longValue() <= 99 && studentScores.longValue()> 10){ 103 //设置分数水印坐标 104 x5 = (int) (srcImgWidth - 17.4*getWatermarkLength(String.valueOf(studentScores),g)); 105 y5 = (int) (srcImgHeight - 14.5*getWatermarkLength(String.valueOf(studentScores),g)); 106 } 107 108 //设置证书编号水印坐标 109 int x6 = 0; 110 int y6 = 0; 111 if (certNums.length() == 15){ 112 x6 = (int) (srcImgWidth - 2.09*getWatermarkLength(certNums,g)); 113 y6 = (int) (srcImgHeight - 4.14*getWatermarkLength(certNums,g)); 114 } 115 //设置证书名称水印坐标 116 int x7 = srcImgWidth - 3*getWatermarkLength(trainCredentialNames,g); 117 int y7 = srcImgHeight - 2*getWatermarkLength(trainCredentialNames,g); 118 //设置模板内容水印坐标 119 int x8 = srcImgWidth - 1*getWatermarkLength(templateContents,g); 120 int y8 = srcImgHeight - 1*getWatermarkLength(templateContents,g); 121 122 //画出水印 123 g.drawString(waterMarkContent,x,y); 124 g.drawString(workerNames,x2,y2); 125 g.drawString(workerCardNums,x3,y3); 126 /* g.drawString(allStaffOrgNames,x4,y4);*/ 127 g.drawString(String.valueOf(studentScores),x5,y5); 128 g.drawString(certNums,x6,y6); 129 /*g.drawString(trainCredentialNames,x7,y7); 130 g.drawString(templateContents,x8,y8);*/ 131 g.dispose(); 132 // 输出图片 133 // FileOutputStream outImgStream = new FileOutputStream(tarImgPath); 134 // ImageIO.write(bufImg, "jpeg", outImgStream); 135 System.out.println("添加水印完成"); 136 return bufImg; 137 } catch (Exception e) { 138 // TODO: handle exception 139 } 140 return null; 141 } 142 143 private byte[] readInputStream(InputStream inputStream) throws IOException { 144 ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 145 //创建一个Buffer字符串 146 byte[] buffer = new byte[1024]; 147 //每次读取的字符串长度,如果为-1,代表全部读取完毕 148 int len = 0; 149 //使用一个输入流从buffer里把数据读取出来 150 while( (len=inputStream.read(buffer)) != -1 ){ 151 //用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度 152 outStream.write(buffer, 0, len); 153 } 154 //关闭输入流 155 inputStream.close(); 156 //把outStream里的数据写入内存 157 return outStream.toByteArray(); 158 } 159 160 public static int getWatermarkLength(String waterMarkContent, Graphics2D g) { 161 return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length()); 162 } 163 }