#ifndef __BITMAP_H #define __BITMAP_H #include "XEPrerequisites.h" #include <stdio.h> #include <string> namespace XE { /// /struct BMP_HEADER /// /brief .bmp文件 的 文件头信息 struct BITMAP_HEADER { char _id1; ///< 两字节的内容用来识别位图的类型:‘BM’ : Windows 3.1x, 95, NT, …, ‘BA’ :OS/2 Bitmap Array, ‘CI’ :OS/2 Color Icon, ‘CP’ :OS/2 Color Pointer, ‘IC’ : OS/2 Icon,‘PT’ :OS/2 Pointer char _id2; ///< 两字节的内容用来识别位图的类型:‘BM’ : Windows 3.1x, 95, NT, …, ‘BA’ :OS/2 Bitmap Array, ‘CI’ :OS/2 Color Icon, ‘CP’ :OS/2 Color Pointer, ‘IC’ : OS/2 Icon,‘PT’ :OS/2 Pointer long _file_size; ///< 用字节表示的整个文件的大小 long _reserved0; ///< 保留,设置为0 long _bitmap_data_offset; ///< 从文件开始到位图数据开始之间的数据(bitmap data)之间的偏移量 long _bitmap_header_size; ///< 位图信息头(Bitmap Info Header)的长度,用来描述位图的颜色、压缩方法等。下面的长度表示:28h - Windows 3.1x, 95, NT, …, 0Ch - OS/2 1.x, F0h - OS/2 2.x long _width; ///< 位图的宽度,以像素为单位 long _height; ///< 位图的高度,以像素为单位 short _planes; ///< 位图的位面数 short _bits_per_pixel; ///< 每个像素的位数, 1 - Monochrome bitmap, 4 - 16 color bitmap, 8 - 256 color bitmap, 16 - 16bit (high color) bitmap, 24 - 24bit (true color) bitmap, 32 - 32bit (true color) bitmap long _compression; ///< 压缩说明:, 0 - none (也使用BI_RGB表示), 1 - RLE 8-bit / pixel (也使用BI_RLE4表示), 2 - RLE 4-bit / pixel (也使用BI_RLE8表示), 3 - Bitfields (也使用BI_BITFIELDS表示) long _bitmap_data_size; ///< 用字节数表示的位图数据的大小。该数必须是4的倍数 long _hres; ///< 用像素/米表示的水平分辨率 long _vres; ///< 用像素/米表示的垂直分辨率 long _colors; ///< 位图使用的颜色数。如8-位/像素表示为100h或者 256. long _important_colors; ///< 指定重要的颜色数。当该域的值等于颜色数时,表示所有颜色都一样重要 char _palette[256][4]; ///< 调色板规范。对于调色板中的每个表项,这4个字节用下述方法来描述RGB的值:, 1字节用于蓝色分量 , 1字节用于绿色分量 , 1字节用于红色分量 , 1字节用于填充符(设置为0)调色板数据,24位及以上像素没有该数据 }; class bitmap { public: bitmap(); ~bitmap(); bool init(); void shutdown(); bool load( const std::string& __bmp_file_name ); bool save( const std::string& __bmp_file_name ); bool set_pixel(int __index, unsigned char __red, unsigned char __green, unsigned char __blue, unsigned char __alpha); bool get_pixel(int __index, unsigned char& __red, unsigned char& __green, unsigned char& __blue, unsigned char& __alpha) const; unsigned char * get_pixel_data() const; int get_pixel_data_size() const; int get_pixel_width() const; int get_pixel_height() const; const std::string& get_name() const; protected: long _get_file_size(FILE* __file); protected: std::string _M_name; ///< 文件名 BITMAP_HEADER _M_header; ///< BMP文件头信息 size_t _M_file_length; ///< BMP文件大小 unsigned char * _M_pixel_data; ///< 像素数据 int _M_pixel_data_size; ///< 像素数据大小 int _M_pixel_width; ///< 像素数据的宽度 int _M_pixel_height; ///< 像素数据的高度 }; } //XE #endif __BITMAP_H #include "XEStableHeaders.h" #include "XEBitmap.h" #include <stdlib.h> #include <assert.h> #include <memory.h> namespace XE { bitmap::bitmap() { _M_name; _M_header; _M_pixel_data = NULL; _M_pixel_data_size = 0; _M_pixel_width = 0; _M_pixel_height = 0; } bitmap::~bitmap() { shutdown(); } bool bitmap::init() { return true; } void bitmap::shutdown() { if(_M_pixel_data != NULL ) free(_M_pixel_data); _M_pixel_data_size = 0; _M_pixel_width = 0; _M_pixel_height = 0; } long bitmap::_get_file_size(FILE* pFile) { long nPos = ftell(pFile); fseek(pFile,0,SEEK_END); long nLen = ftell(pFile); fseek(pFile,nPos,SEEK_SET); return nLen; } unsigned char * bitmap::get_pixel_data() const { return _M_pixel_data; } int bitmap::get_pixel_data_size() const { return _M_pixel_data_size; } int bitmap::get_pixel_width() const { return _M_pixel_width; } int bitmap::get_pixel_height() const { return _M_pixel_height; } const std::string& bitmap::get_name() const { return _M_name; } bool bitmap::set_pixel(int __index, unsigned char __red, unsigned char __green, unsigned char __blue, unsigned char __alpha) { if( __index < 0 || __index > _M_pixel_data_size ) return false; unsigned char* __pixel_buffer = _M_pixel_data + __index * 4; switch ( _M_header._bits_per_pixel ) { case 8: { /*int __palette_index = *__buf_temp++; *__pixel_buffer++ = _M_header._palette[__palette_index][2]; *__pixel_buffer++ = _M_header._palette[__palette_index][1]; *__pixel_buffer++ = _M_header._palette[__palette_index][0]; *__pixel_buffer++ = 0xff;*/ } break; case 16: { /*unsigned short __short_pixel = * ( unsigned short * ) __pixel_buffer; __pixel_buffer += 2; *__pixel_buffer++ = unsigned char(( __short_pixel & ( 31 << 10 ) ) >> 7); *__pixel_buffer++ = unsigned char(( __short_pixel & ( 31 << 5 ) ) >> 2); *__pixel_buffer++ = unsigned char(( __short_pixel & ( 31 ) ) << 3); *__pixel_buffer++ = 0xff;*/ } break; case 24: { *__pixel_buffer++ = __red; *__pixel_buffer++ = __green; *__pixel_buffer++ = __blue; __alpha; } break; case 32: { *__pixel_buffer++ = __red; *__pixel_buffer++ = __green; *__pixel_buffer++ = __blue; *__pixel_buffer++ = __alpha; } break; default: return false; } return true; } bool bitmap::get_pixel(int __index, unsigned char& __red, unsigned char& __green, unsigned char& __blue, unsigned char& __alpha) const { if( __index < 0 || __index > _M_pixel_data_size ) return false; unsigned char* __pixel_buffer = _M_pixel_data + __index * 4; switch ( _M_header._bits_per_pixel ) { case 8: { /*int __palette_index = *__buf_temp++; *__pixel_buffer++ = _M_header._palette[__palette_index][2]; *__pixel_buffer++ = _M_header._palette[__palette_index][1]; *__pixel_buffer++ = _M_header._palette[__palette_index][0]; *__pixel_buffer++ = 0xff;*/ } break; case 16: { /*unsigned short __short_pixel = * ( unsigned short * ) __pixel_buffer; __pixel_buffer += 2; *__pixel_buffer++ = unsigned char(( __short_pixel & ( 31 << 10 ) ) >> 7); *__pixel_buffer++ = unsigned char(( __short_pixel & ( 31 << 5 ) ) >> 2); *__pixel_buffer++ = unsigned char(( __short_pixel & ( 31 ) ) << 3); *__pixel_buffer++ = 0xff;*/ } break; case 24: { __red = *__pixel_buffer++; __green = *__pixel_buffer++; __blue = *__pixel_buffer++; __alpha; } break; case 32: { __red = *__pixel_buffer++; __green = *__pixel_buffer++; __blue = *__pixel_buffer++; __alpha = *__pixel_buffer++;; } break; default: return false; } return true; } bool bitmap::save( const std::string& __bmp_file_name ) { FILE* __file = fopen(__bmp_file_name.c_str(),"wb+"); if(__file == NULL) { return false; } if(_M_pixel_data == NULL) { return false; } //fseek(__file,0,SEEK_SET); fwrite(&_M_header._id1, sizeof(_M_header._id1), 1, __file); fwrite(&_M_header._id2, sizeof(_M_header._id2), 1, __file); fwrite(&_M_header._file_size, sizeof(_M_header._file_size), 1, __file); fwrite(&_M_header._reserved0, sizeof(_M_header._reserved0), 1, __file); fwrite(&_M_header._bitmap_data_offset, sizeof(_M_header._bitmap_data_offset), 1, __file); fwrite(&_M_header._bitmap_header_size, sizeof(_M_header._bitmap_header_size), 1, __file); fwrite(&_M_header._width, sizeof(_M_header._width), 1, __file); fwrite(&_M_header._height, sizeof(_M_header._height), 1, __file); fwrite(&_M_header._planes, sizeof(_M_header._planes), 1, __file); fwrite(&_M_header._bits_per_pixel, sizeof(_M_header._bits_per_pixel), 1, __file); fwrite(&_M_header._compression, sizeof(_M_header._compression), 1, __file); fwrite(&_M_header._bitmap_data_size, sizeof(_M_header._bitmap_data_size), 1, __file); fwrite(&_M_header._hres, sizeof(_M_header._hres), 1, __file); fwrite(&_M_header._vres, sizeof(_M_header._vres), 1, __file); fwrite(&_M_header._colors, sizeof(_M_header._colors), 1, __file); fwrite(&_M_header._important_colors, sizeof(_M_header._important_colors), 1, __file); //fwrite( &_M_header._palette, sizeof(_M_header._palette), 1, __file); //fseek(__file,_M_header._bitmap_data_offset,SEEK_SET); unsigned char* __buffer = (unsigned char*) malloc(_M_pixel_data_size); unsigned char* __buffer_temp = __buffer; size_t __write_buffer_size = 0; if (__buffer == NULL) { fclose(__file); return false; } for ( int __row = _M_pixel_height-1; __row >= 0; __row--) { unsigned char* __pixel_buffer = _M_pixel_data + __row * _M_pixel_width * 4; for ( int __column = 0; __column < _M_pixel_width; __column++ ) { switch ( _M_header._bits_per_pixel ) { case 8: { /*int __palette_index = *__buf_temp++; *__pixel_buffer++ = _M_header._palette[__palette_index][2]; *__pixel_buffer++ = _M_header._palette[__palette_index][1]; *__pixel_buffer++ = _M_header._palette[__palette_index][0]; *__pixel_buffer++ = 0xff;*/ } break; case 16: { /*unsigned short __short_pixel = * ( unsigned short * ) __pixel_buffer; __pixel_buffer += 2; *__pixel_buffer++ = unsigned char(( __short_pixel & ( 31 << 10 ) ) >> 7); *__pixel_buffer++ = unsigned char(( __short_pixel & ( 31 << 5 ) ) >> 2); *__pixel_buffer++ = unsigned char(( __short_pixel & ( 31 ) ) << 3); *__pixel_buffer++ = 0xff;*/ } break; case 24: { unsigned char __red = *__pixel_buffer++; unsigned char __green = *__pixel_buffer++; unsigned char __blue = *__pixel_buffer++; unsigned char __alpha = *__pixel_buffer++; *__buffer_temp++ = __blue; *__buffer_temp++ = __green; *__buffer_temp++ = __red; __alpha; __write_buffer_size+=3; } break; case 32: { unsigned char __red = *__pixel_buffer++; unsigned char __green = *__pixel_buffer++; unsigned char __blue = *__pixel_buffer++; unsigned char __alpha = *__pixel_buffer++; *__buffer_temp++ = __blue; *__buffer_temp++ = __green; *__buffer_temp++ = __red; *__buffer_temp++ = __alpha; __write_buffer_size+=4; } break; default: return false; } } } size_t __write_file_size = fwrite( __buffer, 1, __write_buffer_size, __file); assert( __write_file_size == __write_buffer_size ); if( __write_file_size != __write_buffer_size ) { free(__buffer); fclose(__file); return false; } assert( (int)__write_buffer_size + _M_header._bitmap_data_offset <= _M_header._file_size ); char __tempdata[1] = { 0 }; if( (long)__write_buffer_size + _M_header._bitmap_data_offset < _M_header._file_size ) { size_t __temp = _M_header._file_size - (__write_buffer_size + _M_header._bitmap_data_offset); fwrite( __tempdata, 1, __temp, __file); } else if( (long)__write_buffer_size + _M_header._bitmap_data_offset > _M_header._file_size ) { free(__buffer); fclose(__file); return false; } free(__buffer); fclose(__file); return true; } bool bitmap::load( const std::string& __bmp_file_name ) { FILE* __file = fopen(__bmp_file_name.c_str(),"rb"); if(__file == NULL) { return false; } _M_file_length = _get_file_size(__file); unsigned char* __buffer = (unsigned char*) malloc(_M_file_length); if (__buffer == NULL) { fclose(__file); return false; } size_t __file_reed_length = fread(__buffer, 1, _M_file_length, __file); assert(__file_reed_length == _M_file_length); if( __file_reed_length != _M_file_length) { fclose(__file); return false; } unsigned char* __buf_temp = __buffer; _M_header._id1 = *__buf_temp++; _M_header._id2 = *__buf_temp++; _M_header._file_size = ( * ( long * ) __buf_temp ); __buf_temp += 4; _M_header._reserved0 = ( * ( long * ) __buf_temp ); __buf_temp += 4; _M_header._bitmap_data_offset = ( * ( long * ) __buf_temp ); __buf_temp += 4; _M_header._bitmap_header_size = ( * ( long * ) __buf_temp ); __buf_temp += 4; _M_header._width = ( * ( long * ) __buf_temp ); __buf_temp += 4; _M_header._height = ( * ( long * ) __buf_temp ); __buf_temp += 4; _M_header._planes = ( * ( short * ) __buf_temp ); __buf_temp += 2; _M_header._bits_per_pixel = ( * ( short * ) __buf_temp ); __buf_temp += 2; _M_header._compression = ( * ( long * ) __buf_temp ); __buf_temp += 4; _M_header._bitmap_data_size = ( * ( long * ) __buf_temp ); __buf_temp += 4; _M_header._hres = ( * ( long * ) __buf_temp ); __buf_temp += 4; _M_header._vres = ( * ( long * ) __buf_temp ); __buf_temp += 4; _M_header._colors = ( * ( long * ) __buf_temp ); __buf_temp += 4; _M_header._important_colors = ( * ( long * ) __buf_temp ); __buf_temp += 4; memcpy( _M_header._palette, __buf_temp, sizeof( _M_header._palette ) ); if ( _M_header._bits_per_pixel == 8 ) __buf_temp += 1024; if ( _M_header._id1 != 'B' && _M_header._id2 != 'M' ) { free(__buffer); fclose(__file); return false; } if ( _M_header._file_size != (long)_M_file_length ) { free(__buffer); fclose(__file); return false; } if ( _M_header._compression != 0 ) { free(__buffer); fclose(__file); return false; } if ( _M_header._bits_per_pixel < 8 ) { free(__buffer); fclose(__file); return false; } int __columns = _M_header._width; int __rows = _M_header._height; if(_M_header._bits_per_pixel == 24 ) { if( (__columns & 3) != 0) //检查宽度是否为4倍数 __columns = (__columns & ~3) + 4; //修正位图宽度值,对齐到4的倍数,不然图像会变形 } if ( __rows < 0 ) __rows = -__rows; int __num_pixels = __columns * __rows; _M_pixel_width = __columns; _M_pixel_height = __rows; if(_M_pixel_data != NULL ) free(_M_pixel_data); _M_pixel_data_size = __num_pixels * 4; _M_pixel_data = (unsigned char*)malloc( _M_pixel_data_size ); if( _M_pixel_data == NULL ) { free(__buffer); fclose(__file); return false; } __buf_temp = __buffer + _M_header._bitmap_data_offset; for ( int __row = __rows-1; __row >= 0; __row--) { unsigned char* __pixel_buffer = _M_pixel_data + __row * __columns * 4; for ( int __column = 0; __column < __columns; __column++ ) { switch ( _M_header._bits_per_pixel ) { case 8: { int __palette_index = *__buf_temp++; *__pixel_buffer++ = _M_header._palette[__palette_index][2]; *__pixel_buffer++ = _M_header._palette[__palette_index][1]; *__pixel_buffer++ = _M_header._palette[__palette_index][0]; *__pixel_buffer++ = 0xff; } break; case 16: { unsigned short __short_pixel = * ( unsigned short * ) __pixel_buffer; __pixel_buffer += 2; *__pixel_buffer++ = unsigned char(( __short_pixel & ( 31 << 10 ) ) >> 7); *__pixel_buffer++ = unsigned char(( __short_pixel & ( 31 << 5 ) ) >> 2); *__pixel_buffer++ = unsigned char(( __short_pixel & ( 31 ) ) << 3); *__pixel_buffer++ = 0xff; } break; case 24: { unsigned char __blue = *__buf_temp++; unsigned char __green = *__buf_temp++; unsigned char __red = *__buf_temp++; *__pixel_buffer++ = __red; *__pixel_buffer++ = __green; *__pixel_buffer++ = __blue; *__pixel_buffer++ = 255; } break; case 32: { unsigned char __blue = *__buf_temp++; unsigned char __green = *__buf_temp++; unsigned char __red = *__buf_temp++; unsigned char __alpha = *__buf_temp++; *__pixel_buffer++ = __red; *__pixel_buffer++ = __green; *__pixel_buffer++ = __blue; *__pixel_buffer++ = __alpha; } break; default: return false; } } } //记录文件名 _M_name = std::string(__bmp_file_name); free(__buffer); fclose(__file); return true; } }//XE ////注意bmp文件是由左到右, 由下到上的循序存储的像素.每个像素颜色顺序为B G R (A) ////BMP的行象素是4字节对齐的,不足的补0,比如有个图像每行宽度是63象素, ////BMP文件存储时会每行存储64个字节,最后一个字节用0补齐 //void CDlg::OnPaint() //测试图像 //{ //CPaintDC dc(this); //static uint8* pic = NULL; //static int w,h; //if(pic == NULL) //{ // char spath[MAX_PATH]; // _getcwd(spath, 200); // strcat(spath,"//res//b0000.bmp"); // LoadBMP(spath,&pic,&w,&h); //} //int i,j; //for(j=0;j<h;j++) //{ // for(i=0;i<w;i++) // { // SetPixel(dc,i,j,RGB(pic[0],pic[1],pic[2])); // pic += 4; // } //} //} //}