Pages

  • Twitter
  • Facebook
  • Google+
  • RSS Feed

2013年3月16日 星期六

【J2EE】動態加載浮水印 WaterMarkFilter 處理jpg檔案

沒有留言:
 
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;
    }
}

沒有留言:

張貼留言

Related Posts Plugin for WordPress, Blogger...
 
© 2012. Design by Main-Blogger - Blogger Template and Blogging Stuff