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[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, '', dataBytes);
    if (!pBmpData)
    {
        printf("memory error!");
        free(pBmpData);
        return NULL;
    }

    BYTE * tmpChar = pBmpData;
    int ktmp = 0;
    int restnum = dataBytes;


    /* 这里整个读取会有问题,改成分包读,每次读500字节 */
    while ( ktmp < dataBytes)
    {
        if (restnum < 500)
        {
            fread(tmpChar, 1, restnum, pfile);
            ktmp += restnum;
            break;
        }
        fread(tmpChar, 1, 500, pfile);
        tmpChar += 500;
        ktmp += 500;
        restnum -= 500;
    }
    if (ktmp == 0)
    {
        printf("Read bmp data failed!");
        //delete pBmpInfo;
        free(pBmpData);
        return NULL;
    }

    AUX_RGBImageRec * rgbImage = (AUX_RGBImageRec *)malloc(dataBytes+sizeof(GLint)*2);

    //rgbImage->data = (unsigned char *)malloc(dataBytes);
    //memset(rgbImage->data, '', 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 = 0;
    AUX_RGBImageRec *TextureImage[1];
    memset(TextureImage, 0, sizeof(void *)*1);
    if (TextureImage[0] = newload(fpath))
    {
        Status = 1;
        //注册纹理
        glGenTextures(1, &texture[0]);
        //绑定纹理名称
        glBindTexture(GL_TEXTURE_2D, texture[0]);
        //生成纹理数据
        glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
        //线性滤波
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    }
    if (TextureImage[0])
    {
        if (TextureImage[0]->data)
        {
            free(TextureImage[0]->data);
        }
        free(TextureImage[0]);
    }
    return Status;
}

//调用入口
int InitGL(GLvoid)
{
    if (!LoadGLTextures())
    {
        return 0;
    }
    glEnable(GL_TEXTURE_2D);
    //glShadeModel(GL_SMOOTH);
    //设置背景色为黑色
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    return 1;
}

//贴图绘制
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
");
//        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(300,100);
    glutInitWindowSize(450, 600);
    glutCreateWindow("hello");

    InitGL();
    glutDisplayFunc(&DrawGLScene);
    //glutIdleFunc(idle);
    glutMainLoop();
    return 0;
}

(完)

原文地址:https://www.cnblogs.com/fwst/p/3824634.html