在一张图片中隐藏另一张图片

时间:2024-03-08 17:06:59

首先是在灰度图中隐藏灰度图

因为是交作业嘛,为了简单就依次在每个字节中隐藏信息,如果有什么不想让人看见的东西要隐藏,可以自己有选择性的隐藏

这里先得到两张灰度图

将第二幅图片当作秘密图片插入一图,这里先将第二幅图置乱

 

这里采用的是菱形置乱的方法,即在菱形中从第一行开始从左向右依次写入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 }