OpenGL绘制Bmp图片

合集下载

opengl学习(三)----绘制简单图形(一)

opengl学习(三)----绘制简单图形(一)

opengl学习(三)----绘制简单图形(⼀)今天说⼀说⼏种简单的图元。

所有的⼏何图元都是根据它们的顶点来描绘的。

⽽顶点就是它们在屏幕上的坐标位置。

我喜欢把这⼏个简单的图元称为点线⾯。

点,可以看到⼀个顶点;线,就是两个顶点指定的⼀条有限长度的线段;⾯,其实更准确讲是⼀个凸多边形。

opengl⾥所讲的多边形是内部⽤颜⾊填充的,视觉上称为⾯我个⼈认为是更贴近的。

当然,多边形也是由指定的顶点组成的。

需要注意的是,要想被opengl按照设计被绘制必须正确的认识到,所谓的多边形是顶点都处于⼀个平⾯上,凸多边形。

凸多边形不能理解的,请问度娘。

来看⼀个例⼦:C++代码1. glBegin(GL_POLYGON);2. glVertex2f(0.0, 0.0);3. glVertex2f(0.0, 3.0);4. glVertex2f(4.0, 3.0);5. glVertex2f(6.0, 1.5);6. glVertex2f(4.0, 0.0);7. glEnd();先不去关⼼代码本⾝,这段代码最终的结果是要指定5个顶点绘制⼀个凸五边形。

注意,不是5条线段⽽是⼀个凸五边形的平⾯。

不管是点线⾯的哪⼀种,都是需要指定⼀组顶点的。

如何判定顶点指定的开始和结束就是glBegin和glEnd的⼯作。

引⽤void glBegin(Glenum mode);标志着⼀个顶点数据列表的开始,它描述了⼀个⼏何图元。

mode参数指定了图元的类型。

void glEnd(void);标志着⼀个顶点数据列表的结束。

mode设置的不同,代表着将要绘制的图元也不同。

下⾯这个表就是图元的名称和含义:值含义GL_POINTS 单个的点GL_LINES ⼀对顶点被解释为⼀条直线GL_LINE_STRIP ⼀系列的连接直线GL_LINE_LOOP 和上⾯相同,但第⼀个顶点和最后⼀个顶点彼此相连GL_TRIANGLES 3个顶点被解释为⼀个三⾓形GL_TRIANGLES_STRIP 三⾓形的连接串GL_TRIANGLES_FAN 连接成扇形的三⾓形系列GL_QUADS 4个顶点被解释为⼀个四边形GL_QUADS_STRIP 四边形的连接串GL_POLYGON 简单的凸多边形的边界试想着,如果将glBegin(GL_POLYGON)修改为glBegin(GL_POINTS),绘制出来的将是什么图形呢? 哈哈,那就是5个点⽽已么。

OpenGL绘制Bmp图片

OpenGL绘制Bmp图片

二维坐标OpenGL一、定义二维坐标的尺度:void gluOrtho2D(left, right, top, bottom);四个参数分别代表(左下角x坐标,右上角x坐标,左下角y坐标,右上角y坐标)。

例如,对于一个640*480的窗口,可以指定如下的坐标尺度:gluOrtho2D(-320, 320, -240, 240);或者gluOrtho2D(0, 640, 0, 480);等等。

具体的使用为:int main(int argc, char *argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);glutInitWindowPosition(100, 100);glutInitWindowSize(640, 480);glutCreateWindow("图片显示");gluOrtho2D(0, 640, 0, 480);glutDisplayFunc(&myDisplay);glutMainLoop();return 0;}二、OpenGL颜色的选择void glColor3f(GLfloat red, GLfloat green, GLfloat blue);以1.0表示最大的使用。

void glColor3b(GLbyte red, GLbyte green, GLbyte blue);采用b做后缀的函数,以127表示最大的使用。

void glColor3ub(GLuByte red, GLuByte green, GLuByte blue);采用ub做后缀的函数,以255表示最大的使用。

void glColor3s(GLshort red, GLshort green, GLshort blue);采用s做后缀的函数,以32767表示最大的使用。

void glColor3us(GLuShort red, GLuShort green, GLuShort blue); 采用us做后缀的函数,以65535表示最大的使用。

基于OpenGL的三维图形绘制实验

基于OpenGL的三维图形绘制实验

基于OpenGL的三维图形绘制实验基于OpenGL的三维图形绘制实验⽬录实验题⽬:交互图形程序设计基础实验 (3)1.实验⽬的 (3)2.实验内容 (3)2.1 实验内容 (3)2.2 实验任务 (3)3.实验过程 (4)3.1 预处理 (4)3.3 主要函数说明 (5)3.4 过程描述 (6)3.5 运⾏截图 (7)4.实验结果 (7)5.实验体会 (7)实验题⽬:交互图形程序设计基础实验1.实验⽬的1)理解并掌握三维基本图形数据结构表⽰⽅法。

2)掌握编写OpenGL图形程序的基本⽅法.3)掌握OpenGL基本图形表⽰及绘制。

2.实验内容2.1 实验内容基于OpenGL的三维图形绘制实验⽬的是掌握图形信息的表⽰、数据的组织,在此基础上基于OpenGL绘制出三维图形。

实验内容包括OpenGL编程环境搭建、OpenGL程序结构、基本数据类型、核⼼函数等的使⽤;基本图形的绘制(点、线段、折线、闭合折线、多边形、三⾓形、三⾓扇、三⾓条带、四边形、四边形条带等)及图形属性控制(线宽、颜⾊、线型、填充样式等);对指定的若⼲三维模型进⾏建模、绘制,在⼀个程序框架下实现,提交1次程序,1份实验报告。

2.2 实验任务1、使⽤Visual C++建⽴⼀个单⽂档(SDI)程序,完成OpenGL绘制框架程序的设计。

在此基础上参照提供的资料,定义绘制函数,基于⾃定义的若⼲点坐标与颜⾊,分别绘制绘制点、线段、不闭合折线、闭合折线、多边形、三⾓形、四边形、三⾓扇、三⾓条带、四边形条带。

2、使⽤1中建⽴的程序框架,完成如下任务:(1)绘制正棱柱(底⾯多变形的边数及⾼度可以通过对话框输⼊)(2)正棱锥(底⾯多变形的边数及⾼度可以通过对话框输⼊)(3)正棱台(底⾯多变形的边数、台⾼、锥⾼可以通过对话框输⼊)注意模型坐标系的选择和顶点坐标的计算,每个图形的绘制单独写成函数。

加⼊菜单绘制三、四、五、六边的情况,其他边数情况从弹出对话框中输⼊参数,然后绘制。

基于OpenGL的三维动画效果设计与实现

基于OpenGL的三维动画效果设计与实现

基于OpenGL的三维动画效果设计与实现OpenGL是一种跨平台的图形库,广泛应用于计算机图形学、游戏开发和虚拟现实等领域。

在OpenGL的基础上,可以实现各种精美的三维动画效果,如逼真的光影效果、自然的物理模拟和华丽的特效等。

