springboot——图片添加文字水印

springBoot 给图片添加文字水印

项目要求给每个考生制作证书。这里我们有每个公司需要的背景图片模板,而我现在要做的就是把每个考生的考试信息和个人信息,以水印的形式添加到图片的指定位置。(现在这个灵活性不高)下面就直接上代码。

  1. 首先我这边先写了一个工具类waterMarkUtils 。在这个工具类里面主要设置每个水印的位置以及字体还有存放位置。(我这边因为要上传到服务器,所以就稍微处理了一下,还有我这个可以添加多个水印,图片的来源是网络路径)代码如下:
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;

public class WaterMarkUtils {
   /**
    * @param srcImgPath 源图片路径
    * @param tarImgPath 保存的图片路径
    * @param waterMarkContent 水印内容
    * @param markContentColor 水印颜色
    * @param font 水印字体
    * @param workerNames
    */
   public static Object addWaterMark(String srcImgPath, String tarImgPath, String waterMarkContent, String workerNames,
                                     String workerCardNums, String allStaffOrgNames, BigDecimal studentScores, String certNums, String trainCredentialNames,
                                     String templateContents, Color markContentColor, Font font) {
       try {
           //new一个url对象
           URL url = new URL(srcImgPath);
           //打开链接
           HttpURLConnection  conn = (HttpURLConnection)url.openConnection();
           //设置请求方式
           /*conn.setRequestMethod("GET");*/
           //超时相应时间为5秒
           conn.setConnectTimeout(5*1000);
           //通过输入流获取图片数据
           InputStream inputStream = null;
           try {
               inputStream = conn.getInputStream();
           }catch (Exception e){
               e.printStackTrace();
           }
           //文件转化为图片
           Image srcImg = null;
           try {
               srcImg = ImageIO.read(inputStream);
           }catch (Exception e){
               e.printStackTrace();
           }
           //获取图片的宽
           int srcImgWidth = srcImg.getWidth(null);
           //获取图片的高
           int srcImgHeight = srcImg.getHeight(null);

           // 加水印
           BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
           Graphics2D g = bufImg.createGraphics();
           g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
           //根据图片的背景设置水印颜色
           g.setColor(markContentColor);
           //设置字体
           g.setFont(font);
           //设置时间水印的坐标
           int x = (int) (srcImgWidth - 1.64*getWatermarkLength(waterMarkContent, g));
           int y = (int) (srcImgHeight - 1.15*getWatermarkLength(waterMarkContent, g));
           int x2 = 0;
           int y2 = 0;
           //设置姓名水印坐标
           if (workerNames.length() == 3){
                x2 = (int) (srcImgWidth - 7.4*getWatermarkLength(workerNames,g));
                y2 = (int) (srcImgHeight - 7.27*getWatermarkLength(workerNames,g));
           }else if (workerNames.length() == 2){
                x2 = (int) (srcImgWidth - 11*getWatermarkLength(workerNames,g));
                y2 = (int) (srcImgHeight - 10.9*getWatermarkLength(workerNames,g));
           }else if (workerNames.length() == 4){
               x2 = (int) (srcImgWidth - 5.9*getWatermarkLength(workerNames,g));
               y2 = (int) (srcImgHeight - 5.45*getWatermarkLength(workerNames,g));
           }
           int x3 =0;
           int y3 =0;
           if (workerCardNums.length() == 18){
               //设置身份证号水印坐标
               x3 = (int) (srcImgWidth - 1.6*getWatermarkLength(workerCardNums,g));
               y3 = (int) (srcImgHeight - 0.4*getWatermarkLength(workerCardNums,g));
           }else if (workerCardNums.length() == 17){
               x3 = (int) (srcImgWidth - 1.7*getWatermarkLength(workerCardNums,g));
               y3 = (int) (srcImgHeight - 0.42*getWatermarkLength(workerCardNums,g));
           }else if (workerCardNums.length() == 16){
               x3 = (int) (srcImgWidth - 1.8*getWatermarkLength(workerCardNums,g));
               y3 = (int) (srcImgHeight - 0.45*getWatermarkLength(workerCardNums,g));
           }
           //设置组织名称水印坐标
           int x4 = srcImgWidth - 2*getWatermarkLength(allStaffOrgNames,g);
           int y4 = srcImgHeight - 3*getWatermarkLength(allStaffOrgNames,g);
           int x5 = 0;
           int y5 = 0;
           if (studentScores.longValue() >= 100){
               //设置分数水印坐标
               x5 = (int) (srcImgWidth - 11.8*getWatermarkLength(String.valueOf(studentScores),g));
               y5 = (int) (srcImgHeight - 9.7*getWatermarkLength(String.valueOf(studentScores),g));
           }else if (studentScores.longValue() <10 && studentScores.longValue()>= 0){
               //设置分数水印坐标
               x5 = (int) (srcImgWidth - 35*getWatermarkLength(String.valueOf(studentScores),g));
               y5 = (int) (srcImgHeight - 28.99*getWatermarkLength(String.valueOf(studentScores),g));
           }else if (studentScores.longValue() <= 99 && studentScores.longValue()> 10){
               //设置分数水印坐标
               x5 = (int) (srcImgWidth - 17.4*getWatermarkLength(String.valueOf(studentScores),g));
               y5 = (int) (srcImgHeight - 14.5*getWatermarkLength(String.valueOf(studentScores),g));
           }

           //设置证书编号水印坐标
           int x6 = 0;
           int y6 = 0;
           if (certNums.length() == 15){
               x6 = (int) (srcImgWidth - 2.09*getWatermarkLength(certNums,g));
               y6 = (int) (srcImgHeight - 4.14*getWatermarkLength(certNums,g));
           }
           //设置证书名称水印坐标
           int x7 = srcImgWidth - 3*getWatermarkLength(trainCredentialNames,g);
           int y7 = srcImgHeight - 2*getWatermarkLength(trainCredentialNames,g);
           //设置模板内容水印坐标
           int x8 = srcImgWidth - 1*getWatermarkLength(templateContents,g);
           int y8 = srcImgHeight - 1*getWatermarkLength(templateContents,g);

           //画出水印
           g.drawString(waterMarkContent,x,y);
           g.drawString(workerNames,x2,y2);
           g.drawString(workerCardNums,x3,y3);
          /* g.drawString(allStaffOrgNames,x4,y4);*/
           g.drawString(String.valueOf(studentScores),x5,y5);
           g.drawString(certNums,x6,y6);
           /*g.drawString(trainCredentialNames,x7,y7);
           g.drawString(templateContents,x8,y8);*/
           g.dispose();
           // 输出图片
//            FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
//            ImageIO.write(bufImg, "jpeg", outImgStream);
           System.out.println("添加水印完成");
           return bufImg;
       } catch (Exception e) {
           // TODO: handle exception
       }
       return null;
   }

