lsbanalysisdoc.cpp

来自「信息隐藏中用于数字隐写的常用算法:LSB替换LSB匹配,包括随机的和排序的,以及」· C++ 代码 · 共 1,714 行 · 第 1/4 页

CPP
1,714
字号
// LSBAnalysisDoc.cpp : implementation of the CLSBAnalysisDoc class
//

#include "stdafx.h"
#include "LSBAnalysis.h"

#include "LSBAnalysisDoc.h"
#include "RatioDlg.h"
#include "xxxxx.h"

#include <math.h>

#include "../cximage/ximage.h"
#include "../cximage/xfile.h"

#include "steg_detect/StatTest.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CLSBAnalysisDoc

IMPLEMENT_DYNCREATE(CLSBAnalysisDoc, CDocument)

BEGIN_MESSAGE_MAP(CLSBAnalysisDoc, CDocument)
	//{{AFX_MSG_MAP(CLSBAnalysisDoc)
	ON_COMMAND(ID_EMBED_LSBMATCH, OnEmbedLsbmatch)
	ON_COMMAND(ID_EMBED_LSBMATCH2, OnEmbedLsbmatch2)
	ON_COMMAND(ID_EXTRACT_LSBMATCH, OnExtractLsbmatch)
	ON_COMMAND(ID_EXTRACT_LSBMATCH2, OnExtractLsbmatch2)
	ON_COMMAND(ID_EMBED_LSBMATCH3, OnEmbedLsbmatch3)
	ON_COMMAND(ID_EMBED_LSBMATCH4, OnEmbedLsbmatch4)
	ON_COMMAND(ID_EMBED_LSBREPLACE, OnEmbedLsbreplace)
	ON_COMMAND(ID_EMBED_LSBREPLACE2, OnEmbedLsbreplace2)
	ON_COMMAND(ID_DETECT_HMM, OnDetectHmm)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CLSBAnalysisDoc construction/destruction

CLSBAnalysisDoc::CLSBAnalysisDoc()
{
	// TODO: add one-time construction code here
	image = 0;
	m_bModified = FALSE;
	nImgType = 0;
	m_strPathName = _T("");
}

CLSBAnalysisDoc::~CLSBAnalysisDoc()
{
	if (image) delete image;
}

BOOL CLSBAnalysisDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	// TODO: add reinitialization code here
	// (SDI documents will reuse this document)

	return TRUE;
}



/////////////////////////////////////////////////////////////////////////////
// CLSBAnalysisDoc serialization

void CLSBAnalysisDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}

/////////////////////////////////////////////////////////////////////////////
// CLSBAnalysisDoc diagnostics

#ifdef _DEBUG
void CLSBAnalysisDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CLSBAnalysisDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG


/////////////////////////////////////////////////////////////////////////////
// CLSBAnalysisDoc commands
CString CLSBAnalysisDoc::FindExtension(const CString& name)
{
	int len = name.GetLength();
	int i;
	for (i = len-1; i >= 0; i--){
		if (name[i] == '.'){
			return name.Mid(i+1);
		}
	}
	return CString("");
}
//////////////////////////////////////////////////////////////////////////////
int CLSBAnalysisDoc::FindType(const CString& ext)
{
	int type = 0;
	if (ext == "bmp")					type = CXIMAGE_FORMAT_BMP;
#if CXIMAGE_SUPPORT_JPG
	else if (ext=="jpg"||ext=="jpeg")	type = CXIMAGE_FORMAT_JPG;
#endif
#if CXIMAGE_SUPPORT_GIF
	else if (ext == "gif")				type = CXIMAGE_FORMAT_GIF;
#endif
#if CXIMAGE_SUPPORT_PNG
	else if (ext == "png")				type = CXIMAGE_FORMAT_PNG;
#endif
#if CXIMAGE_SUPPORT_MNG
	else if (ext=="mng"||ext=="jng")	type = CXIMAGE_FORMAT_MNG;
#endif
#if CXIMAGE_SUPPORT_ICO
	else if (ext == "ico")				type = CXIMAGE_FORMAT_ICO;
#endif
#if CXIMAGE_SUPPORT_TIF
	else if (ext=="tiff"||ext=="tif")	type = CXIMAGE_FORMAT_TIF;
#endif
#if CXIMAGE_SUPPORT_TGA
	else if (ext=="tga")				type = CXIMAGE_FORMAT_TGA;
#endif
#if CXIMAGE_SUPPORT_PCX
	else if (ext=="pcx")				type = CXIMAGE_FORMAT_PCX;
#endif
#if CXIMAGE_SUPPORT_WBMP
	else if (ext=="wbmp")				type = CXIMAGE_FORMAT_WBMP;
#endif
#if CXIMAGE_SUPPORT_WMF
	else if (ext=="wmf"||ext=="emf")	type = CXIMAGE_FORMAT_WMF;
#endif
#if CXIMAGE_SUPPORT_J2K
	else if (ext=="j2k"||ext=="jp2")	type = CXIMAGE_FORMAT_J2K;
#endif
#if CXIMAGE_SUPPORT_JBG
	else if (ext=="jbg")				type = CXIMAGE_FORMAT_JBG;
#endif
#if CXIMAGE_SUPPORT_JP2
	else if (ext=="jp2"||ext=="j2k")	type = CXIMAGE_FORMAT_JP2;
#endif
#if CXIMAGE_SUPPORT_JPC
	else if (ext=="jpc"||ext=="j2c")	type = CXIMAGE_FORMAT_JPC;
#endif
#if CXIMAGE_SUPPORT_PGX
	else if (ext=="pgx")				type = CXIMAGE_FORMAT_PGX;
#endif
#if CXIMAGE_SUPPORT_RAS
	else if (ext=="ras")				type = CXIMAGE_FORMAT_RAS;
#endif
#if CXIMAGE_SUPPORT_PNM
	else if (ext=="pnm"||ext=="pgm"||ext=="ppm") type = CXIMAGE_FORMAT_PNM;
#endif
	else type = CXIMAGE_FORMAT_UNKNOWN;

	return type;
}

