Java 实现数字盲水印,java 盲水印实现比其他版本的速度更快 !!!

##### 我写的盲水印版本速度上更快 ,参照了c的底层实现改编的 java 语法 。 结合先人的经验得以完成。希望能帮助有困惑的朋友

下面就是我的代码实现 :

首先是盲水印工具类

import org.bytedeco.javacpp.Loader;

import org.bytedeco.opencv.opencv_java;

import org.opencv.core.*;

import java.util.ArrayList;

import java.util.List;

import static org.opencv.core.Core.*;

import static org.opencv.core.Core.merge;

import static org.opencv.core.CvType.*;

import static org.opencv.core.CvType.CV_8UC1;

import static org.opencv.imgcodecs.Imgcodecs.imwrite;

import static org.opencv.imgproc.Imgproc.FONT_HERSHEY_COMPLEX;

import static org.opencv.imgproc.Imgproc.putText;

public class ImgWatermarkUtil {

/**

*


* 添加图片文字水印

*


* @param sourceFilePath 图片对象

* @param watermarkText 水印文字

*/

public static void addImageWatermarkWithText(String sourceFilePath, String watermarkText, String outputFilePath) {

List planes = new ArrayList<>(3);

List allPlanes = new ArrayList<>(3);

Mat src = ImgUtils.read(sourceFilePath, CV_8S);

splitSrc(src, allPlanes);

for (int i = 0; i < 3; i++) {

Mat res = new Mat();

Mat padded = allPlanes.get(i).clone();

padded.convertTo(padded, CV_32F);

Mat zeros = Mat.zeros(padded.size(), CV_32F);

List planesa = new ArrayList<>(2);

planesa.add(0, padded);

planesa.add(1, zeros);

merge(planesa, res);

dft(res, res);

//加水印

Scalar s = new Scalar(0, 0, 0);

Point p = new Point(src.cols() / 8, src.rows() / 8);

putText(res, watermarkText, p, FONT_HERSHEY_COMPLEX, 1.0, s, 3,

8, false);

flip(res, res, -1);

putText(res, watermarkText, p, FONT_HERSHEY_COMPLEX, 1.0, s, 3,

8, false);

flip(res, res, -1);

List aplanes = new ArrayList<>(2);

idft(res, res, Core.DFT_SCALE | Core.DFT_REAL_OUTPUT, 0);

res.convertTo(res, CvType.CV_8U);

planes.add(i, res);

}

Mat invDFT = new Mat();

merge(planes, invDFT);

if (invDFT.rows() != src.rows() || invDFT.cols() != src.cols()) {

invDFT = new Mat(invDFT, new Rect(0, 0, src.width(), src.height()));

}

imwrite(outputFilePath, invDFT);

}

/**

*


* 获取图片水印

*


* @param

*/

public static void getImageWatermarkWithText(String sourceFilePath, String output) {

Mat src = ImgUtils.read(sourceFilePath, CV_8U);

src.convertTo(src, CV_32F);

List planes = new ArrayList<>(2);

Mat com = new Mat();

planes.add(0, src);

planes.add(1, Mat.zeros(src.size(), CV_32F));

merge(planes, com);

dft(com, com);

List newPlanes = new ArrayList<>(2);

Mat mag = new Mat();

split(com, newPlanes);

magnitude(newPlanes.get(0), newPlanes.get(1), mag);

add(Mat.ones(mag.size(), CV_32F), mag, mag);

log(mag, mag);

mag.convertTo(mag, CV_8UC1);

normalize(mag, mag, 0, 255, NORM_MINMAX, CV_8UC1);

imwrite(output, mag);

}

private static Mat splitSrc(Mat mat, List allPlanes) {

mat = optimizeImageDim(mat);

split(mat, allPlanes);

return mat;

}

/**

*


* 为加快傅里叶变换的速度,对要处理的图片尺寸进行优化

*


* @param image

* @return

*/

private static Mat optimizeImageDim(Mat image) {

Mat padded = new Mat();

int addPixelRows = getOptimalDFTSize(image.rows());

int addPixelCols = getOptimalDFTSize(image.cols());

copyMakeBorder(image, padded, 0, addPixelRows - image.rows(), 0, addPixelCols - image.cols(),

Core.BORDER_CONSTANT, Scalar.all(0));

return padded;

}

public static void main(String[] args) throws Exception {

//必须要现加载

Loader.load(opencv_java.class);

long start = System.currentTimeMillis();

ImgWatermarkUtil.addImageWatermarkWithText("/Users/XXX/Desktop/测试.jpg", "testtng", "/Users/XXX/Desktop/测试_text_ed.jpeg");

System.out.println("encode cost : " + (System.currentTimeMillis() - start));

long start1 = System.currentTimeMillis();

ImgWatermarkUtil.getImageWatermarkWithText("/Users/XXX/Desktop/测试_text_en.jpeg", "/Users/XXX/Desktop/测试_text_de.jpeg");

System.out.println("decode cost : " + (System.currentTimeMillis() - start1));

System.out.println("");

}

}

