原始图像数据

来源:互联网 发布:linux 司机售票员问题 编辑:程序博客网 时间:2024/04/30 19:30

位图:图像数据都是由位图(一系列表示开启和关闭像素值的0和1)表示的。在位图中,每个内存块中的每个位都与屏幕上某个像素的状态一一对应。图5-2

像素图:由像素组成的矩形中,每个像素都显示了256个不同深度的灰色中的一种。图5-3



----------- 像素包装

        在默认情况下,OpenGL采用4个字节的对齐方式,这种方式适合于很多目前正在使用的系统。很多程序员简单地将图像宽度值乘以高度值,在乘以每个像素的字节数,这样就错误判断了存储一个图像所需的存储器数量。一副RGB图像,包含3个分量(一个红色分量、一个绿色分量和一个蓝色分量),每个分量都存储在一个字节中(每个颜色通道8位,实际上这是非常典型的情况),那么,如果图像的宽度为199个像素,图像的没一会需要多少存储空间呢。199*3(三个颜色通道个需要一个字节),结果应该是图像数据的每一行需要597个字节。这也许是对的。如果硬件本身的体系结构是4字节排列的(大部分是这样的),那么图像每一行的末尾都将有额外的3个空字节进行填充(这就使每一行都有了600个字节),而这只是为了使每一行的存储器从一个能够被4整除的地址开始。

    许多未经压缩的图像文件格式也都遵循这种惯例。Windows中的.BMP文件格式的像素数据使用4字节排列;然而Targa(.TAG)文件格式则是1个字节排列的……这样不会浪费空间。内存分配意图对于OpenGL来说这样重要?这是因为,在我们向OpenGL提交图像数据或从OpenGL获取图像数据时,OpenGL需要知道我们想要在内存中对数据进行怎样的包装或解包。

     图像数据在内存中很少以紧密包装的形式存在。在许多硬件平台上,处于性能上的考虑,一副图像的每一行都应高从一个特定的字节对齐地址开始。绝大多数编译器会自动吧变量和缓冲区放置在一个针对该架构对齐优化的地址上。

    我们想要改成紧密包装的像素数据,应该这样调用函数

    getPixelStorei(GL_UNPACK_ALIGNMENT,1);

    其中GL_UNPACK_ALIGNMENT指定OpenGL如何从数据缓冲区中解包图像数据。

    类似的,我们可以用GL_PACK_ALIGNMENT来告诉OpenGL如何将从像素缓冲区中读取并放置到一个用户指定的内存缓冲区的数据进行包装。

    

    可以用下列函数改变或者恢复像素的存储方式。

    getPixelStorei(GLenum pname,GLint param);

    getPixelStoref(GLenum pname,GLint param);


   表5.1 列出了这个函数支持的像素存储模式的完整列表。附录C 有详细讨论。


------------- 像素图

     像素图在内存布局上与位图非常相似,但是每个像素将需要一个以上的存储位来表示。每个像素的附加位允许存储强度(intensity ,有时被称为亮度,即 luminance值)或者颜色分量值。在OpenGL核心版本中,我们无法直接将一个像素图绘制到颜色缓冲区中,但是可以使用下面的函数将颜色缓冲区的内容作为像素图直接读取。

     void glReadPixels(GLint x,GLint y,GLSuzei width,GLSizei height,GLenum format,GLenum type,const void *pixels);

     x和y值指定为矩形左下角的窗口坐标,然后再指定矩形的width和height值(像素形式)。如果颜色缓冲区存储的数据与我们要求的不同,OpenGL将负责进行必要的转换。

    这种能力会非常有用。指向图像数据的指针*pixels必须是合法的,并且必须包含足够的存储空间来存储转换后的图像数据,否则我们可能就会遇到严重的内存运行时异常。我们还要注意,如果指定的窗口坐标超出了允许的范围,那么只能获得实际OpenGL帧缓冲区内像素的数据。

    第四个参数format,指定pixels指向的数据元素的颜色布局。表5.2

    type 参数解释参数pixels指向的数据,它告诉OpenGL使用缓冲区中的什么数据类型来存储颜色分量。表5.3列出了使用的值。


    glReadPixels从图形硬件中复制数据,通常通过总线传输到系统内存。在这种情况下,应用程序将被阻塞,知道内存传输完成。此外,如果我们指定一个与图形硬件的本地排列不同的像素布局,那么在数据进行重定格式时讲产生额外的性能开销。


----------------包装的像素格式

     包装的像素格式将颜色数据压缩到了尽可能少的存储位中,每个颜色通道的位数显示在常量中。指定的分量(红、绿、蓝和Alpha)的排列顺序仍然是根据format 参数确定的。


    UNSIGNED_BYTE_3_3_2

    7   6    5         4     3     2        1     0

   第一个分量     第二个分量      第三个分量


    UNSIGNED_BYTE_2_3_3_REV

    7   6               5     4     3         2     1     0

   第一个分量     第二个分量      第三个分量


两种包装像素格式的布局示例


    对于glReadPixels 函数来说,读取操作在双缓冲区渲染环境下将在后台缓冲区进行,而在单缓冲区渲染环境下则在前台缓冲区进行。下面函数改变像素操作的源。


     void glReadBuffer(GLenum mode);

   模式的参数GL_FRONT、GLBACK 等。



-------------保存像素






0 0
原创粉丝点击