本文将介绍如何基于OpenGL实现三维动画效果。

一、OpenGL简介OpenGL(Open Graphics Library)是一种跨平台的图形库,可以用于开发高性能的3D图形应用程序。

它提供了一套标准的API,程序员可以使用OpenGL库里的函数来绘制各种图形,包括点、线、三角形等。

OpenGL的主要优点是跨平台,程序可以在不同的操作系统和硬件上运行,并且不需要对程序做太多的修改。

二、OpenGL开发环境在开始OpenGL开发之前,需要配置正确的开发环境。

OpenGL的开发环境包括编程语言、OpenGL库、窗口系统和OpenGL的开发工具等。

编程语言:OpenGL支持多种编程语言,如C/C++、Java、Python等。

其中,C/C++是最常用的开发语言,因为它可以直接调用OpenGL的函数库。

OpenGL库:OpenGL库是开发OpenGL程序时必须的工具,它包含了OpenGL 的所有函数和常量。

窗口系统:OpenGL需要一个可视化的窗口系统,用来显示图形界面。

常用的窗口系统有Windows、Linux和MacOS等。

开发工具:开发OpenGL程序需要使用各种IDE和编辑器,如Visual Studio、CodeBlocks和Eclipse等。

三、实现三维动画效果的基础知识1.三维坐标系OpenGL使用右手坐标系表示三维坐标系,其中x轴向右,y轴向上,z轴向外。

2.矩阵变换OpenGL可以通过矩阵变换来实现图形的移动、旋转、缩放等操作。

常用的变换矩阵包括平移矩阵、旋转矩阵和缩放矩阵。

3.光照模型光照模型是OpenGL中重要的概念之一,它用来计算光源对物体的影响。

其中,主要包括光源的位置、光线的颜色和强度等因素。

OpenGL图像保存为bmp文件

OpenGL图像保存为bmp文件

OpenGL图像保存为bmp文件如果我没理解错的话,您需要的应该就是个“截屏”功能吧?如下这段代码是从OpenGL Super Bible中摘抄出来的,我自己加了个writeBMP函数,可以将front color buffer(也就是当前显示的画面)转存为一张bmp格式图片,默认保存在当前目录下。

bool screenshot(const char* filename){GLenum lastBuffer;GLbyte* pBits = 0; // 图像数据unsigned long lImageSize;GLint iViewport[4]; // 视图大小glGetIntegerv(GL_VIEWPORT, iViewport);lImageSize = iViewport[2] * iViewport[3] * 3;pBits = (GLbyte*)new unsigned char[lImageSize];if (!pBits)return false;// 从color buffer中读取数据glPixelStorei(GL_PACK_ALIGNMENT, 1);glPixelStorei(GL_PACK_ROW_LENGTH, 0);glPixelStorei(GL_PACK_SKIP_ROWS, 0);glPixelStorei(GL_PACK_SKIP_PIXELS, 0);//glGetIntegerv(GL_READ_BUFFER, (GLint*)&lastBuffer);glReadBuffer(GL_FRONT);glReadPixels(0, 0, iViewport[2], iViewport[3], GL_BGR_EXT, GL_UNSIGNED_BYTE, pBits);glReadBuffer(lastBuffer);if (writeBMP(filename, (unsigned char*)pBits, iViewport[2], iViewport[3]))return true;return false;}bool writeBMP(const char filename[], unsigned char* data, unsigned int w, unsigned int h){std::ofstream out_file;/** 检查data */if(!data){std::cerr << "data corrupted! " << std::endl;out_file.close();return false;}/** 创建位图文件信息和位图文件头结构 */BITMAPFILEHEADER header;BITMAPINFOHEADER bitmapInfoHeader;//unsigned char textureColors = 0;/**< 用于将图像颜色从BGR 变换到RGB *//** 打开文件,并检查错误 */out_file.open(filename, std::ios::out | std::ios::binary);if (!out_file){std::cerr << "Unable to open file " << filename << std::endl;return false;}/** 填充BITMAPFILEHEADER */header.bfType = BITMAP_ID;header.bfSize = w*h*3 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);header.bfReserved1 = 0;header.bfReserved2 = 0;header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);/** 写入位图文件头信息 */out_file.write((char*)&header, sizeof(BITMAPFILEHEADER));/** 填充BITMAPINFOHEADER */bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);bitmapInfoHeader.biWidth = w;bitmapInfoHeader.biHeight = h;bitmapInfoHeader.biPlanes = 1;bitmapInfoHeader.biBitCount = 24;bitmapInfoHeader.biCompression = BI_RGB; // BI_RLE4 BI_RLE8bitmapInfoHeader.biSizeImage = w * h * 3; // 当压缩类型为BI_RGB是也可以设置为0bitmapInfoHeader.biXPelsPerMeter = 0;bitmapInfoHeader.biYPelsPerMeter = 0;bitmapInfoHeader.biClrUsed = 0;bitmapInfoHeader.biClrImportant = 0;/** 写入位图文件信息 */out_file.write((char*)&bitmapInfoHeader,sizeof(BITMAPINFOHEADER));/** 将指针移到数据开始位置 */out_file.seekp(header.bfOffBits, std::ios::beg);/** 写入图像数据 */out_file.write((char*)data, bitmapInfoHeader.biSizeImage);out_file.close();return true;}我测试过,工作正常。

BMP图像格式详解

BMP图像格式详解

BMP格式图像文件详析首先请注意所有的数值在存储上都是按“高位放高位、低位放低位的原则”,如12345678h放在存储器中就是7856 3412)。

下图是导出来的开机动画的第一张图加上文件头后的16进制数据,以此为例进行分析。

T408中的图像有点怪,图像是在电脑上看是垂直翻转的。

在分析中为了简化叙述,以一个字(两个字节为单位,如424D就是一个字)为序号单位进行,“h”表示是16进制数。

424D 4690 0000 0000 0000 4600 0000 2800 0000 8000 0000 9000 0000 0100*1000 0300 0000 0090 0000 A00F 0000 A00F 0000 0000 0000 0000 0000*00F8 0000 E007 0000 1F00 0000 0000 0000*02F1 84F1 04F1 84F1 84F1 06F2 84F1 06F2 04F2 86F2 06F2 86F2 86F2......BMP文件可分为四个部分:位图文件头、位图信息头、彩色板、图像数据阵列,在上图中已用*分隔。

一、图像文件头1)1:图像文件头。

424Dh=’BM’,表示是Windows支持的BMP 格式。

2)2-3:整个文件大小。

4690 0000,为00009046h=36934。

3)4-5:保留,必须设置为0。

4)6-7:从文件开始到位图数据之间的偏移量。

4600 0000,为00000046h=70,上面的文件头就是35字=70字节。

5)8-9:位图图信息头长度。

6)10-11:位图宽度,以像素为单位。

8000 0000,为00000080h=128。

7)12-13:位图高度,以像素为单位。

9000 0000,为00000090h=144。

8)14:位图的位面数,该值总是1。

