现在的位置: 首页 > 综合 > 正文

OpenGL编程指南第八章:绘制像素、位图、字体和图像

2012年08月23日 ⁄ 综合 ⁄ 共 5176字 ⁄ 字号 评论关闭

这里的位图(bitmap)单bit每像素的阵列。这一章主要讲解如何把位图、图像绘制到帧缓冲区,以及如何从缓冲区读取像素数据。

1、bitmap

位图是0和1组成的矩形阵列,一般作为绘图时的遮罩。如果当前的的颜色是红色,当你使用glBitmap绘制一个位图时,1的位置绘制红色像素,而0的位置被忽略。位图常见的用途是绘制字体。
位图数据必需是8bit的整数倍,当然位图的实际宽度无此要求。位图数据的排列顺序是从下至上,从左至右:首先是位图的底部一行,再往上一行,如此一直到顶部一行。

api glRasterPos*()设置位图、图像将要绘制的坐标位置(对应图像左下角的位置),这个位置和glVertex*()设置的顶点位置一样,会经过各种矩阵变换。
另一个函数glWindowPos*可以直接再窗口坐标系内指定位置。
 glBitmap(GLsizei width, GLsizei height,GLfloat xbo, GLfloat ybo,GLfloat xbi, GLfloat ybi,const GLubyte *bitmap)绘制位图:width是位图宽度,height是位图高度,这两个值没有要求是8的倍数;xbo和ybo是设定相对于raster
position的一个偏移;xbi和ybi再绘制完成后把当前的raster position移动一定的距离;最后bitmap参数就是位图数据的指针。

raster颜色的设置实际上发生的glRasterPos或glWindowPos被调用时,此时之前glColor所设置的颜色会被当作raster的颜色,如果之后再通过glColor设置别的颜色,并不会影响到当前的raster颜色。可以通过getFloatv(GL_CURRENT_RASTER_COLOR)来查询这个值。

2、image

图像相比位图,包含完整的像素数据,比如RGBA值。图像来自照相机、或其他软件,或从framebuffer读取。自然地,可能认为应该从color buffer读取图像数据,实际上depth buffer,stencil buffer都可以读取。
图像可以直接显示,也可以作为纹理应用。
不同的帧缓冲区有不同的数据格式,本地图像数据也可能有不同格式,这样在做数据搬移时就需要考虑不同的像素数据格式并进行数据转换。

基本API
glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,GLenum format, GLenum type, GLvoid *pixels),从帧缓冲区读取像素数据到本地内存:
x,y 是窗口坐标位置,欲读取区块的左下角;
width,height:读取区块的大小;
format:实际指示了读取的目标数据,比如GL_RG是说读取颜色缓冲区的每个像素的Red和Green颜色分量,GL_ALPHA则只读取单独的alpha分量,GL_DEPTH_COMPONENT读取depth buffer的值,等等;
type:读取的每个像素的数据在本地内存的存储格式,比如GL_UNSIGNED_INT是说每个像素的每个分量占32位,GL_UNSIGNED_INT_8_8_8_8是说每个元素占32位,数据的每个成员分量占8位,GL_UNSIGNED_SHORT_5_6_5则是一个16位的格式,诸如此类请参考手册。这个参数值应该和format相对应,并不是可以随意组合。
pixels:本地内存指针。
读取数据的过程中会发生数据的映射转换,假设帧里面的颜色数据是浮点形的,要被读入一个8位的整形,那么这个数据会进行映射。像素数据的各成员如果被打包成一个整形,正常是第一个成员放置在高位,最后一个成员放置在低位;但如果type参数是*_REV这样的形式,那么这个顺序就是反过来的。

glDrawPixels(GLsizei width, GLsizei height, GLenum format,GLenum type, const GLvoid *pixels),从本地缓存写像素数据到帧缓冲区,参数含义参考glReadPixels。
glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height,GLenum buffer);:从帧缓冲区的一个位置拷贝一个区域至另一个位置:
x,y:源数据的位置;
width,height:源数据的大小;
buffer:读取那种buffer,颜色、深度....
写入的目标位置由glRasterPos指定。

