校验两张BMP图像的RGB矩阵有多少个像素点不同

版权声明:分享、借鉴或使用刁肥宅的劳动成果请务必注明出处!刁肥宅保留追究剽窃者的一切权利! https://blog.csdn.net/u25th_engineer/article/details/87216878

       数据结构课设我选的的二值图像(要求是.bmp格式)数字水印,代码实现之后,我就萌生了校验一下水印信息是否编码成功的想法。经水印算法编码后的二值图像,有的被编码图与原图不存在显著的人眼上的差异。这份代码我主要是用来检测:

       1、水印算法的稳健性;

       2、水印算法的安全性;

       3、水印算法的不可访问性;

       4、水印算法的有效性。

       具体用途将在课设答辩完成后,将课设代码、报告与详细说明一同写到博客里。

       另外,代码里面的析构函数如果加了那几行delete语句将引起程序运行时崩溃(RTE):或为两次释放内存。个人感觉问题出在 void OperateBMP::compareBMP() 函数里的两个OperateBMP类的调用,具体原因未分析。如有朋友有何高见,欢迎指教!

       

图1 程序崩溃
图2 正确运行时控制台结果

       

图3 RGB矩阵比较结果(局部)

       

扫描二维码关注公众号,回复: 6072119 查看本文章
图4 RGB矩阵比较结果(局部)

       

图5 水印结果展示

       

       从图5明显看出编码前后图像的纹理有显著差异。

       开发环境:Ubuntu 16.04 LTS,g++。

       源代码:

#include <stdio.h>  
#include <string.h>  
#include <sys/types.h>  
#include <fstream>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string>
 
#include <iostream>  
#pragma pack(2)
using namespace std;  
 
typedef struct BITMAPFILEHEADER  
{   
    u_int16_t bfType;   
    u_int32_t bfSize;   
    u_int16_t bfReserved1;   
    u_int16_t bfReserved2;   
    u_int32_t bfOffBits;   
}BITMAPFILEHEADER;   
typedef struct BITMAPINFOHEADER  
{   
    u_int32_t biSize;   
    u_int32_t biWidth;   
    u_int32_t biHeight;   
    u_int16_t biPlanes;   
    u_int16_t biBitCount;   
    u_int32_t biCompression;   
    u_int32_t biSizeImage;   
    u_int32_t biXPelsPerMeter;   
    u_int32_t biYPelsPerMeter;   
    u_int32_t biClrUsed;   
    u_int32_t biClrImportant;   
}BITMAPINFODEADER;  
 

class OperateBMP
{
public:
    int readBmp();
    int saveBmp();
    void work();
    void compareBMP();
    ~OperateBMP();

private:
    BITMAPFILEHEADER BMFH;
    BITMAPINFODEADER BMIH;
    int biWidth;            //图像宽  
    int biHeight;           //图像高  
    int biBitCount;         //图像类型,每像素位数  
    unsigned char *pBmpBuf; //存储图像数据  
    int lineByte;           //图像数据每行字节数

    string originFileName_string;
    string newFileName_string;
    const char *originFileName_char;
    const char *newFileName_char;

    string pictureName_without_type;

    //string resultName_string;
    char *resultName_char;
    int lengthOfResultName_char;

    string compareResult;
};


OperateBMP::~OperateBMP()
{
    /*
    delete pBmpBuf;
    delete originFileName_char;
    delete newFileName_char;
    delete resultName_char;
    */
}

int OperateBMP::readBmp()  
{  
    FILE *fp;  
    cout << "Please input the name of the origin BMP file:" << endl;
    cin >> originFileName_string;
    originFileName_char = new char[ originFileName_string.length() ];
    originFileName_char = originFileName_string.c_str();

    if( (fp = fopen(originFileName_char,"rb")) == NULL)  //以二进制的方式打开文件  
    {  
        cout<<"The file "<<originFileName_char<<"was not opened"<<endl;  
        return -1;  
    }  
    if(fseek(fp,sizeof(BITMAPFILEHEADER),SEEK_CUR))  //跳过BITMAPFILEHEADE  
    {  
        cout<<"跳转失败"<<endl;  
        return -1;  
    }  
    
    fread(&BMIH,sizeof(BITMAPINFOHEADER),1,fp);   //从fp中读取BITMAPINFOHEADER信息到infoHead中,同时fp的指针移动  
    biWidth = BMIH.biWidth;  
    biHeight = BMIH.biHeight;  
    biBitCount = BMIH.biBitCount;  
    lineByte = (biWidth*biBitCount/8+3)/4*4;   //lineByte必须为4的倍数
    //24位bmp没有颜色表,所以就直接到了实际的位图数据的起始位置  
    pBmpBuf = new unsigned char[lineByte * biHeight];  
    fread(pBmpBuf,sizeof(char),lineByte * biHeight,fp);  
    fclose(fp);   //关闭文件  
    return 0;  
}

