java给图片添加文字水印,以及docker容器添加中文字体支持

    
    最近项目需要给用户上传的图片打上时间戳等信息的水印。由于我们图片是存在阿里云OSS上,首先想的是用OSS自带的方式添加省事,地址是https://help.aliyun.com/document_detail/44957.html

发现虽然简单,但是水印内容通过编码拼接在图片地址后面,每次访问都要加上,如果要保存下来还需要自己存第二遍有水印的图。可是我们并不需要没有水印的原图,于是决定通过代码添加,更自由。

代码如下:

/**
     * 添加文字水印
     * @param inputStream    原图片
     * @param waterMarkContent 水印文字内容数组
     * @param markContentColor 颜色
     * @param font 字体
     * @param format 图片格式
     * @return
     */
    public static byte[] addWaterMark(byte[] inputStream, String[] waterMarkContent,Color markContentColor,Font font,String format) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
//        printSysFont();
        try {
            if(markContentColor==null)
                markContentColor=new Color(189, 66, 71, 255);    //水印图片色彩以及透明度 255是不透明
            if(font==null)
                font = new Font("宋体", Font.PLAIN, 15);                     //水印字体
            ByteArrayInputStream in = new ByteArrayInputStream(inputStream);    //将b作为输入流;
            Image srcImg = ImageIO.read(in);
            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);              //设置字体

            //设置水印的坐标
            for(int i = 0;i<waterMarkContent.length;i++){
                if(StringUtils.isBlank(waterMarkContent[i]))
                    continue;
                System.out.println("内容:"+waterMarkContent[i]);
                int x = srcImgWidth - getWatermarkLength(waterMarkContent[i], g);
                int y = font.getSize()*(i+1);
                g.drawString(waterMarkContent[i], x>0?x:0, y);  //画出水印
                System.out.println("画出水印x:"+x+",y:"+y);
            }
            g.dispose();
            // 输出图片
            ImageIO.write(bufImg, format, out);
            System.out.println("添加水印完成");
            byte[] ret =  out.toByteArray();
            return ret;
        } catch (Exception e) {
            e.printStackTrace();
            return inputStream;
            // TODO: handle exception
        }
    }
    public static byte[] addWaterMark(byte[] inputStream, String[] waterMarkContent,String format) {
        return addWaterMark(inputStream, waterMarkContent, null, null,format);
    }

    /**
     * 要打上文字的长度
     * @param waterMarkContent
     * @param g
     * @return
     */
    private static int getWatermarkLength(String waterMarkContent, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
    }
    

 

其中因为水印内容预计有三行,分别是公司名,时间戳以及另一个内容,所以传入的是字符数组,它会一行一行印上去,传入的是一个byte[],因为是在其它业务逻辑里面添加的功能,所以返回也是byte 其它格式转也很方便的。

使用:

String[] waterMarkContent = new String[3];
waterMarkContent[0] = "XXXXX";
waterMarkContent[1] = "XXXXX公司";
waterMarkContent[2] = new SimpleDateFormat("yyyy-MM-dd  HH:mm").format(new Date());
imageFile = ImageUtil.addWaterMark(imageFile, waterMarkContent, "jpg");

之后在我自己电脑上测试了一下没什么问题

项目通过docker部署,打包后发现中文显示不出来!是框框!

因为不是乱码排除编码格式问题,比较明显是该环境下没有对应的字体。

搜了一下解决办法,比较好的解决方式是在dockerfile制作镜像的时候把你要用的字体文件放进去:

自己找个 simsun.ttf 放到工程目录

然后添加一行:COPY simsun.ttf /usr/share/fonts/simsun.ttf

FROM java:8
ENV TZ=Asia/Shanghai
RUN apt-get install tzdata
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 配置字体
COPY simsun.ttf /usr/share/fonts/simsun.ttf

VOLUME /tmp
ADD myApp.jar /app.jar
EXPOSE 0000
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

OK,问题解决。希望能帮助遇到同样问题的人,毕竟网上其他手动安装,加入字体下载命令 等方式不太好用

 

11月15日更新一下:水印的字体大小自适应。发现用户上传的图片大小不一,字体需要相应变化。

int srcImgWidth = srcImg.getWidth(null);//获取图片的宽
int srcImgHeight = srcImg.getHeight(null);//获取图片的高
if(font==null){
    int fontSize = srcImgWidth/300*10+10;
    font = new Font("宋体", Font.PLAIN, fontSize);//水印字体
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值