• 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;
    }

    (完)

  • 相关阅读:
    业务线--node中间层做一个透传的项目
    JavaScript 字符串replace全局替换
    纯HTML和CSS实现点击切换
    css 清除一些默认的设置
    js异步请求方式
    VScode编辑器个性化配置
    webpack 解决跨域问题
    node.js连接MongoDB数据库,db.collection is not a function完美解决
    nodejs中&#x5B89;&#x5353;&#x7AEF;的编码如何转换为中文
    深入理解js的变量提升和函数提升
  • 原文地址:https://www.cnblogs.com/fwst/p/3824634.html
Copyright © 2020-2023  润新知