效果图:
这里显示的图和原图有明显的色差,目前猜测是opengl渲染时的颜色表顺序跟BMP文件里的颜色表顺序相反导致。
BMP里应该是BGRBGRBRG... ,而opengl渲染时应该是按照RGBRGBRGB...的顺序,所以就是B和R是反的,白色和
黑色区域不变是因为白色是全F,黑色是全0,交换后还是一样,这也证明了猜测。此问题待解决。
原图: 显示:
使用freeglut开源库
freeglut库是glut库的开源实现,API同glut的无缝衔接,几乎无区别
下载地址:http://download.chinaunix.net/download/0004000/3280.shtml
这里使用的是freeglut-2.4.0.tar.gz 版本;
1. 将freeglut-2.4.0.tar.gz 在linux下解压,然后进入解压后的文件夹,首先执行./configure, 然后执行make, 然后执行make install,
都执行成功后会显示.h文件安装到 /usr/include/GL/目录下,而库文件安装到 /usr/lib/目录下。
库文件要用libglut.so,libGLU.so,libGL.so, 头文件用gl.h ,glu.h, glut.h
2. Eclipse新建C工程, 配置工程属性,C/C++ Build --> Setting --> GCC C Compiler--> Directories --> Include Path 中加上/usr/include/GL/
GCC C Linker --> Miscellaneous 中加上 /usr/lib/ligblut.so, /usr/lib/libGLU.so, /usr/lib/libGL.so ,注意这里使用的动态库,不能用静态编译-a。
非Eclipse参考http://blog.csdn.net/qwyang/article/details/7163165,然后就可以开始写opengl程序了。
3. BMP格式是windows专有的,在linux下读写就需要用文件流操作,然后自定义一下bmp文件的头结构体。头文件如下:
里面的结构体都是从windows下的头文件中直接拷过来的,AUX_RGBImageRec结构体是从glaux.h文件中拷过来的,opengl纹理贴图的时候需要这个结构体的指针,这个结构体包含了一个图片的长,宽和RGB颜色表,opengl根据这个信息就能画出这个图片。
/* * gluttest.h * * Created on: Jul 4, 2014 * Author: root */ #ifndef GLUTTEST_H_ #define GLUTTEST_H_ #include "glut.h" #include "gl.h" #include "freeglut.h" typedef unsigned long DWORD; typedef int BOOL; typedef unsigned char BYTE; typedef unsigned short WORD; typedef char CHAR; typedef short SHORT; typedef long LONG;
typedef struct _AUX_RGBImageRec { GLint sizeX, sizeY; unsigned char *data; } AUX_RGBImageRec; typedef struct tagBITMAPFILEHEADER { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER; typedef struct tagBITMAPINFOHEADER{ DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAPINFOHEADER; #endif /* GLUTTEST_H_ */
接下来是 .c文件,这里新建的是C文件,没有了new 和 delete, 分配内存用malloc, 释放用free。
/* * gluttest.c * * Created on: Jul 4, 2014 * Author: root */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "gluttest.h" GLuint texture[1]; //存储一个纹理 AUX_RGBImageRec *newload(char * Filename) { BITMAPFILEHEADER bmpHeader;//文件头 BITMAPINFOHEADER bmpInfo;//信息头 FILE * pfile; if ((pfile = fopen(Filename, "rb")) == NULL) { return NULL; } int fortest1 = sizeof(BITMAPFILEHEADER); int fortest2 = sizeof(BITMAPINFOHEADER); //读取文件头到bmpHeader //int nn = fread(&bmpHeader, sizeof(BITMAPFILEHEADER),1, pfile); /************************************************************* * 这里之前用整个结构体一起读取的方法,但是除了第一项读取正确外后面的都错位了, * 具体原因不清楚,改成一项一项读之后就可以了。后面的结构体也是 ************************************************************* */ int nn = fread(&(bmpHeader.bfType), sizeof(WORD), 1, pfile); fread(&(bmpHeader.bfSize), sizeof(DWORD), 1, pfile); fread(&(bmpHeader.bfReserved1), sizeof(WORD), 1, pfile); fread(&(bmpHeader.bfReserved2), sizeof(WORD), 1, pfile); fread(&(bmpHeader.bfOffBits), sizeof(DWORD), 1, pfile); if ( nn == 0) { printf("read bmp header failed!"); return NULL; } /*0x4d42=’BM’,表示是Windows支持的BMP格式。 (注意:查ascii表B 0x42,M0x4d,bfType 为两个字节,B为low字节,M为high字节 所以bfType=0x4D42,而不是0x424D */ if (bmpHeader.bfType != 0x4d42) { printf("invalid file type!"); return NULL; } //读取文件信息头bmpInfo fread(&bmpInfo.biSize, 1, sizeof(DWORD), pfile); fread(&bmpInfo.biWidth, 1, sizeof(LONG), pfile); fread(&bmpInfo.biHeight, 1, sizeof(LONG), pfile); fread(&bmpInfo.biPlanes, 1, sizeof(WORD), pfile); fread(&bmpInfo.biBitCount, 1, sizeof(WORD), pfile); fread(&bmpInfo.biCompression, 1, sizeof(DWORD), pfile); fread(&bmpInfo.biSizeImage, 1, sizeof(DWORD), pfile); fread(&bmpInfo.biXPelsPerMeter, 1, sizeof(LONG), pfile); fread(&bmpInfo.biYPelsPerMeter, 1, sizeof(LONG), pfile); fread(&bmpInfo.biClrUsed, 1, sizeof(DWORD), pfile); fread(&bmpInfo.biClrImportant, 1, sizeof(DWORD), pfile); // if (fread(&bmpInfo, 1, sizeof(BITMAPINFOHEADER), pfile) == 0) // { // printf("read bmp infor header failed! "); // return NULL; // } //确认是24位位图 if (bmpInfo.biBitCount != 24)//图像的位数 { printf("File is not 24 bit.Application doesn't support this kind of file!"); return NULL; } //计算颜色表区域大小:结构体的大小(包含颜色表)-颜色数据的偏移量 DWORD dataBytes = bmpHeader.bfSize - bmpHeader.bfOffBits; BYTE * pBmpData = (BYTE *)malloc(dataBytes); memset(pBmpData, '