这里主要是指用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);}