/////////////////////////////////////////////////////////////////////////////
// CLSBAnalysisDoc commands

BOOL CLSBAnalysisDoc::OnOpenDocument(LPCTSTR lpszPathName) 
{
//	if (!CDocument::OnOpenDocument(lpszPathName))
//		return FALSE;
	
	m_strPathName = CString(lpszPathName);
	CString ext(FindExtension(m_strPathName));
	ext.MakeLower();
	if (ext == "") return FALSE;

	nImgType = FindType(ext);

	image = new CxImage(m_strPathName, nImgType);

	if (!image->IsValid()){
		AfxMessageBox(image->GetLastError());
		delete image;
		image = NULL;
		return FALSE;
	}

	UpdateAllViews(NULL,WM_USER_NEWIMAGE);

	//multiple images (TIFF/ICO)
	if (image->GetNumFrames()>1){
		CString s;
		s.Format("File with %d images. Read all?",image->GetNumFrames());
		if (AfxMessageBox(s,MB_OKCANCEL)==IDOK){
			
			int j; // points to the document name
			for(j=strlen(m_strPathName)-1;j>=0;j--){
				if (m_strPathName[j]=='\\'){	j++; break;	}
			}
			// create the documents for the other images
			for(int i=1;i<image->GetNumFrames();i++){
				CLSBAnalysisDoc *NewDoc=(CLSBAnalysisDoc*)((CLSBAnalysisApp*)AfxGetApp())->LSBAnalysisTemplate->OpenDocumentFile(NULL);
				if (NewDoc)	{
					CxImage *newImage = new CxImage();
					newImage->SetFrame(i);
					newImage->Load(m_strPathName, nImgType);
					NewDoc->image = newImage;
					CString s;
					s.Format("%s (%d)",m_strPathName.Mid(j),i+1);
					NewDoc->SetTitle(s);
					NewDoc->UpdateAllViews(NULL,WM_USER_NEWIMAGE);
				}
			}
		}
	}

	return TRUE;
}

BOOL CLSBAnalysisDoc::OnSaveDocument(LPCTSTR lpszPathName) 
{
	CString filename(lpszPathName);
	CString ext(FindExtension(filename));
	ext.MakeLower();
	if (ext == "") return FALSE;

	int type = FindType(ext);
	if (type == CXIMAGE_FORMAT_UNKNOWN) return FALSE;

	bool retval;
	retval = image->Save(filename, type);
	if (retval) return TRUE;
	AfxMessageBox(image->GetLastError());

	return FALSE;	
//	return CDocument::OnSaveDocument(lpszPathName);
}


//////////////////////////////////////////////////////////////////////////////
BOOL CLSBAnalysisDoc::DoSave(LPCTSTR pszPathName, BOOL bReplace /*=TRUE*/)
{
	if (!image)	return FALSE;

	CString newName = pszPathName;
	BOOL bModified = IsModified();

	BOOL bSaveAs = FALSE;
	if (newName.IsEmpty()) bSaveAs = TRUE;
	else if (!theApp.GetWritableType(image->GetType()))	bSaveAs = TRUE;

	if (bSaveAs){
		newName = m_strPathName;
		if (bReplace && newName.IsEmpty()){
			newName = m_strTitle;
			int iBad = newName.FindOneOf(_T("#%;/\\"));    // dubious filename
			if (iBad != -1)	//newName.ReleaseBuffer(iBad);
				newName = "UntitledImage";

			// append the default suffix if there is one
			if (image->GetType()) newName += theApp.GetExtFromType(image->GetType()).Mid(1,4);
		}

		int nDocType = image->GetType();
		if (!theApp.PromptForFileName(newName, 
			bReplace ? AFX_IDS_SAVEFILE : AFX_IDS_SAVEFILECOPY,
			OFN_HIDEREADONLY | OFN_PATHMUSTEXIST, FALSE, &nDocType))
		{
			return FALSE;       // don't even try to save
		}
	}

	BeginWaitCursor();
	if (!OnSaveDocument(newName)){
		if (pszPathName == NULL){
			// be sure to delete the file
			TRY 
			{
				CFile::Remove(newName);
			}
			CATCH_ALL(e)
			{
				TRACE0("Warning: failed to delete file after failed SaveAs\n");
			}
			END_CATCH_ALL
		}
		EndWaitCursor();
		return FALSE;
	}

	EndWaitCursor();
	if (bReplace) {
		// Reset the title and change the document name
		SetPathName(newName, TRUE);
		ASSERT(m_strPathName == newName); // must be set
	}
	else // SaveCopyAs
	{
		SetModifiedFlag(bModified);
	}
	return TRUE;        // success
}


