我們這一節用代碼實現,把字符串藏入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文本插入到圖片里面去。
新聞熱點
疑難解答