如何給共享文件夾中的圖片添加水印

場景

一個圖片文件查看或者下載前需要加上水印,文件本身存儲在共享文件夾下。


共享文件(Smb共享)

mac下共享文件

操作步驟:

  1. 系統偏好設置-共享-文件共享-使用smb共享文件或文件夾,訪問用戶爲guset,密碼爲空
  2. 系統偏好設置-用戶和羣組-解鎖-客人用戶-允許客人登錄到這臺電腦

百度經驗 Mac如何共享文件夾

linux下共享文件

操作步驟:安裝smb-創建文件夾-修改smb配置文件-重啓smb服務即可

Linux和Windows共享文件的三種方法

Windows下共享文件

操作步驟:創建文件夾-右鍵設置共享目錄-共享用戶添加

詳細 請移步百度搜索…


操作共享文件

Maven依賴

<dependency>
       <groupId>jcifs</groupId>
       <artifactId>jcifs</artifactId>
       <version>1.3.17</version>
</dependency>

共享文件操作

使用SmbFile類

NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("", "guest", "");
SmbFile smbFile = new SmbFile("smb://127.0.0.1/shareDir/1.jpg", auth);

圖片文件加水印

import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbException;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileOutputStream;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.net.MalformedURLException;

/**
 * 遠程圖片添加水印工具類
 */
@Slf4j
public final class FileWatermarkUtils {
    private static final String IMG_FILE_NAME_SEPARATOR = ".";

    /**
     * 水印文字字體名
     */
    private static final String FONT_NAME = "華文楷體";

    /**
     * 水印文字樣式
     */
    private static final int FONT_STYLE = Font.BOLD;

    /**
     * 水印文字顏色
     */
    private static final Color FONT_COLOR = Color.BLACK;

    /**
     * 水印文字字體大小
     */
    private static final int FONT_SIZE = 20;

    /**
     * 透明度
     */
    private static final float ALPHA = 0.1f;

    /**
     * 水印旋轉角度
     */
    private static final int DEGREE = -30;

    /**
     * 各個水印文字間隔像素-X 根據圖片大小 可自行調整
     */
    private static final int OFFSET_GAP_X = 200;

    /**
     * 各個水印文字間隔像素-Y 根據圖片大小 可自行調整
     */
    private static final int OFFSET_GAP_Y = 100;

    private FileWatermarkUtils() {}

    /**
     * 讀取smbFile圖片文件 添加水印後 生成到newSmbFile
     * @param smbFile 原遠程圖片文件
     * @param newSmbFile 新的添加水印後的文件
     * @param watermarkText 添加的水印
     */
    public static void addWatermarkToNewSmbFile(SmbFile smbFile, SmbFile newSmbFile, String watermarkText) {
        try (InputStream smbFileInputStream = smbFile.getInputStream(); SmbFileOutputStream newSmbFileOutputStream = (SmbFileOutputStream) newSmbFile.getOutputStream()) {
            log.info("Start to add watermark to image file.");
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            // 1、讀取輸入流,構建Image對象
            Image src = ImageIO.read(smbFileInputStream);
            log.info("Read file end, cost {}", stopWatch.getTime());

            int width = src.getWidth(null);
            int height = src.getHeight(null);
            log.info("Get image width and height end, cost {}", stopWatch.getTime());

            // 2、構建Graphics2D
            BufferedImage bufferedImage = new BufferedImage(width, height,
                    BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics2D = bufferedImage.createGraphics();
            graphics2D.drawImage(src, 0, 0, width, height, null);
            // 設置字體與顏色
            Font font = new Font(FONT_NAME, FONT_STYLE, FONT_SIZE);
            graphics2D.setColor(FONT_COLOR);
            graphics2D.setFont(font);
            // 設置透明度
            graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));
            log.info("Prepare to draw image end, cost {}", stopWatch.getTime());

            // 3、獲取要添加的水印文字所佔的像素
            FontRenderContext context = graphics2D.getFontRenderContext();
            Rectangle2D stringBounds = font.getStringBounds(watermarkText, context);
            log.info("Get string bounds end, cost {}", stopWatch.getTime());

            // 4、繪製水印
            int textWidthHalf = ((int) stringBounds.getWidth()) >>> 1;
            int textHeightHalf = ((int) stringBounds.getHeight()) >>> 1;
            AffineTransform old = graphics2D.getTransform();
            int positionX = 0;
            int positionY = 0;
            while (positionX <= width) {
                while (positionY <= height) {
                    // 以當前要繪製的文字的中心點爲中心進行旋轉
                    graphics2D.rotate(Math.toRadians(DEGREE), positionX + textWidthHalf, positionY + textHeightHalf);
                    // 繪製水印
                    graphics2D.drawString(watermarkText, positionX, positionY);
                    // 重置transform
                    graphics2D.setTransform(old);
                    positionY += OFFSET_GAP_Y;
                }
                positionY = 0;
                positionX += OFFSET_GAP_X;
            }
            log.info("Draw watermark text end, cost {}", stopWatch.getTime());
            // 銷燬繪製使用的資源
            graphics2D.dispose();

            // 5、添加完水印的文件寫到新的遠程文件中
            // 獲取文件後綴
            String filePath = newSmbFile.getPath();
            String fileSuffix = filePath.substring(filePath.lastIndexOf(IMG_FILE_NAME_SEPARATOR) + 1);
            // 圖片緩存寫入新文件
            ImageIO.write(bufferedImage, fileSuffix, newSmbFileOutputStream);
            log.info("Save image with watermark to new smb file, cost {}", stopWatch.getTime());
            stopWatch.stop();
        } catch (Exception ex) {
            log.error("FileWatermarkUtils-addWatermarkToSmbFile: add watermark to smb file exception.", ex);
        }

    }

    public static void main(String [] args) throws MalformedURLException, SmbException {
        NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("", "guest", "");
        SmbFile smbImageFile = new SmbFile("smb://127.0.0.1/shareDir/1.jpg", auth);
        SmbFile newTempImageFileWithWatermark = new SmbFile("smb://127.0.0.1/shareDir/1_temp.jpg", auth);
        addWatermarkToNewSmbFile(smbImageFile, newTempImageFileWithWatermark, "one piece");
        // newTempImageFileWithWatermark.delete();
    }

}

水印圖片效果:
水印圖片效果


遇到的問題

生成的圖片無法打開

圖片無法打開
解決:
權限問題,右鍵圖片-顯示簡介,解鎖圖片,添加上當前用戶的讀寫權限即可
添加文件權限

訪問文件時報錯

如賬號密碼錯誤,文件找不到,沒有權限等

jcifs.smb.SmbAuthException: Logon failure: unknown user name or bad password
jcifs.smb.SmbException: The system cannot find the file specified

解決:
仔細檢查當前使用的訪問用戶是否有共享文件夾的讀寫權限,文件名,文件路徑是否正確。可以在windows機器上訪問試下,如果能正常訪問,程序應該也是可以訪問到的。


參考:
SmbFile 類實現局域網文件共享讀寫
Java 圖片加水印(圖片或者文本)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章