int OperateBMP::saveBmp()  
{  
    FILE *fp;  
    newFileName_char = new char[ originFileName_string.length() + 4 ];
    newFileName_string = "New_" + originFileName_string;
    newFileName_char = newFileName_string.c_str();

    int pos = originFileName_string.find(".bmp");
    pictureName_without_type = originFileName_string.erase( pos, 4 );
    //cout << pictureName_without_type << endl;

    if( (fp = fopen(newFileName_char,"wb") )== NULL)   //以二进制写入方式打开  
    {  
        cout<<"打开失败!"<<endl;  
        return -1;  
    }  
    //设置BITMAPFILEHEADER参数  
    BMFH.bfType = 0x4D42;     
    BMFH.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + lineByte * biHeight;  
    BMFH.bfReserved1 = 0;  
    BMFH.bfReserved2 = 0;  
    BMFH.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);  
    fwrite(&BMFH,sizeof(BITMAPFILEHEADER),1,fp);  
    //设置BITMAPINFOHEADER参数  
    
    BMIH.biSize = 40;  
    BMIH.biWidth = biWidth;  
    BMIH.biHeight = biHeight;  
    BMIH.biPlanes = 1;  
    BMIH.biBitCount = biBitCount;  
    BMIH.biCompression = 0;  
    BMIH.biSizeImage = lineByte * biHeight;  
    BMIH.biXPelsPerMeter = 0;  
    BMIH.biYPelsPerMeter = 0;  
    BMIH.biClrUsed = 0;  
    BMIH.biClrImportant = 0;  
    //写入  
    fwrite(&BMIH,sizeof(BITMAPINFOHEADER),1,fp); 
 
 
    fwrite(pBmpBuf,sizeof(char),lineByte * biHeight,fp);  
    fclose(fp);    //关闭文件  
    return 0;  
}
void OperateBMP::work()  
{  
    if(-1 == readBmp())  
        cout<<"readfile error!"<<endl;  
    //输出图像的信息  
    cout<<"Width = "<<biWidth<<" Height = "<<biHeight<<" biBitCount="<<biBitCount<<endl;
    string TXT = "imageData_" + originFileName_string + ".txt"; //15

    const char *TXT_char = TXT.c_str();  

    resultName_char = new char[ 15 + originFileName_string.length() ];

    strcpy( resultName_char, TXT_char );

    lengthOfResultName_char = 15 + originFileName_string.length();
    ofstream outfile(TXT_char,ios::in | ios::trunc);  
    if(!outfile)  
    {  
        cout<<"open error"<<endl;  
        return ;  
    }  
    int count = 0;  
    //图像数据信息是从左下角按行开始存储的  
    for(int i = 0; i < biHeight; i++ )  
    {  
        for(int j = 0; j < biWidth; j++ )  
        {  
            for(int k = 0; k < 3; k++ )  
            {  
                int temp = *(pBmpBuf + i * lineByte + j + k);  
                count++;  
                outfile<<temp<<" ";  
                if(count % 8 == 0)  
                {  
                    outfile<<endl;  
                }  
            }  
        }  
    }  
    cout<<"总的像素数:"<<count / 3<<endl;
    newFileName_string = "_" + originFileName_string;
    newFileName_char = new char[ newFileName_string.length() ];
    newFileName_char = newFileName_string.c_str();  
    saveBmp();  
    
    return ;
}  
 
 void OperateBMP::compareBMP()
 {
    OperateBMP OBMP1, OBMP2;
    OBMP1.work();
    OBMP2.work();
    char *fileName1, *fileName2;
    fileName1 = new char[OBMP1.lengthOfResultName_char];
    strcpy(fileName1, OBMP1.resultName_char );
    fileName2 = new char[OBMP2.lengthOfResultName_char];
    strcpy( fileName2, OBMP2.resultName_char );


    FILE *fp1 = fopen( fileName1, "r" ), *fp2 = fopen( fileName2, "r" );

    int arr1[10], arr2[10], firstRow, firstColumn;
    int length = 0;
    long long cnt = 0;
    compareResult = OBMP1.pictureName_without_type + "_With_" + OBMP2.pictureName_without_type + "_Comparing_Result.txt";
    char *resultTXT = new char[ compareResult.length() ];//compareResultLength.c_str();
    strcpy( resultTXT, compareResult.c_str() );
    freopen( resultTXT, "w", stdout );
    while( ( fscanf( fp1, "%d %d %d %d %d %d %d %d \n", &arr1[0], &arr1[1], &arr1[2], &arr1[3], &arr1[4], &arr1[5], &arr1[6], &arr1[7] ) != EOF ) && ( fscanf( fp2, "%d %d %d %d %d %d %d %d \n", &arr2[0], &arr2[1], &arr2[2], &arr2[3], &arr2[4], &arr2[5], &arr2[6], &arr2[7] ) != EOF ) )
    {
        length ++;
        for( int i = 0; i < 7; i ++ )
        {
            if( arr1[i] != arr2[i] )
            {
                cnt ++;
                cout << "NO " << cnt << " difference:" << endl;
                cout << "row = " << length << ", " << "column = " << i + 1 << endl;
                printf( "In file %s\narr1[%d][%d] = %d\nIn file %s\narr2[%d][%d] = %d\n\n", fileName1,length, i + 1, arr1[i], fileName2, length, i + 1, arr2[i] );
                //break;
                //return 0;
            }
        }
    }
    delete fileName1;
    delete fileName2;
    if( cnt == 0 )
    {
        cout << "These two pictures come to one!" << endl;
    }

    delete fp1;
    delete fp2;
    delete resultTXT;
 }


int main(int argc,char *argv[])  
{ 
    
    OperateBMP OBMP;
    OBMP.compareBMP();
     
    return 0;  
}

猜你喜欢

转载自blog.csdn.net/u25th_engineer/article/details/87216878