C/C++信息隐写术(二)之字符串藏入BMP文件

47 篇文章 38 订阅

我们这一节用代码实现,把字符串藏入BMP文件,并且能正常读取出来。

看这篇的同学请先阅读第一篇了解理论:

http://blog.csdn.net/qq78442761/article/details/54863034


下面开始进入此节:

从上一节,我们知道了Bmp文件的结构,如下图所示:


其中最关键的两个结构体BITMAPFILEHEADER和BITMAPINFOHEADER,这里面保存了这个Bmp文件的很多信息。

恰好,Windows给我们提供了这个两个结构体,如下图所示:

typedef struct tagBITMAPFILEHEADER {
        WORD    bfType;
        DWORD   bfSize;
        WORD    bfReserved1;
        WORD    bfReserved2;
        DWORD   bfOffBits;
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER{
        DWORD      biSize;
        LONG       biWidth;
        LONG       biHeight;
        WORD       biPlanes;
        WORD       biBitCount;
        DWORD      biCompression;
        DWORD      biSizeImage;
        LONG       biXPelsPerMeter;
        LONG       biYPelsPerMeter;
        DWORD      biClrUsed;
        DWORD      biClrImportant;
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;

我们在到010Editor看看(图如下):


关于高度为负的问题,在第一节已经说明,不知道的同学请从文章最上面的链接进入第一节。在此不再说明。


那么问题就简单了,现在这个程序的思路就是:

1.用C/C++代码读取图片文件里面的这两个结构体。

2.读取这个文件到内存中。

3.获取bfOffBIts,再获取alpha通道(+4)。

4.把数据拆分,插入到alpha通道。

5.保存文件。

6.读取被修改文件的alpha通道,组合成字符串。

理论就是这么简单:

下面是程序源码打包下载地址:

http://download.csdn.net/detail/qq78442761/9747338



下面是程序源码:

dwBmpSize.h

#pragma  once
#include <string>
#include <Windows.h>
using namespace std;

class CBMPHide
{
public:
	CBMPHide();
	~CBMPHide();

	bool setBmpFileName(char* szFileName);	//设置Bmp文件名

	int getBmpWidth();	//获取宽度
	int getBmpHeight();	//获取高度
	int getBmpBitCount();	//获取Bit总数
	bool save();

	bool hideString2BMP(char* szStr2Hide);	//隐藏String到BMP文件中
	void showStringInBmp(char* szBmpFIleName=NULL);	//展示
private:
	DWORD dwBmpSize;	//图片文件大小
	string sBmpFileName;
	LPBYTE pBuf;	//用于存放图片信息的内存

	BITMAPFILEHEADER* m_fileHdr;
	BITMAPINFOHEADER* m_infoHdr;
};

dwBmpSIze.cpp

#include "dwBmpSize.h"

CBMPHide::CBMPHide()
{
	sBmpFileName = "";
	pBuf = 0;
	dwBmpSize = 0;
}

CBMPHide::~CBMPHide()
{

}

bool CBMPHide::setBmpFileName(char* szFileName)
{
	this->sBmpFileName = szFileName;
	if (pBuf)	//如果已经生成就释放掉
	{
		delete[]pBuf;
	}

	HANDLE hfile = CreateFileA(szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
	if (hfile == INVALID_HANDLE_VALUE)
	{
		return false;
	}

	//和struct BITMAPFILEHEADER bmfh里面的 bfSize的大小应该是一样的。
	dwBmpSize = GetFileSize(hfile, 0);	//获取文件的大小
	pBuf = new byte[dwBmpSize];
	DWORD dwRead = 0;
	ReadFile(hfile, pBuf, dwBmpSize, &dwRead, 0);
	if (dwRead != dwBmpSize)
	{
		delete[]pBuf;
		pBuf = 0;
		return false;
	}
	CloseHandle(hfile);
	m_fileHdr = (BITMAPFILEHEADER*)pBuf;
	m_infoHdr = (BITMAPINFOHEADER*)(pBuf + sizeof(BITMAPFILEHEADER));
	return true;	//成功话就是文件的内容读取到pBuf里面
}


int CBMPHide::getBmpWidth()
{
	return m_infoHdr->biWidth;
}

int CBMPHide::getBmpHeight()
{
	return m_infoHdr->biHeight;
}

int CBMPHide::getBmpBitCount()
{
	return m_infoHdr->biBitCount;
}

bool CBMPHide::save()
{
	string sDstFileName = sBmpFileName + ".hide.bmp";
	HANDLE hfile = CreateFileA(sDstFileName.c_str(),
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		NULL,
		CREATE_ALWAYS, 0, 0);
	if (hfile == INVALID_HANDLE_VALUE)
	{
		return false;
	}

	DWORD dwWritten = 0;
	WriteFile(hfile, pBuf, dwBmpSize, &dwWritten, 0);
	if (dwBmpSize != dwWritten)
	{
		return false;
	}
	CloseHandle(hfile);
	return true;
}
//隐藏一个字符串到图片中,把字符串拆成字节,写入每个像素的alpha通道中
bool CBMPHide::hideString2BMP(char* szStr2Hide)
{
	LPBYTE pAlpha = pBuf + m_fileHdr->bfOffBits + 3;	//第一个像素的通道位置
	int nHide;	//成功隐藏的字节数

	//每次循环写入一个字节,吸入alpha通道
	//(pAlpha - pBuf) < m_fileHdr->bfSize这个是判断字符串是太大,图片不能隐藏
	for (nHide = 0; (pAlpha - pBuf) < m_fileHdr->bfSize && szStr2Hide[nHide] != 0; nHide++, pAlpha += 4)
	{
		*pAlpha = szStr2Hide[nHide];	//写入一个字节
	}

	return true;
}

void CBMPHide::showStringInBmp(char* szBmpFIleName/*=NULL*/)
{
	string sDstFileName="";
	if (szBmpFIleName == 0)
	{
		sDstFileName = sBmpFileName + ".hide.bmp";
	}
	else
		sDstFileName = szBmpFIleName;

	HANDLE hfile = CreateFileA(sDstFileName.c_str(),
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING, 0, 0);
	if (hfile == INVALID_HANDLE_VALUE)
	{
		return;
	}
	DWORD dwSize = GetFileSize(hfile, 0);
	LPBYTE pBuf1 = new byte[dwSize];

	DWORD dwRead = 0;

	ReadFile(hfile, pBuf1, dwSize, &dwRead, 0);
	CloseHandle(hfile);

	//文件内容读取到pBuf1中
	BITMAPFILEHEADER *pHdr = (BITMAPFILEHEADER *)pBuf1;
	LPBYTE pStr = pBuf1 + pHdr->bfOffBits + 3;
	char szTmp[1280];
	RtlZeroMemory(szTmp, 1280);
	for (int i = 0; i < 1280; i++)
	{
		if (*pStr == 0 || *pStr == 0xFF)
		{
			break;
		}
		szTmp[i] = *pStr;
		pStr += 4;
	}
	printf_s(szTmp);

	delete[]pBuf1;
}


main.h

#include <stdio.h>
#include "dwBmpSize.h"

int main()
{
	CBMPHide hide;
	hide.setBmpFileName("test.bmp");
	printf_s("test.bmp width:%d,height:%d,bitCount%d\n",
		hide.getBmpWidth(),
		hide.getBmpHeight(),
		hide.getBmpBitCount());
	hide.hideString2BMP("Hello Word");
	hide.save();
	hide.showStringInBmp("test.bmp.hide.bmp");
	getchar();
	return 0;
}


程序运行结果如下:

在此不一一举出。

在这里:可能出现特殊情况,比如写入了0或oxFF(判断自有数据是否结束标志)

在下面一节中,我们解决这个问题,并且,把一个不大的txt文本插入到图片里面去。



  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT1995

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值