Hide Data into bitmap with ARGB8888 format
将保存重要信息,如银行卡密码的文本文件隐藏到ARGB8888的A通道。
bitmap.h
#ifndef BMP_H
#define BMP_H #include <fstream>
#include <string>
#include <iostream> #define DEBUG 0 #define LOG std::cout
#define HEX std::hex
#define DEC std::dec #define FLAG_0 (0xFF)
#define FLAG_1 (0xEE)
#define FLAG_2 (0xDD)
#define FLAG_3 (0xCC) #define DATA_CODE (0xCC) #define BYTE_PER_PIXEL (4) #pragma pack(push, 1)
typedef struct
{
uint16_t bfType; // Type of bitmap, in windows, always 'BM'
uint32_t bfSize; // Size of the bitmap file
uint16_t bfReserved1; // reserved feild
uint16_t bfReserved2; // reserved feild
uint32_t bfOffBits; // the start address of the bitmap data
}BMP_FILE_HEADER; typedef struct
{
uint32_t biSize; // size of this struct
uint32_t biWidth; // image width, unit is pixel
uint32_t biHeight; // image height, unit is pixel
uint16_t biPlanes; // alsways 1
uint16_t biBitCount; // color depth of the image, 1, 4, 8, 16, 24 and 32
uint32_t biCompression; // compression type, 0=no compress, 1=RLE8 compress
// 2=RLE4 compress, 3=pixel color mask
uint32_t biSizeImage; // pixel data size of the image
uint32_t biXPelsPerMeter; // H resolution, pixel per meter
uint32_t biYPelsPerMeter; // V resolution, pixel per meter
uint32_t biClrUsed; // color number that used, 0=all color
uint32_t biClrImportant; // important color amount, 0=all color important
}BMP_INFO_HEADER;
#pragma pacn(pop) class Bitmap
{
private:
BMP_FILE_HEADER m_fileHeader;
BMP_INFO_HEADER m_infoHeader; std::string m_bmpPath;
bool m_parseFlag;
public:
Bitmap(std::string path);
~Bitmap();
bool bmpParse();
uint32_t getBmpSize();
uint32_t getBmpDataAddr();
std::string getBmpPath();
uint32_t getBmpPixelNum();
}; class DataHider
{
private:
uint8_t m_flags[4];
uint8_t m_length[4];
Bitmap m_bitmapHeader;
std::string m_dataFilePath; bool isAHider();
uint32_t getFileSize(std::ifstream &in);
bool readTransByte(std::fstream &file, uint8_t &val, int pos);
bool writeTransByte(std::fstream &file, uint8_t val, int pos);
void length2Byte(uint32_t length);
uint32_t byte2Length();
public:
DataHider(std::string dataPath, std::string bmpPath);
~DataHider();
bool doEncode();
bool doDecode();
}; #endif // BMP_H
bitmap.cpp
#include "bitmap.h" Bitmap::Bitmap(std::string path)
: m_fileHeader(), m_infoHeader(), m_bmpPath(path), m_parseFlag(false)
{
} Bitmap::~Bitmap()
{
} bool Bitmap::bmpParse()
{
std::ifstream in;
in.open(m_bmpPath, std::ios::binary); in.read((char *)&m_fileHeader, sizeof(m_fileHeader));
/*char * p = (char *)&m_fileHeader;
for(uint32_t i=0; i<sizeof(m_fileHeader); ++i)
{
in.read(p, 1);
LOG << HEX << (int)*p << " ";
++p;
}*/
if( !in.good() )
{
LOG << "read bitmap file head error!\n";
in.close();
return false;
} in.read((char *)&m_infoHeader, sizeof(m_infoHeader));
/* LOG << "read bitmap information header!\n";
p = (char *)&m_infoHeader;
for(uint32_t i=0; i<sizeof(m_infoHeader); ++i)
{
in.read(p, 1);
LOG << HEX << (int)*p << " ";
++p;
}*/
if( !in.good() )
{
LOG << "read bitmap information header error!\n";
in.close();
return false;
} in.close();
m_parseFlag = true; #if 1 == DEBUG
LOG << "Bitmap file header:"
<< "\nbfType: " << HEX << (int)m_fileHeader.bfType
<< "\nbfSize: " << (int)m_fileHeader.bfSize
<< "\nbfReserved1: " << (int)m_fileHeader.bfReserved1
<< "\nbfReserved2: " << (int)m_fileHeader.bfReserved2
<< "\nbfOffBits: " << (int)m_fileHeader.bfOffBits
<< "\nBitmap information header:"
<< "\nbiSize: " << (int)m_infoHeader.biSize << DEC << "\n";
#endif return true;
} uint32_t Bitmap::getBmpSize()
{
if(!m_parseFlag)
{
LOG << "please do bitmap parse first!\n";
}
return m_fileHeader.bfSize;
} std::string Bitmap::getBmpPath()
{
return m_bmpPath;
} uint32_t Bitmap::getBmpDataAddr()
{
if(!m_parseFlag)
{
LOG << "please do bitmap parse first!\n";
}
return m_fileHeader.bfOffBits;
} uint32_t Bitmap::getBmpPixelNum()
{
return m_infoHeader.biWidth * m_infoHeader.biHeight;
} DataHider::DataHider(std::string dataPath, std::string bmpPath)
: m_bitmapHeader(bmpPath), m_dataFilePath(dataPath)
{
} DataHider::~DataHider()
{
} bool DataHider::isAHider()
{
return (m_flags[0] == FLAG_0) &
(m_flags[1] == FLAG_1) &
(m_flags[2] == FLAG_2) &
(m_flags[3] == FLAG_3);
} uint32_t DataHider::getFileSize(std::ifstream &in)
{
if(!in.good())
{
LOG << "the data file has some error.\n";
return false;
} uint32_t pos = in.tellg();
in.seekg(0, std::ios_base::end);
uint32_t size = in.tellg();
in.seekg(pos, std::ios_base::beg); return size;
} bool DataHider::readTransByte(std::fstream &file, uint8_t &val, int pos)
{
file.seekg(m_bitmapHeader.getBmpDataAddr()+BYTE_PER_PIXEL*pos, std::ios_base::beg);
#if DEBUG == 1
LOG << "pos " << HEX << m_bitmapHeader.getBmpDataAddr()+BYTE_PER_PIXEL*pos << "\n";
#endif
file.read((char *)&val, 1);
return file.good();
} bool DataHider::writeTransByte(std::fstream &file, uint8_t val, int pos)
{
file.seekp(m_bitmapHeader.getBmpDataAddr()+BYTE_PER_PIXEL*pos, std::ios_base::beg);
file.write((char *)&val, 1);
return file.good();
} void DataHider::length2Byte(uint32_t length)
{
for(uint32_t i=0; i<4; ++i)
m_length[i] = (uint8_t)(length >> (i*8)) & 0xFF;
#if DEBUG == 1
LOG << "length: " << length << "\n"
<< (int)m_length[0] << " "
<< (int)m_length[1] << " "
<< (int)m_length[2] << " "
<< (int)m_length[3] << "\n";
#endif
} uint32_t DataHider::byte2Length()
{
uint32_t length = 0;
uint32_t temp;
for(uint32_t i=0; i<4; ++i)
{
temp = m_length[i];
#if DEBUG == 1
LOG << "temp: " << temp << "\n";
#endif
temp <<= (i*8);
#if DEBUG == 1
LOG << "temp: " << temp << "\n";
#endif
length += temp;
} #if DEBUG == 1
LOG << "length: " << length << "\n";
#endif return length;
} bool DataHider::doEncode()
{
m_bitmapHeader.bmpParse(); std::ifstream dataFile;
dataFile.open(m_dataFilePath, std::ios::binary);
if(!dataFile.good())
{
LOG << "open " << m_dataFilePath << " failed!\n";
return false;
}
uint32_t dataSize = getFileSize(dataFile);
if(dataSize > m_bitmapHeader.getBmpPixelNum() + 8) // flag size add length size
{
LOG << "data is too big to save into the bitmap!\n";
dataFile.close();
return false;
} std::fstream bmpFile;
bmpFile.open(m_bitmapHeader.getBmpPath(), std::ios_base::binary|
std::ios_base::out|std::ios_base::in);
// |std::ios_base::ate|std::ios_base::app
if(!bmpFile.good())
{
LOG << "open " << m_bitmapHeader.getBmpPath() << " failed!\n";
dataFile.close();
return false;
}
dataFile.seekg(0, std::ios_base::beg); // flags
m_flags[0] = FLAG_0;
m_flags[1] = FLAG_1;
m_flags[2] = FLAG_2;
m_flags[3] = FLAG_3; for(uint32_t i=0; i<4; ++i)
writeTransByte(bmpFile, m_flags[i], i); // length
length2Byte(dataSize); for(uint32_t i=0; i<4; ++i)
writeTransByte(bmpFile, m_length[i], i+4); // pos start at the 8th pixel
int pos = 0;
uint8_t data;
while(pos < dataSize)
{
dataFile.read((char *)&data, 1);
#if DEBUG == 1
LOG << HEX << (int)data << " ";
#endif
data ^= DATA_CODE;
writeTransByte(bmpFile, data, pos+8);
++pos;
} bmpFile.close();
dataFile.close();
return true;
} bool DataHider::doDecode()
{
m_bitmapHeader.bmpParse(); std::fstream bmpFile;
bmpFile.open(m_bitmapHeader.getBmpPath(), std::ios_base::binary|std::ios_base::in);
if(!bmpFile.good())
{
LOG << "open " << m_bitmapHeader.getBmpPath() << " failed!\n";
return false;
}
bmpFile.seekg(0, std::ios_base::beg); // flags
for(uint32_t i=0; i<4; ++i)
{
readTransByte(bmpFile, m_flags[i], i);
#if DEBUG
LOG << HEX << (int)m_flags[i] << " ";
#endif
} if( !isAHider() )
{
LOG << "this bitmap is not a hider file!\n";
bmpFile.close();
return false;
} // length
for(uint32_t i=0; i<4; ++i)
readTransByte(bmpFile, m_length[i], i+4); #if DEBUG == 1
LOG << (int)m_length[0] << " "
<< (int)m_length[1] << " "
<< (int)m_length[2] << " "
<< (int)m_length[3] << "\n";
#endif uint32_t dataSize = byte2Length(); std::ofstream dataFile;
dataFile.open(m_dataFilePath, std::ios::binary);
if(!dataFile.good())
{
LOG << "open " << m_dataFilePath << " failed!\n";
bmpFile.close();
return false;
}
// pos start at the 8th pixel
int pos = 0;
uint8_t data;
while(pos < dataSize)
{
readTransByte(bmpFile, data, pos+8);
data ^= DATA_CODE;
dataFile.write((char *)&data, 1);
++pos; } bmpFile.close();
dataFile.close();
return true;
}
main.cpp
#include <iostream>
#include "bitmap.h"
using namespace std; int main(int argc, char **argv)
{
cout << "Hello world!" << endl; if(argc < 4)
{
cout << "please type the right command!\n"
<< "DataHider encode ./data.txt ./ARGB8888.bmp\n"
<< "or DataHider decode ./data_out.txt ./ARGB8888.bmp\n";
return -1;
} string mode = argv[1];
string dataFile = argv[2];
string bmpFile = argv[3]; if(mode == "encode")
{
cout << "encoder\n";
DataHider encoder(dataFile, bmpFile);
encoder.doEncode();
}
else if(mode == "decode")
{
cout << "decoder\n";
DataHider decoder(dataFile, bmpFile);
decoder.doDecode();
} return 0;
}
Hide Data into bitmap with ARGB8888 format的更多相关文章
- [Data Structure] Bit-map空间压缩和快速排序去重
Bit-map是一种很巧妙的数据存储结构.所谓的Bit-map就是用一个bit位来标记某个元素对应的Value,而Key即是该元素.由于采用了Bit为单位来存储数据,可以大大节省存储空间.Bit-ma ...
- 转:Hide data inside pointers(在指针中隐藏数据)
该文介绍了如何使用指针中一些未使用的位来隐藏一些数据. When we write C code, pointers are everywhere. We can make a little extr ...
- 3ds Max File Format (Part 3: The department of redundancy department; Config)
Now we'll have a look at the Config stream. It begins like follows, and goes on forever with various ...
- android 通过uri获取bitmap图片并压缩
很多人在调用图库选择图片时会在onActivityResult中用Media.getBitmap来获取返回的图片,如下: Uri mImageCaptureUri = data.getData(); ...
- python字符串格式化方法 format函数的使用
python从2.6开始支持format,新的更加容易读懂的字符串格式化方法, 从原来的% 模式变成新的可读性更强的 花括号声明{}.用于渲染前的参数引用声明, 花括号里可以用数字代表引用参数的序 ...
- Objects and Data Structures
Date Abstraction Hiding implementation is not just a matter of putting a layer of fucntions between ...
- BitMap排序
问题描述: BitMap排序思想: 用1bit位标记某个元素对应的值 优点: 效率高,不允许进行比较和移位 ...
- Bit-Map
昨日读July大神<教你如何迅速秒杀掉:99%的海量数据处理面试题>博客,有这么一题与大家分享: 给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断 ...
- beej's 网络编程 打包数据pack data
7.4. Serialization—How to Pack Data It's easy enough to send text data across the network, you're fi ...
随机推荐
- thymeleaf 添加语法提示
thymeleaf 添加语法提示: xmlns:th="http://www.thymeleaf.org"
- 泛型-----键值对----映射 hashmap--entry中key value 链表
connection map 集合框架 * java.util.Collection *集合与数组相似,也是可以保存一组元素,并且提供了操作元素的相关方法. *collection是所有集合的顶级接口 ...
- 各版本最新的Visual C++可再发行组件包(Redistributable Package)下载和合集
Microsoft Visual C++ 2005 Redistributable Package (x86):Microsoft Visual C++ 2005 可再发行组件包 (x86):http ...
- springmvc学习路线1-基本配置
1.第一个springmvc实例helloword 关键点拨 1.1 web.xml文件的配置 <servlet> <servlet-name>springMVC</se ...
- L2-025. 分而治之
分而治之,各个击破是兵家常用的策略之一.在战争中,我们希望首先攻下敌方的部分城市,使其剩余的城市变成孤立无援,然后再分头各个击破.为此参谋部提供了若干打击方案.本题就请你编写程序,判断每个方案的可行性 ...
- flutter_webview_plugin 无法加载网页的异常处理
Flutter 本身并未集成webview,所以当需要使用webview 的时候,使用flutter_webview_plugin插件,也就是使用的原生webview组件, flutter_webvi ...
- 安装GDB-ImageWatch ,在QT中查看图像
GDB_ImageWatch是在Linux下基于QT编写图像处理程序的调试程序. 由于并非像ImageWatch一样由官方提供,而是在github上以代码的方式进行提供,我们在使用的时候需要自己编译, ...
- onsubmit 事件
onsubmit 事件 Event 对象 定义和用法 onsubmit 事件会在表单中的确认按钮被点击时发生. 语法 onsubmit="SomeJavaScriptCode" 参 ...
- freeswqitch odbc
1.安装驱动 yum install unixODBC unixODBC-devel libtool-ltdl libtool-ltdl-devel -y yum install mysql-conn ...
- Code Pages
https://docs.microsoft.com/en-us/windows/desktop/intl/code-pages Most applications written today han ...