0100,为0001h=1。

二、位图信息头9)15:每个像素的位数。

使用opengl程序绘制实线虚线和点划线

使用opengl程序绘制实线虚线和点划线

使用opengl程序绘制实线虚线和点划线OpenGL是一种用于绘制2D和3D图形的跨平台编程接口。

它提供了一套功能强大的函数和工具,可以在各种显示设备上渲染图形。

在OpenGL中,可以使用不同的绘制模式来绘制实线、虚线和点划线。

本文将介绍如何使用OpenGL程序实现这些效果。

在开始之前,我们首先需要安装OpenGL库和开发环境。

OpenGL可以在不同的平台上使用,例如Windows、Linux和macOS。

对于Windows用户,可以使用MinGW或者MSYS2等工具链来配置开发环境。

对于Linux和macOS用户,可以使用GCC和Xcode来配置开发环境。

安装完成后,我们可以开始编写OpenGL程序。

在OpenGL中,绘图是通过一系列函数和状态来实现的。

以下是一个基本的OpenGL程序的框架:```cpp#include <GL/glut.h>void displa//清空屏幕glClear(GL_COLOR_BUFFER_BIT);//设置绘图颜色glColor3f(1.0f, 1.0f, 1.0f);//绘制实线glBegin(GL_LINES);glVertex2f(-0.5f, 0.0f);glVertex2f(0.5f, 0.0f);glEnd(;//绘制虚线//...//绘制点划线//...//刷新缓冲区glutSwapBuffers(;int main(int argc, char** argv)// 初始化窗口和OpenGL环境glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE , GLUT_RGB); glutInitWindowSize(800, 600); glutCreateWindow("OpenGL Program");//注册绘图函数glutDisplayFunc(display);//进入主循环glutMainLoop(;return 0;```在以上程序中,`glClear(GL_COLOR_BUFFER_BIT)`用于清空屏幕,`glColor3f(1.0f, 1.0f, 1.0f)`用于设置绘图颜色。

C语言实现OpenGL渲染

C语言实现OpenGL渲染

C语言实现OpenGL渲染OpenGL是一种强大的图形渲染API(应用程序接口),它可用于创建高性能的2D和3D图形应用程序。

在本文中,我们将探讨如何使用C语言实现OpenGL渲染。

1. 初始化OpenGL环境在开始之前,我们需要初始化OpenGL环境。

这可以通过以下步骤完成:1.1. 创建窗口使用C语言中的窗口创建库(如GLUT或GLFW)创建一个可见的窗口。

这个窗口将充当我们OpenGL渲染的目标。

1.2. 设置视口使用glViewport函数将窗口的尺寸设置为需要进行渲染的大小。

视口定义了OpenGL将渲染的区域。

1.3. 创建正交投影或透视投影矩阵使用glOrtho或gluPerspective函数创建透视或正交投影矩阵。

投影矩阵将定义OpenGL渲染的视图。

2. 渲染基本图形一旦我们初始化了OpenGL环境,我们可以开始渲染基本图形。

以下是一些常见的基本图形渲染函数:2.1. 绘制点使用glBegin和glEnd函数,以及glVertex函数,可以绘制一个或多个点。

2.2. 绘制线段使用glBegin和glEnd函数,以及glVertex函数,可以绘制一条或多条线段。

2.3. 绘制三角形使用glBegin和glEnd函数,以及glVertex函数,可以绘制一个或多个三角形。

2.4. 绘制多边形使用glBegin和glEnd函数,以及glVertex函数,可以绘制一个或多个多边形。

3. 设置光照效果为了给渲染的图形添加逼真感,可以设置光照效果。

以下是一些常见的光照函数:3.1. 设置光源使用glLight函数,可以设置光源的位置、光照颜色等参数。

3.2. 设置材质属性使用glMaterial函数,可以设置渲染对象的表面材质属性,如漫反射、镜面反射等。

3.3. 使用光照模型使用glShadeModel函数,可以选择光照模型,如平滑光照模型或平面光照模型。

4. 纹理映射纹理映射能够使渲染的图形更逼真。

OpenGL入门教程(精)

OpenGL入门教程(精)

4、把解压得到的 glut.dll 和 glut32.dll 放到操作系统目录下面的 system32 文件夹内。(典型的位置为: C:\Windows\Sy st em32) 第三步,建立一个 OpenGL 工程 这里以 VisualStudio2005 为例。 选择 File->New->Project,然后选择 Win32 Console Application,选择一个名字,然后按 OK。 在谈出的对话框左边点 Application Settings,找到 Empty project 并勾上,选择 Finish。 然后向该工程添加一个代码文件,取名为“OpenGL.c”,注意用.c 来作为文件结尾。 搞定了,就跟平时的工程没什么两样的。 第一个 OpenGL 程序
在 glutDisplayFunc 函数中,我们设置了“当需要画图时,请调用 myDisplay 函数”。于是 myDisplay 函数就 用来画图。观察 myDisplay 中的三个函数调用,发现它们都以 gl 开头。这种以 gl 开头的函数都是 OpenGL 的标准函数,下面对用到的函数进行介绍。 1、glClear,清除。GL_COLOR_BUFFER_BIT 表示清除颜色,glClear 函数还可以清除其它的东西,但这里 不作介绍。 2、glR ect f,画一个矩形。四个参数分别表示了位于对角线上的两个点的横、纵坐标。 3、glFlush,保证前面的 OpenGL 命令立即执行(而不是让它们在缓冲区中等待)。其作用跟 fflush(stdout) 类似。
OpenGL 入门教程
1.第一课:
说起编程作图,大概还有很多人想起 TC 的#include < graphics.h>吧? 但是各位是否想过,那些画面绚丽的 PC 游戏是如何编写出来的?就靠 TC 那可怜的 640*480 分辨率、16 色来做吗?显然是不行的。

OpenGL教程009_纹理映射

OpenGL教程009_纹理映射

纹理映射(Texture Mapping,/wiki/Texture_mapping)是⼀一种中等难度的渲染⽅方法。

其基本思路是将⼀一张或者⼏几张图⽚片作为纹理,将其贴在模型表⾯面。

纹理映射的算法实在是⾮非常简单。

⽤用OpenGL实现纹理映射,最⼤大的难度不在于OpenGL,⽽而在于如何加载图⽚片!⽤用C++读取图⽚片有很多库可以选择,例如CImg、ImageStone和OpenCV之类的。

这些库都是跨平台的,但使⽤用起来过于复杂。

于是我找了⼀一个简单的库EasyBMP(/projects/easybmp/?source=directory),只能读取BMP 数据,够⽤用也跨平台。

所需要的就是将纹理图全部转换为BMP格式,⽤用图像处理软件很容易做到这⼀一点。

我们引⼊入⼀一个新的函数来加载纹理://加载纹理GLuint const char//使⽤用EasyBMP加载纹理图⽚片//使⽤用什么库没有关系,最终纹理需要⽣生成⼀一个数组,数组的格式如下://{r1,g1,b1,r2,g2,b2,...,rn,gn,bn},其中ri,gi,bi表⽰示i位置的//像素点的rgb值。

