• 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!
    ";
            in.close();
            return false;
        }
    
        in.read((char *)&m_infoHeader, sizeof(m_infoHeader));
        /*    LOG << "read bitmap information header!
    ";
        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!
    ";
            in.close();
            return false;
        }
    
        in.close();
        m_parseFlag = true;
    
        #if 1 == DEBUG
            LOG << "Bitmap file header:"
                << "
    bfType: " << HEX << (int)m_fileHeader.bfType
                << "
    bfSize: " << (int)m_fileHeader.bfSize
                << "
    bfReserved1: " << (int)m_fileHeader.bfReserved1
                << "
    bfReserved2: " << (int)m_fileHeader.bfReserved2
                << "
    bfOffBits: " << (int)m_fileHeader.bfOffBits
                << "
    Bitmap information header:"
                << "
    biSize: " << (int)m_infoHeader.biSize << DEC << "
    ";
        #endif
    
        return true;
    }
    
    uint32_t Bitmap::getBmpSize()
    {
        if(!m_parseFlag)
        {
            LOG << "please do bitmap parse first!
    ";
        }
        return m_fileHeader.bfSize;
    }
    
    std::string Bitmap::getBmpPath()
    {
        return m_bmpPath;
    }
    
    uint32_t Bitmap::getBmpDataAddr()
    {
        if(!m_parseFlag)
        {
            LOG << "please do bitmap parse first!
    ";
        }
        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.
    ";
            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 << "
    ";
        #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 << "
    "
                << (int)m_length[0] << " "
                << (int)m_length[1] << " "
                << (int)m_length[2] << " "
                << (int)m_length[3] << "
    ";
        #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 << "
    ";
        #endif
            temp <<= (i*8);
        #if DEBUG == 1
            LOG << "temp: " << temp << "
    ";
        #endif
            length += temp; 
        }
    
        #if DEBUG == 1
            LOG << "length: " << length << "
    ";
        #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!
    ";
            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!
    ";
            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!
    ";
            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!
    ";
            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!
    ";
            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] << "
    ";
        #endif
    
        uint32_t dataSize = byte2Length();
    
        std::ofstream dataFile;
        dataFile.open(m_dataFilePath, std::ios::binary);
        if(!dataFile.good())
        {
            LOG << "open " << m_dataFilePath << " failed!
    ";
            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!
    "
                 << "DataHider encode ./data.txt ./ARGB8888.bmp
    "
                 << "or DataHider decode ./data_out.txt ./ARGB8888.bmp
    ";
            return -1;
        }
    
        string mode =  argv[1];
        string dataFile = argv[2];
        string bmpFile = argv[3];
    
        if(mode == "encode")
        {
            cout << "encoder
    ";
            DataHider encoder(dataFile, bmpFile);
            encoder.doEncode();
        }
        else if(mode == "decode")
        {
            cout << "decoder
    ";
            DataHider decoder(dataFile, bmpFile);
            decoder.doDecode();
        }
    
        return 0;
    }
    

      

  • 相关阅读:
    java中的死锁现象
    Maven 创建动态web 3.0项目
    查询数据库主外键关系
    函数指针的应用学习Demo
    WCF宿主Window Service Demo
    一段小程序理解getchar和putchar
    Flash在线签名小程序,可回放,动态导出gif图片
    uninstall gitlab
    使用SCP在命令行传输文件
    Linux下网卡eth编号配置文件路径
  • 原文地址:https://www.cnblogs.com/zhanghang-BadCoder/p/8080863.html
Copyright © 2020-2023  润新知