Java 图片添加数字暗水印工具类

Java 图片添加数字暗水印工具类。

package cnki.thesis.common.utils;

import org.opencv.core.*;

import java.util.ArrayList;
import java.util.List;

import static org.opencv.core.Core.*;
import static org.opencv.imgproc.Imgproc.*;
import static org.opencv.imgproc.Imgproc.FONT_HERSHEY_DUPLEX;

public class ImageDarkMarkUtils {
    private static List<Mat> planes;
    private static Mat complexImage;

    private ImageDarkMarkUtils(){}
    private static final ImageDarkMarkUtils dftUtil = new ImageDarkMarkUtils();

    public static ImageDarkMarkUtils getInstance () {
        planes = new ArrayList<>();
        complexImage = new Mat();
        return dftUtil;
    }

    public Mat transformImage(Mat image) {
        // planes数组中存的通道数若开始不为空,需清空.
        if (!planes.isEmpty()) {
            planes.clear();
        }
        // optimize the dimension of the loaded image
        Mat padded = this.optimizeImageDim(image);
        padded.convertTo(padded, CvType.CV_32F);
        // prepare the image planes to obtain the complex image
        planes.add(padded);
        planes.add(Mat.zeros(padded.size(), CvType.CV_32F));
        // prepare a complex image for performing the dft
        merge(planes, complexImage);
        dft(complexImage, complexImage);

        // optimize the image resulting from the dft operation
        Mat magnitude = this.createOptimizedMagnitude(complexImage);
        planes.clear();
        return magnitude;
    }

    public void transformImageWithText(Mat image, String watermarkText, Point point, Double fontSize, Scalar scalar) {
        // planes数组中存的通道数若开始不为空,需清空.
        if (!planes.isEmpty()) {
            planes.clear();
        }
        // optimize the dimension of the loaded image
        Mat padded = this.optimizeImageDim(image);
        padded.convertTo(padded, CvType.CV_32F);
        // prepare the image planes to obtain the complex image
        planes.add(padded);
        planes.add(Mat.zeros(padded.size(), CvType.CV_32F));
        // prepare a complex image for performing the dft
        merge(planes, complexImage);
        dft(complexImage, complexImage);
        // 频谱图上添加文本
        putText(complexImage, watermarkText, point, FONT_HERSHEY_DUPLEX, fontSize, scalar,2);
        flip(complexImage, complexImage, -1);
        putText(complexImage, watermarkText, point, FONT_HERSHEY_DUPLEX, fontSize, scalar,2);
        flip(complexImage, complexImage, -1);

        planes.clear();
    }

    public Mat antitransformImage() {
        Mat invDFT = new Mat();
        idft(complexImage, invDFT, DFT_SCALE | DFT_REAL_OUTPUT, 0);
        Mat restoredImage = new Mat();
        invDFT.convertTo(restoredImage, CvType.CV_8U);
        planes.clear();
        return restoredImage;
    }

    /**
     * 为加快傅里叶变换的速度,对要处理的图片尺寸进行优化
     *
     * @param image
     *            the {@link Mat} to optimize
     * @return the image whose dimensions have been optimized
     */
    private Mat optimizeImageDim(Mat image) {
        // init
        Mat padded = new Mat();
        // get the optimal rows size for dft
        int addPixelRows = getOptimalDFTSize(image.rows());
        // get the optimal cols size for dft
        int addPixelCols = getOptimalDFTSize(image.cols());
        // apply the optimal cols and rows size to the image
        Core.copyMakeBorder(image, padded, 0, addPixelRows - image.rows(), 0, addPixelCols - image.cols(),
                Core.BORDER_CONSTANT, Scalar.all(0));

        return padded;
    }

    /**
     * Optimize the magnitude of the complex image obtained from the DFT, to
     * improve its visualization
     *
     * @param complexImage
     *            the complex image obtained from the DFT
     * @return the optimized image
     */
    private Mat createOptimizedMagnitude(Mat complexImage) {
        // init
        List<Mat> newPlanes = new ArrayList<>();
        Mat mag = new Mat();
        // split the comples image in two planes
        split(complexImage, newPlanes);
        // compute the magnitude
        magnitude(newPlanes.get(0), newPlanes.get(1), mag);

        // move to a logarithmic scale
        add(Mat.ones(mag.size(), CvType.CV_32F), mag, mag);
        log(mag, mag);
        // optionally reorder the 4 quadrants of the magnitude image
        this.shiftDFT(mag);
        // normalize the magnitude image for the visualization since both JavaFX
        // and OpenCV need images with value between 0 and 255
        // convert back to CV_8UC1
        mag.convertTo(mag, CvType.CV_8UC1);
        normalize(mag, mag, 0, 255, NORM_MINMAX, CvType.CV_8UC1);

        return mag;
    }

