读取,写入和复制像素数据: glReadPixels():从帧缓存区读取一个矩形像素数组,并把数据保存在内存中。 glDrawPixels():把内存中所保存的一个矩形像素数组写入到帧缓冲区中由glRasterPos*()所指定的当前位置。 glCopyPixels():把一个矩形像素数组从帧缓冲区的一个部分复制到另一部分。这个函数相当于先Read再Draw,但数据并不会写入内存中(可能)。(Opengl第四版,Page193) 读取(屏幕截图): 假设我们先建立一个1*1大小的24位色BMP,文件名为dummy.bmp,又假设新的BMP文件名称为grab.bmp。则可以编写如下代码: #include <stdio.h> #include <stdlib.h> //截取函数grab,抓取窗口中宽度WindowWidth和WindowHeigh的像素 #define BMP_HEADER_LENGHT 54 void grad( void ) { FILE * PdUMMYfILE; FILE * pWritingFile; GLubyte* pPixelData; GLubyte BMP_HEADER[BMP_Header_Lenght]; GLint i, j; GLint PixelDataLength; //3-》24位色BMP,这个值可以通过位图信息头来获取 //里面有个参数biBitCount指定了颜色要用到的位数 //计算像素数据的实际长度 i = WidhowWidth*3; //得到每一行的像素数据长度 while( i%4!=0) //补充数据,直到是4的倍数 ++i; PixelDataLenght=i*WindowHeight; //实际的数据量 //分配内存和打开文件 pPixelData = (GLubyte*)malloc(PixelDataLength); if( pPixelData==0 ) //分配失败 exit(0); //读取像素 glPixelStorei( GL_UNPACK_ALIGNMENT, 4 ); glReadPixels( 0, 0, WindowWidth, WindowHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, pPixelData); //把dummy.bmp的文件头复制为新文件的文件头 fread( BMP_HEADER, sizeof( BMP_HEADER), 1, pDummyFile); fwrite( BMP_HEADER, sizeof( BMP_HEADER), 1, pWritingFile ); fseek( pWritingFile, 0x0012, SEEK_SET ); i = WindowWidth; j = WindowHeight; fwrite( &i, sizeof(i), pWritingFile ); fwrite( &j, sizeof(j), pWritingFile ); //写入像素数据 fseek( pWritingFile, 0, SEEK_END ); fwrite( pPixelData, PixelDataLength, 1, pWritingFile ); //释放内存和关闭文件 fclose( pDummyFile ); fclose( pWritingFile ); free( pPixelData );} 绘制:(完整代码)。 #include <gl/glut.h> #include <stdio.h> #include <stdlib.h> #define FileName "Bliss.bmp" static GLint ImageWidth; static GLint ImageHeigth; static GLint PixelLength; static GLubyte* PixelData; void display( void ) { glClear( GL_COLOR_BUFFER_BIT ); //绘制像素 //宽度,高度,像素数据内容,像素数据在内存中的格式,数据位置 glDrawPixels( ImageWidth,ImageHeigth, GL_BGR_EXT, GL_UNSIGNED_BYTE, PixelData); //完成绘制 glutSwapBuffers();} int main( int argc, char* argv[] ) { // 打开文件 FILE* pFile = fopen("Bliss.bmp", "rb"); if( pFile == 0 ) exit(0); // 读取图象的大小信息 fseek(pFile, 0x0012, SEEK_SET); fread(&ImageWidth, sizeof(ImageWidth), 1, pFile); fread(&ImageHeigth, sizeof(ImageHeigth), 1, pFile); // 计算像素数据长度 PixelLength = ImageWidth * 3; while( PixelLength % 4 != 0 ) ++PixelLength; PixelLength *= ImageHeigth; // 读取像素数据 PixelData = (GLubyte*)malloc(PixelLength); if( PixelData == 0 ) exit(0); fseek(pFile, 54, SEEK_SET); fread(PixelData, PixelLength, 1, pFile); // 关闭文件 fclose(pFile); // 初始化GLUT并运行 glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100, 100); glutInitWindowSize(ImageWidth, ImageHeigth); glutCreateWindow(FileName); glutDisplayFunc(&display); glutMainLoop(); // 释放内存 // 实际上,glutMainLoop函数永远不会返回,这里也永远不会到达 // 这里写释放内存只是出于一种个人习惯 // 不用担心内存无法释放。在程序结束时操作系统会自动回收所有内存 free(PixelData); return 0;} 复制像素: #include <gl/glut.h> #include <stdio.h> #include <stdlib.h> #define WindowWidth 400 #define WindowHeight 400 void display(void) { // 清除屏幕 glClear(GL_COLOR_BUFFER_BIT); // 绘制 glBegin(GL_TRIANGLES); glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(0.0f, 0.0f); glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(1.0f, 0.0f); glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(0.5f, 1.0f); glEnd(); glPixelZoom( -0.5f, -0.5f); glRasterPos2i( 0, 0 ); //1、2表示复制像素来源的矩形的左下角坐标 //3、4表示复制像素来源的矩形的高度和宽度 //复制像素的颜色,可以是GL_DEPTH或GL_STENCIL,深度/模板缓存 glCopyPixels(WindowWidth/2, WindowHeight/2, WindowWidth/2, WindowHeight/2, GL_COLOR); // 完成绘制,并抓取图象保存为BMP文件 glutSwapBuffers(); } int main( int argc, char* argv[] ) { // 初始化GLUT并运行 glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(0, 0); glutInitWindowSize(WindowWidth, WindowHeight); glutCreateWindow("FileName"); glutDisplayFunc(display); glutMainLoop(); return 0;} |
Saturday, May 14, 2011
6、Opengl对像素的操作
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment