Demo網頁:
http://myimagewall.no-ip.org:8080/sessionWeb/index.jsp
設置Filter順序 注意與gzipFilter的順序
順序錯誤將會先進行壓縮才打上浮水印
此時將會無法讀取已經過壓縮的圖檔 而導致動態加載浮水印失敗
觀念圖片:
在web.xml中的設定:
<filter>
<filter-name>gzipFilter</filter-name>
<filter-class>com.helloweenvsfei.gzip.GZipFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>gzipFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>waterMarkFilter</filter-name>
<filter-class>
com.helloweenvsfei.watermark.WaterMarkFilter
</filter-class>
<init-param>
<param-name>waterMarkFile</param-name>
<param-value>/logo.png</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>waterMarkFilter</filter-name>
<url-pattern>*.jpg</url-pattern>
</filter-mapping>
以下為浮水印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);
System.out.println(waterMarkFile);
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
System.out.println("執行浮水印過濾器");
// 自定義的response
WaterMarkResponseWrapper waterMarkRes = new WaterMarkResponseWrapper(response, waterMarkFile);
chain.doFilter(request, waterMarkRes);
// 打水印,輸出到客戶端瀏覽器
waterMarkRes.finishResponse();
}
public void destroy() {
}
}
WaterMarkResponseWrapper.java為自訂的類別,為了overwrite getOutputStream():
import java.io.IOException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import com.helloweenvsfei.util.ImageUtil;
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實作複寫的類別:
package com.helloweenvsfei.watermark;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.servlet.ServletOutputStream;
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利用JDK的影像處理類別動態打上浮水印
package com.helloweenvsfei.util;
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
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;
import java.awt.MediaTracker;
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;
}
}
訂閱:
張貼留言 (Atom)





沒有留言:
張貼留言