    /**
     * Reorder the 4 quadrants of the image representing the magnitude, after
     * the DFT
     *
     * @param image
     *            the {@link Mat} object whose quadrants are to reorder
     */
    private void shiftDFT(Mat image) {
        image = image.submat(new Rect(0, 0, image.cols() & -2, image.rows() & -2));
        int cx = image.cols() / 2;
        int cy = image.rows() / 2;

        Mat q0 = new Mat(image, new Rect(0, 0, cx, cy));
        Mat q1 = new Mat(image, new Rect(cx, 0, cx, cy));
        Mat q2 = new Mat(image, new Rect(0, cy, cx, cy));
        Mat q3 = new Mat(image, new Rect(cx, cy, cx, cy));

        Mat tmp = new Mat();
        q0.copyTo(tmp);
        q3.copyTo(q0);
        tmp.copyTo(q3);

        q1.copyTo(tmp);
        q2.copyTo(q1);
        tmp.copyTo(q2);
    }
}

调用方法

 public static void matDropTextToBuffer() {
        Mat img11 = Imgcodecs.imread("C:\\Users\\WXL\\Desktop\\77.jpg");
        ImageDarkMarkUtils pdf = ImageDarkMarkUtils.getInstance();
        Mat s = pdf.transformImage(img11);
        pdf.transformImageWithText(s,"1342536475869",new Point(img11.height()/3,img11.width()/3),12.0,new Scalar(0, 0, 0));
        //Mat s = addImageWatermarkWithText(img11, "onejane");
        Imgcodecs.imwrite("C:\\Users\\WXL\\Desktop\\3.jpg", s);
        //Mat watermarkImg11 = getImageWatermarkWithText(img11);
        Mat watermarkImg11 = pdf.transformImage(s);
        Imgcodecs.imwrite("C:\\Users\\WXL\\Desktop\\4.jpg", watermarkImg11);
    }

生成暗水印

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
图片添加水印Java实现需要用到Java图像处理库,常用的有Java Advanced Imaging (JAI)和ImageIO。下面提供一种使用ImageIO的实现方式: ```java import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import javax.imageio.ImageIO; public class Watermark { public static void main(String[] args) throws Exception { String inputImagePath = "input.jpg"; String outputImagePath = "output.jpg"; String watermarkText = "confidential"; File inputFile = new File(inputImagePath); BufferedImage inputImage = ImageIO.read(inputFile); // 创建一个与原图像相同的新图像 BufferedImage outputImage = new BufferedImage( inputImage.getWidth(), inputImage.getHeight(), BufferedImage.TYPE_INT_RGB); // 将原图像复制到新图像中 Graphics2D g2d = outputImage.createGraphics(); g2d.drawImage(inputImage, 0, 0, null); // 添加水印 Font font = new Font("Arial", Font.BOLD, 48); g2d.setFont(font); g2d.setColor(Color.BLACK); AlphaComposite alphaComposite = AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.3f); // 设置水印透明度 g2d.setComposite(alphaComposite); FontMetrics fontMetrics = g2d.getFontMetrics(); int x = inputImage.getWidth() - fontMetrics.stringWidth(watermarkText) - 50; // 水印位置 int y = inputImage.getHeight() - fontMetrics.getHeight() - 50; g2d.drawString(watermarkText, x, y); g2d.dispose(); // 输出图像 File outputFile = new File(outputImagePath); ImageIO.write(outputImage, "jpg", outputFile); } } ``` 上述代码中,首先读取一个JPEG格式的输入图像,然后创建一个与原图像大小相同的新图像,将原图像复制到新图像中,再在新图像上添加水印,最后输出新图像。可以根据需要修改字体、水印文本、水印位置等参数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值