编写过滤器,完成对bmp图片的信息隐写操作和读取

来源:互联网 发布:c语言 stdio.h 编辑:程序博客网 时间:2024/06/06 00:50

编写过滤器,完成对bmp图片的信息隐写操作和读取

上上周老师布置的web作业,我才今天写完,而且写的很艰难(下面是题目信息):

老师给的信息
老师给的信息


写这道题的思路:
- 首先上传txt文件和bmp文件
- 从input里面获取文件名,分别处理txt文件和image文件
- txt文件就是先获取文件内容转换为byte,再将byte转换为二进制的数组
- 对image文件处理:先获取image图片rgb值,再将txt文件转换的数组的每一位赋值给rgb的red green和blue的值的最后一位,再由新的rgb组成一张新的图片,存储到webContent的image文件夹下,再由MyAPI的类调用而显示出来
- 图片的读取则和隐写相反,先获取rgb里面的每个的最后一位存到数组里面,再将数组由二进制转换为byte,再由byte直接返回到过滤器的response的值


代码块

获取input里面的文件名称:

DiskFileUpload diskFileUpload = new DiskFileUpload();            List<FileItem> list = null;            try {                list = diskFileUpload.parseRequest(httpServletRequest);            } catch (FileUploadException e) {                e.printStackTrace();            }            for(FileItem file : list) {                System.out.println(file..getFieldName())            }

判断为txt文件:

