(转)一个不错的水印filter

WaterMarkFilter.java
import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class WaterMarkFilter implements Filter {

// 水印图片,配置在初始化参数中
private String waterMarkFile;

public void init(FilterConfig config) throws ServletException {
String file = config.getInitParameter("waterMarkFile");
waterMarkFile = config.getServletContext().getRealPath(file);
}

public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;

// 自定义的response
WaterMarkResponseWrapper waterMarkRes = new WaterMarkResponseWrapper(
response, waterMarkFile);

chain.doFilter(request, waterMarkRes);

// 打水印,输出到客户端浏览器
waterMarkRes.finishResponse();
}

public void destroy() {
}

WaterMarkResponseWrapper.java
public class WaterMarkResponseWrapper extends HttpServletResponseWrapper {

// 水印图片位置
private String waterMarkFile;

// 原response
private HttpServletResponse response;

// 自定义servletOutputStream,用于缓冲图像数据
private WaterMarkOutputStream waterMarkOutputStream;

public WaterMarkResponseWrapper(HttpServletResponse response,
String waterMarkFile) throws IOException {
super(response);
this.response = response;
this.waterMarkFile = waterMarkFile;
this.waterMarkOutputStream = new WaterMarkOutputStream();
}

// 覆盖getOutputStream(),返回自定义的waterMarkOutputStream
public ServletOutputStream getOutputStream() throws IOException {
return waterMarkOutputStream;
}

public void flushBuffer() throws IOException {
waterMarkOutputStream.flush();
}

// 将图像数据打水印,并输出到客户端浏览器
public void finishResponse() throws IOException {

// 原图片数据
byte[] imageData = waterMarkOutputStream.getByteArrayOutputStream()
.toByteArray();

// 打水印后的图片数据
byte[] image = ImageUtil.waterMark(imageData, waterMarkFile);

// 将图像输出到浏览器
response.setContentLength(image.length);
response.getOutputStream().write(image);

waterMarkOutputStream.close();
}

WaterMarkOutputstream.java:
public class WaterMarkOutputStream extends ServletOutputStream {

// 缓冲图片数据
private ByteArrayOutputStream byteArrayOutputStream;

public WaterMarkOutputStream() throws IOException {
byteArrayOutputStream = new ByteArrayOutputStream();
}

public void write(int b) throws IOException {
byteArrayOutputStream.write(b);
}

public void close() throws IOException {
byteArrayOutputStream.close();
}

public void flush() throws IOException {
byteArrayOutputStream.flush();
}

public void write(byte[] b, int off, int len) throws IOException {
byteArrayOutputStream.write(b, off, len);
}

public void write(byte[] b) throws IOException {
byteArrayOutputStream.write(b);
}

public ByteArrayOutputStream getByteArrayOutputStream() {
return byteArrayOutputStream;
}


ImageUtil.java,添加图象水印的操作:
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class ImageUtil {

/**
*
* @param imageData
* JPG 图像文件
* @param waterMarkFile
* 水印图片
* @return 加水印后的图像数据
* @throws IOException
*/
public static byte[] waterMark(byte[] imageData, String waterMarkFile)
throws IOException {

// 水印图片的右边距 下边距
int paddingRight = 10;
int paddingBottom = 10;

// 原始图像
Image image = new ImageIcon(imageData).getImage();
int imageWidth = image.getWidth(null);
int imageHeight = image.getHeight(null);

// 水印图片
Image waterMark = ImageIO.read(new File(waterMarkFile));
int waterMarkWidth = waterMark.getWidth(null);
int waterMarkHeight = waterMark.getHeight(null);

// 如果图片尺寸过小,则不打水印,直接返回
if (imageWidth < waterMarkWidth + 2 * paddingRight
|| imageHeight < waterMarkHeight + 2 * paddingBottom) {
return imageData;
}
BufferedImage bufferedImage = new BufferedImage(imageWidth,
imageHeight, BufferedImage.TYPE_INT_RGB);

Graphics g = bufferedImage.createGraphics();

// 绘制原始图像
g.drawImage(image, 0, 0, imageWidth, imageHeight, null);
// 绘制水印图片
g.drawImage(waterMark, imageWidth - waterMarkWidth - paddingRight,
imageHeight - waterMarkHeight - paddingBottom, waterMarkWidth,
waterMarkHeight, null);
g.dispose();

// 转成JPEG格式
ByteArrayOutputStream out = new ByteArrayOutputStream();
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(bufferedImage);
byte[] data = out.toByteArray();
out.close();
return data;
}

web.xml:
<filter-mapping>
<filter-name>waterMarkFilter</filter-name>
<url-pattern>*.jpg</url-pattern>
</filter-mapping>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: FFmpeg是一个免费的、跨平台的多媒体框架,可以用于处理音频、视频以及流媒体等不同类型的多媒体数据。如果需要给一个视频加上多个水印,可以使用FFmpeg提供的filter_complex滤镜进行实现。 filter_complex 可以将多个滤镜拼接起来,实现多种效果,其中一个滤镜是水印。在加多个水印的情况下,需要使用多个overlay滤镜,每个滤镜对应一个水印。可以使用如下命令: ffmpeg -i input.mp4 -i watermark1.png -i watermark2.png -filter_complex "[0:v][1:v]overlay=W-w-10:H-h-10[o1];[o1][2:v]overlay=W-w-20:H-h-20" output.mp4 此命令中,input.mp4 是要加水印的源视频;watermark1.png 和 watermark2.png 分别是两个水印图像;filter_complex "[0:v][1:v]overlay=W-w-10:H-h-10[o1];[o1][2:v]overlay=W-w-20:H-h-20" 中的[o1]是中间结果,表示第一次overlay加水印后的输出。第二次overlay再在此输出上加水印,最终结果是加上了两个水印的视频。 其中 W-w-x 和 H-h-y 表示水印距离输出视频右边缘和底部的距离,x 和 y 的数值可以适当调整。此命令执行后会返回处理的日志信息和输出的视频文件路径。 总之,只需在滤镜中依次使用overlay并设置每个水印的位置,就可以实现为视频加多个水印。 ### 回答2: ffmpeg是一款功能强大的开源多媒体处理工具,能够对音频、视频等各种多媒体格式进行换、编辑等处理。其中,添加水印是一种常见的视频编辑需求,而在实际应用中,有时需要在同一视频中加入多个水印。 ffmpeg添加水印的基本命令如下: ffmpeg -i input.mp4 -i watermark.png -filter_complex "overlay=10:10" output.mp4 其中,input.mp4为源视频文件,watermark.png为水印图片文件,overlay=10:10表示水印位置为视频左上角偏移(10,10)的位置,output.mp4为输出文件名。 如果要在同一视频中加入多个水印,需要使用复合滤镜(filter_complex),如下所示: ffmpeg -i input.mp4 -i watermark1.png -i watermark2.png -filter_complex "[1:v]overlay=10:10[wm1];[2:v]overlay=50:50[wm2];[0:v][wm1][wm2]overlay=100:100" output.mp4 其中,[1:v]表示第一个水印,[2:v]表示第二个水印,overlay=10:10表示第一个水印位置为视频左上角偏移(10,10)的位置,overlay=50:50表示第二个水印位置为左上角偏移(50,50)的位置,最后的overlay=100:100表示将第一个和第二个水印叠加到源视频上,并输出至output.mp4。 需要注意的是,添加多个水印可能会影响视频的观感,因此在添加水印时,应尽量保持简洁、合理的布局和透明度,以达到更好的效果。同时,ffmpeg支持多种滤镜效果,如模糊、旋、缩放等,可以进一步增强视频的视觉效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值