将保存重要信息,如银行卡密码的文本文件隐藏到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. 基于CSS属性display:table的表格布局的使用

    项目改造中遇到DIV+CSS实现的table,新需求需要在表格使用单元格合并,网上调查返现CSS display:table实现的table表格,没有单元格的属性和样式,经过一番思考,曲折现实了单元格 ...

  2. 隐藏非选中的checkBox

    //隐藏非选中的checkBox function onlyCheckBox(){ $("#dtlTable tr:gt(0)").each(function(i) { var c ...

  3. Tensorflow serving with Kubernetes

    1.Build docker image 由于自己build镜像总是遇到问题,此处暂时借用dockerhub上的一个镜像 docker.io/mochin/tensorflow-serving 将此镜 ...

  4. codeforces #305 C Mike and Foam

    首先我们注意到ai<=50w 因为2*3*5*7*11*13*17=510510 所以其最多含有6个质因子 我们将每个数的贡献分离, 添加就等于加上了跟这个数相关的互素对 删除就等于减去了跟这个 ...

  5. 写Java代码分别使堆溢出,栈溢出

    首先要搞清楚堆栈里放的什么东西: 栈存储运行时声明的变量——对象引用(或基础类型, primitive)内存空间,堆分配每一个对象内容(实例)内存空间. 一个变量可以先后指向多个对象实例:数组.链表等 ...

  6. 微信小程序,天气预报(百度地图开放平台API)

    小程序看似一种全新的东西,但好在基本上就是曾经HTML,CSS,JS的一个微变版本. 语法和之前一样.只是一些用法和名字(标签)发生了一些变化. 小程序主要就四种扩展名的文件:js,json,wxml ...

  7. Codeforces 333E Summer Earnings - bitset

    题目传送门 传送门I 传送门II 传送门III 题目大意 给定平面上的$n$个点,以三个不同点为圆心画圆,使得圆两两没有公共部分(相切不算),问最大的半径. 显然答案是三点间任意两点之间的距离的最小值 ...

  8. opencv3.0之后IPLimage转换成MAT的问题

    转自http://www.cnblogs.com/edver/p/5187190.html IplImage * ipl = ...; cv::Mat m = cv::cvarrToMat(ipl); ...

  9. [pytorch修改]npyio.py 实现在标签中使用两种delimiter分割文件的行

    from __future__ import division, absolute_import, print_function import io import sys import os impo ...

  10. Bytom信息上链教程

    比原项目仓库: Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockchain/bytom 用比原链 ...