**具体使用方法**

加盲水印

↵↵↵

public void blindWaterMarkEncode(InputStream inputStream, String text, HttpServletResponse response) throws Exception {

BufferedImage bufferedImage = ImageIO.read(inputStream);

String sourceFilePath = null;

String targetFilePath = null;

try {

String fileDirectory = "/tmp/images";

createFileDirectoryIfAbsent(fileDirectory);

String filePathPrefix = fileDirectory + File.separator + System.currentTimeMillis() + "_";

sourceFilePath = filePathPrefix + "test.jpg";

try (BufferedOutputStream outStream = new BufferedOutputStream(new FileOutputStream(sourceFilePath))) {

ImageIO.write(bufferedImage, "jpg", outStream);

}

targetFilePath = filePathPrefix + "blindwatermark_" + "test.jpg";

//加 盲水印

long startTime = System.currentTimeMillis();

ImgWatermarkUtil.addImageWatermarkWithText(sourceFilePath, text, targetFilePath);

log.info("增加盲水印 耗时 cost :{}", System.currentTimeMillis() - startTime);

response.setContentType("jpg");

//把加盲水印后的图片 输出到 HttpServletResponse

try (InputStream inputStream = new BufferedInputStream(new FileInputStream(targetFilePath))) {

ImageIO.write(ImageIO.read(inputStream), "jpg", response.getOutputStream());

}

} catch (IOException e) {

throw new Exception("增加盲水印失败");

} finally {

//使用后删除临时文件,避免磁盘爆满

Files.deleteIfExists(Paths.get(sourceFilePath));

Files.deleteIfExists(Paths.get(targetFilePath));

}

}

解盲水印

public void blindWaterMarkDecode(MultipartFile multipartFile, HttpServletResponse response) throws Exception {

int dotIndex = multipartFile.getOriginalFilename().lastIndexOf(".");

if (dotIndex <= 0 || (dotIndex + 1) == multipartFile.getOriginalFilename().length()) {

log.info("fileName is illegal! fileName:{} ", multipartFile.getOriginalFilename());

throw new Exception("图片的文件名非法");

}

String fileDirectory = "/tmp/images";

createFileDirectoryIfAbsent(fileDirectory);

String filePathPrefix = fileDirectory + File.separator + System.currentTimeMillis() + "_";

String sourceFilePath = filePathPrefix + "decode_" + multipartFile.getOriginalFilename();

Files.write(Paths.get(sourceFilePath), multipartFile.getBytes());

String targetFilePath = filePathPrefix + "watermark_" + multipartFile.getOriginalFilename();

//获取图片的水印

long startTime = System.currentTimeMillis();

ImgWatermarkUtil.getImageWatermarkWithText(sourceFilePath, targetFilePath);

log.info("解开盲水印 耗时 cost :{}", System.currentTimeMillis() - startTime);

//设置缓存

response.setContentType(multipartFile.getContentType());

try (InputStream inputStream = new BufferedInputStream(new FileInputStream(targetFilePath))) {

ImageIO.write(ImageIO.read(inputStream), multipartFile.getOriginalFilename().substring(dotIndex + 1), response.getOutputStream());

}

//使用后删除临时文件,避免磁盘爆满

Files.deleteIfExists(Paths.get(sourceFilePath));

Files.deleteIfExists(Paths.get(targetFilePath));

}

你可能感兴趣的:(Java,实现数字盲水印)