如何给共享文件夹中的图片添加水印

场景

一个图片文件查看或者下载前需要加上水印,文件本身存储在共享文件夹下。


共享文件(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 图片加水印(图片或者文本)

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