校验两张BMP图像的RGB矩阵有多少个像素点不同
程序员文章站
2022-07-13 14:10:30
...
数据结构课设我选的的二值图像(要求是.bmp格式)数字水印,代码实现之后,我就萌生了校验一下水印信息是否编码成功的想法。经水印算法编码后的二值图像,有的被编码图与原图不存在显著的人眼上的差异。这份代码我主要是用来检测:
1、水印算法的稳健性;
2、水印算法的安全性;
3、水印算法的不可访问性;
4、水印算法的有效性。
具体用途将在课设答辩完成后,将课设代码、报告与详细说明一同写到博客里。
另外,代码里面的析构函数如果加了那几行delete语句将引起程序运行时崩溃(RTE):或为两次释放内存。个人感觉问题出在 void OperateBMP::compareBMP() 函数里的两个OperateBMP类的调用,具体原因未分析。如有朋友有何高见,欢迎指教!
从图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;
}
上一篇: C语言 实现两张图片的拼接