OPENGL的位图和图象
2015-11-03 23:10
489 查看
在前面的章节中,已经讲述了几何数据(点、线、多边形)绘制的有关方法,但OpenGL还有另外两种重要的数据类:一是位图,二是图像。这两种数据都是以象素矩阵形式存储,即用一个矩形数组来表示某一位图或图像。二者不同之处是位图包含每个象素的一位信息,而图像数据一般包含每个象素的多位信息(如,红、绿、蓝和Alpha值);还有位图类似于掩码,可用于遮掩别的图像,而图像数据则简单地覆盖先前已经存在的数据或者与之混合。下面将详述这些内容。
11.1、位图
11.1.1 位图(Bitmap)与字符(Font)
位图是以元素值为0或1的矩阵形式存储的,通常用于对窗口中相应区域的绘图屏蔽。比如说,当前颜色设置为红色,则在矩阵元素值为1的地方象素用红色来取代,反之,在为0的地方,对应的象素不受影响。位图普遍用于字符显示,请看下面例子:
例11-1 位图字符例程(font.c)
以上程序运行结果是显示三个相同的字符F。OpenGL函数库只提供了最底层操作,即用glRasterPos*()和glBitmap()在屏幕上定位和画一个位图,图11-1显示了F的位图和相应的位图数据。
在图中,字符大小为12*8的方阵,每一行数据用8位16进制表示。注意:位图数据总是按块存储,每块的位数总是8的倍数,但实际位图的宽并不一定使8的倍数。组成位图的位从位图的左下角开始画:首先画最底下的一行,然后是这行的上一行,依此类推。这个程序中的几个重要函数的解释将在下面几个小节,其中函数glPixelstorei()描述了位图数据在计算机内存中存储的方式。
11.1.2 当前光栅位置
当前光栅位置函数就是:
在上一例中,颜色设置的位置与当前光栅位置函数调用的位置有关,glColor*()必须放 在glRasterPos*()前,则紧跟其后的位图就都继承当前的颜色,例前两个紫色的F;若要改变当前位图颜色,则需重新调用glColor*()和glRasterPos*(),如第三个黄色字符F的显示。
11.1.3 位图显示
当设置了光栅位置后,就可以调用glBitmap()函数来显示位图数据了。这个函数形式为:
第一个字符F与第二个字符F的间距是由glBitmap()的两个增量参数决定的,即第二个字符F在第一个字符F的基础上分别向X正轴和Y负轴移动20个象素单位。
11.2 图像
一般来说,OpenGL图像(image)操作包括象素读写、象素拷贝和图像缩放,下面分别来介绍。
11.2.1 象素读写
OpenGL提供了最基本的象素读和写函数,它们分别是:
读取象素数据:
函数参数(x, y)定义图像区域左下角点的坐标,width和height分别是图像的高度和宽度,*pixel是一个指针,指向存储图像数据的数组。参数format指出所读象素数据元素的格式(索引值或R、G、B、A值,如表11-1所示),而参数type指出每个元素的数据类型(见表11-2)。
写入象素数据:
函数参数format和type与glReadPixels()有相同的意义,pixel指向的数组包含所要画的象素数据。注意,调用这个函数前必须先设置当前光栅位置,若当前光栅位置无效,则给出该函数时不画任何图形,并且当前光栅位置仍然保持无效。
图像的每个元素按表11-2给出的数据类型存储。若元素表示连续的值,如红、绿、蓝或亮度分量,每个值都按比例放缩使之适合于可用的位数。例如,红色分量是0.0到1.0之 间的浮点值。若它需要放到无符号单字节整数中,也仅有8位精度保存下来,其他无符号整数类型同理。对于有符号的数据类型还要少一位,例如颜色索引存到有符号的8位整数中,它的第一位被0xfe屏蔽掉了(即这个掩码包含7个1)。若类型是GL_FLOAT,索引值简单地转化成单精度浮点值,例如索引17转化成17.0,同理。
11.2.2 象素拷贝
象素拷贝函数是:
这个函数使用起来有点类似于先调用glReadPixels()函数后再调用glDrawPixels()一样,但它不需要将数据写到内存中去,因它只将数据写到framebuffer里。函数功能就是拷贝framebuffer中左下角点在(x, y)尺寸为width、height的矩形区域象素数据。数据拷贝到一个新的位置,其左下角点在当前光栅的位置,参数type可以是GL_COLOR、GL_STENCIL、GL_DEPTH。在拷贝过程中,参数type要按如下方式转换成format:
1)若type为GL_DEPTH或GL_STENCIL,那么format应分别是GL_DEPTH_COMPONENT或GL_STENCIL_INDEX;
2)若type为GL_COLOR,format则用GL_RGB或GL_COLOR_INDEX,这要依赖于图形系统是处于RGBA方式还是处于颜色表方式。
11.2.3 图像缩放
一般情况下,图像的一个象素写到屏幕上时也是一个象素,但是有时也需要将图像放大或缩小,OpenGL提供了这个函数:
设置象素写操作沿X和Y方向的放大或缩小因子。缺省情况下,zoomx、zoomy都是1.0。如果它们都是2.0,则每个图像象素被画到4个屏幕象素上面。注意:小数形式的缩放因子和负数因子都是可以的。
11.2.4 图像例程
下面举出一个图像应用的例子:
例11-2 图像应用例程(image.c)
以上程序运行的结果是在屏幕正上方显示一个最初的五彩三角形,然后在下半部显示一串拷贝的三角形。当然,读者自己可以再加上图像放大缩小等,试试看,会发生怎样的情形?
11.1、位图
11.1.1 位图(Bitmap)与字符(Font)
位图是以元素值为0或1的矩阵形式存储的,通常用于对窗口中相应区域的绘图屏蔽。比如说,当前颜色设置为红色,则在矩阵元素值为1的地方象素用红色来取代,反之,在为0的地方,对应的象素不受影响。位图普遍用于字符显示,请看下面例子:
例11-1 位图字符例程(font.c)
#include "glos.h" #include <GL/gl.h> #include <GL/glu.h> #include <GL/glaux.h> void myinit(void); void CALLBACK myReshape(GLsizei w, GLsizei h); void CALLBACK display(void); GLubyte rasters[12] = { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xff, 0xff}; void myinit(void) { glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glClearColor (0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); } void CALLBACK display(void) { glColor3f (1.0, 0.0, 1.0); glRasterPos2i (100, 200); glBitmap (8, 12, 0.0, 0.0, 20.0, 20.0, rasters); lBitmap (8, 12, 0.0, 0.0, 0.0, 0.0, rasters); glColor3f (1.0, 1.0, 0.0); glRasterPos2i (150, 200); glBitmap (8, 12, 0.0, 0.0, 0.0, 0.0, rasters); glFlush(); } void CALLBACK myReshape(GLsizei w, GLsizei h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho (0, w, 0, h, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); } void main(void) { auxInitDisplayMode (AUX_SINGLE | AUX_RGBA); auxInitPosition (0, 0, 500, 500); auxInitWindow ("Bitmap"); myinit(); auxReshapeFunc (myReshape); auxMainLoop(display); }
以上程序运行结果是显示三个相同的字符F。OpenGL函数库只提供了最底层操作,即用glRasterPos*()和glBitmap()在屏幕上定位和画一个位图,图11-1显示了F的位图和相应的位图数据。
在图中,字符大小为12*8的方阵,每一行数据用8位16进制表示。注意:位图数据总是按块存储,每块的位数总是8的倍数,但实际位图的宽并不一定使8的倍数。组成位图的位从位图的左下角开始画:首先画最底下的一行,然后是这行的上一行,依此类推。这个程序中的几个重要函数的解释将在下面几个小节,其中函数glPixelstorei()描述了位图数据在计算机内存中存储的方式。
11.1.2 当前光栅位置
当前光栅位置函数就是:
void glRasterPos{234}{SIFD}[V](TYPE x,TYPE y,TYPE z,TYPE w);设置当前所画位图或图像的原点。其中参数x、y、z、w给出了光栅位置坐标。在变换到屏幕坐标时(即用模型变换和透视变换),光栅位置坐标与glVertex*()提供的坐标同样对待。也就是说,变换后要么确定一个有效点,要么认为位于视口以外的点的当前光栅位置无效。
在上一例中,颜色设置的位置与当前光栅位置函数调用的位置有关,glColor*()必须放 在glRasterPos*()前,则紧跟其后的位图就都继承当前的颜色,例前两个紫色的F;若要改变当前位图颜色,则需重新调用glColor*()和glRasterPos*(),如第三个黄色字符F的显示。
11.1.3 位图显示
当设置了光栅位置后,就可以调用glBitmap()函数来显示位图数据了。这个函数形式为:
void glBitmap( GLsizei width,GLsizei height,GLfloat xbo,GLfloat ybo,GLfloat xbi,GLfloat ybi,const GLubyte *bitmap);显示由bitmap指定的位图,bitmap是一个指向位图的指针。位图的原点放在最近定义的当前光栅位置上。若当前光栅位置是无效的,则不显示此位图或其一部分,而且当前光栅位置仍然无效。参数width和height一象素为单位说明位图的宽行高。宽度不一定是8的倍数。参数xbo和ybo定义位图的原点(正值时,原点向上移动;负值时,原点向下移动)。参数xbi和ybi之处在位图光栅化后光栅位置的增量。在上一例中:
glColor3f (1.0, 0.0, 1.0); glRasterPos2i (100, 200); glBitmap (8, 12, 0.0, 0.0, 20.0, 20.0, rasters); glBitmap (8, 12, 0.0, 0.0, 0.0, 0.0, rasters);
第一个字符F与第二个字符F的间距是由glBitmap()的两个增量参数决定的,即第二个字符F在第一个字符F的基础上分别向X正轴和Y负轴移动20个象素单位。
11.2 图像
一般来说,OpenGL图像(image)操作包括象素读写、象素拷贝和图像缩放,下面分别来介绍。
11.2.1 象素读写
OpenGL提供了最基本的象素读和写函数,它们分别是:
读取象素数据:
void glReadPixels(GLint x,GLint y,GLsizesi width,GLsizei height,GLenum format,GLenum type,GLvoid *pixel);
函数参数(x, y)定义图像区域左下角点的坐标,width和height分别是图像的高度和宽度,*pixel是一个指针,指向存储图像数据的数组。参数format指出所读象素数据元素的格式(索引值或R、G、B、A值,如表11-1所示),而参数type指出每个元素的数据类型(见表11-2)。
写入象素数据:
void glDrawPixels(GLsizesi width,GLsizei height,GLenum format,GLenum type,GLvoid *pixel);
函数参数format和type与glReadPixels()有相同的意义,pixel指向的数组包含所要画的象素数据。注意,调用这个函数前必须先设置当前光栅位置,若当前光栅位置无效,则给出该函数时不画任何图形,并且当前光栅位置仍然保持无效。
名称 | 象素数据类型 |
GL_INDEX | 单个颜色索引 |
GL_RGB | 先是红色分量,再是绿色分量,然后是蓝色分量 |
GL_RED | 单个红色分量 |
GL_GREEN | 单个绿色分量 |
GL_BLUE | 单个蓝色分量 |
GL_ALPHA | 单个Alpha值 |
GL_LUMINANCE_ALPHA | 先是亮度分量,然后是Alpha值 |
GL_STENCIL_INDEX | 单个的模板索引 |
GL_DEPTH_COMPONENT | 单个深度分量 |
表11-1 函数glReadPixels()及glDrawPixels()的象素格式 |
名称 | 数据类型 |
GL_UNSIGNED_BYTE | 无符号的8位整数 |
GL_BYTE | 8位整数 |
GL_BITMAP | 无符号的8位整数数组中的单个数位 |
GL_UNSIGNED_SHORT | 无符号的16位整数 |
GL_SHORT | 16位整数 |
GL_UNSIGNED_INT | 无符号的32位整数 |
GL_INT | 32位整数 |
GL_FLOAT | 单精度浮点数 |
表11-2 函数glReadPixels()及glDrawPixels()的象素数据类型 |
11.2.2 象素拷贝
象素拷贝函数是:
void glCopyPixels(GLint x,GLint y,GLsizesi width,GLsizei height, GLenum type);
这个函数使用起来有点类似于先调用glReadPixels()函数后再调用glDrawPixels()一样,但它不需要将数据写到内存中去,因它只将数据写到framebuffer里。函数功能就是拷贝framebuffer中左下角点在(x, y)尺寸为width、height的矩形区域象素数据。数据拷贝到一个新的位置,其左下角点在当前光栅的位置,参数type可以是GL_COLOR、GL_STENCIL、GL_DEPTH。在拷贝过程中,参数type要按如下方式转换成format:
1)若type为GL_DEPTH或GL_STENCIL,那么format应分别是GL_DEPTH_COMPONENT或GL_STENCIL_INDEX;
2)若type为GL_COLOR,format则用GL_RGB或GL_COLOR_INDEX,这要依赖于图形系统是处于RGBA方式还是处于颜色表方式。
11.2.3 图像缩放
一般情况下,图像的一个象素写到屏幕上时也是一个象素,但是有时也需要将图像放大或缩小,OpenGL提供了这个函数:
void glPixelZoom(GLfloat zoomx,GLfloat zoomy);
设置象素写操作沿X和Y方向的放大或缩小因子。缺省情况下,zoomx、zoomy都是1.0。如果它们都是2.0,则每个图像象素被画到4个屏幕象素上面。注意:小数形式的缩放因子和负数因子都是可以的。
11.2.4 图像例程
下面举出一个图像应用的例子:
例11-2 图像应用例程(image.c)
#include "glos.h" #include <GL/gl.h> #include <GL/glu.h> #include <GL/glaux.h> void myinit(void); void triangle(void); void SourceImage(void); void CALLBACK display(void); void CALLBACK myReshape(GLsizei w, GLsizei h); void myinit (void) { glClear (GL_COLOR_BUFFER_BIT); } void triangle(void) { glBegin (GL_TRIANGLES); glColor3f (0.0, 1.0, 0.0); glVertex2f (2.0, 3.0); glColor3f(0.0,0.0,1.0); glVertex2f (12.0, 3.0); glColor3f(1.0,0.0,0.0); glVertex2f (7.0, 12.0); glEnd (); } void SourceImage(void) { glPushMatrix(); glLoadIdentity(); glTranslatef(4.0,8.0,0.0); glScalef(0.5,0.5,0.5); triangle (); glPopMatrix(); } void CALLBACK display(void) { int i; /* 绘制原始图像 */ SourceImage(); /* 拷贝图像 */ for(i=0;i<5;i++) { glRasterPos2i( 1+i*2,i); glCopyPixels(160,310,170,160,GL_COLOR); } glFlush (); } void CALLBACK myReshape(GLsizei w, GLsizei h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) gluOrtho2D (0.0, 15.0, 0.0, 15.0 * (GLfloat) h/(GLfloat) w); else gluOrtho2D (0.0, 15.0 * (GLfloat) w/(GLfloat) h, 0.0, 15.0); g lMatrixMode(GL_MODELVIEW); } void main(void) { auxInitDisplayMode (AUX_SINGLE | AUX_RGBA); auxInitPosition (0, 0, 500, 500); auxInitWindow ("Pixel Processing"); myinit(); auxReshapeFunc (myReshape); auxMainLoop(display); }
以上程序运行的结果是在屏幕正上方显示一个最初的五彩三角形,然后在下半部显示一串拷贝的三角形。当然,读者自己可以再加上图像放大缩小等,试试看,会发生怎样的情形?
相关文章推荐
- 后盾网php网站开发培训
- linux中rz, sz命令的安装与使用------实现Windows与linux文件的快捷互传
- CentOS 6.5安装jdk1.8
- 判断网站的访问平台,并且动态加载外部CSS
- Common Linux command - 持续更新
- Linux初学必备命令
- linux下core文件调试方法
- shell类型与配置文件
- Apache Kafka 分布式消息队列中间件安装与配置
- 推荐一个好的代码下载网站
- Hadoop---安装Fuse-DFS(难)
- Mybatis的整体架构
- Tomcat环境变量?JDK环境变量?
- 二,游戏的game loop搭建
- haproxy实现反向代理和负载均衡
- ls命令
- Centos下telnet的安装和配置
- 把Apache和MySQL配置为开启启动
- Apache建立虚拟主机
- 如何修改tomcat端口