infohiding.java

来自「使用java编写的LSB图像信息隐藏算法演示程序」· Java 代码 · 共 524 行 · 第 1/2 页

JAVA
524
字号
package hideInfo;

import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.MemoryImageSource;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


class InfoHiding {
	BmpHeader bh;        //bmp文件头 里面很多信息
	File originalBMP;		//
	FileInputStream fs;	//从源图像中读取内容的 流
	Image origBMPImage;	//源图像对象
	byte[] originalImageData;   //源图像被读如内存后得到的byte序列
	
	File originalText;
	FileInputStream fs2;
	byte[] originalTextData;
	String originalTextString;  //与上面类似 名字很有规律 

	File targetBMP;
	FileOutputStream fos;
	byte[] targetImageData;
	
	int forReserved;   //暂存文本的长度
	
	
	
	
	public void setOriginalBMP(File origin) throws FileNotFoundException  //把源图像文件对象读入
	{
		this.originalBMP=origin;
		this.fs=new FileInputStream(this.originalBMP);
	
	}
	
	public void getBMPHeaderInfo() throws IOException
	{
		this.bh=new BmpHeader();	
		bh.getHeaderInfo(this.fs);
	}
	
	public void setOriginalText(File origin) throws Exception  //读入源文本文件,同时压缩一下
	{
		File tmpInZip=new File("c:/tmpIn.zip");
		if (tmpInZip.exists()) tmpInZip.delete();
		
//		创建文件输入流对象 
		FileInputStream in = new FileInputStream(origin ); 
//		创建文件输出流对象
		FileOutputStream out = new FileOutputStream( "c:/tmpIn.zip" ); 
//		创建ZIP数据输出流对象 
		ZipOutputStream zipOut = new ZipOutputStream( out ); 
//		创建指向压缩原始文件的入口
		ZipEntry entry = new ZipEntry(origin.getName());
		zipOut.putNextEntry( entry );
//		向压缩文件中输出数据
		int nNumber; 
		byte[] buffer = new byte[4096]; 
		while ((nNumber=in.read(buffer)) != -1) 
		zipOut.write(buffer,0,nNumber); 
//		关闭创建的流对象
		zipOut.close(); 
		out.close(); 
		in.close(); 
		this.originalText=new File("c:/tmpIn.zip");
		this.fs2=new FileInputStream(this.originalText);   
	}
	
	public void setTargetBMP(File target) throws FileNotFoundException //设定目标图片对象
	{
		this.targetBMP=target;
		this.fos=new FileOutputStream(this.targetBMP);
	}
	
    
	public void readMap16() throws IOException     //读取16bit制式图像内容
	{
		int len=(int) (this.originalBMP.length()-this.bh.ndataOffset);
		this.originalImageData= new byte[len];
 //       System.out.println("this.originalImageData.length= "+this.originalImageData.length);
  //      System.out.println("(file.length-54)= "+(this.originalBMP.length()-54));     
        this.fs.skip(this.bh.ndataOffset-54);  //jump to the data position
  //      System.out.println("bh.ndataOffset-54= "+(bh.ndataOffset-54));
        this.fs.read(this.originalImageData,0,len);    
        fs.close();
	}
	
	
	
	/**
	 * 	 read the 24bit bmp file into byte[] and then into Image object ==
	 * 	 Way2: From the angle of File length
	 */
	public void readMap24() throws IOException //读取24bit制式图像内容
	{
		int len=(int) (this.originalBMP.length()-this.bh.ndataOffset);
//		System.out.println("this.originalBMP.length()-this.bh.ndataOffset= "+len);
		int ndata[] = new int[len];
        this.originalImageData= new byte[len];
 //       System.out.println("this.originalImageData.length= "+this.originalImageData.length);
  //      System.out.println("(file.length-54)= "+(this.originalBMP.length()-54));
        
        this.fs.skip(this.bh.ndataOffset-54);  //jump to the data position
  //      System.out.println("bh.ndataOffset-54= "+(bh.ndataOffset-54));
        this.fs.read(this.originalImageData,0,len);
        
        fs.close();
	}
	
	/**
	 *  read the 32bit bmp file into byte[] and then into Image object
	 */	
	public void readMap32() throws IOException//读取32bit制式图像内容
	{
		int len=(int) (this.originalBMP.length()-this.bh.ndataOffset);
//		System.out.println("this.originalBMP.length()-this.bh.ndataOffset= "+len);
		int ndata[] = new int[len];
        this.originalImageData= new byte[len];
 //       System.out.println("this.originalImageData.length= "+this.originalImageData.length);
  //      System.out.println("(file.length-54)= "+(this.originalBMP.length()-54));
        
        this.fs.skip(this.bh.ndataOffset-54);  //jump to the data position
  //      System.out.println("bh.ndataOffset-54= "+(bh.ndataOffset-54));
        this.fs.read(this.originalImageData,0,len);
         fs.close();
             
	}
	