如果图像由alpha值,数组的格式如下://{r1,g1,b1,a1,r2,g2,b2,a2,...,rn,gn,bn,an}BMPReadFromFileint TellWidthint TellHeightunsigned char new unsignedchar3int0for int0for int0row col Redrow col Greenrow col Blue//创建纹理,并将纹理数据传递给OpenGLGLuint1glGenTextures1glBindTexture GL_TEXTURE_2D0//设置纹理参数glTexParameteri GL_TEXTURE_2D GL_TEXTURE_WRAP_S GL_REPEATglTexParameteri GL_TEXTURE_2D GL_TEXTURE_WRAP_T GL_REPEATglTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTERGL_LINEARglTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTERGL_LINEAR//传输数据glTexImage2D GL_TEXTURE_2D0GL_RGB0GL_RGB GL_UNSIGNED_BYTE deletereturn0加载纹理通常分为以下⼏几个步骤:(1)⽤用图像处理库(这⾥里是EasyBMP)读取纹理⽂文件。

位图文件(BMP)格式分析以及程序实现

位图文件(BMP)格式分析以及程序实现

inf.read((char*)&header, sizeof(header));if(header.bfType != 0x4D42)return false;这个很简单,没有什么好说的。

2、加载位图信息头//Load the image information headerBITMAPINFOHEADER infoheader;memset(&infoheader, 0, sizeof(infoheader));inf.read((char*)&infoheader, sizeof(infoheader));m_iImageWidth = infoheader.biWidth;m_iImageHeight = infoheader.biHeight;m_iBitsPerPixel = infoheader.biBitCount;这里我们得到了3各重要的图形属性:宽,高,以及每个像素颜色所占用的位数。

3、行对齐由于Windows在进行行扫描的时候最小的单位为4个字节,所以当图片宽X 每个像素的字节数!= 4的整数倍时要在每行的后面补上缺少的字节,以0填充(一般来说当图像宽度为2的幂时不需要对齐)。

位图文件里的数据在写入的时候已经进行了行对齐,也就是说加载的时候不需要再做行对齐。

但是这样一来图片数据的长度就不是:宽X 高X 每个像素的字节数了,我们需要通过下面的方法计算正确的数据长度://Calculate the image data sizeint iLineByteCnt = (((m_iImageWidth*m_iBitsPerPixel) + 31) >> 5) << 2;m_iImageDataSize = iLineByteCnt * m_iImageHeight;4、加载图片数据对于24位和32位的位图文件,位图数据的偏移量为sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER),也就是说现在我们可以直接读取图像数据了。

用OpenGL进行曲线、曲面的绘制

用OpenGL进行曲线、曲面的绘制

⽤OpenGL进⾏曲线、曲⾯的绘制实验⽬的理解Bezier曲线、曲⾯绘制的基本原理;理解OpenGL中⼀维、⼆维插值求值器的⽤法。

掌握OpenGL中曲线、曲⾯绘图的⽅法,对⽐不同参数下的绘图效果差异;代码1:⽤四个控制点绘制⼀条三次Bezier曲线#include "stdafx.h"#include <stdlib.h>#include <time.h>#include <GL/glut.h>//4个控制点的3D坐标——z坐标全为0GLfloat ctrlpoints[4][3] = {{ -4, -4, 0 }, { -2, 4, 0 }, { 2, -4, 0 }, { 4, 4, 0 }};void init(void){//背景⾊glClearColor(0.0, 0.0, 0.0, 1.0);//将控制点坐标映射为曲线坐标//参数1:GL_MAP1_VERTEX_3,3维点坐标//参数2和3:控制参数t或u的取值范围[0, 1]//参数4:曲线内插值点间的步长3————3维坐标//参数5:曲线间的补偿为顶点数4个————总步长为12//参数6:控制点⼆维数组⾸元素地址//注意: 若是在这⾥设置了相关参数,后续对ctrlpoints内容更改曲线不变glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);//打开开关——允许3维坐标控制点到参数点转换开关glEnable(GL_MAP1_VERTEX_3);glShadeModel(GL_FLAT);//代码开关2:去掉本注释,可启⽤反⾛样/*glEnable(GL_BLEND);glEnable(GL_LINE_SMOOTH); //允许直线反⾛样glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST); // Antialias the linesglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);*/}void display(void){int i;glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 1.0, 1.0);//代码开关1:去掉本注释,查看动态的曲线绘图效果:动态更新控制点坐标/*for(int t = 0; t < 4; t++) {for(int j = 0; j < 3; j++)ctrlpoints[t][j] = (rand() % 1024 / 1024.0 - 0.5) * 10;}//动态映射glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);*/glLoadIdentity();glColor3f(1.0, 0.0, 0.0);//绘制连续线段glBegin(GL_LINE_STRIP);//参数t或u取值为i/30,共计31个点for (i = 0; i <= 30; i++)glEvalCoord1f((GLfloat)i / 30.0); //根据4个控制点坐标的参数化插值glEnd();/* 显⽰控制点 */glPointSize(5.0);glBegin(GL_POINTS);for (i = 0; i < 4; i++)glVertex3fv(&ctrlpoints[i][0]);glEnd();glTranslatef(-0.1f, 0.1f, 0.0f);glColor3f(0.0, 1.0, 0.0);//glLineWidth(2.0);//绘制连续线段——线段数越多,曲线越光滑glBegin(GL_LINE_STRIP);//设置参数t或u取值为i/60,共计61个点//实验:若让t从-2变化到+2,可看到什么效果for (i = 0; i <= 60; i++)glEvalCoord1f((GLfloat)i / 60.0); //根据4个控制点坐标的参数化插值glEnd();glTranslatef(-0.1f, 0.1f, 0.0f);glColor3f(1.0, 1.0, 1.0);//绘制连续线段glBegin(GL_LINE_STRIP);//设置参数t或u取值为i/60,共计61个点//实验:若让t从-2变化到+2,可看到什么效果for (i = 0; i <= 100; i++)glEvalCoord1f((GLfloat)i / 100.0);glEnd();glutSwapBuffers();}//3D空间中绘制2D效果,采⽤正交投影void reshape(GLsizei w, GLsizei h){glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if (w <= h)glOrtho(-5.0, 5.0, -5.0*(GLfloat)h / (GLfloat)w, 5.0*(GLfloat)h / (GLfloat)w, -5.0, 5.0);elseglOrtho(-5.0*(GLfloat)w / (GLfloat)h, 5.0*(GLfloat)w / (GLfloat)h, -5.0, 5.0, -5.0, 5.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();}void keyboard(unsigned char key, int x, int y){switch (key){case'x':case'X':case27: //ESC键exit(0);break;default:break;}}int main(int argc, char** argv){srand((unsigned int)time(0));glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);//使⽤双缓存模式和深度缓存 glutInitWindowSize(800, 800);glutInitWindowPosition(0, 0);glutCreateWindow("2D Bezier曲线");init();glutDisplayFunc(display);glutReshapeFunc(reshape);glutKeyboardFunc(keyboard);glutIdleFunc(display);//设置空闲时调⽤的函数glutMainLoop();return0;}此时我们打开代码开关1,查看动态Bezier曲线绘制效果:关闭代码开关1,打开代码开关2,查看直线反⾛样效果:对⽐刚开始的效果图,我们发现,使⽤了直线反⾛样后,绘制出的曲线很光滑,看着很舒服。

