BMP图像信息隐藏 您所在的位置:网站首页 隐藏秘密的图片 BMP图像信息隐藏

BMP图像信息隐藏

2024-04-26 00:14| 来源: 网络整理| 查看: 265

图像隐写算法LSB—Least Significant Bits,又称最不显著位。LSB算法就是将秘密信息嵌入到载体图像像素值得最低有效位,改变这一位置对载体图像的品质影响最小。

原理如下:

 

以实验用的24位真彩图为例,每个像素用3Byte表示,每Byte分别表示R、G、B三色的亮度,亮度取值范围位0~0xFF。采用LSB算法就是将图像信息的每一Byte的最后一位二进制替换为待嵌入的秘密信息的一位,按顺序进行。因为对最后一位的替换操作其实就是对亮度信息的加一或减一,对颜色影响甚微,所以肉眼难以察觉,这就达到了隐藏信息的目的。对于24位真彩图,所能嵌入的最大秘密信息的大小为像素数量的3/8字节

 

步骤如下:

以二进制的方式读取载体图像并分别头数据与像素数据 用二进制秘密信息中的每一笔特信息替换与之对应的载体数据的最低有效位 利用得到的新的二进制数据构造图像,即得到含有秘密信息的隐秘图像 /*** change.c ***/ #include #include #include"define.h" int main() { //创建头文件,信息头结构变量 BMP_FILE_HEADER fileHeader; BMP_INFO_HEADER infoHeader; //打开载体图像文件,新建修改后的图像文件 FILE *file = fopen("football.bmp","rb"); FILE *newFile = fopen("change.bmp","wbx"); //读取文件头,信息头 fread(&fileHeader,14,1,file); fread(&infoHeader,40,1,file); //读取24位真彩图像的像素信息 RGB *img = (RGB *)malloc(infoHeader.sizeImage); fread(img,infoHeader.sizeImage,1,file); printf("Picture Size(width x height):%d x %d \n", infoHeader.width, infoHeader.height); //对图片内容进行修改,每隔五个像素染黑一个像素 int i = 0; for (i = 0; i < infoHeader.sizeImage / 3; i += 5) { img[i].red = 0; img[i].green = 0; img[i].blue = 0; } printf("fwirte\n"); //将新的二进制文件写入到新文件中 fwrite(&fileHeader,14,1,newFile); fwrite(&infoHeader,40,1,newFile); fwrite(img,infoHeader.sizeImage,1,newFile); fclose(file); fclose(newFile); return 0; }

修改图像内容的核心代码如下:

int i = 0; for (i = 0; i < infoHeader.sizeImage / 3; i += 5) { img[i].red = 0; img[i].green = 0; img[i].blue = 0; }

infoHeader.sizeImage表示图像数据的字节数,在24位真彩位图中,表示每个像素需要三个字节,infoHeader.sizeImage/3表示位图总像素数

循环体中将每个颜色分量的亮度赋值为0,让像素变黑,最终得到修改后的图像。

以上是处理BMP图像信息的原理。

 

下面通过LSB算法隐藏秘密信息,这里把define.h文件作为秘密信息隐藏,也可以选择任何大小合适的文件作为秘密信息。

/*** define.c ***/ typedef unsigned short WORD; //2 byte typedef unsigned int DWORD; //4 byte typedef unsigned char BYTE; //1 byte //head of file typedef struct BMP_FILE_HEADER { WORD type; DWORD size; WORD reserved1; WORD reserved2; DWORD offBits; }BMP_FILE_HEADER; //head of infomation typedef struct BMP_INFO_HEADER { DWORD size; int width; int height; WORD planes; WORD bitCount; DWORD compression; DWORD sizeImage; int xPelsPerMeter; int yPelsPerMeter; DWORD colorUsed; DWORD colorImportant; }BMP_INFO_HEADER; //RGBQUAD typedef struct RGBQUAD { BYTE blue; BYTE green; BYTE red; BYTE reserved; }RGBQUAD; //RGB typedef struct RGB { BYTE blue; BYTE green; BYTE red; }RGB;

隐藏信息代码:

