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 + -
显示快捷键?