OpenGL三维图形编程基础

OpenGL三维图形编程基础
2009年3月又公布了升级版新规范OpenGL 3.1,也是这套跨平台免费API有史以来的第九次更新。 OpenGL 3.1将此前引入的OpenGL着色语言“GLSL”从1.30版升级到了1.40版,通过改进程序增强 了对最新可编程图形硬件的访问,还有更高效的顶点处理、扩展的纹理功能、更弹性的缓冲管 理等等。
rgba模式颜色索引模式colorindexrgba模式为每个像素点指定颜色可提供丰富多彩的色彩效果其中a是混合因子用于各种特效处理对于显示能力不足的硬件可采用颜色索引模式系统提供一个颜色表通常有256或4096种颜色各像素点通过索引颜色表项得到颜色值opengl基本功能711光照和材质在现实生活中物体因为受光照射和自身对各种频率光波的吸收与反射能力的不同而呈现各自不同的颜色opengl的实现假设光仅仅由三原色rgb组成物体对三原色分别有不同的反射率即材质利用物理光学模型计算物体实际的颜色opengl基本功能811纹理映射texturemapping由于物体采用图元primitive表示点线多边形绘制时有效渲染的地方也仅仅是这些点线多边形其它位置的颜色值则通过插值实现这就造成了物体绘制的不真实纹理映射通过贴图的方式为物体表面贴上真实的色彩花纹这些被指定贴上的图片就称作纹理textureopengl提供了完善的纹理映射机制opengl基本功能911反走样antialiasing线段在计算机中是通过一系列的像素来近似逼近的而这些像素实际上是一个个的小正方形因此线段常常呈锯齿状这被称为走样aliasingopengl通过计算线段对各个像素的不同覆盖率来实现反走样antialiasingopengl基本功能1011图像特效融合blending为了使三维图形更加具有真实感经常需要处理半透明或透明的物体图像这就需要用到融合技雾fog正如自然界中存在烟雾一样opengl提供了fog的基本操作来达到对场景进行雾化的效果opengl基本功能1111双缓存doublebuffering动画出色的动画效果是opengl的一大特色opengl通过双缓存实现动画前台缓存显示当前帧后台缓存同时进行后续帧的场景计算生成画面opengl语法特点15所有opengl函数都使用gl作为前缀如glclearcolor所有opengl常量都使用gl开头并且所有字母都大写如glfalseopengl语法特点25opengl函数后缀说明后缀中的阿拉伯数字一般表示参数的数目如glvertex2i13表示该函数有两个参数阿拉伯数字后的小写字符一个或多个表示参数类型如glvertex2i13表示该函数的两个参数都为32位整数integer表示参数类型的后缀定义见下表opengl语法特点35opengl函数后缀说明opengl语法特点45opengl函数后缀说明有

计算机图形学基础OpenGL

计算机图形学基础OpenGL

计算机图形学基础OpenGL1. 使用OpenGL在屏幕上画一条直线,其中端点的坐标分别是(2,3)和(6,9)。

