OpenGL颜色(4)

2019-03-22 11:47

例11-2 图像应用例程(image.c)

#include \ #include #include #include 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 (\); myinit();

auxReshapeFunc (myReshape); auxMainLoop(display); }

以上程序运行的结果是在屏幕正上方显示一个最初的五彩三角形,然后在下半部显示一串拷贝的三角形。当然,读者自己可以再加上图像放大缩小等,试试看,会发生怎样的情形?

posted @ 2010-11-19 11:25 白了少年头 Views(453) Comments(0) Edit

OpenGL像素操作

今天我们先简单介绍Windows中常用的BMP文件格式,然后讲OpenGL的像素操作。虽然看起来内容可能有点多,但实际只有少量几个知识点,如果读者对诸如“显示BMP图象”等

内容比较感兴趣的话,可能不知不觉就看完了。

像素操作可以很复杂,这里仅涉及了简单的部分,让大家对OpenGL像素操作有初步的印象。 学过多媒体技术的朋友可能知道,计算机保存图象的方法通常有两种:一是“矢量图”,一是“像素图”。矢量图保存了图象中每一几何物体的位置、形状、大小等信息,在显示图象时,根据这些信息计算得到完整的图象。“像素图”是将完整的图象纵横分为若干的行、列,这些行列使得图象被分割为很细小的分块,每一分块称为像素,保存每一像素的颜色也就保存了整个图象。

这两种方法各有优缺点。“矢量图”在图象进行放大、缩小时很方便,不会失真,但如果图象很复杂,那么就需要用非常多的几何体,数据量和运算量都很庞大。“像素图”无论图象多么复杂,数据量和运算量都不会增加,但在进行放大、缩小等操作时,会产生失真的情况。 前面我们曾介绍了如何使用OpenGL来绘制几何体,我们通过重复的绘制许多几何体,可以绘制出一幅矢量图。那么,应该如何绘制像素图呢?这就是我们今天要学习的内容了。 1、BMP文件格式简单介绍

BMP文件是一种像素文件,它保存了一幅图象中所有的像素。这种文件格式可以保存单色位图、16色或256色索引模式像素图、24位真彩色图象,每种模式种单一像素的大小分别为1/8字节,1/2字节,1字节和3字节。目前最常见的是256色BMP和24位色BMP。这种文件格式还定义了像素保存的几种方法,包括不压缩、RLE压缩等。常见的BMP文件大多是不压缩的。

这里为了简单起见,我们仅讨论24位色、不使用压缩的BMP。(如果你使用Windows自带的画图程序,很容易绘制出一个符合以上要求的BMP)

Windows所使用的BMP文件,在开始处有一个文件头,大小为54字节。保存了包括文件格式标识、颜色数、图象大小、压缩方式等信息,因为我们仅讨论24位色不压缩的BMP,所以文件头中的信息基本不需要注意,只有“大小”这一项对我们比较有用。图象的宽度和高度都是一个32位整数,在文件中的地址分别为0x0012和0x0016,于是我们可以使用以下代码来读取图象的大小信息:

GLint width, height; // 使用OpenGL的GLint类型,它是32位的。 // 而C语言本身的int则不一定是32位的。 FILE* pFile;

// 在这里进行“打开文件”的操作

fseek(pFile, 0x0012, SEEK_SET); // 移动到0x0012位置 fread(&width, sizeof(width), 1, pFile); // 读取宽度

fseek(pFile, 0x0016, SEEK_SET); // 移动到0x0016位置 // 由于上一句执行后本就应该在0x0016位置 // 所以这一句可省略 fread(&height, sizeof(height), 1, pFile); // 读取高度

54个字节以后,如果是16色或256色BMP,则还有一个颜色表,但24位色BMP没有这

个,我们这里不考虑。接下来就是实际的像素数据了。24位色的BMP文件中,每三个字节表示一个像素的颜色。

注意,OpenGL通常使用RGB来表示颜色,但BMP文件则采用BGR,就是说,顺序被反过来了。

另外需要注意的地方是:像素的数据量并不一定完全等于图象的高度乘以宽度乘以每一像素的字节数,而是可能略大于这个值。原因是BMP文件采用了一种“对齐”的机制,每一行像素数据的长度若不是4的倍数,则填充一些数据使它是4的倍数。这样一来,一个17*15的24位BMP大小就应该是834字节(每行17个像素,有51字节,补充为52字节,乘以15得到像素数据总长度780,再加上文件开始的54字节,得到834字节)。分配内存时,一定要小心,不能直接使用“图象的高度乘以宽度乘以每一像素的字节数”来计算分配空间的长度,否则有可能导致分配的内存空间长度不足,造成越界访问,带来各种严重后果。 一个很简单的计算数据长度的方法如下:

int LineLength, TotalLength;

LineLength = ImageWidth * BytesPerPixel; // 每行数据长度大致为图象宽度乘以 // 每像素的字节数

while( LineLength % 4 != 0 ) // 修正LineLength使其为4的倍数 ++LineLenth;

