将保存重要信息,如银行卡密码的文本文件隐藏到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的更多相关文章

  1. [Data Structure] Bit-map空间压缩和快速排序去重

    Bit-map是一种很巧妙的数据存储结构.所谓的Bit-map就是用一个bit位来标记某个元素对应的Value,而Key即是该元素.由于采用了Bit为单位来存储数据,可以大大节省存储空间.Bit-ma ...

  2. 转:Hide data inside pointers(在指针中隐藏数据)

    该文介绍了如何使用指针中一些未使用的位来隐藏一些数据. When we write C code, pointers are everywhere. We can make a little extr ...

  3. 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 ...

  4. android 通过uri获取bitmap图片并压缩

    很多人在调用图库选择图片时会在onActivityResult中用Media.getBitmap来获取返回的图片,如下: Uri mImageCaptureUri = data.getData(); ...

  5. python字符串格式化方法 format函数的使用

      python从2.6开始支持format,新的更加容易读懂的字符串格式化方法, 从原来的% 模式变成新的可读性更强的 花括号声明{}.用于渲染前的参数引用声明, 花括号里可以用数字代表引用参数的序 ...

  6. Objects and Data Structures

    Date Abstraction Hiding implementation is not just a matter of putting a layer of fucntions between ...

  7. BitMap排序

    问题描述:       BitMap排序思想:             用1bit位标记某个元素对应的值       优点:             效率高,不允许进行比较和移位            ...

  8. Bit-Map

    昨日读July大神<教你如何迅速秒杀掉:99%的海量数据处理面试题>博客,有这么一题与大家分享: 给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断 ...

  9. 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 ...

随机推荐

  1. TLS握手、中断恢复与证书中心的原因

    在双方都拿到随机数A.B.C后,将会使用这三个随机数生成一个对话密钥,然后使用该对话密钥进行对称加密通信,这种方式我们可以看到,安全性取决于随机数C的加密,前面的几个都是明文传的,这里就取决于服务器的 ...

  2. C++引用和const引用、常量指针、指针常量

    1.引用.常量引用 引用主要被用做函数的形式参数--通常将类对象传递给一个函数. 引用在内部存放的是一个对象的地址,它是该对象的别名.引用不占用内存,因为取地址引用的值和被引用变量的地址相同.但是ob ...

  3. oracle数据库调整字段顺序

    oracle数据库调整字段顺序 https://blog.csdn.net/xiaobaixie/article/details/77892034

  4. AUTEL MaxiSYS Pro MS908P Diagnostic System with WiFi Update Online

    The MaxiSYS? Pro has been designed to be the go-to tool for the professional technician who performs ...

  5. k-means算法 - 数据挖掘算法(5)

    (2017-05-02 银河统计) k-means算法,也被称为k-平均或k-均值,是数据挖掘技术中一种广泛使用的聚类算法. 它是将各个聚类子集内的所有数据样本的均值作为该聚类的代表点,算法的主要思想 ...

  6. 提bug

    大多数公司都是用bugzilla来管理bug,也有的公司使用内部开发的bug管理平台.这里以bugzilla为例,我最不爽的是提bug的时候既要选择severity(严重级别)又要选择priority ...

  7. Python Semaphore

    Semaphore信号量的使用 信号量: 互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人 ...

  8. 剑指offer(64)滑动窗口中的最大值

    题目描述 给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值.例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6 ...

  9. Learning-Python【13】:迭代器和生成器

    一.什么是迭代器 迭代指的是一个重复的过程,每一次重复都是基于上一次的结果而来的 # 这里的循环也是一个迭代,每次基于上一次的结果而取值 li = 'hello' i = 0 while i < ...

  10. [转载]Windows系统的错误报告保存在哪个文件夹里?

    转自:http://www.xitonghe.com/jiaocheng/xp-786.html   Windows系统的错误报告保存在哪个文件夹里? 发布时间:2014-10-31 20:52:20 ...