完成后语: 我在编辑的时候好好的,怎么显示成这样?》
SUCKS
这里主要是指用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;
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);}//大小为数据部分+ 54byte的两个header + 多余的2个字节的0