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. 常 ...
随机推荐
- Flutter移动电商实战 --(25)列表页_使用Provide控制子类-1
主要是二级分类的UI布局 生成我们的右侧动态类 定义list变量 开始写里面的子项,把每一个小的写了 再拼成一个大的 这样我们的小类就写完了 开始写我的大类别:是一个横向的ListView.写横向的L ...
- python 语法糖是什么意思
语法糖指那些没有给计算机语言添加新功能,而只是对人类来说更“甜蜜”的语法.语法糖往往给程序员提供了更实用的编码方式,有益于更好的编码风格,更易读.不过其并没有给语言添加什么新东西.
- 回归regression
X-Y存在某种映射关系,回归:确定出关系模型.
- kotlin 泛型约束
fun <T:Comparable<T>> sort(list :List<T>){} 冒号之后指定的类型就是泛型参数的上界,对于泛型参数T,只允许使用Compar ...
- 003-log-jul,jdk自带日志服务
一.简介 java官方日志jul,位于java.util.logging包下. 1.1.POM依赖 无依赖 1.2.配置 JUL的默认配置文件是logging.properties ,在 $JAVA_ ...
- Cinder LVM Oversubscription in thin provisioning
目录 文章目录 目录 Oversubscription in thin provisioning Oversubscription in thin provisioning Cinder spec: ...
- 13 Flutter仿京东商城项目 商品列表筛选以及上拉分页加载更多
ProductList.dart import 'package:flutter/material.dart'; import '../services/ScreenAdaper.dart'; imp ...
- scikit-learn机器学习(二)逻辑回归进行二分类(垃圾邮件分类),二分类性能指标,画ROC曲线,计算acc,recall,presicion,f1
数据来自UCI机器学习仓库中的垃圾信息数据集 数据可从http://archive.ics.uci.edu/ml/datasets/sms+spam+collection下载 转成csv载入数据 im ...
- Saltstack之使用salt安装es6.0以上的head插件
本实验使用salt安装es6.0以上的head插件 ES6.0以上手动安装head插件参考:https://www.cnblogs.com/minseo/p/9117470.html 文件夹目录为 / ...
- Spring Security(20)——整合Cas
整合Cas 目录 1.1 配置登录认证 1.1.1 配置AuthenticationEntryPoint 1.1.2 配置CasAuthenticationFilt ...