linux 下使用opengl的glut库显示和旋转BMP图片
效果图:
这里显示的图和原图有明显的色差,目前猜测是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[]; //存储一个纹理 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), , pfile);
fread(&(bmpHeader.bfSize), sizeof(DWORD), , pfile);
fread(&(bmpHeader.bfReserved1), sizeof(WORD), , pfile);
fread(&(bmpHeader.bfReserved2), sizeof(WORD), , pfile);
fread(&(bmpHeader.bfOffBits), sizeof(DWORD), , pfile);
if ( nn == )
{
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, , sizeof(DWORD), pfile);
fread(&bmpInfo.biWidth, , sizeof(LONG), pfile);
fread(&bmpInfo.biHeight, , sizeof(LONG), pfile);
fread(&bmpInfo.biPlanes, , sizeof(WORD), pfile);
fread(&bmpInfo.biBitCount, , sizeof(WORD), pfile);
fread(&bmpInfo.biCompression, , sizeof(DWORD), pfile);
fread(&bmpInfo.biSizeImage, , sizeof(DWORD), pfile);
fread(&bmpInfo.biXPelsPerMeter, , sizeof(LONG), pfile);
fread(&bmpInfo.biYPelsPerMeter, , sizeof(LONG), pfile);
fread(&bmpInfo.biClrUsed, , sizeof(DWORD), pfile);
fread(&bmpInfo.biClrImportant, , sizeof(DWORD), pfile); // if (fread(&bmpInfo, 1, sizeof(BITMAPINFOHEADER), pfile) == 0)
// {
// printf("read bmp infor header failed!\n");
// return NULL;
// } //确认是24位位图
if (bmpInfo.biBitCount != )//图像的位数
{
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, '\0', dataBytes);
if (!pBmpData)
{
printf("memory error!");
free(pBmpData);
return NULL;
} BYTE * tmpChar = pBmpData;
int ktmp = ;
int restnum = dataBytes; /* 这里整个读取会有问题,改成分包读,每次读500字节 */
while ( ktmp < dataBytes)
{
if (restnum < )
{
fread(tmpChar, , restnum, pfile);
ktmp += restnum;
break;
}
fread(tmpChar, , , pfile);
tmpChar += ;
ktmp += ;
restnum -= ;
}
if (ktmp == )
{
printf("Read bmp data failed!");
//delete pBmpInfo;
free(pBmpData);
return NULL;
} AUX_RGBImageRec * rgbImage = (AUX_RGBImageRec *)malloc(dataBytes+sizeof(GLint)*); //rgbImage->data = (unsigned char *)malloc(dataBytes);
//memset(rgbImage->data, '\0', sizeof(rgbImage->data)); rgbImage->data = pBmpData;
//memcpy(rgbImage->data, pBmpData, dataBytes); rgbImage->sizeX = bmpInfo.biWidth;
rgbImage->sizeY = bmpInfo.biHeight; return rgbImage;
} //生成纹理
int LoadGLTextures()
{
char * fpath; fpath = "/home/zhu/aaa.bmp"; int Status = ;
AUX_RGBImageRec *TextureImage[];
memset(TextureImage, , sizeof(void *)*);
if (TextureImage[] = newload(fpath))
{
Status = ;
//注册纹理
glGenTextures(, &texture[]);
//绑定纹理名称
glBindTexture(GL_TEXTURE_2D, texture[]);
//生成纹理数据
glTexImage2D(GL_TEXTURE_2D, , , TextureImage[]->sizeX, TextureImage[]->sizeY, , GL_RGB, GL_UNSIGNED_BYTE, TextureImage[]->data);
//线性滤波
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
if (TextureImage[])
{
if (TextureImage[]->data)
{
free(TextureImage[]->data);
}
free(TextureImage[]);
}
return Status;
} //调用入口
int InitGL(GLvoid)
{
if (!LoadGLTextures())
{
return ;
}
glEnable(GL_TEXTURE_2D);
//glShadeModel(GL_SMOOTH);
//设置背景色为黑色
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
return ;
} //贴图绘制
void DrawGLScene(GLvoid)
{
//清除屏幕缓存
glClear(GL_COLOR_BUFFER_BIT);
//重置当前的模型观察矩阵
glLoadIdentity(); /**************************************
* 旋转函数备用 -90表示顺时针绕Z轴旋转90度
***************************************/
//glRotatef(-90,0.0f,0.0f,1.0f); //开始绘制四边形
glBegin(GL_QUADS); //贴图及映射(glTexCoord2f对应纹理坐标, glVertex2f对应矩形坐标,此处已做旋转处理)
glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex2f( 1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex2f(-1.0f, -1.0f); glEnd();
glFlush();
//交换缓冲区
//glutSwapBuffers();
} //void idle()
//{
// //
// if (!LoadGLTextures())
// {
// printf("load GL Textures Error\n");
// exit(-1);
// //return false;
// }
// DrawGLScene();
// sleep(500);
//} int main(int argc, char **argv)
{
//初始化glut运行
glutInit(&argc,argv);
//GLUT_SINGLE表示单缓冲
glutInitDisplayMode(GLUT_DEPTH|GLUT_SINGLE|GLUT_RGBA);
glutInitWindowPosition(,);
glutInitWindowSize(, );
glutCreateWindow("hello"); InitGL();
glutDisplayFunc(&DrawGLScene);
//glutIdleFunc(idle);
glutMainLoop();
return ;
}
(完)
linux 下使用opengl的glut库显示和旋转BMP图片的更多相关文章
- OpenGL学习之windows下安装opengl的glut库
OpenGL学习之windows下安装opengl的glut库 GLUT不是OpenGL所必须的,但它会给我们的学习带来一定的方便,推荐安装. Windows环境下的GLUT下载地址:(大小约为15 ...
- Linux下动态链接库和静态链接库
第一部分:编译过程 先了解一下linux下C代码的编译过程,C代码的编译,一般分成四个阶段,包括:预编译,编译,汇编和链接,这四个阶段的分工是 预处理过程,负责头文件展开,宏替换,条件编译的选择,删除 ...
- Linux下制作和使用静态库和动态库
概述 Linux操作系统支持的函数库分为静态库和动态库,动态库又称共享库.linux系统有几个重要的目录存放相应的函数库,如/lib /usr/lib. 静态函数库: 这类库的名字一般是libxxx. ...
- linux下P2P协议(BitTorrent)-libtorrent库编译,测试
1.libtorrent 简介,下载和编译 libtorrent简介 libtorrent是功能齐全的C ++ bittorrent的p2p协议实现,专注于效率和可伸缩性.它可以在嵌入式设备和台式机上 ...
- linux下使用sqlplus使用上下键显示历史命令
在linux下使用sqlplus没有在windows下方便,既不好用习惯的退格键,也无法通过上键来显示上一条的命令,这里我们使用rlwrap来解决. 1.安装rlwrap [root@toughhou ...
- linux下java调用.so动态库方法2: JNA
摘自:http://blog.csdn.net/todorovchen/article/details/21319033 另请参见: http://blog.sina.com.cn/s/blog_8c ...
- linux 下启动程序的时候会显示坏的解释器,或者没有那个文件
又一次开发的时候在windowns上编写完的程序放到linux下运行的时候,比如:./start.sh的时候显示:"坏的解释器,没有那个文件"错误, 原因是windowns下写的s ...
- Linux下C语言使用openssl库进行加密
在这里插一小节加密的吧,使用openssl库进行加密. 使用MD5加密 我们以一个字符串为例,新建一个文件filename.txt,在文件内写入hello ,然后在Linux下可以使用命令md5sum ...
- Linux下C语言编程中库的使用
零.问题 1. 为什么要用到库? 2. 我要用一个库,但是,尼玛命令行上该怎么写呢?或者说库文件如何使用? 3. Linux的库在那些地方? 4. 什么是静态库,什么是动态库,二者有啥区别? 5. 常 ...
随机推荐
- 在HTML中直接使用onclick很不专业
原因 1.onclick添加的事件处理函数是在全局环境下执行的,这污染了全局环境,很容易产生意料不到的后果: 2.给很多DOM元素添加onclick事件,可能会影响网页的性能,毕竟网页需要的事件处理函 ...
- onNewIntent
当Activity不是Standard模式,并且被复用的时候,会触发onNewIntent(Intent intent) 这个方法,一般用来获取新的Intent传递的数据 我们一般会把MainAcit ...
- MongoDB的安装和配置成服务的三种方法
1. Hotfix KB2731284 or later update is not installed的问题: If you are running any edition of Windows S ...
- redis分布式锁练习【我】
package redis; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; public class ...
- C++ STL Heap算法
#include <iostream>#include <algorithm>#include <vector> using namespace std; int ...
- mysql连接工具记录
港优: Sequel pro
- 数学建模python matlab 编程(疾病传播模型)
例12:一只游船上有800(1000)人,一名游客不慎患传染病,12(10)小时后有3人发病,由于船上不能及时隔离,问经过60(30)小时,72小时,患此病的人数.(与人口模型和Logistic模型类 ...
- windows下libnet ARP
查找自己的网卡: #include <libnet.h> #include <stdio.h> #include <iostream> #pragma commen ...
- 义隆单片机学习笔记之(一) 硬件框架&资源下载
参考网址: 点击链接或右键链接地址 (台湾义隆官网)http://www.emc.com.tw/chs/tech_8bit.asp (EM78P153K官方资料)http://www.emc.com. ...
- 【ARM-Linux开发】Linux链接 -ln
ln命令是Linux中的一个非常重要的命令,它为一个文件在另一位置创建同步链接,有两种:符号链接和硬链接. [ln命令详解]ln [options] source dist 常用参数: -f : 链接 ...