if(file.getFieldName().equals("docField")) {                    byte[] bt = file.get();                    int len = (bt.length+1)*8;                    bit = new byte[len];                    for(int i = 0 ; i < bt.length ; i++) {                        for(int j = 0 ; j <= 7 ; j++) {                        //通过右移将byte数组转换为二进制  先右移再和0x01与得到最后一位 再赋值给二进制数组                             bit[ i*8 + j] = (byte)((bt[i]>>(7-j)) & 0x01);                        }                    }                }

判断为image文件:

else if(file.getFieldName().equals("imageField")) {                    InputStream img = file.getInputStream();                    BufferedImage image = ImageIO.read(img);                    int height = image.getHeight(); //获取图片的高度                    int width = image.getWidth();//获取图片宽度                    int count = 0;  //定义一个数来计数                    for(int imgX = 0 ; imgX < width ; imgX++ ) {                        for(int imgY = 0 ; imgY < height ; imgY++ ) {                            int rgb = image.getRGB(imgX, imgY);  //获取image图片的rgb值                            Color color = new Color(rgb); //通过rgb值来定义color 再通过color分别获取red,green,blue的值                            //再将获取到的值转换为 string类型  方便下面的substring运算                            String r1 = Integer.toBinaryString((Integer)color.getRed());                            String g1 = Integer.toBinaryString((Integer)color.getGreen());                            String b1 = Integer.toBinaryString((Integer)color.getBlue());                            //判断count有没有超出二进制数组的最大长度,进行substring运算来将二进制数组bit里面的值直接赋值给red,green和blue                            if(count+2<bit.length) {                                b1 = b1.substring(0, b1.length() - 1) + String.valueOf(bit[count+2]);                            }                            if(count+1<bit.length) {                                g1 = g1.substring(0, g1.length() - 1) + String.valueOf(bit[count+1]);                            }                            if(count<bit.length) {                                r1 = r1.substring(0, r1.length() - 1) + String.valueOf(bit[count]);                            }                            //将新的red green 和blue 用Integer.parseInt(red,2)来转换为数字,并组成新的rgb                            rgb = new Color(Integer.parseInt(r1, 2),Integer.parseInt(g1, 2),Integer.parseInt(b1, 2)).getRGB();                              //将新的rgb重新填入到图片当中                            image.setRGB(imgX, imgY, rgb);                            //一轮结束后因为 red green blue 用掉了三个值 所以count+3                            count = count + 3;                          }                    }                           //for循环结束之后 将新的图片保存到 image文件夹下                    //httpServletRequest.getRealPath("image")  是通过image这个名字获取该文件夹的路径                    //ImageIO可以直接写入图片                    ImageIO.write(image, "bmp", new File(httpServletRequest.getRealPath("image") + "/image.bmp"));                }

判断结果是什么都不是:

else break;

这就完成了Image的写入操作

完成对图片的读取操作:

            //通过文件名的路径来一个文件夹            //httpServletRequest.getRealPath("image")可以获取image的路径            File imgfile = new File(httpServletRequest.getRealPath("image") + "/image.bmp");            //用BufferedImage新建img  通过ImageIO.read(file)获取图片            BufferedImage img = ImageIO.read(imgfile);            //将数组new一下  不new的话将会报空指针的错误            bit = new byte[197024 * 8];            //int 两个新的数来计数            int count = 0;            int n = 0;            //new一个新的byte数组存放二进制数            byte[] bt = new byte[bit.length*8];            //通过获取图片rgb来获取red green blue的最后一位            for(int imgX = 0 ; imgX < img.getWidth() ; imgX++) {                for(int imgY = 0 ; imgY < img.getHeight() ; imgY++ ) {                    int rgb = img.getRGB(imgX, imgY);                    Color color = new Color(rgb);                    int r  = color.getRed();                    int g = color.getGreen();                    int b = color.getBlue();                    if(count<bit.length) {                        bt[count] = (byte) ( r & 0x01);                    }                    if(count+1<bit.length) {                        bt[count+1] = (byte) ( g & 0x01);                    }                    if(count+2<bit.length) {                        bt[count+2] = (byte) ( b & 0x01);                    }                    //因为red blue green 用掉了三个计数的 所以cout+3                    count = count+3;                }            }            //将二进制数组bt 转换为byte数组            //byte数组由8个二进制数组成 所以第二个循环的大小为8            //左移7-j得到的是由高到低的二进制 再相加            //相加后的整数赋值给bit里面的bit[n] 一个j循环 n加一次 代表的就是8个二进制数组成一个byte            for(int i = 0 ;i < bt.length; i=i+8 ) {                count = 0;                for(int j = 0 ; j < 8 ; j++) {                    count = count + (bt[i+j]<<(7-j));                }                bit[n] = (byte) count;                n++;            }            //将bit传给respContext            respContext.setEntity(bit);

这就完成了Image的读出操作

web.xml中需要将request和response配置一下 由于provider和filter(过滤器)和intercepter(拦截器)都是配置再provider 里面的:

<context-param>    <param-name>resteasy.providers</param-name>    <param-value>   restful.filter.SteganalysisRequestFilter , restful.filter.SteganalysisResponseFilter        </param-value>  </context-param>

整个项目的各个文件的配置

MyAPI的内容:

package restful.api;import javax.ws.rs.GET;import javax.ws.rs.POST;import javax.ws.rs.Path;@Path("/a")public class MyAPI {    @POST    @Path("writeImage")    public String writeImage() {        return "<script>window.location.href = '../image/image.bmp' </script>";    }    @GET    @Path("readImage")    public String readImage() {             return "";    }}

SteganalysisRequestFilter的内容:

package restful.filter;import java.awt.Color;import java.awt.image.BufferedImage;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.util.List;import javax.imageio.ImageIO;import javax.servlet.http.HttpServletRequest;import javax.ws.rs.container.ContainerRequestContext;import javax.ws.rs.container.ContainerRequestFilter;import javax.ws.rs.core.Context;import org.apache.commons.fileupload.DiskFileUpload;import org.apache.commons.fileupload.FileItem;import org.apache.commons.fileupload.FileUploadException;public class SteganalysisRequestFilter implements ContainerRequestFilter {    @Context    private HttpServletRequest httpServletRequest;    private byte[] bit;    @Override    public void filter(ContainerRequestContext reqContext) throws IOException {        if(httpServletRequest.getRequestURL().toString().contains(("writeImage"))) {            DiskFileUpload diskFileUpload = new DiskFileUpload();            List<FileItem> list = null;            try {                list = diskFileUpload.parseRequest(httpServletRequest);            } catch (FileUploadException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }            for(FileItem file : list) {                if(file.getFieldName().equals("docField")) { //字符串用equals                    byte[] bt = file.get();                    int len = (bt.length+1)*8;                    bit = new byte[len];                    for(int i = 0 ; i < bt.length ; i++) {                        for(int j = 0 ; j <= 7 ; j++) {                            //通过右移将byte数组转换为二进制  先右移再和0x01与得到最后一位 再赋值给二进制数组                             bit[ i*8 + j] = (byte)((bt[i]>>(7-j)) & 0x01);                        }                    }                } else if(file.getFieldName().equals("imageField")) {                    InputStream img = file.getInputStream();                    BufferedImage image = ImageIO.read(img);                    int height = image.getHeight(); //获取图片的高度                    int width = image.getWidth();//获取图片宽度                    int count = 0;  //定义一个数来计数                    for(int imgX = 0 ; imgX < width ; imgX++ ) {                        for(int imgY = 0 ; imgY < height ; imgY++ ) {                            int rgb = image.getRGB(imgX, imgY);  //获取image图片的rgb值                            Color color = new Color(rgb); //通过rgb值来定义color 再通过color分别获取red,green,blue的值                            //再将获取到的值转换为 string类型  方便下面的substring运算                            String r1 = Integer.toBinaryString((Integer)color.getRed());                            String g1 = Integer.toBinaryString((Integer)color.getGreen());                            String b1 = Integer.toBinaryString((Integer)color.getBlue());                            //判断count有没有超出二进制数组的最大长度,进行substring运算来将二进制数组bit里面的值直接赋值给red,green和blue                            if(count+2<bit.length) {                                b1 = b1.substring(0, b1.length() - 1) + String.valueOf(bit[count+2]);                            }                            if(count+1<bit.length) {                                g1 = g1.substring(0, g1.length() - 1) + String.valueOf(bit[count+1]);                            }                            if(count<bit.length) {                                r1 = r1.substring(0, r1.length() - 1) + String.valueOf(bit[count]);                            }                            //将新的red green 和blue 用Integer.parseInt(red,2)来转换为数字,并组成新的rgb                            rgb = new Color(Integer.parseInt(r1, 2),Integer.parseInt(g1, 2),Integer.parseInt(b1, 2)).getRGB();                              //将新的rgb重新填入到图片当中                            image.setRGB(imgX, imgY, rgb);                            //一轮结束后因为 red green blue 用掉了三个值 所以count+3                            count = count + 3;                          }                    }                           //for循环结束之后 将新的图片保存到 image文件夹下                    //httpServletRequest.getRealPath("image")  是通过image这个名字获取该文件夹的路径                    //ImageIO可以直接写入图片                    ImageIO.write(image, "bmp", new File(httpServletRequest.getRealPath("image") + "/image.bmp"));                }                else break;            }        }    }}

StegananlysisResponseFilter的内容:

package restful.filter;import java.awt.Color;import java.awt.image.BufferedImage;import java.io.File;import java.io.IOException;import javax.imageio.ImageIO;import javax.servlet.http.HttpServletRequest;import javax.ws.rs.container.ContainerRequestContext;import javax.ws.rs.container.ContainerResponseContext;import javax.ws.rs.container.ContainerResponseFilter;import javax.ws.rs.core.Context;public class SteganalysisResponseFilter implements ContainerResponseFilter {    @Context    private HttpServletRequest httpServletRequest;    private byte[] bit;    @Override    public void filter(ContainerRequestContext reqContext, ContainerResponseContext respContext) throws IOException {        if(httpServletRequest.getRequestURL().toString().contains("readImage")) {            //通过文件名的路径来一个文件夹            //httpServletRequest.getRealPath("image")可以获取image的路径            File imgfile = new File(httpServletRequest.getRealPath("image") + "/image.bmp");            //用BufferedImage新建img  通过ImageIO.read(file)获取图片            BufferedImage img = ImageIO.read(imgfile);            //将数组new一下  不new的话将会报空指针的错误            bit = new byte[197024 * 8];            //int 两个新的数来计数            int count = 0;            int n = 0;            //new一个新的byte数组存放二进制数            byte[] bt = new byte[bit.length*8];            //通过获取图片rgb来获取red green blue的最后一位            for(int imgX = 0 ; imgX < img.getWidth() ; imgX++) {                for(int imgY = 0 ; imgY < img.getHeight() ; imgY++ ) {                    int rgb = img.getRGB(imgX, imgY);                    Color color = new Color(rgb);                    int r  = color.getRed();                    int g = color.getGreen();                    int b = color.getBlue();                    if(count<bit.length) {                        bt[count] = (byte) ( r & 0x01);                    }                    if(count+1<bit.length) {                        bt[count+1] = (byte) ( g & 0x01);                    }                    if(count+2<bit.length) {                        bt[count+2] = (byte) ( b & 0x01);                    }                    //因为red blue green 用掉了三个计数的 所以cout+3                    count = count+3;                }            }            //将二进制数组bt 转换为byte数组            //byte数组由8个二进制数组成 所以第二个循环的大小为8            //左移7-j得到的是由高到低的二进制 再相加            //相加后的整数赋值给bit里面的bit[n] 一个j循环 n加一次 代表的就是8个二进制数组成一个byte            for(int i = 0 ;i < bt.length; i=i+8 ) {                count = 0;                for(int j = 0 ; j < 8 ; j++) {                    count = count + (bt[i+j]<<(7-j));                }                bit[n] = (byte) count;                n++;            }            //将bit传给respContext            respContext.setEntity(bit);        }    }}

web.xml的内容:

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">  <display-name>restful</display-name>  <context-param>    <param-name>resteasy.resources</param-name>    <param-value>restful.api.MyAPI</param-value>  </context-param>  <context-param>    <param-name>resteasy.providers</param-name>    <param-value>   restful.filter.SteganalysisRequestFilter,restful.filter.SteganalysisResponseFilter        </param-value>  </context-param>  <listener>    <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>  </listener>  <servlet>    <servlet-name>Resteasy</servlet-name>    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>  </servlet>  <context-param>    <param-name>resteasy.servlet.mapping.prefix</param-name>    <param-value>/</param-value>  </context-param>  <servlet-mapping>    <servlet-name>Resteasy</servlet-name>    <url-pattern>/a/*</url-pattern>  </servlet-mapping></web-app>

index.jsp 的内容:

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><script type="text/javascript" src="js/jquery-3.1.0.min.js"></script><title></title></head><body>    <form action="${pageContext.request.contextPath}/a/writeImage" method="post" enctype="multipart/form-data">        <div align="center">            <fieldset style="width:80%">                <legend>上传文件</legend><br/>                    <div align="left">需要保密的文件</div>                    <div align="left">                        <input type="file" name="docField"/>                    </div>                    <div align="left">保密信息载体BMP图片文件</div>                    <div align="left">                        <input type="file" name="imageField"/>                    </div>                    <div>                        <div align='left'>                            <input type='submit' value="上传文件"/>                        </div>                    </div>            </fieldset>        </div>      </form>    <script>    </script></body></html>
原创粉丝点击