注意,后两个API欲写入的数据还是要经过Rasterization和片段处理两个阶段的。
像素数据pack&unpack
把像素数据从frame buffer读取出来存储的本地的数据转换过程叫pack,反过来就是unpack。
本地存储可能随不同的硬件平台有所区别,比如不同的平台有不同的字节序,不同的字节对齐要求。还有就是你可能想显示图像中间的某一部分。这些功能都通过glPixelMode*()来完成。
glPixelStore*(GLenum pname, TYPE param)定义了图像数据在内存中的一些特性,影响到glDrawPixels(),glReadPixels(), glBitmap(), glPolygonStipple(), glTexImage*()等API的行为。pname是属性明,param是属性值,可能的pname包括:
GL_(UN)PACK_SWAP_BYTES:影响到数据的字节序,当然只会影响多字节元素类型,如果没有定义了这个属性,则会反转元素的字节序;
GL_(UN)PACK_LSB_FIRST:影响到单bit每像素的位图或图像数据,如果设置为false,则数据存储高位优先,否则低位优先;
GL_(UN)PACK_ROW_LENGTH:如果只想显示图像一个子矩形部分,那么在glDrawPixel的宽度、高度值应该是欲显示的宽度高度,那么这个参数可以指明图像数据的真实宽度,否则不能正确定位数据元素;
GL_(UN)PACK_SKIP_PIXELS:和上一属性结合使用,每行数据忽略前几个像素;
GL_(UN)PACK_SKIP_ROWS:和上一属性结合使用,图像数据忽略前几行;
GL_(UN)PACK_ALIGNMENT:每行图像数据的字节对齐,默认值是4。
像素传输操作(Pixel-Transfer Operations)
在像素数据从内存往framebuffer传输的时候,可能需要对数据进行一些处理,比如把颜色浮点数进行scale,offset等。通过glPixelTransfer*()和glPixelMap*()两个API完成。
glPixelTransfer{if}(GLenum pname, TYPE param):pname操作名,param操作参数,pname的可能取值很多,下面仅举几例。
GL_MAP_COLOR :开启颜色映射,稍后讲
GL_MAP_STENCIL:stencil映射;
GL_RED_SCALE:颜色red分量scale;
GL_RED_BIAS:颜色red分量偏移。
glPixelMap{ui us f}v(GLenum map, GLint mapsize,const TYPE *values),映射操作,需要先通过上一api开启,map是映射的类型,mapsize和values分别是映射表的大小和数据。
ZOOM
在上述操作之后的rasterization阶段,可以对像素矩形进行zoom操作,达到放大,缩小,翻转的目的。
glPixelZoom(GLfloat zoomx, GLfloat zoomy):x和y反向的zoom参数,可以为负数,拉升都是相对起点(glRasterPos所设立的位置)进行的。
在Rasterization的过程中,每个像素数据对应一个(zoomx,zoomy)的矩形,这个矩形内的fragement都基于这个像素数据产生。
使用BO
使用BO可以减少图像数据的传送,提高效率。
BO的使用和前面章节所述类似,以drawPixel为例:
生成BO名字:glGenBuffers(1, &pixelBuffer); 
绑定BO:glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixelBuffer);
初始化BO数据:glBufferData(GL_PIXEL_UNPACK_BUFFER,size,imageData, GL_STATIC_DRAW);
使用BO绘图:glDrawPixels(width, height, GL_RGB,GL_UNSIGNED_BYTE, BUFFER_OFFSET(0)); //已绑定BO

3、image subset

image subset是Opengl的一个扩展,提供glPixelTransfer和glPixelMap额外的像素处理功能。在像素数据传入/传出OpenGl的时候,都可以被image subset处理:
1、使用color table替换像素值;
2、使用卷积过滤图像;
3、使用颜色矩阵进行颜色转换;
4、收集图像的统计数据。
Color Tables
color table是用于颜色替换的查找表,可以应用于进行对比度调节、滤镜、图像均横。
有三种table,分别在不同的阶段起作用(请参考原书),GL_COLOR_TABLE,GL_POST_CONVOLUTION_COLOR_TABLE ,
GL_POST_COLOR_MATRIX_COLOR_TABLE。
创建color table
glColorTable(GLenum target, GLenum internalFormat,GLsizei width, GLenum format, GLenum type,const GLvoid *data)
target:table类型
internalFormat :指定和进行何种替换;
format和type与glDrawPixels一致;

读取帧缓冲区创建table
void glCopyColorTable(GLenum target, GLenum internalFormat,GLint x, GLint y, GLsizei width);

修改color table(部分)数据
glColorSubTable(GLenum target, GLsizei start, GLsizei count,GLenum format, GLenum type,const GLvoid *data);
glCopyColorSubTable(GLenum target, GLsizei start, GLint x,GLint y, GLsizei count);

获取colortable数据
glGetColorTable();
Convolution(卷积)
卷积是一种用像素及周边像素值的加权组合结果来替换像素值的运算。可以实现模糊、锐化等效果。
卷积运算的核心是一个矩阵,矩阵的元素是数字值,运算的过程就是使用矩阵中的值与对应位置的像素进行相乘再求和,得出新的像素值。

定义卷积: glConvolutionFilter2D(GLenumtarget,
GLenuminternalFormat,GLsizeiwidth,
GLsizeiheight,
GLenumformat,
GLenumtype,const GLvoid *image);  

从帧缓冲读取像素值以定义卷积:glCopyConvolutionFilter2D(GLenumtarget,GLenuminternalFormat,GLintx,
GLinty,GLsizeiwidth,
GLsizeiheight); 


定义卷积相关参数,比如边缘模式等glConvolutionParameter{if}(GLenumtarget,
GLenumpname,TYPE param); 


Color Matrix

颜色矩阵是一个4*4的矩阵,用来对像素颜色进行线性变换,比如颜色空间的变换。

使用方式:glMatrixMode(GL_COLOR);

                     glLoadMatrix(matrixdata);

Histogram

用于对图像颜色进行统计,使用方法:

定义histogram: glHistogram(GLenumtarget,
GLsizeiwidth,GLenuminternalFormat, GLbooleansink); 

收集histogram数据glGetHistogram(GLenumtarget, GLboolean reset, GLenum format,GLenum
type, GLvoid *values); 

MinMax

和histogram类似,统计图像颜色的最大值和最小值


抱歉!评论已关闭.