//..........................................................//
//                 单文件随机LSB Match嵌入                  //
//..........................................................//
void CLSBAnalysisDoc::OnEmbedLsbmatch() 
{
	//确保打开文件不为空
	ASSERT(m_strPathName != _T(""));

//................得到嵌入率和密码..................
	CRatioDlg RatioDlg;
	float fRatio;
	int   nSeed;
	if(RatioDlg.DoModal()==IDOK)
	{
		fRatio = RatioDlg.m_fRatio;
		nSeed = RatioDlg.m_key;
	}
	else
	{
		fRatio = 1.0;
		nSeed = 12;
	}

//................得到图像基本信息....................
	DWORD dwHeight = image->GetHeight();           //高
	DWORD dwWidth = image->GetWidth();             //宽
	DWORD dwEffWidth  = image->GetEffWidth();      //实际宽度,对灰度图象为4倍数后的宽度;对彩色图像,为灰度图象宽度的3倍
	DWORD dwImgSize  = dwHeight * dwEffWidth;      //图像数据大小
	DWORD dwColors = image->GetNumColors();        //颜色数
	WORD  wBpp = image->GetBpp();                  //位数


	BYTE* pImg  = NULL;                 //图像数据指针
	pImg = image->GetBits();             

	BYTE* pData = NULL;				 //待嵌入数据指针
	pData = ReadPRNData(dwImgSize);       
	if (pData == NULL)
		return;

//.................得到图像置乱的排序...................
	int* m_pImgPerm = NULL;
	m_pImgPerm = new int[dwImgSize];
	memset(m_pImgPerm, 0, dwImgSize * sizeof(int));
	srand(nSeed);
//	srand( (unsigned)time( NULL ) ); 
	Rand_Perm(m_pImgPerm, dwImgSize);

//.................随机LSB Match嵌入....................
	LSBMatchEmbed(pImg, pData, m_pImgPerm, dwImgSize, fRatio);

//.................另存为新的图像文件...................
	CString m_strPrefix = _T("");
	m_strPrefix.Format("_Random_%d", int(fRatio * 100));
	char cDrive[_MAX_DRIVE];              //驱动器名字符串
	char cDir  [_MAX_DIR];                //子路径字符串   
    char cFname[_MAX_FNAME];              //纯文件名字符串
    char cExt  [_MAX_EXT];                //后缀名字符串
	char cPath [_MAX_DRIVE + _MAX_DIR];   //全路径名字符串

	//从文件全名中分割得到驱动名和子路径
	_splitpath((LPCTSTR)m_strPathName, cDrive, cDir, cFname, cExt);
	strcpy(cPath, cDrive);
	strcat(cPath, cDir);
	CString m_strSaveName = (CString)cPath + (CString)cFname + m_strPrefix + (CString)cExt;

	memcpy(image->info.pImage, pImg, dwHeight * dwEffWidth);
	image->Save(m_strSaveName, nImgType);    
	
//	m_bModified = TRUE;
//	UpdateAllViews(NULL, WM_USER_NEWIMAGE);

	if (pData != NULL)
	{	delete []pData;	pData = NULL;	}
	if (m_pImgPerm != NULL)
	{	delete []m_pImgPerm; m_pImgPerm = NULL;	}

}


//..........................................................//
//                 单文件序贯LSB Match嵌入                  //
//..........................................................//
void CLSBAnalysisDoc::OnEmbedLsbmatch2() 
{

	//确保打开文件不为空
	ASSERT(m_strPathName != _T(""));

//...........得到嵌入率和密码,密码作为种子数..................
	CRatioDlg RatioDlg;
	float fRatio;
	int   nSeed;
	
	//得到嵌入率和密码
	if(RatioDlg.DoModal()==IDOK)
	{
		fRatio = RatioDlg.m_fRatio;
		nSeed = RatioDlg.m_key;
	}
	else
	{
		fRatio = 1.0;
		nSeed = 12;
	}

//.................得到图像基本信息..........................
	DWORD dwHeight = image->GetHeight();           //高
	DWORD dwWidth = image->GetWidth();             //宽
	DWORD dwEffWidth  = image->GetEffWidth();      //实际宽度
	DWORD dwImgSize  = dwHeight * dwEffWidth;      //图像数据大小
	DWORD dwColors = image->GetNumColors();        //颜色数

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?