首先是在灰度图中隐藏灰度图
因为是交作业嘛,为了简单就依次在每个字节中隐藏信息,如果有什么不想让人看见的东西要隐藏,可以自己有选择性的隐藏
这里先得到两张灰度图
将第二幅图片当作秘密图片插入一图,这里先将第二幅图置乱
这里采用的是菱形置乱的方法,即在菱形中从第一行开始从左向右依次写入1到n,替换时从第一列从上到下依次读取序号,即第一列序号对应的像素作为第一个像素
代码如下,这里我用的算法比较笨就将就吧,恢复置乱时只需要更改其中一条代码,在代码中已说明
再说明一下,我是将菱形补全为正方形,用0填充,方法虽笨但是能用
/* 对图片进行置乱处理 2015年6月2日20:02:18 blog:http://www.cnblogs.com/wd1001/ */ #include<stdio.h> #include<malloc.h> #include<stdlib.h> /* 位图头结构 */ #pragma pack(1) typedef struct tagBITMAPFILEHEADER { unsigned char bfType[2];//文件格式 unsigned long bfSize;//文件大小 unsigned short bfReserved1;//保留 unsigned short bfReserved2; unsigned long bfOffBits; //DIB数据在文件中的偏移量 }fileHeader; #pragma pack() /* 位图数据信息结构 */ #pragma pack(1) typedef struct tagBITMAPINFOHEADER { unsigned long biSize;//该结构的大小 long biWidth;//文件宽度 long biHeight;//文件高度 unsigned short biPlanes;//平面数 unsigned short biBitCount;//颜色位数 unsigned long biCompression;//压缩类型 unsigned long biSizeImage;//DIB数据区大小 long biXPixPerMeter; long biYPixPerMeter; unsigned long biClrUsed;//多少颜色索引表 unsigned long biClrImporant;//多少重要颜色 }fileInfo; #pragma pack() /* 调色板结构 */ #pragma pack(1) typedef struct tagRGBQUAD { unsigned char rgbBlue; //蓝色分量亮度 unsigned char rgbGreen;//绿色分量亮度 unsigned char rgbRed;//红色分量亮度 unsigned char rgbReserved; }rgbq; #pragma pack() typedef struct MixSpace { unsigned long mix[600]; }MixS; int main() { FILE * fpOri,* fpSec; int i,j,k,t; int m=1; unsigned char ImgData[300][300]; unsigned char ImgData2[300][300]; /*这里采用菱形置乱*/ MixS * MixBox=(MixS *)malloc(sizeof(MixS)*600);//置乱模板 MixS * MixBox2=(MixS *)malloc(sizeof(MixS)*300);//置乱后模板 fileHeader * fh; fileInfo * fi; rgbq * fq; if((fpOri=fopen("G:/vc6.0/work/3/31.bmp","rb"))==NULL) { printf("打开文件失败"); exit(0); } if((fpSec=fopen("G:/vc6.0/work/3/32.bmp","wb"))==NULL) { printf("创建文件失败"); exit(0); } fh=(fileHeader *)malloc(sizeof(fileHeader)); fi=(fileInfo *)malloc(sizeof(fileInfo)); fq=(rgbq *)malloc(sizeof(rgbq)*256); fread(fh,sizeof(fileHeader),1,fpOri); fread(fi,sizeof(fileInfo),1,fpOri); fread(fq,sizeof(rgbq),256,fpOri); for(i=0;i<fi->biHeight;i++) { for(j=0;j<(fi->biWidth+3)/4*4;j++) fread(&ImgData[i][j],1,1,fpOri); } /*置乱模板初始化*/ for(i=0;i<(fi->biWidth+3)/4*4*2-1;i++) { if(i<(fi->biWidth+3)/4*4) { k=(fi->biWidth+3)/4*4-1-i; t=i+1; for(j=0;j<(fi->biWidth+3)/4*4*2-1;j++) { if(k>0) { (MixBox+i)->mix[j]=0; k--; } else if(t>0) { (MixBox+i)->mix[j]=m; (MixBox+i)->mix[j+1]=0; j++; m++; t--; } else (MixBox+i)->mix[j]=0; } } else { k=i-(fi->biWidth+3)/4*4+1; t=(fi->biWidth+3)/4*4-k; for(j=0;j<(fi->biWidth+3)/4*4*2-1;j++) { if(k>0) { (MixBox+i)->mix[j]=0; k--; } else if(t>0) { (MixBox+i)->mix[j]=m; (MixBox+i)->mix[j+1]=0; j++; m++; t--; } else (MixBox+i)->mix[j]=0; } } } /*置乱后模板*/ k=t=0; for(i=0;i<(fi->biWidth+3)/4*4*2-1;i++) { for(j=0;j<(fi->biWidth+3)/4*4*2-1;j++) { if(((MixBox+j)->mix[i])!=0) { (MixBox2+k)->mix[t]=(MixBox+j)->mix[i]; t++; if(t>=(fi->biWidth+3)/4*4) { k++; t=0; } } } } /*将图片置乱*/ for(i=0;i<fi->biHeight;i++) { for(j=0;j<(fi->biWidth+3)/4*4;j++) { k=((MixBox2+i)->mix[j])/((fi->biWidth+3)/4*4); t=((MixBox2+i)->mix[j])%((fi->biWidth+3)/4*4-1); /* 恢复置乱时只需将这句改为 ImgData2[k][t]=ImgData[i][j]; 并修改前面文件路径即可 */ ImgData2[i][j]=ImgData[k][t]; } } /*将图片数据写入*/ fwrite(fh,sizeof(fileHeader),1,fpSec); fwrite(fi,sizeof(fileInfo),1,fpSec); fwrite(fq,sizeof(rgbq),256,fpSec); for(i=0;i<fi->biHeight;i++) { for(j=0;j<(fi->biWidth+3)/4*4;j++) fwrite(&ImgData2[i][j],1,1,fpSec); } free(fh); free(fi); free(fq); free(MixBox); free(MixBox2); fclose(fpOri); fclose(fpSec); printf("success\n"); return 0; }
好了下面就是隐藏后图片了,这里舍弃图片低四位,将秘密图片高四位隐藏到载体图低四位
载体图片改变有点大,可以考虑将图片隐藏在大一点图片中,一字节只隐藏2位或者1位,效果会更好
1 /* 2 将一张图片隐藏到另一张图片中 3 载体图为灰度图 4 blog:http://www.cnblogs.com/wd1001/ 5 2015年6月3日17:59:34 6 */ 7 #include<stdio.h> 8 #include<malloc.h> 9 #include<stdlib.h> 10 /* 11 位图头结构 12 */ 13 #pragma pack(1) 14 typedef struct tagBITMAPFILEHEADER 15 { 16 unsigned char bfType[2];//文件格式 17 unsigned long bfSize;//文件大小 18 unsigned short bfReserved1;//保留 19 unsigned short bfReserved2; 20 unsigned long bfOffBits; //DIB数据在文件中的偏移量 21 }fileHeader; 22 #pragma pack() 23 /* 24 位图数据信息结构 25 */ 26 #pragma pack(1) 27 typedef struct tagBITMAPINFOHEADER 28 { 29 unsigned long biSize;//该结构的大小 30 long biWidth;//文件宽度 31 long biHeight;//文件高度 32 unsigned short biPlanes;//平面数 33 unsigned short biBitCount;//颜色位数 34 unsigned long biCompression;//压缩类型 35 unsigned long biSizeImage;//DIB数据区大小 36 long biXPixPerMeter; 37 long biYPixPerMeter; 38 unsigned long biClrUsed;//多少颜色索引表 39 unsigned long biClrImporant;//多少重要颜色 40 }fileInfo; 41 #pragma pack() 42 /* 43 调色板结构 44 */ 45 #pragma pack(1) 46 typedef struct tagRGBQUAD 47 { 48 unsigned char rgbBlue; //蓝色分量亮度 49 unsigned char rgbGreen;//绿色分量亮度 50 unsigned char rgbRed;//红色分量亮度 51 unsigned char rgbReserved; 52 }rgbq; 53 #pragma pack() 54 55 int main() 56 { 57 FILE * fpCov,* fpSec,*fpSte; 58 int i,j; 59 unsigned char ImgData[300][300]; 60 unsigned char ImgData2[300][300]; 61 62 fileHeader * fh,*fh2; 63 fileInfo * fi,*fi2; 64 rgbq * fq,*fq2; 65 if((fpCov=fopen("G:/vc6.0/work/3/21.bmp","rb"))==NULL) 66 { 67 printf("打开文件失败"); 68 exit(0); 69 } 70 71 if((fpSec=fopen("G:/vc6.0/work/3/32.bmp","rb"))==NULL) 72 { 73 printf("打开文件失败"); 74 exit(0); 75 } 76 if((fpSte=fopen("G:/vc6.0/work/3/123.bmp","wb"))==NULL) 77 { 78 printf("创建文件失败"); 79 exit(0); 80 } 81 /* 82 读取载体图片 83 */ 84 fh=(fileHeader *)malloc(sizeof(fileHeader)); 85 fi=(fileInfo *)malloc(sizeof(fileInfo)); 86 fq=(rgbq *)malloc(sizeof(rgbq)*256); 87 fread(fh,sizeof(fileHeader),1,fpCov); 88 fread(fi,sizeof(fileInfo),1,fpCov); 89 fread(fq,sizeof(rgbq),256,fpCov); 90 91 for(i=0;i<fi->biHeight;i++) 92 { 93 for(j=0;j<(fi->biWidth+3)/4*4;j++) 94 fread(&ImgData[i][j],1,1,fpCov); 95 } 96 /*读取秘密图片*/ 97 fh2=(fileHeader *)malloc(sizeof(fileHeader)); 98 fi2=(fileInfo *)malloc(sizeof(fileInfo)); 99 fq2=(rgbq *)malloc(sizeof(rgbq)*256); 100 fread(fh2,sizeof(fileHeader),1,fpSec); 101 fread(fi2,sizeof(fileInfo),1,fpSec); 102 fread(fq2,sizeof(rgbq),256,fpSec); 103 104 for(i=0;i<fi->biHeight;i++) 105 { 106 for(j=0;j<(fi->biWidth+3)/4*4;j++) 107 fread(&ImgData2[i][j],1,1,fpSec); 108 } 109 /*隐藏图片*/ 110 for(i=0;i<fi->biHeight;i++) 111 { 112 for(j=0;j<(fi->biWidth+3)/4*4;j++) 113 { 114 /*将载体图片低四位置零*/ 115 ImgData[i][j]=ImgData[i][j]&240; 116 /*将秘密图片低四位置零*/ 117 ImgData2[i][j]=ImgData2[i][j]&240; 118 /*将秘密图片高四位移到低四位*/ 119 ImgData2[i][j]=ImgData2[i][j]>>4; 120 /*将秘密图片隐藏到载体图片中*/ 121 ImgData[i][j]=ImgData[i][j]+ImgData2[i][j]; 122 } 123 } 124 /*将图片数据写入*/ 125 fwrite(fh,sizeof(fileHeader),1,fpSte); 126 fwrite(fi,sizeof(fileInfo),1,fpSte); 127 fwrite(fq,sizeof(rgbq),256,fpSte); 128 for(i=0;i<fi->biHeight;i++) 129 { 130 for(j=0;j<(fi->biWidth+3)/4*4;j++) 131 fwrite(&ImgData[i][j],1,1,fpSte); 132 } 133 134 135 free(fh); 136 free(fi); 137 free(fq); 138 fclose(fpCov); 139 fclose(fpSec); 140 fclose(fpSte); 141 printf("success\n"); 142 return 0; 143 }
秘密图片的提取呢,也就非常简单了
提取并恢复置乱:
下面是提取秘密图片的代码,就不多做解释了,跟隐藏代码差不多
1 /* 2 从灰度图片中提取隐藏图片 3 2015年6月3日19:32:12 4 blog:http://www.cnblogs.com/wd1001/ 5 */ 6 #include<stdio.h> 7 #include<malloc.h> 8 #include<stdlib.h> 9 /* 10 位图头结构 11 */ 12 #pragma pack(1) 13 typedef struct tagBITMAPFILEHEADER 14 { 15 unsigned char bfType[2];//文件格式 16 unsigned long bfSize;//文件大小 17 unsigned short bfReserved1;//保留 18 unsigned short bfReserved2; 19 unsigned long bfOffBits; //DIB数据在文件中的偏移量 20 }fileHeader; 21 #pragma pack() 22 /* 23 位图数据信息结构 24 */ 25 #pragma pack(1) 26 typedef struct tagBITMAPINFOHEADER 27 { 28 unsigned long biSize;//该结构的大小 29 long biWidth;//文件宽度 30 long biHeight;//文件高度 31 unsigned short biPlanes;//平面数 32 unsigned short biBitCount;//颜色位数 33 unsigned long biCompression;//压缩类型 34 unsigned long biSizeImage;//DIB数据区大小 35 long biXPixPerMeter; 36 long biYPixPerMeter; 37 unsigned long biClrUsed;//多少颜色索引表 38 unsigned long biClrImporant;//多少重要颜色 39 }fileInfo; 40 #pragma pack() 41 /* 42 调色板结构 43 */ 44 #pragma pack(1) 45 typedef struct tagRGBQUAD 46 { 47 unsigned char rgbBlue; //蓝色分量亮度 48 unsigned char rgbGreen;//绿色分量亮度 49 unsigned char rgbRed;//红色分量亮度 50 unsigned char rgbReserved; 51 }rgbq; 52 #pragma pack() 53 54 int main() 55 { 56 FILE * fpCov,* fpSec,*fpSte; 57 int i,j; 58 unsigned char ImgData[300][300]; 59 unsigned char ImgData2[300][300]; 60 61 fileHeader * fh; 62 fileInfo * fi; 63 rgbq * fq; 64 if((fpSte=fopen("G:/vc6.0/work/3/123.bmp","rb"))==NULL) 65 { 66 printf("打开文件失败"); 67 exit(0); 68 } 69 70 if((fpCov=fopen("G:/vc6.0/work/3/123C.bmp","wb"))==NULL) 71 { 72 printf("创建文件失败"); 73 exit(0); 74 } 75 if((fpSec=fopen("G:/vc6.0/work/3/123S.bmp","wb"))==NULL) 76 { 77 printf("创建文件失败"); 78 exit(0); 79 } 80 /* 81 读取图片 82 */ 83 fh=(fileHeader *)malloc(sizeof(fileHeader)); 84 fi=(fileInfo *)malloc(sizeof(fileInfo)); 85 fq=(rgbq *)malloc(sizeof(rgbq)*256); 86 fread(fh,sizeof(fileHeader),1,fpSte); 87 fread(fi,sizeof(fileInfo),1,fpSte); 88 fread(fq,sizeof(rgbq),256,fpSte); 89 90 for(i=0;i<fi->biHeight;i++) 91 { 92 for(j=0;j<(fi->biWidth+3)/4*4;j++) 93 fread(&ImgData[i][j],1,1,fpSte); 94 } 95 96 /*提取图片*/ 97 for(i=0;i<fi->biHeight;i++) 98 { 99 for(j=0;j<(fi->biWidth+3)/4*4;j++) 100 { 101 /*提取低四位存到秘密图片中*/ 102 ImgData2[i][j]=ImgData[i][j]&15; 103 /*将秘密图片低四位移到高四位*/ 104 ImgData2[i][j]=ImgData2[i][j]<<4; 105 /*提取载体图片*/ 106 ImgData[i][j]=ImgData[i][j]&240; 107 } 108 } 109 /*将载体图片数据写入*/ 110 fwrite(fh,sizeof(fileHeader),1,fpCov); 111 fwrite(fi,sizeof(fileInfo),1,fpCov); 112 fwrite(fq,sizeof(rgbq),256,fpCov); 113 for(i=0;i<fi->biHeight;i++) 114 { 115 for(j=0;j<(fi->biWidth+3)/4*4;j++) 116 fwrite(&ImgData[i][j],1,1,fpCov); 117 } 118 /*将秘密图片数据写入*/ 119 fwrite(fh,sizeof(fileHeader),1,fpSec); 120 fwrite(fi,sizeof(fileInfo),1,fpSec); 121 fwrite(fq,sizeof(rgbq),256,fpSec); 122 for(i=0;i<fi->biHeight;i++) 123 { 124 for(j=0;j<(fi->biWidth+3)/4*4;j++) 125 fwrite(&ImgData2[i][j],1,1,fpSec); 126 } 127 128 free(fh); 129 free(fi); 130 free(fq); 131 fclose(fpCov); 132 fclose(fpSec); 133 fclose(fpSte); 134 printf("success\n"); 135 return 0; 136 }
在RGB图片中隐藏图片
到此这次作业也就完成了,下面是额外搞的一个在RGB图中隐藏灰度图,因为不是作业,也就没写提取代码
1 /* 2 将一张图片隐藏到另一张图片中 3 载体图为真彩图 4 blog:http://www.cnblogs.com/wd1001/ 5 2015年6月5日16:06:16 6 */ 7 #include<stdio.h> 8 #include<malloc.h> 9 #include<stdlib.h> 10 /* 11 位图头结构 12 */ 13 #pragma pack(1) 14 typedef struct tagBITMAPFILEHEADER 15 { 16 unsigned char bfType[2];//文件格式 17 unsigned long bfSize;//文件大小 18 unsigned short bfReserved1;//保留 19 unsigned short bfReserved2; 20 unsigned long bfOffBits; //DIB数据在文件中的偏移量 21 }fileHeader; 22 #pragma pack() 23 /* 24 位图数据信息结构 25 */ 26 #pragma pack(1) 27 typedef struct tagBITMAPINFOHEADER 28 { 29 unsigned long biSize;//该结构的大小 30 long biWidth;//文件宽度 31 long biHeight;//文件高度 32 unsigned short biPlanes;//平面数 33 unsigned short biBitCount;//颜色位数 34 unsigned long biCompression;//压缩类型 35 unsigned long biSizeImage;//DIB数据区大小 36 long biXPixPerMeter; 37 long biYPixPerMeter; 38 unsigned long biClrUsed;//多少颜色索引表 39 unsigned long biClrImporant;//多少重要颜色 40 }fileInfo; 41 #pragma pack() 42 /* 43 调色板结构 44 */ 45 #pragma pack(1) 46 typedef struct tagRGBQUAD 47 { 48 unsigned char rgbBlue; //蓝色分量亮度 49 unsigned char rgbGreen;//绿色分量亮度 50 unsigned char rgbRed;//红色分量亮度 51 unsigned char rgbReserved; 52 }rgbq; 53 #pragma pack() 54 55 int main() 56 { 57 FILE * fpCov,* fpSec,*fpSte; 58 int i,j,k; 59 int h,m,l;//分别存储灰度图的高四位的2位、1位、1位 60 unsigned char ImgData[300][300][3]; 61 unsigned char ImgData2[300][300]; 62 63 fileHeader * fh,*fh2; 64 fileInfo * fi,*fi2; 65 rgbq * fq; 66 if((fpCov=fopen("G:/vc6.0/work/3/2.bmp","rb"))==NULL) 67 { 68 printf("打开文件失败"); 69 exit(0); 70 } 71 72 if((fpSec=fopen("G:/vc6.0/work/3/32.bmp","rb"))==NULL) 73 { 74 printf("打开文件失败"); 75 exit(0); 76 } 77 if((fpSte=fopen("G:/vc6.0/work/3/121.bmp","wb"))==NULL) 78 { 79 printf("创建文件失败"); 80 exit(0); 81 } 82 /* 83 读取载体图片 84 */ 85 fh=(fileHeader *)malloc(sizeof(fileHeader)); 86 fi=(fileInfo *)malloc(sizeof(fileInfo)); 87 fread(fh,sizeof(fileHeader),1,fpCov); 88 fread(fi,sizeof(fileInfo),1,fpCov); 89 90 for(i=0;i<fi->biHeight;i++) 91 { 92 for(j=0;j<(fi->biWidth+3)/4*4;j++) 93 { for(k=0;k<3;k++) 94 fread(&ImgData[i][j][k],1,1,fpCov); 95 } 96 } 97 /*读取秘密图片*/ 98 fh2=(fileHeader *)malloc(sizeof(fileHeader)); 99 fi2=(fileInfo *)malloc(sizeof(fileInfo)); 100 fq=(rgbq *)malloc(sizeof(rgbq)*256); 101 fread(fh2,sizeof(fileHeader),1,fpSec); 102 fread(fi2,sizeof(fileInfo),1,fpSec); 103 fread(fq,sizeof(rgbq),256,fpSec); 104 105 for(i=0;i<fi->biHeight;i++) 106 { 107 for(j=0;j<(fi->biWidth+3)/4*4;j++) 108 fread(&ImgData2[i][j],1,1,fpSec); 109 } 110 /*隐藏图片*/ 111 for(i=0;i<fi2->biHeight;i++) 112 { 113 for(j=0;j<(fi2->biWidth+3)/4*4;j++) 114 { 115 /*提取秘密图片高两位*/ 116 h=ImgData2[i][j]&192; 117 h=h>>6; 118 /*提取秘密图片第6位*/ 119 m=ImgData2[i][j]&32; 120 m=m>>5; 121 /*提取秘密图片第5位*/ 122 l=ImgData2[i][j]&16; 123 l=l>>4; 124 for(k=0;k<3;k++) 125 { 126 /*将秘密图片高两位隐藏到底2位*/ 127 if(k==0) 128 { 129 ImgData[i][j][k]=ImgData[i][j][k]&252; 130 ImgData[i][j][k]+=h; 131 } 132 /*将秘密图片第6位隐藏到底1位*/ 133 else if(k==1) 134 { 135 ImgData[i][j][k]=ImgData[i][j][k]&254; 136 ImgData[i][j][k]+=m; 137 } 138 /*将秘密图片第6位隐藏到底1位*/ 139 else 140 { 141 ImgData[i][j][k]=ImgData[i][j][k]&254; 142 ImgData[i][j][k]+=l; 143 } 144 } 145 } 146 } 147 /*将图片数据写入*/ 148 fwrite(fh,sizeof(fileHeader),1,fpSte); 149 fwrite(fi,sizeof(fileInfo),1,fpSte); 150 for(i=0;i<fi->biHeight;i++) 151 { 152 for(j=0;j<(fi->biWidth+3)/4*4;j++) 153 for(k=0;k<3;k++) 154 fwrite(&ImgData[i][j][k],1,1,fpSte); 155 } 156 157 158 free(fh); 159 free(fi); 160 free(fq); 161 fclose(fpCov); 162 fclose(fpSec); 163 fclose(fpSte); 164 printf("success\n"); 165 return 0; 166 }