/*** hide.c ***/ #include #include #include #include #include"define.h" //获取文件大小 int getFileSizeSystemCall(char *strFileName) { struct stat temp; stat(strFileName,&temp); return temp.st_size; } int main() { //创建文件头,信息头结构体变量 BMP_FILE_HEADER fileHeader; BMP_INFO_HEADER infoHeader; //打开载体图像文件,读取文件头和信息头,打开隐秘图像信息 FILE *file = fopen("football.bmp","rb"); FILE *newFile = fopen("hide.bmp","wbx"); fread(&fileHeader,14,1,file); fread(&infoHeader,40,1,file); //读取秘密信息文件“define.h” int infoSize = getFileSizeSystemCall("define.h"); printf("info size : %d\n",infoSize); BYTE *info = (BYTE *)malloc(infoSize); FILE *infoFile = fopen("define.h","rb"); fread(info,infoSize,1,infoFile); //读取24位真彩图像像素信息 BYTE *img = (BYTE *)malloc(infoHeader.sizeImage); fread(img,infoHeader.sizeImage,1,file); printf("Picture Size (Width x height) : %d x %d\n",infoHeader.width,infoHeader.height); printf("Can hide %d byte infomation\n",infoHeader.sizeImage/8); //LBS算法实现,把隐秘信息的每一个字节8bit按照低字节到高字节的顺序隐藏到像素信息的 //每8byte中的最低位 int i = 0,j = 1; BYTE tmp = 0x00; for(i = 0; i < infoSize; i++) { for(j = 0; j < 8; j++) { tmp = info[i] &0x01; if(tmp) { img[i*8+j] = img[i * 8 + j] | 0x01; } else { img[i*8+j] = img[i * 8 + j] & 0xfe; } info[i] = info[i] >> 1; } } //将修改后的二进制数据写入到隐秘图像文件中 fwrite(&fileHeader,14,1,newFile); fwrite(&infoHeader,40,1,newFile); fwrite(img,infoHeader.sizeImage,1,newFile); fclose(file); fclose(newFile); return 0; }

LSB算法实现:

int i = 0,j = 1; BYTE tmp = 0x00; for(i = 0; i < infoSize; i++) { for(j = 0; j < 8; j++) { tmp = info[i] &0x01; if(tmp) { img[i*8+j] = img[i * 8 + j] | 0x01; } else { img[i*8+j] = img[i * 8 + j] & 0xfe; } info[i] = info[i] >> 1; } }

info[i]是存储秘密信息的数组,通过把像素Byte数据与0x01按位或运算使得最后一位为1,通过把像素Byte数据与0xfe(1111,1110)做按位与运算使得最后一位为0(0 & x = 0)

 

stat函数用来获取指定路径下文件或文件夹的属性。路径可以不指定。

 

使用md5sum命令查看两张图片的MD5 HASH值

 

 

再对比一下文件的16进制内容,先使用xxd命令生成16进制内容:

xxd football.bmp > football.hex

xxd hide.bmp > hide.hex

 

再使用sed命令查看对比第五行内容

sed -n 5p football.hex

sed -n 5p hide.hex

 

 

很明显的可以看到像素数据的每一字节的最后一位发生了变化,验证了LSB算法的原理。

 

提取信息

/*** extract.c ***/ #include #include #include"define.h" int main() { //创建头文件,信息头结构体变量 BMP_FILE_HEADER fileHeader; BMP_INFO_HEADER infoHeader; //读取隐秘图像文件,创建秘密信息文件 FILE *file = fopen("hide.bmp","rb"); FILE *extractFile = fopen("extract.txt","wbx"); BYTE *info = (BYTE *)malloc(738); //读取头文件,信息头 fread(&fileHeader,14,1,file); fread(&infoHeader,40,1,file); //读取24位真彩图像的像素信息 BYTE *img = (BYTE *)malloc(infoHeader.sizeImage); fread(img,infoHeader.sizeImage,1,file); printf("Picture size : %d x %d \n",infoHeader.width,infoHeader.height); //信息提取部分,根据秘密信息的长度,依次读取隐秘图像信息像素信息的最低bit,凭借成Byte int i = 0,j = 0; BYTE tmp = 0x00,ttmp = 0x00; for(i = 0; i < 738; i++) { tmp = 0x00; for(j = 0; j < 8; j++) { /*取每8位bit像素信息的最后一位拼接为1Byte的秘密信息*/ ttmp = img[i*8+j] & 0x01; ttmp = ttmp


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有