1. 程式人生 > >java給圖片新增文字水印,以及docker容器新增中文字型支援

java給圖片新增文字水印,以及docker容器新增中文字型支援

發現雖然簡單,但是水印內容通過編碼拼接在圖片地址後面,每次訪問都要加上,如果要儲存下來還需要自己存第二遍有水印的圖。可是我們並不需要沒有水印的原圖,於是決定通過程式碼新增,更自由。

程式碼如下:

/**
     * 新增文字水印
     * @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());
    }
    private static GraphicsEnvironment environment;

其中因為水印內容預計有三行,分別是公司名,時間戳以及另一個內容,所以傳入的是字元陣列,它會一行一行印上去,傳入的是一個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製作映象的時候把你要用的字型檔案放進去:

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 8085
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

OK,問題解決。希望能幫助遇到同樣問題的人,畢竟網上其他手動安裝,加入字型下載命令 等方式不太好用