bmp file dump source code(I write)

/*  showbmp.cxx **************************************************************************/
#include
#include "bmp.hxx"
#include "util.hxx"

using namespace std;
using namespace dzb_image;

int main(int argc, char *argv[])
{
        CBmp my_bmp;
       
        if( argc != 2 ) return FAILED;


        if( my_bmp.read_file(argv[1]) == FAILED ) return FAILED;

        my_bmp.dump_header();
        my_bmp.convert_YCrCb();
       
        return SUCCESSED;
}
/***********************************************************************************************************/

/* bmp.hxx ***********************************************************************************************/
#include
#include

#ifndef BMP_HXX
#define BMP_HXX

using namespace std;

namespace dzb_image {
       
        typedef unsigned char UCHAR;
        typedef unsigned long ULONG;
        typedef unsigned short USHORT;

        // struct RGBQuad
        struct RGBQuad {
                char blud;
                char green;
                char red;
                char res;
        };

        // struct Palette
        struct Palette {
                int num;
                struct RGBQuad pRGBQuads;
        };

        // struct BmpFileHeader
        struct BmpFileHeader {
                USHORT m_file_id;
                ULONG m_file_size;
                ULONG m_reserved;
                ULONG m_bmp_data_offset;
        } __attribute__ ((packed));

        // struct BmpInfoHeader
        struct BmpInfoHeader {               
                ULONG m_bmp_header_size;
                ULONG m_width;
                ULONG m_height;
                USHORT m_planes;
                USHORT m_bits_per_pixel;
                ULONG m_compression;
                ULONG m_bmp_data_size;
                ULONG m_HResolution;
                ULONG m_VResolution;
                ULONG m_colors;
                ULONG m_imp_colors;
        } __attribute__ ((packed));

        // class CBmp
        class CBmp {
        private:
#define FILE_NAME_LEN 63
                enum { BM = 0x424d, BI_RGB = 0, BI_RLE8 = 1, BI_RLE4 = 2, BI_BITFIELDS = 3 };
                char m_filename[FILE_NAME_LEN + 1];
                ifstream m_bmpstream;
                struct BmpFileHeader m_bmfh;
                struct BmpInfoHeader m_bmih;
                struct Palette m_palette;
                UCHAR *m_bmpdata;
                UCHAR *m_ycbcr;
        public:
                CBmp() {
                        memset(m_filename, 0, FILE_NAME_LEN + 1);
                        memset(&m_bmfh, 0, sizeof(m_bmfh));
                        memset(&m_bmih, 0, sizeof(m_bmih));
                        memset(&m_palette, 0, sizeof(m_palette));
                        m_bmpdata = NULL;
                        m_ycbcr = NULL;
                }

                ~CBmp() {
                        m_bmpstream.close();
                        if( m_bmpdata != NULL ) delete []m_bmpdata;
                        if( m_ycbcr != NULL ) delete []m_ycbcr;
                }

                int read_file(char* file);

                void convert_YCrCb();
                void dump_header();
                void dump_data();
        };
}

/* bmp.cxx **********************************/
#include
#include

#include "bmp.hxx"
#include "util.hxx"

using namespace std;
using namespace dzb_image;


/*
 * just deal with bmp file with:
 * compression = 0
 * bits per pixel = 24
 * ( no palette )
 */
int CBmp::read_file(char *file)
{
        int ret = SUCCESSED;
        strncpy(m_filename, file, FILE_NAME_LEN);

        m_bmpstream.open(m_filename, ios::in | ios::binary);
        assert(m_bmpstream);

        // read the bmp file header
        m_bmpstream.read((char*)&m_bmfh, sizeof(m_bmfh));
        BitOrder::ch_word(&m_bmfh.m_file_id);

        if( m_bmfh.m_file_id != BM ) {
                ret = FAILED;
                return ret;
        }

        // read the bmp info header
        m_bmpstream.read((char*)&m_bmih, sizeof(m_bmih));

        // read the palette, if exist
        // re-sum the Image size field
        if( m_bmih.m_compression == BI_RGB ) {
                switch (m_bmih.m_bits_per_pixel) {
                case 1:
                case 4:
                case 8:
                case 16:
                case 24:
                case 32:
                        m_bmih.m_bmp_data_size = ( ( (m_bmih.m_width * m_bmih.m_bits_per_pixel + 31) >> 5 ) << 2) * m_bmih.m_height;

                        // set palette
                        if( m_bmih.m_bits_per_pixel == 24 ) m_palette.num = 0;

                        break;
                default:
                        cout << "Illegal bits per pixel: " << m_bmih.m_bits_per_pixel << endl;
                        exit(-1);
                }
        } else {
                cout << "This bmp file is compressed, compression = " << ( m_bmih.m_compression == BI_RLE8 ? "BI_RLE8" : (m_bmih.m_compression == BI_RLE4 ? "BI_RLE4" : "BI_BITFIELDS") ) << endl;
        }

        // read the bitmap data
        if( m_palette.num == 0 && m_bmih.m_compression == BI_RGB && m_bmih.m_bits_per_pixel == 24 ) {

                if( m_bmpdata != NULL ) {
                        delete []m_bmpdata;
                        m_bmpdata = NULL;
                }

                if( m_ycbcr != NULL ) {
                        delete []m_ycbcr;
                        m_ycbcr = NULL;
                }
                m_bmpdata = new UCHAR[m_bmih.m_bmp_data_size];
                assert(m_bmpdata);
                m_bmpstream.read((char*)m_bmpdata, m_bmih.m_bmp_data_size);
        } else {
                cout << "Only deal with no compression, bits per pixel = 24 bmp file!" << endl;
                exit(-1);
        }

        return ret;
}

