Ubuntu下使用GLUT与GDK将图片文件加载到纹理单元

在Linux系统中有不少开源好用的工具库用来读取图片文件,识别其格式,然后以RGB等原生像素格式存储到存储器中。比如libpng就是其中之一。不过我们这里使用更方便好用、更通用的GTK+库中所包含的GDK工具库对指定的图片文件进行读取,然后读取其内部原生像素数据,最后映射到纹理单元上。
我们可以参考这篇博文来下载安装GTK+:Ubuntu下如何安装GTK+3

下面我们先建立一个shell文件,命名为 build.sh,用它进行构建整个程序。

clang main.c -std=gnu11 -lglut -lGL -I/usr/include/glib-2.0/ -I/usr/include/atk-1.0/ -I/usr/include/gdk-pixbuf-2.0/ -I/usr/include/cairo/ -I/usr/include/pango-1.0/ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include/ -I/usr/include/gtk-3.0/ -L/usr/lib/x86_64-linux-gnu/ -lgtk-3 -lgobject-2.0 -lpangocairo-1.0 -lgio-2.0 -latk-1.0 -lgdk-3 -lgdk_pixbuf-2.0 -lglib-2.0 -o glutTexture

如果各位没有安装Clang,也可以使用GCC。如果用GCC进行编译构建的话,只需要将上述的 clang 改为 gcc 即可。

下面展示 main.c 源文件:

#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#include <GL/freeglut.h>
#include <GL/gl.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>

#ifndef var
#define var __auto_type
#endif

static const GLfloat sRectVertices[] = {
    // top left
    -0.4f, 0.4f,

    // bottom left
    -0.4f, -0.4f,

    // top right
    0.4f, 0.4f,

    // bottom right
    0.4f, -0.4f
};

static const GLfloat sRectTexCoords[] = {
    // top left
    0.0f, 0.0f,

    // bottom left
    0.0f, 1.0f,

    // top right
    1.0f, 0.0f,

    // bottom right
    1.0f, 1.0f
};

static void TimerHandler(int value);

static GLfloat sDisplacement = -0.5f;
static GLfloat sDelta = 0.005f;
static int sTimerDuration = 20;     // 默认以50FPS的帧率进行刷新

static void RenderHandler(void)
{
    glutTimerFunc(sTimerDuration, TimerHandler, 0);
    sTimerDuration = 20;

    glClear(GL_COLOR_BUFFER_BIT);

    // Draw rectangle
    glVertexPointer(2, GL_FLOAT, 0, sRectVertices);
    glTexCoordPointer(2, GL_FLOAT, 0, sRectTexCoords);

    glLoadIdentity();
    glTranslatef(sDisplacement, 0.0f, -2.0f);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    
    glFlush();

    glutSwapBuffers();

    sDisplacement += sDelta;
    if(sDisplacement >= 0.5f)
    {
        sDisplacement = 0.5f;
        sDelta = -sDelta;
        sTimerDuration = 1500;
    }
    else if(sDisplacement <= -0.5f)
    {
        sDisplacement = -0.5f;
        sDelta = -sDelta;
        sTimerDuration = 1500;
    }
}

static void TimerHandler(int value)
{
    RenderHandler();
}


static bool LoadPixelsFromImageToTexture(const char *filePath)
{
    var pixBuf = gdk_pixbuf_new_from_file(filePath, NULL);
    if(pixBuf == NULL)
    {
        puts("The image is not found!");
        printf("The file path is: %s\n", filePath);
        return false;
    }

    const var width = gdk_pixbuf_get_width(pixBuf);
    const var height = gdk_pixbuf_get_height(pixBuf);
    printf("The image width is: %d, height is: %d\n", width, height);

    var pixels = gdk_pixbuf_read_pixels(pixBuf);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

    g_object_unref(pixBuf);

    return true;
}


int main(int argc, char* argv[])
{
    gtk_init(&argc, &argv);

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_MULTISAMPLE);
    glutInitWindowSize(480, 480);
    glutInitWindowPosition(200, 100);
    glutCreateWindow("OpenGL GLUT Demo");

    glutSetOption(GLUT_MULTISAMPLE, 4);
    glutDisplayFunc(RenderHandler);

    var vendor = (const char*)glGetString(GL_VENDOR);
    var renderer = (const char*)glGetString(GL_RENDERER);
    var version = (const char*)glGetString(GL_VERSION);
    printf("The vendor is: %s\n", vendor);
    printf("The renderer is: %s\n", renderer);
    printf("The GL version is: %s\n", version);

    glViewport(0, 0, 480, 480);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glShadeModel(GL_SMOOTH);
    glFrontFace(GL_CCW);
    glCullFace(GL_BACK);

    glEnable(GL_CULL_FACE);
    glEnable(GL_MULTISAMPLE_ARB);
    glEnable(GL_TEXTURE_2D);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glActiveTexture(GL_TEXTURE0);

    GLuint texID;
    glGenTextures(1, &texID);
    glBindTexture(GL_TEXTURE_2D, texID);

    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    char path[512];
    int size = readlink("/proc/self/exe", path, 512);
    int index = 0;
    for(int i = size - 1; i >= 0; i--)
    {
        const var ch = path[i];
        if(ch == '/')
        {
            index = i + 1;
            break;
        }
    }

    bool result = false;
    do
    {
        if(index == 0)
            break;

        strcpy(&path[index], "image.png");

        result = LoadPixelsFromImageToTexture(path);
    }
    while(false);

    if(!result)
    {
        puts("Image data load failed!");
        glDeleteTextures(1, &texID);
        return 0;
    }

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 3.0f);

    glMatrixMode(GL_MODELVIEW);

    glutMainLoop();

    glDeleteTextures(1, &texID);
}

各位在运行上述程序之前需要注意,先搞一个PNG的图片,命名为 image.png,然后将它放到 build.shmain.c 同一文件目录下。这里对image.png是有要求的,其宽与高的像素个数必须至少为 32 的倍数,并且最小值为64,这样才符合作为纹理的要求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值