答案:glBegin(GL_LINES);glVertex2f(2,3);glVertex2f(6,9);glEnd(;2. 如何使用OpenGL把一个三角形绘制在屏幕上,其三个顶点的坐标分别是(1,3)、(6,7)和(9,6)?答案:glBegin(GL_TRIANGLES);glVertex2f(1,3);glVertex2f(6,7);glVertex2f(9,6);glEnd(;3. 如何使用OpenGL在屏幕上绘制一个正方形,正方形的中心点坐标为(4,6),边长为5?答案:glBegin(GL_QUADS);glVertex2f(4-2.5, 6+2.5);glVertex2f(4+2.5, 6+2.5);glVertex2f(4+2.5, 6-2.5);glVertex2f(4-2.5, 6-2.5);glEnd(;4. 如何使用OpenGL在屏幕上绘制一个圆,圆心坐标为(7,3),半径为4?答案:glBegin(GL_POLYGON);int i;for(i=0;i<360;i++)glVertex2f(7+4*cos(i*PI/180.0f),3+4*sin(i*PI/180.0f));}glEnd(;5. 如何使用OpenGL在屏幕上绘制一个贝塞尔曲线,其中(1,2)、(3,4)、(5,6)、(7,7)是控制点?答案:GLfloat points[4][2] = {{1,2}, {3,4}, {5,6}, {7,7}};glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &points[0][0]);glEnable(GL_MAP1_VERTEX_3);glBegin(GL_LINE_STRIP);int i;for (i=0;i<=30;i++)glEvalCoord1f((GLfloat) i/30.0f);glEnd(;6. 如何使用OpenGL实现2D矢量图形的缩放操作,指定缩放中心点为(-2,4),缩放比例为1.3?答案:glTranslatef(-2,4,0);。

opengl用法

opengl用法

opengl用法OpenGL(Open Graphics Library)是一种用于图形渲染的跨平台编程接口,它提供了一组函数和命令,用于创建和操作2D、3D图形。

OpenGL被广泛应用于计算机图形学、游戏开发、虚拟现实和科学可视化等领域,具有强大的图形处理能力和灵活性。

一、OpenGL的基本概念OpenGL使用一种状态机的方式来管理和调用图形渲染的函数。

在开始使用OpenGL之前,我们需要了解一些基本概念和术语。

1. 坐标系:OpenGL使用右手坐标系,其中x轴向右延伸,y轴向上延伸,z轴指向观察者。

2. 顶点:顶点是构成图形的基本元素,它们包含位置、颜色和纹理坐标等信息。

3. 三角形:OpenGL最基本的图形是三角形。

通过连接三个顶点,可以构成一个平面上的三角形。

4. 缓冲区对象:OpenGL使用缓冲区来存储顶点数据、纹理数据等。

通过绑定缓冲区对象,我们可以将数据发送到显卡中进行处理。

5. 着色器(Shader):着色器是OpenGL中用于将顶点数据转换为屏幕上可见像素的程序。

二、OpenGL的基本用法下面我们将介绍一些常用的OpenGL函数,以帮助你了解如何使用OpenGL进行图形渲染。

1. 初始化OpenGL环境在开始渲染之前,我们首先需要初始化OpenGL环境。

通过调用glutInit函数和glutCreateWindow函数,可以创建一个OpenGL窗口。

2. 设置视口设置视口是指确定OpenGL窗口中要渲染的区域。

通过调用glViewport函数,我们可以指定视口的位置、宽度和高度。

3. 设置投影矩阵投影矩阵用于将三维坐标转换为二维坐标。

通过调用glMatrixMode和glOrtho函数,我们可以设置投影矩阵的类型和具体数值。

4. 绘制图形在设置好渲染环境后,我们可以开始绘制图形。

通过调用glBegin和glEnd函数,我们可以定义一个形状(如三角形或四边形)并填充颜色、添加纹理等。

用opengl做的一个高程图,其实就是个地形图

用opengl做的一个高程图,其实就是个地形图

⽤opengl做的⼀个⾼程图,其实就是个地形图哦,在写代码之前最好先把项⽬的属性中的字符集由unicode改为多字符集。

⾸先预定义了⼀些宏:#define WIN32_LEAN_AND_MEAN //裁减windows函数库#define BITMAP_ID 0x4D42 //全球位图标识#define PI 3.14159f#define MAP_X 32 //地形的X⽅向上的最⼤栅格数#define MAP_Z 32 //地形的Z⽅向上的最⼤栅格数#define MAP_SCARE 20.0f //⽐例因⼦下⾯是包含的⼀些⽂件:#include <windows.h> // standard Windows app include#include <stdio.h>#include <stdlib.h>#include <math.h>#include <gl/gl.h> // standard OpenGL include#include <gl/glu.h> // OpenGL utilties#include <gl/glaux.h> // OpenGL auxiliary functions#include <string.h>#include <gl/glut.h>//连接动态库#pragma comment(lib, "opengl32.lib") // Link OpenGL32.lib#pragma comment(lib, "glu32.lib")#pragma comment(lib,"glaux.lib") // Link Glu32.lib声明的全局变量:HDC hDC=NULL; // Private GDI Device ContextHGLRC hRC=NULL; // Permanent Rendering ContextHWND hWnd=NULL; // Holds Our Window HandleHINSTANCE hInstance; // Holds The Instance Of The Applicationint Mywidth=0;int Myheight=0;bool keys[256]; // Array Used For The Keyboard Routinebool active=TRUE; // Window Active Flag Set To TRUE By Defaultbool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Defaultunsigned char *imageData=NULL; //灰度图位图数据unsigned char *landTexture=NULL; //陆地纹理位图数据unsigned char *waterTexture=NULL; //⽔⾯纹理位图数据BITMAPINFOHEADER bitmapInfoHeader; //位图信息头BITMAPINFOHEADER waterInfo;BITMAPINFOHEADER landInfo;unsigned int land; //纹理对象unsigned int water;float angle=0.0f; //视点⽅向的⾓度值(⾓度)float radians=0.0f; //试点⽅向的⾓度值(弧度)float waterHeight=154.0f; //⽔⾯⾼度bool waterDir=true; //⽔的动态效果,waterDir=true:⽔向上运动,反之,向下运动.int mouseX,mouseY; //存储新的⿏标坐标int oldMouseX,oldMouseY; //存储旧的⿏标坐标float cameraX,cameraY,cameraZ; //视点的位置float lookX,lookY,lookZ; //试点的⽅向float terrain[MAP_X][MAP_Z][3]; //存储每个点的坐标值下⾯是源代码:#define WIN32_LEAN_AND_MEAN //裁减windows函数库#define BITMAP_ID 0x4D42 // the universal bitmap ID#define PI 3.14159f#define MAP_X 32#define MAP_Z 32#define MAP_SCARE 20.0f////// Includes#include <windows.h> // standard Windows app include#include <stdio.h>#include <stdlib.h>#include <math.h>#include <gl/gl.h> // standard OpenGL include#include <gl/glu.h> // OpenGL utilties#include <gl/glaux.h> // OpenGL auxiliary functions#include <string.h>#include <gl/glut.h>#pragma comment(lib, "opengl32.lib") // Link OpenGL32.lib#pragma comment(lib, "glu32.lib")#pragma comment(lib,"glaux.lib") // Link Glu32.libHDC hDC=NULL; // Private GDI Device ContextHGLRC hRC=NULL; // Permanent Rendering ContextHWND hWnd=NULL; // Holds Our Window HandleHINSTANCE hInstance; // Holds The Instance Of The Applicationint Mywidth=0;int Myheight=0;bool keys[256]; // Array Used For The Keyboard Routinebool active=TRUE; // Window Active Flag Set To TRUE By Defaultbool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Defaultunsigned char *imageData=NULL;unsigned char *landTexture=NULL;unsigned char *waterTexture=NULL;BITMAPINFOHEADER bitmapInfoHeader;BITMAPINFOHEADER waterInfo;BITMAPINFOHEADER landInfo;unsigned int land;unsigned int water;float angle=0.0f;float radians=0.0f;float waterHeight=154.0f;bool waterDir=true;int mouseX,mouseY;int oldMouseX,oldMouseY;float cameraX,cameraY,cameraZ;float lookX,lookY,lookZ;float terrain[MAP_X][MAP_Z][3];void InitializeTerrain() //初始化terrain的值. 每个点的X值等于X位置处的栅格数乘以⽐例因⼦,Z同理,{for(int z=0;z<MAP_Z;z++){for(int x=0;x<MAP_X;x++){terrain[x][z][0]=float(x)*MAP_SCARE;terrain[x][z][1]=(float)imageData[(z*MAP_Z+x)*3];terrain[x][z][2]=-float(z)*MAP_SCARE;}}}LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc // DrawBitmap// desc: draws the bitmap image data in bitmapImage at the location// (350,300) in the window. (350,300) is the lower-left corner// of the bitmap.void KeyFunc(){}// LoadBitmapFile// desc: Returns a pointer to the bitmap image of the bitmap specified// by filename. Also returns the bitmap header information.// No support for 8-bit bitmaps.unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader){FILE *filePtr; // the file pointerBITMAPFILEHEADER bitmapFileHeader; // bitmap file headerunsigned char *bitmapImage; // bitmap image dataint imageIdx = 0; // image index counterunsigned char tempRGB; // swap variable// open filename in "read binary" modefilePtr = fopen(filename, "rb");if (filePtr == NULL)return NULL;// read the bitmap file headerfread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);// verify that this is a bitmap by checking for the universal bitmap idif (bitmapFileHeader.bfType != BITMAP_ID){fclose(filePtr);return NULL;}// read the bitmap information headerfread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);// move file pointer to beginning of bitmap datafseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);// allocate enough memory for the bitmap image databitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);// verify memory allocationif (!bitmapImage){free(bitmapImage);fclose(filePtr);return NULL;}// read in the bitmap image datafread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);// make sure bitmap image data was readif (bitmapImage == NULL){fclose(filePtr);return NULL;}// swap the R and B values to get RGB since the bitmap color format is in BGR for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx+=3) {tempRGB = bitmapImage[imageIdx];bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];bitmapImage[imageIdx + 2] = tempRGB;}// close the file and return the bitmap image datafclose(filePtr);return bitmapImage;}。

如何在C++中进行图形绘制操作

如何在C++中进行图形绘制操作

如何在C++中进行图形绘制操作C++是一种强大的编程语言,可以用于进行各种图形绘制操作。

在C++中,可以使用一些图形库来实现图形绘制,其中最常用的是OpenGL 和SFML。

1.使用OpenGL进行图形绘制OpenGL是一种跨平台的图形库,可以用于在不同的操作系统上进行图形绘制。

使用OpenGL进行图形绘制需要安装相应的OpenGL库,并在代码中添加相关的头文件和链接库。

在C++中,可以使用OpenGL进行图形绘制的基本步骤如下:-初始化OpenGL环境:在程序的开始处,需要进行OpenGL的初始化,并设置相关的窗口参数和OpenGL的版本。

-创建窗口:使用OpenGL库中的函数创建一个窗口,用于显示绘制的图形。

可以设置窗口的大小、标题等。

-设置视口:将窗口设置为视口,指定绘制的区域。

-定义图形数据:在程序中定义需要绘制的图形的顶点数据,例如点、线、三角形等。

-编写着色器程序:在OpenGL中,需要使用着色器程序来进行图形的着色和光照等处理。

着色器程序通常由顶点着色器和片段着色器组成,分别用于处理顶点和片段的绘制过程。

-编写绘制函数:编写一个函数,用于将图形数据传递给OpenGL,并进行绘制操作。

在绘制函数中,需要进行相关的操作,例如绑定缓冲区、设置顶点属性、绘制图形等。

-事件循环:使用一个循环,不断地监听用户的输入和系统的事件,并根据事件进行相应的处理。

例如,可以监听键盘输入,根据输入进行相应的图形操作。

-渲染循环:使用一个循环,在每一帧中对图形进行渲染,并更新窗口的显示内容。

使用OpenGL进行图形绘制需要对图形学的基本原理有一定的了解,例如顶点和片段的概念,以及图形变换、投影等操作的原理。

同时,也需要学习OpenGL库中的一些函数和参数的使用方法。

2.使用SFML进行图形绘制SFML(Simple and Fast Multimedia Library)是一个简单易用的多媒体库,可以用于进行图形、声音和输入输出等操作。

opencv bmp标准格式

opencv bmp标准格式

一、介绍OpenCV是一个开源的计算机视觉库,提供了大量的图像处理和计算机视觉算法,广泛应用于图像处理、模式识别、计算机视觉等领域。

在OpenCV中,BMP(Bitmap)是一种常见的图像文件格式,它以其简单的存储结构和广泛的应用而闻名。

二、BMP格式简介1. BMP图像文件格式是Windows操作系统中最常见的图像文件格式之一。

2. BMP格式的图像数据以像素点阵列存储,每个像素用24位或32位的RGB值表示。

3. BMP格式的文件头包含文件类型、文件大小、图像数据偏移量等信息。

4. BMP格式的图像数据按从左到右、从下到上的顺序排列。

三、OpenCV中的BMP处理1. OpenCV提供了对BMP格式图像文件的读取和写入功能,可以利用OpenCV读取BMP格式的图像文件,并对其进行各种图像处理操作。

2. 通过OpenCV的imread()函数可以读取BMP格式的图像文件,并返回一个Mat对象,方便对图像进行处理。

3. 通过OpenCV的imwrite()函数可以将处理后的图像保存为BMP格式的文件,方便后续的使用和展示。

四、BMP格式的优势1. BMP格式的图像数据存储方式简单,易于理解和处理。

2. BMP格式的图像文件大小相对较小,适合在存储和传输时使用。

3. BMP格式的图像在Windows系统中具有较好的兼容性,可在多种软件和设备中进行展示和使用。

五、BMP格式的局限性1. BMP格式不支持压缩,因此其文件大小相对较大,在存储和传输时可能占用较多的空间和带宽。

2. BMP格式的图像不能包含透明通道信息,无法实现半透明效果。

3. BMP格式不支持多帧图像,无法存储动态图像或视瓶。

六、BMP格式的应用场景1. 由于BMP格式的存储结构简单、易于处理,因此在一些对图像质量要求不高、但对图像处理速度和实时性要求较高的场景中得到广泛应用,如监控摄像头图像处理、工业自动化图像处理等。

2. 由于BMP格式的文件大小相对较小,适合在一些资源受限的环境中进行图像存储和传输,如嵌入式系统、传感器网络等。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

二维坐标OpenGL一、定义二维坐标的尺度:void gluOrtho2D(left, right, top, bottom);四个参数分别代表(左下角x坐标,右上角x坐标,左下角y坐标,右上角y坐标)。

例如,对于一个640*480的窗口,可以指定如下的坐标尺度:gluOrtho2D(-320, 320, -240, 240);或者gluOrtho2D(0, 640, 0, 480);等等。

具体的使用为:int main(int argc, char *argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);glutInitWindowPosition(100, 100);glutInitWindowSize(640, 480);glutCreateWindow("图片显示");gluOrtho2D(0, 640, 0, 480);glutDisplayFunc(&myDisplay);glutMainLoop();return 0;}二、OpenGL颜色的选择void glColor3f(GLfloat red, GLfloat green, GLfloat blue);以1.0表示最大的使用。

void glColor3b(GLbyte red, GLbyte green, GLbyte blue);采用b做后缀的函数,以127表示最大的使用。

void glColor3ub(GLuByte red, GLuByte green, GLuByte blue);采用ub做后缀的函数,以255表示最大的使用。

void glColor3s(GLshort red, GLshort green, GLshort blue);采用s做后缀的函数,以32767表示最大的使用。

void glColor3us(GLuShort red, GLuShort green, GLuShort blue); 采用us做后缀的函数,以65535表示最大的使用。

例如:表示不使用绿、蓝色,而将红色使用最多可以调用如下的函数之一glColor3f(1.0f, 0.0f, 0.0f);glColor3ub(255, 0, 0);等等。

实验五 BMP文件BMP 文件是一种像素文件,它保存了一幅图像中所有的像素。

这种文件格式可以保存单色位图、16色或256色索引模式像素图、24位真彩色图像,每种模式种单一像素的大小分别为1/8字节,1/2字节,1字节和3字节。

目前最常见的是256色BMP和24位色BMP。

这种文件格式还定义了像素保存的几种方法,包括不压缩、RLE压缩等。

常见的BMP文件大多是不压缩的。

BMP文件具有如下格式:1:BMP由四部分组成:位图文件头(14字节)、位图信息头(40字节)、颜色表(可选)、位图数据。

2:位图文件头(14字节)格式:struct tagBmpFileHeader_T{unsigned short bfType; // 位图文件的类型,必须为BMP(0-1字节)unsigned int bfSize; // 位图文件的大小,以字节为单位(2-5字节)unsigned short bfReserved1; // 位图文件保留字,必须为0(6-7字节)unsigned short bfReserved2; // 位图文件保留字,必须为0(8-9字节)unsigned int bfOffBits; // 位图数据的起始位置(10-13字节),以相对于位图// 文件头的偏移量表示,以字节为单位};3:位图信息头(40字节)struct tagBmpInfoHeader_T{unsigned int biSize; // 本结构所占用字节数(14-17字节)unsigned int biWidth; // 位图的宽度,以像素为单位(18-21字节)unsigned int biHeight; // 位图的高度,以像素为单位(22-25字节)unsigned short biPlanes; // 目标设备的级别,必须为1(26-27字节)unsigned short biBitCount;// 每个像素所需的位数(28-29字节),必须是1(双色)、(28-29字节)、4(16色)、8(256色)或24(真彩色)之一unsigned int biCompression; // 位图压缩类型,必须是 0(不压缩),(30-33字节)// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一unsigned int biSizeImage; // 位图的大小,以字节为单位(34-37字节)unsigned int biXPelsPerMeter; // 位图水平分辨率,每米像素数(38-41字节)unsigned int biYPelsPerMeter; // 位图垂直分辨率,每米像素数(42-45字节)unsigned int biClrUsed;// 位图实际使用的颜色表中的颜色数(46-49字节)unsigned int biClrImportant;// 位图显示过程中重要的颜色数(50-53字节) };4:颜色表这里为了简单起见,我们仅讨论24位色、不使用压缩的BMP。

因此,位图文件中不包含有颜色表,跳过不处理。

5:位图数据位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上【即第一个像素为左下角的像素,最后一个为右上角的像素】。

每个像素存储的颜色顺序为Blue,Green,Red(即BGR,刚好与我们熟悉的RGB相反)。

struct tagRgbQuad_T {unsigned char rgbBlue;// 蓝色的亮度(值范围为-255)unsigned char rgbGreen; // 绿色的亮度(值范围为-255)unsigned char rgbRed; // 红色的亮度(值范围为-255)};这里为了简单起见,我们仅讨论24位色。

位图的一个像素值占3个字节(每三个字节表示一个像素的颜色)。

于是,一行像素所占的有效..字节数为:int effectiveLen = 一行的像素数量*3;但是,Windows规定一个扫描行.....所占的字节数必须是4的倍数(即以long为单位),不足的以0填充。

需要注意的地方是:像素的数据量并不一定完全等于图像的高度乘以宽度乘以每一像素的字节数,而是可能略大于这个值。

原因是BMP文件采用了一种“对齐”的机制,每一行像素数据的长度若不是4的倍数,则填充一些数据使它是4的倍数。

这样一来,一个17*15的24位BMP大小就应该是834字节(每行17 个像素,有51字节,补充为52字节,乘以15得到像素数据总长度780,再加上文件开始的54字节,得到834字节)。

因此,文件中存储一行像素所占的实际..字节数为:int rowLen = (effectiveLen +3)&~3; //即不小于effectiveLen且能被4整除的最小整数。

例如,若effectiveLen=51,则rowLen=52。

我们可以读取一个具体的BMP文件内容来进一步了解其格式:void main(){FILE *fp;fp = fopen("test.bmp", "rb"); //一定记得以二进制文件形式打开unsigned char b1;for(unsigned int i=0; i<60; i++) //只显示前面60个字节的内容{printf("%d: ", i);fread(&b1, 1, 1, fp);printf("0x%x\n", b1);}fclose(fp);}因此,在程序中,我们可以按照BMP文件头部的格式来进行文件的读取。

程序部分代码如下:tagBmpFileHeader_T bmpFileHdr; //定义为全局变量tagBmpInfoHeader_T bmpInfoHdr;tagRgbQuad_T *p;tagRgbQuad_T *pBmpData;void main(){FILE *fp;fp = fopen("test.bmp", "rb"); //一定记得以二进制文件形式打开fread(&bmpFileHdr, 1, sizeof(tagBmpFileHeader_T), fp);fread(&bmpInfoHdr, 1, sizeof(tagBmpInfoHeader_T), fp);//分配pBmpData空间,用于保存位图所有像素的RGB数据//分配的大小 = 行宽*列高*每像素所占字节数pBmpData = (tagRgbQuad_T *)malloc(bmpInfoHdr.biWidth *bmpInfoHdr.biHeight * sizeof(tagRgbQuad_T));//从文件中读取位图像素的颜色信息//记录顺序是在扫描行内是从左到右,扫描行之间是从下到上//【即第一个像素为左下角的像素,最后一个为右上角的像素】。

//每个像素存储的颜色顺序为Blue,Green,Red//读取完一行的像素信息后,注意使用 fseek(fp, rowLen - effectiveLen, SEEK_CUR)函数跳过BMP文件每行像素因4字节“对齐”而可能填充进来的数据int effectiveLen = bmpInfoHdr.biWidth * 3;int rowLen = (effectiveLen +3)&~3; //即不小于effectiveLen且能被4整除的最小整数。

p = pBmpData;for(unsigned int iRow=0; iRow<bmpInfoHdr.biHeight; iRow++){for(unsigned int iCol=0; iCol<bmpInfoHdr.biWidth; iCol++){fread(p, sizeof(tagRgbQuad_T), 1, fp);p++;}fseek(fp, rowLen - effectiveLen, 1);}fclose(fp);//此处自行添加OpenGL的代码,显示保存在pBmpData中的像素glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);glutInitWindowPosition(100, 100);glutInitWindowSize(bmpInfoHdr.biWidth, bmpInfoHdr.biHeight);glutCreateWindow("图片显示");gluOrtho2D(0, bmpInfoHdr.biWidth, 0, bmpInfoHdr.biHeight);//set coordinate system glutDisplayFunc(&myDisplay);glutMainLoop();return 0;}/************************************************************* 把下面的这个函数放在main()函数的上面!!!!!! **************************************************************/ void myDisplay(void){glClear(GL_COLOR_BUFFER_BIT);glPointSize(1.0);glBegin(GL_POINTS);p = pBmpData;for(unsigned int i=0; i<bmpInfoHdr.biHeight; i++){for(unsigned int j=0; j<bmpInfoHdr.biWidth; j++){glColor3ub(p->rgbRed, p->rgbGreen, p->rgbBlue);glVertex2i(j, i);p++;}}glEnd();glFlush();}其实,位图像素也可以用二维数组来进行保存tagRgbQuad_T **pBmpData2D; //定义一个指针的指针,相当于二维数组pBmpData2D = malloc(bmpInfoHdr.biHeight*sizeof(tagRgbQuad_T *));pBmpData2D = (tagRgbQuad_T **)malloc( bmpInfoHdr.biHeight *sizeof(tagRgbQuad_T *)); //分配行数for(unsigned int i=0; i<bmpInfoHdr.biHeight; i++){pBmpData2D[i] = (tagRgbQuad_T *) malloc( bmpInfoHdr.biWidth * sizeof(tagRgbQuad_T)); //分配每一行的元素}for(unsigned int iRow=0; iRow<bmpInfoHdr.biHeight; iRow++){for(unsigned int iCol=0; iCol<bmpInfoHdr.biWidth; iCol++){fread(&(pBmpData2D[iRow][iCol]), sizeof(tagRgbQuad_T), 1, fp);}fseek(fp, rowLen - tempLen, 1);}//void myDisplay(void) 函数自己完成。

相关文档
最新文档