void CBmp::dump_header()
{
       
        cout << "File id: " << hex << "0x" << m_bmfh.m_file_id << endl;
        cout << dec;
        cout << "Total file size: " << m_bmfh.m_file_size << endl;
        cout << "Bitmap data offset: " <<  m_bmfh.m_bmp_data_offset << endl;
        cout << "Bmp info header size: " << m_bmih.m_bmp_header_size << endl;
        cout << "Bmp width: " << m_bmih.m_width <<  endl;
        cout << "Bmp height: " << m_bmih.m_height << endl;
        cout << "Bmp Planes: " << m_bmih.m_planes << endl;
        cout << "Bits per pixel: " << m_bmih.m_bits_per_pixel << endl;
        cout << "Is compression: " << m_bmih.m_compression << endl;
        cout << "Image size: " << m_bmih.m_bmp_data_size << endl;
        cout << "H resolution: " << m_bmih.m_HResolution << " pixel/meter" << endl;
        cout << "V resolution: " << m_bmih.m_VResolution << " pixel/meter" << endl;
        cout << "Color used: " << m_bmih.m_colors << endl;
        cout << "Important color number: " << m_bmih.m_imp_colors << endl;
}

void CBmp::dump_data()
{
        UCHAR *data = m_bmpdata;
        int i = 0;
 
        if( data != NULL ) {
                cout << endl;
                cout << hex;
                while( data <= m_bmpdata + m_bmih.m_bmp_data_size ) {
                        i++;
                        cout <<" 0x" << setw(4) << setfill('0') << (USHORT) *data;
                        if( i % 10 == 0 ) cout << endl;

                        data += sizeof(USHORT);
                }
                cout << endl;
        }
}

/*
 * convert bmp data array to YCrCb format
 */
void CBmp::convert_YCrCb()
{
        int i, j, k;

        if( m_ycbcr != NULL ) return;

        m_ycbcr = new UCHAR[m_bmih.m_bmp_data_size];
        assert(m_ycbcr);
       
        k = 0;
        for ( i = m_bmih.m_height - 1; i >= 0; i-- ) {
                // locate the first pixel
                for( j = 0; j < m_bmih.m_width; j++ ) {
                        // get red, blue, green component
                        UCHAR red, blue, green;
                        UCHAR *base;
                        base = &m_bmpdata[i * m_bmih.m_bmp_data_size / m_bmih.m_height + j * 3];
                        red = *base;
                        base++;
                        green = *base;
                        base++;
                        blue = *base;

                        // caculate Y, Cr, Cb for this pixel
                        m_ycbcr[k++] = (UCHAR)(0.299 * red + 0.587 * green + 0.114 * blue); // Y
                        m_ycbcr[k++] = (UCHAR)(-0.1687 * red - 0.3313 * green + 0.5 * blue + 128); // Cb
                        m_ycbcr[k++] = (UCHAR)(0.5 * red - 0.4187 * green - 0.0813 * blue + 128); // Cr

//                         cout << "Y = 0x" << hex << (USHORT)m_ycbcr[k-3] <<
//                           "         cb = 0x" << (USHORT)m_ycbcr[k-2] <<
//                           "         cr = 0x" << (USHORT)m_ycbcr[k-1] << endl;
                }
        }
}

/* util.hxx ***********************************************************************************************/
#include "bmp.hxx"
#ifndef UTIL_HXX
#define UTIL_HXX

#define SUCCESSED 0
#define FAILED 1

namespace dzb_image {
        // class BitOrder
        class BitOrder {
        public:
                static void ch_byte(UCHAR *c);
                static void ch_word(USHORT *word);
                static void ch_dword(ULONG *dword);
        };
}

#endif
/*************************************************************************************************************/
#include "util.hxx"

using namespace dzb_image;

void BitOrder::ch_byte(UCHAR *c)
{
        UCHAR lobyte = 0x0f;
       
        lobyte = *c & lobyte;
        *c = (*c >> 4) + (lobyte << 4);
}

void BitOrder::ch_word(USHORT *word)
{
        USHORT lobyte = 0xff;
       
        lobyte = *word & lobyte;
        *word = (*word >> 8) + (lobyte << 8);
}

void BitOrder::ch_dword(ULONG *dword)
{
        ULONG loword = 0xffff;

        cout << hex << "0x" << *dword << endl;

        loword = *dword & loword;
        *dword = (*dword >> 16) + (loword << 16);

        ch_word( (USHORT*)dword + 1 ); // low word
        ch_word( (USHORT*)dword ); // high word
}
/**************************************************************************************************/

/* Makefile **************************************************************************************/
showbmp: showbmp.cxx util.o bmp.o
    g++ -g showbmp.cxx bmp.o util.o  -o showbmp

util.o: util.cxx util.hxx
    g++ -g util.cxx -c -o util.o

bmp.o: bmp.cxx bmp.hxx
    g++ -g bmp.cxx -c -o bmp.o

clean:
    rm *.o showbmp

你可能感兴趣的:(unix操作系统设计与实现相关)