	/**
	 * 	read the 8bit bmp file into byte[] and then into Image object
	 * 	attention : since the 8bit bmp use the index in the main data region
	 *  			it is proper to read just the platte area and hide the info in the platte 
	 *  			unfortunately only a max number of 3*256*2/8=192B could be hide so the 8 bit solution will be neglect here             
	 */	 
	public void readMap8() throws IOException 
	{
		int nNumColors = 0;//determing the number of colors
        if (bh.nclrused > 0) nNumColors = bh.nclrused;
        else nNumColors = (1 & 0xff) << bh.nbitcount;

        System.out.println("The number of Colors is"+nNumColors);

        if (bh.nsizeimage == 0)
        {
            bh.nsizeimage = ((((bh.nwidth * bh.nbitcount) + 31) & ~31) >> 3);
            bh.nsizeimage *= bh.nheight;
            //          System.out.println("nsizeimage (backup) is"+nsizeimage);
        }
        
        //      Read the palatte colors.
        int npalette[] = new int[nNumColors];
        byte bpalette[] = new byte[nNumColors * 4];
        fs.read(bpalette, 0, nNumColors * 4);
        int nindex8 = 0;
        for (int n = 0; n < nNumColors; n++)
        {
            npalette[n] = Utility.constructInt3(bpalette, nindex8);
            nindex8 += 4;
        }
        //Read the image data (actually indices into the palette)
        // Scan lines are still padded out to even 4-byte boundaries.
        int npad8 = (bh.nsizeimage / bh.nheight) - bh.nwidth;
        //    System.out.println("nPad is:"+npad8);
        int ndata8[] = new int[bh.nwidth * bh.nheight];
        this.originalImageData = new byte[(bh.nwidth + npad8) * bh.nheight];
        
        fs.read(this.originalImageData, 0, (bh.nwidth + npad8) * bh.nheight);
        
        nindex8 = 0;
        for (int j8 = 0; j8 < bh.nheight; j8++)
        {
            for (int i8 = 0; i8 < bh.nwidth; i8++)
            {
                ndata8[bh.nwidth * (bh.nheight - j8 - 1) + i8] =npalette[((int) this.originalImageData[nindex8] & 0xff)];
                nindex8++;
            }
            nindex8 += npad8;
        }
        this.origBMPImage = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(bh.nwidth, bh.nheight,ndata8, 0, bh.nwidth));        
	}
	
///////////////////////////////////////////////////////////////////////////
	
	public void getText() throws IOException  //把文件内容读入内存,到byte【】 中
	{
//		System.out.print("Lenth of text: "+this.originalText.length()+"\n");
		int len= (int) this.originalText.length();
		this.forReserved=len;
		this.originalTextData=new byte[len+512];
		this.fs2.read(this.originalTextData,0,len);
		
		String name=this.originalText.getName();
		byte[] bname=name.getBytes();
		Utility.extractInt(bname.length,this.originalTextData,len);
		for (int i=0;i<bname.length;i++) this.originalTextData[len+4+i]=bname[i];
		this.fs2.close();   
		
	}
	
	public boolean isAdequate16()   //判断是否足够容下文本文件
	{
		long bitTextLen=this.originalText.length()*8;
		long bitSpace=this.originalImageData.length/4;
		return (bitSpace>bitTextLen+512);
		
	}
	
	
	/*
	 * check whether the 24bit bmp can contain the content of text
	 */
	public boolean isAdequate24()//判断是否足够容下文本文件
	{
		long bitTextLen=this.originalText.length()*8;
		long bitSpace=this.originalImageData.length*2;
		return (bitSpace>bitTextLen+512);
		
	}
	
	/*
	 * check whether the 32bit bmp can contain the content of text
	 */
	public boolean isAdequate32()//判断是否足够容下文本文件
	{
		long bitTextLen=this.originalText.length()*8;
		long bitSpace=this.originalImageData.length*2;
		return (bitSpace>bitTextLen+512);
		
	}
	
	
	/**
	 * To hide info into 16bit bmp file
	 * must do pre-work: setBMP and setTExt and isAdequate and getMap16 and setTargetBMP;
	 * hide 1bit in 2byte (1pixel)
	 *
	 */
	public void hideInfo16() //原理: 就是读出一个象素,拆开文本文件为一个一个bit,藏到每个象素的最低bit 下面的都一样 
	{
		this.targetImageData=new byte[this.originalImageData.length];
		for (int i=0;i<this.originalImageData.length;i++) this.targetImageData[i]=this.originalImageData[i];
		
		int countPixel=0;
		int countText=0;
		while(countText<this.originalTextData.length)
		{
			byte textByte=this.originalTextData[countText];
			byte tmpText;
			byte tmpPixel;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?