   private byte[] readInputStream(InputStream inputStream) throws IOException {
       ByteArrayOutputStream outStream = new ByteArrayOutputStream();
       //创建一个Buffer字符串
       byte[] buffer = new byte[1024];
       //每次读取的字符串长度,如果为-1,代表全部读取完毕
       int len = 0;
       //使用一个输入流从buffer里把数据读取出来
       while( (len=inputStream.read(buffer)) != -1 ){
           //用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
           outStream.write(buffer, 0, len);
       }
       //关闭输入流
       inputStream.close();
       //把outStream里的数据写入内存
       return outStream.toByteArray();
   }

   public static int getWatermarkLength(String waterMarkContent, Graphics2D g) {
       return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
   }
}

然后就是自己写查询的代码了,我这里是直接在serviceImpl 实现类里面调用的这个工具类 代码如下:

service层接口:
在这里插入图片描述
serviceImpl实现类:

 /**
     * 获取证书需要的字段
     * @return
     */
    @Override
    public Map<String,Object> getAllStaffTrainWorker(JSONObject jsonParam) {
        String allStaffWorkerId = jsonParam.getString("allStaffWorkerIds");
        if (null == allStaffWorkerId){
            errLog("getAllStaffTrainWorker", ErrorCodeMsg.PARAM_ERROR.getMessage(), "员工id不存在");
            throw new AttemptException(ErrorCodeMsg.PARAM_ERROR,"员工id不存在");
        }
        //员工表查询出员工的基本信息
        Example example = new Example(AllStaffTrainWorker.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("isDeleted", CmnConstants.IS_DELETED_NO);
        criteria.andEqualTo("isEnabled", CmnConstants.IS_ENABLED_YES);
        String [] allStaffWorkerArry = allStaffWorkerId.split(",");
        List<Long> allStaffWorkerIds = new ArrayList<>();
        for (String allStaffWorkerIdss :allStaffWorkerArry){
            allStaffWorkerIds.add(Long.valueOf(allStaffWorkerIdss));
        }
        criteria.andIn("allStaffWorkerId",allStaffWorkerIds);
        List<AllStaffTrainWorker> allStaffTrainWorkerList = this.allStaffTrainWorkerMapper.selectByExample(example);
        //姓名
        String workerName = null;
        //身份证号
        String workerCardNum = null;
        //组织名称
        String allStaffOrgName = null;
        //学员得分
        BigDecimal studentScore = null;
        //证书编号
        String certNum = null;
        //证书名称
        String trainCredentialName = null;
        //获取模板内容
        String templateContent = null;
        //获取背景图片路径
        String imgUrl =null;
        if (null != allStaffTrainWorkerList){
            for (AllStaffTrainWorker allStaffTrainWorker1 : allStaffTrainWorkerList){
                workerName= allStaffTrainWorker1.getWorkerName();
                workerCardNum = allStaffTrainWorker1.getWorkerCardNum();
                allStaffOrgName = allStaffTrainWorker1.getAllStaffOrgName();
            }
            //考试表获取分数
            Example example1 = new Example(AllStaffTrainWorkerExam.class);
            Example.Criteria criteria1 = example1.createCriteria();
            criteria1.andEqualTo("isDeleted", CmnConstants.IS_DELETED_NO);
            criteria1.andEqualTo("isEnabled", CmnConstants.IS_ENABLED_YES);
            criteria1.andEqualTo("allStaffWorkerId",allStaffWorkerId);
            List<AllStaffTrainWorkerExam> allStaffTrainWorkerExamList = this.allStaffTrainWorkerExamMapper.selectByExample(example1);
            for (AllStaffTrainWorkerExam allStaffTrainWorkerExam : allStaffTrainWorkerExamList){
                studentScore =  allStaffTrainWorkerExam.getStudentScore();
            }
            //证书表得到证书编号
            Example example2 = new Example(AllStaffTrainWorkerCert.class);
            Example.Criteria criteria2 = example2.createCriteria();
            criteria2.andEqualTo("isDeleted", CmnConstants.IS_DELETED_NO);
            criteria2.andEqualTo("isEnabled", CmnConstants.IS_ENABLED_YES);
            criteria2.andEqualTo("allStaffWorkerId",allStaffWorkerId);
            List<AllStaffTrainWorkerCert> allStaffTrainWorkerCertList = this.allStaffTrainWorkerCertMapper.selectByExample(example2);
            Long allStaffTrainCertId = null;
            for (AllStaffTrainWorkerCert allStaffTrainWorkerCert : allStaffTrainWorkerCertList){
                certNum =  allStaffTrainWorkerCert.getCertNum();
                allStaffTrainCertId = allStaffTrainWorkerCert.getAllStaffTrainCertId();
            }
            //配置证书表获取证书名称
            Example example3= new Example(AllStaffTrainCert.class);
            Example.Criteria criteria3 = example3.createCriteria();
            criteria3.andEqualTo("isDeleted", CmnConstants.IS_DELETED_NO);
            criteria3.andEqualTo("isEnabled", CmnConstants.IS_ENABLED_YES);
            criteria3.andEqualTo("allStaffTrainCertId",allStaffTrainCertId);
            List<AllStaffTrainCert> allStaffTrainCertList = this.allStaffTrainCertMapper.selectByExample(example3);
            //模板id
            Long allStaffTrainTemplateId = null;
            //图片id
            Long allStaffTrainImgId = null;
            for (AllStaffTrainCert allStaffTrainCert : allStaffTrainCertList){
                trainCredentialName = allStaffTrainCert.getTrainCredentialName();
                allStaffTrainTemplateId = allStaffTrainCert.getAllStaffTrainTemplateId();
                allStaffTrainImgId = allStaffTrainCert.getAllStaffTrainImgId();
            }
            Example example4 = new Example(AllStaffTrainCertTemplate.class);
            Example.Criteria criteria4 = example4.createCriteria();
            criteria4.andEqualTo("isDeleted", CmnConstants.IS_DELETED_NO);
            criteria4.andEqualTo("isEnabled", CmnConstants.IS_ENABLED_YES);
            criteria4.andEqualTo("allStaffTrainTemplateId",allStaffTrainTemplateId);
            AllStaffTrainCertTemplate allStaffTrainCertTemplate = this.allStaffTrainCertTemplateMapper.selectOneByExample(example4);
            //获取模板内容
             templateContent = allStaffTrainCertTemplate.getTemplateContent();
            Example example5 = new Example(AllStaffTrainCertImg.class);
            Example.Criteria criteria5 = example5.createCriteria();
            criteria5.andEqualTo("isDeleted", CmnConstants.IS_DELETED_NO);
            criteria5.andEqualTo("isEnabled", CmnConstants.IS_ENABLED_YES);
            criteria5.andEqualTo("allStaffTrainImgId",allStaffTrainImgId);
            AllStaffTrainCertImg allStaffTrainCertImg = this.allStaffTrainCertImgMapper.selectOneByExample(example5);
            //获取背景图片路径
             imgUrl = allStaffTrainCertImg.getImgUrl();
        }
        ClassPathResource classPathResource = new ClassPathResource("fonts/msyh.ttc");
        InputStream inputStream = null;
        try {
           inputStream = classPathResource.getInputStream();
        }catch (Exception e){
            e.getMessage();
        }
        Font dynamicFont = null;
        try {
            dynamicFont = Font.createFont(Font.TRUETYPE_FONT, inputStream);
        }catch (Exception e){
            e.printStackTrace();
        }
        Font font = dynamicFont.deriveFont(Font.PLAIN, 28); //水印字体 方法3
        //水印字体
        /*Font font = new Font("微软雅黑", Font.PLAIN, 28);*/
        //源图片地址
        String srcImgPath="http://"+imgUrl;
        //待存储的地址
        String tarImgPath = "F:/证书.jpeg";
        //格式化时间
        SimpleDateFormat f=new SimpleDateFormat("yyyy     MM     dd");
        String format = f.format(new Date());
        //时间
        String waterMarkContent=format;
        //姓名
        String workerNames = workerName;
        //身份证号
        String workerCardNums = workerCardNum;
        //组织名称
        String allStaffOrgNames = allStaffOrgName;
        //学员得分
        BigDecimal studentScores = studentScore;
        //证书编号
        String certNums =certNum;
        //证书名称
        String trainCredentialNames = trainCredentialName;
        //获取模板内容
        String templateContents = templateContent;

        //水印图片色彩以及透明度
        Color color=new Color(79 ,79 ,79);
        BufferedImage bufferedImage = (BufferedImage) WaterMarkUtils.addWaterMark(srcImgPath, tarImgPath, waterMarkContent, workerNames, workerCardNums, allStaffOrgNames, studentScores, certNums, trainCredentialNames, templateContents, color, font);
        String sessionToke =jsonParam.getString("sessionToke");
        String attname = "证书"+".jpeg";
        String url = null;
        try {
            byte[] jpegs = imageToBytes(bufferedImage, "jpeg");
            url = FastDFSUtils.getDoUpload(sessionToke,attname,jpegs);
        }catch (Exception e){
            errLog("getDownloadAllStaffWorkers",ErrorCodeMsg.UNKNOWN_ERROR.getMessage(),e.getMessage());
            throw new AttemptException(ErrorCodeMsg.UNKNOWN_ERROR,e.getMessage());
        }
        Map<String, Object> resultMap = getFastDFSFileInfoMap(url,attname);
        return resultMap;
    }

    public  byte[] imageToBytes(BufferedImage bImage, String format) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(bImage, format, out);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return out.toByteArray();
    }

    /**
     * 返回给前端下载地址
     *
     * @param url
     * @param attname
     * @return
     */
    private Map<String, Object> getFastDFSFileInfoMap(String url, String attname) {
        String filePath = null;
        if (StringUtils.isNotEmpty(url)) {
            JSONObject jsonObject = JSONObject.parseObject(url);
            String data = jsonObject.getString("data");
            JSONObject dataObject = JSONObject.parseObject(data);
            filePath = dataObject.getString("filePath");
            if (StringUtils.isEmpty(filePath)) {
                errLog("getFastDFSFileInfoMap", ErrorCodeMsg.UNKNOWN_ERROR.getMessage(), "获取文件服务下载地址为空");
                throw new AttemptException(ErrorCodeMsg.UNKNOWN_ERROR, "获取文件服务下载地址为空");
            }
        }
        Map<String, Object> map = new HashMap<>(32);
        map.put("url",fileServer+"/"+filePath);
        map.put("attname", attname);
        return map;
    }

controller层代码

/**
     * 证书需要的内容
     * @return
     */
    @PostMapping("/getAllStaffTrainWorker")
    public ResponseStruct getAllStaffTrainWorker(@RequestBody JSONObject jsonParam){
        return ResponseStruct.success(this.allStaffTrainWorkerCertInterface.getAllStaffTrainWorker(jsonParam));
    }

总结:
这里面的坑:
1.图片是我们这边上传到服务器的所以数据库存放的的 url 而且输入到浏览器可以直接下载的。所以读取文件url的时候,我进行了了处理 具体代码就在工具类最上面
2.每个水印因为文字的字体和大小变动,位置也会变动
3.刚一开始文字字体用的Windows自带的字体,上传到服务器之后,因为服务器没有字体。要么下载一个要么想我这样 把字体包放到项目根目录然后再用流方式获取。
4.字体包位置
在这里插入图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

司小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值