TotalLength = LineLength * ImageHeight; // 数据总长 = 每行长度 * 图象高度

这并不是效率最高的方法,但由于这个修正本身运算量并不大,使用频率也不高,我们就不需要再考虑更快的方法了。 2、简单的OpenGL像素操作

OpenGL提供了简洁的函数来操作像素:

glReadPixels:读取一些像素。当前可以简单理解为“把已经绘制好的像素(它可能已经被保存到显卡的显存中)读取到内存”。

glDrawPixels:绘制一些像素。当前可以简单理解为“把内存中一些数据作为像素数据,进行绘制”。

glCopyPixels:复制一些像素。当前可以简单理解为“把已经绘制好的像素从一个位置复制到另一个位置”。虽然从功能上看,好象等价于先读取像素再绘制像素,但实际上它不需要把已经绘制的像素(它可能已经被保存到显卡的显存中)转换为内存数据,然后再由内存数据进行重新的绘制,所以要比先读取后绘制快很多。

这三个函数可以完成简单的像素读取、绘制和复制任务,但实际上也可以完成更复杂的任务。当前,我们仅讨论一些简单的应用。由于这几个函数的参数数目比较多,下面我们分别介绍。 3、glReadPixels的用法和举例 3.1 函数的参数说明

该函数总共有七个参数。前四个参数可以得到一个矩形,该矩形所包括的像素都会被读取出来。(第一、二个参数表示了矩形的左下角横、纵坐标,坐标以窗口最左下角为零,最右上

角为最大值;第三、四个参数表示了矩形的宽度和高度)

第五个参数表示读取的内容,例如:GL_RGB就会依次读取像素的红、绿、蓝三种数据,GL_RGBA则会依次读取像素的红、绿、蓝、alpha四种数据,GL_RED则只读取像素的红色数据(类似的还有GL_GREEN,GL_BLUE,以及GL_ALPHA)。如果采用的不是RGBA颜色模式,而是采用颜色索引模式,则也可以使用GL_COLOR_INDEX来读取像素的颜色索引。目前仅需要知道这些,但实际上还可以读取其它内容,例如深度缓冲区的深度数据等。 第六个参数表示读取的内容保存到内存时所使用的格式,例如:GL_UNSIGNED_BYTE会把各种数据保存为GLubyte,GL_FLOAT会把各种数据保存为GLfloat等。

第七个参数表示一个指针,像素数据被读取后,将被保存到这个指针所表示的地址。注意,需要保证该地址有足够的可以使用的空间,以容纳读取的像素数据。例如一幅大小为256*256的图象,如果读取其RGB数据,且每一数据被保存为GLubyte,总大小就是:256*256*3 = 196608字节,即192千字节。如果是读取RGBA数据,则总大小就是256*256*4 = 262144字节,即256千字节。

注意:glReadPixels实际上是从缓冲区中读取数据,如果使用了双缓冲区,则默认是从正在显示的缓冲(即前缓冲)中读取,而绘制工作是默认绘制到后缓冲区的。因此,如果需要读取已经绘制好的像素,往往需要先交换前后缓冲。

再看前面提到的BMP文件中两个需要注意的地方:

3.2 解决OpenGL常用的RGB像素数据与BMP文件的BGR像素数据顺序不一致问题 可以使用一些代码交换每个像素的第一字节和第三字节,使得RGB的数据变成BGR的数据。当然也可以使用另外的方式解决问题:新版本的OpenGL除了可以使用GL_RGB读取像素的红、绿、蓝数据外,也可以使用GL_BGR按照相反的顺序依次读取像素的蓝、绿、红数据,这样就与BMP文件格式相吻合了。即使你的gl/gl.h头文件中没有定义这个GL_BGR,也没有关系,可以尝试使用GL_BGR_EXT。虽然有的OpenGL实现(尤其是旧版本的实现)并不能使用GL_BGR_EXT,但我所知道的Windows环境下各种OpenGL实现都对GL_BGR提供了支持,毕竟Windows中各种表示颜色的数据几乎都是使用BGR的顺序,而非RGB的顺序。这可能与IBM-PC的硬件设计有关。

3.3 消除BMP文件中“对齐”带来的影响

实际上OpenGL也支持使用了这种“对齐”方式的像素数据。只要通过glPixelStore修改“像素保存时对齐的方式”就可以了。像这样: int alignment = 4;

glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);

第一个参数表示“设置像素的对齐值”,第二个参数表示实际设置为多少。这里像素可以单字节对齐(实际上就是不使用对齐)、双字节对齐(如果长度为奇数,则再补一个字节)、四字节对齐(如果长度不是四的倍数,则补为四的倍数)、八字节对齐。分别对应alignment的值为1, 2, 4, 8。实际上,默认的值是4,正好与BMP文件的对齐方式相吻合。


OpenGL颜色(4).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:江苏省南通市通州区金北学校九年级物理上册 14.1 电阻学案

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: