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