opengl将bmp读成像素_OpenGL像素操作

本文介绍了OpenGL如何处理像素,特别是如何读取24位色不压缩的BMP文件并进行显示。讲解了BMP文件格式、像素数据的对齐问题,以及如何使用glReadPixels、glDrawPixels、glCopyPixels进行像素操作。通过示例代码展示了读取BMP像素数据并保存为新的BMP文件,以及如何在OpenGL中绘制BMP图象。
摘要由CSDN通过智能技术生成

今天我们先简单介绍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;  //数据总长=每行长度*图象高度

这并不是效率最高的方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值