基于LSB的信息隐藏实现的方法
基于LSB的信息隐藏实现的方法
LSB就是最不重要位信息隐藏算法,读取出图片中每个点的象素值,然后把信息的bit序列填充到这些象素的最低上.然后在分析检测的时候提取出最低位,就可以恢复原始信息.因为是在最低位上进行隐藏,所以图像的失真是比较小的,肉眼无法察觉,但是它会破坏图像的统计特性,这样通过统计的方法可以检测到有信息的嵌入.此外在图片有损压缩时,隐藏的信息容易丢失.如果嵌入高位,会带来失真,但是嵌入强度高,可以抵御有损压缩.
/*
位操作的类,自己写的.
*
// BitOperate.cpp: implementation of the BitOperate class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "BitOperate.h"
#include "iostream.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
BitOperate::BitOperate()
{
}
BitOperate::~BitOperate()
{
}
/*
功能:把ch从右数的第position位设置为value;
*/
byte BitOperate::bitSet(byte ch, short position, bool value)
{
byte temp = ch;
if(position>8||position<1)
{
cout<<"Out of Bound! Position must be a number between 1 --- 8 "<<endl;
return ch;
}
bool bit = bitAt(temp,position);
if(bit^value)//如果不相同的话
{
if(bit == 0)
{
byte m = (byte)value;
for(int i = 1;i<position;i++)
m = m<<1;
ch+=m;
return ch;
}
else
{
byte m = (byte)bit;
for(int i = 1;i<position;i++)
m = m<<1;
ch-=m;
return ch;
}
}
else return ch;
}
/*
功能:返回ch从右数第i位的值;
*/
bool BitOperate::bitAt(byte ch, short position)
{
byte temp = ch;
if(position>8||position<1)
{
cout<<"Out of Bound! Position must be a number between 1 --- 8 "<<endl;
return false;
}
for(int j = 1;j<position;j++)
temp = temp>>1;
if(temp%2==0)return 0;
else return 1;
}
// HideInFo.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "iostream.h"
#include "stdio.h"
#include "BitOperate.h"
#include "stdlib.h"
#include "ctype.h"
#include"conio.h"
#include <string.h>
#define MAX 1000
typedef unsigned char byte;
/*1. BMP文件头
BMP文件头数据结构含有BMP文件的类型、
文件大小和位图起始位置等信息。其结构定义如下:
*/
typedef struct tagBitMapFileHeader
{
byte bfType[2]; // 位图文件的类型,必须为"BM"
byte bfSize[4]; // 位图文件的大小,以字节为单位
byte bfReserved1[2]; // 位图文件保留字,必须为0
byte bfReserved2[2]; // 位图文件保留字,必须为0
byte bfOffBits[4]; // 位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位
} *BitMap;//该结构占据14个字节。
/*功能:返回图像的长度*/
int getValue(byte*A,int num)
{
int result = 0;
for(int i = num-1;i>0;i--)
{
result+=A[i];
result = result<<8;
}
result+=A[0];
return result;
}
/*功能:将信息隐藏到图片中*/
void hideInFo()
{
FILE* fp;
char data[MAX];
BitOperate operate;
if((fp = fopen("H://tao.bmp", "r+"))==NULL)
{
cout<<"打开文件的时候出现错误!"<<endl;
return;
}
BitMapmap = //存放文件头信息;
(BitMap)malloc(sizeof(struct tagBitMapFileHeader ));
fread(map,sizeof(struct tagBitMapFileHeader ),1,fp);
printf("Input the data you want to hide:/n");
gets(data);
int datalength = strlen(data);
int maplength = getValue(map->bfSize,4);
int databegin = getValue(map->bfOffBits,4);
if((datalength*8)>(maplength-databegin))
{
printf("The data is too long!Choose a bigger picture or hide it in pieces!/n");
return;
}
printf("#######Datalength = %d/n",datalength);
printf("#######Malength = %d/n",maplength);
printf("DataBegin = %d/n",databegin);
//首先将文件的长度隐藏起来;
byte temp[32];
fseek(fp,databegin,SEEK_SET);//定位到数据块的起点;
fread(temp,sizeof(char)*32,1,fp);
int copy = datalength;
for(int i = 31;i>=0;i--)
{
bool v = (bool)(copy%2);
temp[i] = operate.bitSet(temp[i],1,v);
copy = copy/2;
}
fseek(fp,databegin,SEEK_SET);//定位到数据块的起点;
fwrite(temp,sizeof(byte)*32,1,fp);
//以下将数据信息隐藏到图像中;
int times = 0;
byte ch[8];
while(times<datalength)//加上隐藏的文件长度信息;
{
fseek(fp,databegin+32+times*8,SEEK_SET);//定位到数据块的起点;
fread(ch,sizeof(byte),8,fp);//读出8个字节;
for(int i = 7;i>=0;i--)
ch[i] = operate.bitSet(ch[i],1,operate.bitAt(data[times],8-i));
fseek(fp,databegin+32+times*8,SEEK_SET);//定位到数据块的起点;
fwrite(ch,sizeof(byte),8,fp);//写入8个字节;
times++;
}
fclose(fp);
}
/*将图片中隐藏的信息提取出来*/
void getInFo()
{
FILE* fp;
byte data[MAX];
BitOperate operate;
if((fp = fopen("H://tao.bmp", "r+"))==NULL)
{
cout<<"打开文件的时候出现错误!"<<endl;
return;
}
BitMapmap = //存放文件头信息;
(BitMap)malloc(sizeof(struct tagBitMapFileHeader ));
fread(map,sizeof(struct tagBitMapFileHeader ),1,fp);
int databegin = getValue(map->bfOffBits,4);//得到数据块开始的偏移地址;
//获取文件的长度;
int datalength = 0;
//首先将隐藏文件的长度读出来;
byte temp[32];
fseek(fp,databegin,SEEK_SET);//定位到数据块的起点;
fread(temp,sizeof(char)*32,1,fp);
for(int i = 0;i<31;i++)
{
datalength += (int)operate.bitAt(temp[i],1);
datalength = datalength<<1;
}
datalength += (int)operate.bitAt(temp[31],1);
printf("/n/nDatalength = %d/n",datalength);
int times = 0;
byte ch[8];
while(times<datalength)//加上隐藏的文件长度信息;
{
fseek(fp,databegin+32+times*8,SEEK_SET);
fread(ch,sizeof(byte),8,fp);//读出8个字节;
//printf("/nch = %s/n",ch);
data[times] = 0;
for(int i = 0;i<7;i++)
{
data[times]+= (int)operate.bitAt(ch[i],1);
data[times] = data[times]*2;
}
data[times]+= (int)operate.bitAt(ch[7],1);
printf("%c",data[times]);
times++;
}
fclose(fp);
}
void main()
{
//hideInFo();
getInFo();
getch();
}