用OpenGL 生成 bmp .bmp 文件


这里主要是指用glReadPixels读取一块矩形区域,然后保存为bmp文件

这里使用最简单,最常用,无压缩的24bit bmp

有两个header 

file header 大小14byte 

#pragma pack( push, 2 )

struct BMPFileHeader
{
	unsigned short usType; 
    unsigned int file_size; 
    unsigned short usReserved1; 
    unsigned short usReserved2; 
    unsigned int uiOffBits; 
};

#pragma pack( pop )



info header 大小40byte

struct BMPInfoHeader
{
	unsigned int  header_size; 
    long   lWidth; 
    long   lHeight; 
    unsigned short usPlanes; 
    unsigned short usBitCount; 
    unsigned int uiCompression; 
    unsigned int raw_data_size; 
    long lXPelsPerMeter; //0x0B12 always
    long lYPelsPerMeter; ////0x0B12 always
    unsigned int uiClrUsed; 
    unsigned int uiClrImportant; 
};



本文有意回避了一个技术难点

BMP 文件每一行宽度总字节数必须为4 的整数倍,多余的以0 作为padding。

所以使用本文的方法的时候,glReadPixels中的宽度为4 的整数倍

下面就是数据部分了,总大小为 width*height*3 byte

以BGR方式,从图片的左下方开始 ( 额外,photoshop生成的BMP在文件最末尾有两个byte的0, 我这里也加上了)

#define BMP_SIGNATURE 0x4D42
#define  MPW 1000//MAX_PIC_WIDTH
#define  MPH 800 //MAX_PIC_HEIGHT




class CPic{
public:
	unsigned char* m_data;
	wchar_t m_width;
	wchar_t m_height;
	wchar_t m_pad;
	CPic(){
		m_pad = 0;
		m_data=0;
		m_data= new unsigned char[MPW*MPH*3];
	}
	~CPic(){if(m_data) delete [] m_data;}
	//singleton interface
	
	
	void SaveBmp(wchar_t,wchar_t,wchar_t,wchar_t,char*);
};



生成方法:

void CPic::SaveBmp(wchar_t x,wchar_t y,wchar_t width, wchar_t height,char *filename)//使用时,width为4的整数倍
{
	static FILE* fp = fopen(filename,"wb");
	static BMPFileHeader bitmapFileHeader;
	static BMPInfoHeader bitmapInfoHeader;
	m_width = width;
	m_height = height;
	glPixelStorei(GL_UNPACK_ALIGNMENT,1);
	glReadPixels(x,y,width,height,GL_BGR_EXT,GL_UNSIGNED_BYTE,m_data);//GL_BGR_EXT很方便,免得手工做字节交换
	

	//fill the header structs with information
	bitmapFileHeader.file_size	    = m_width*m_height*3+56;
//大小为数据部分+ 54byte的两个header + 多余的2个字节的0
bitmapFileHeader.usType = BMP_SIGNATURE; //定义为0x4D42 也就是“BM”bitmapFileHeader.usReserved1= 0;bitmapFileHeader.usReserved2= 0;bitmapFileHeader.uiOffBits = 54;//偏移值,俩个header的大小fwrite( &bitmapFileHeader, 1, 14, fp );bitmapInfoHeader.header_size = 40;//第二个header的大小bitmapInfoHeader.usPlanes = 1;bitmapInfoHeader.usBitCount = 24;//24位文件bitmapInfoHeader.uiCompression = 0;bitmapInfoHeader.raw_data_size = m_width*m_height*3+2;//数据部分bitmapInfoHeader.lXPelsPerMeter= 0x0B12;bitmapInfoHeader.lYPelsPerMeter= 0x0B12;bitmapInfoHeader.uiClrUsed = 0;bitmapInfoHeader.uiClrImportant= 0;bitmapInfoHeader.lWidth = m_width;bitmapInfoHeader.lHeight = m_height;fwrite( &bitmapInfoHeader, 1, 40, fp);fwrite(m_data,m_width*m_height*3,1,fp);fwrite(&m_pad,2,1,fp);fclose(fp);}

  

posted on 2011-10-10 12:56  legion  阅读(485)  评论(0)    收藏  举报

导航